View Javadoc
1   /*
2    * Copyright (c) 2001-2017, Zoltan Farkas All Rights Reserved.
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this program; if not, write to the Free Software
16   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17   *
18   * Additionally licensed with:
19   *
20   * Licensed under the Apache License, Version 2.0 (the "License");
21   * you may not use this file except in compliance with the License.
22   * You may obtain a copy of the License at
23   *
24   *      http://www.apache.org/licenses/LICENSE-2.0
25   *
26   * Unless required by applicable law or agreed to in writing, software
27   * distributed under the License is distributed on an "AS IS" BASIS,
28   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29   * See the License for the specific language governing permissions and
30   * limitations under the License.
31   */
32  package org.spf4j.log;
33  
34  import com.fasterxml.jackson.core.JsonGenerator;
35  import com.fasterxml.jackson.core.JsonParser;
36  import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
37  import java.io.IOException;
38  import java.io.Serializable;
39  import java.io.UncheckedIOException;
40  import java.time.Instant;
41  import java.util.Collections;
42  import java.util.Iterator;
43  import java.util.Map;
44  import java.util.concurrent.TimeUnit;
45  import org.slf4j.Marker;
46  import org.spf4j.base.CharSequences;
47  import org.spf4j.base.Json;
48  import org.spf4j.base.JsonWriteable;
49  import org.spf4j.base.Pair;
50  import org.spf4j.base.StackSamples;
51  import org.spf4j.io.AppendableWriter;
52  
53  /**
54   * @author Zoltan Farkas
55   */
56  @SuppressFBWarnings({ "PIS_POSSIBLE_INCOMPLETE_SERIALIZATION", "SE_NO_SUITABLE_CONSTRUCTOR" })
57  public final class LogAttribute<T> extends Pair<String, T>
58    implements JsonWriteable, Marker {
59  
60    private static final long serialVersionUID = 1L;
61  
62    public static final String ID_ATTR_NAME = "trId";
63  
64    public static final String PROFILE_SAMPLES_ATTR_NAME = "prSamples";
65  
66    public LogAttribute(final String first, final T second) {
67      super(first, second);
68    }
69  
70    public String getName() {
71      return first;
72    }
73  
74    public static <T> LogAttribute<T> of(final String val, final T obj) {
75      return new LogAttribute(val, obj);
76    }
77  
78    public static LogAttribute<CharSequence> traceId(final CharSequence id) {
79      return new LogAttribute(ID_ATTR_NAME, id);
80    }
81  
82    public static LogAttribute<StackSamples> profileSamples(final StackSamples ss) {
83      return new LogAttribute(PROFILE_SAMPLES_ATTR_NAME, ss);
84    }
85  
86    public static LogAttribute<Level> origLevel(final Level level) {
87      return new LogAttribute("origLevel", level);
88    }
89  
90    public static LogAttribute<Level> origLoggerName(final String loggerName) {
91      return new LogAttribute("origLogger", loggerName);
92    }
93  
94    public static LogAttribute<Level> origTimeStamp(final Instant instant) {
95      return new LogAttribute("origTs", instant);
96    }
97  
98    public static LogAttribute<Level> origTimeStamp(final long millisSinceEpoch) {
99      return new LogAttribute("origTs", Instant.ofEpochMilli(millisSinceEpoch));
100   }
101 
102   public static LogAttribute<Slf4jLogRecord> log(final Slf4jLogRecord record) {
103     return new LogAttribute("log", record);
104   }
105 
106   public static LogAttribute<Long> execTimeMicros(final long time, final TimeUnit tu) {
107     return new LogAttribute("execUs", tu.toMicros(time));
108   }
109 
110   public static LogAttribute<Long> value(final String what, final long value) {
111     return new LogAttribute(what, value);
112   }
113 
114   @Override
115   public String toString() {
116     StringBuilder result = new StringBuilder(32);
117     writeJsonTo(result);
118     return result.toString();
119   }
120 
121   @Override
122   public void writeJsonTo(final Appendable appendable) throws IOException {
123     JsonGenerator gen = Json.FACTORY.createGenerator(new AppendableWriter(appendable));
124     gen.setCodec(Json.MAPPER);
125     writeJsonTo(gen);
126     gen.flush();
127   }
128 
129   public void writeJsonTo(final JsonGenerator gen) throws IOException {
130     gen.writeStartObject();
131     gen.writeFieldName(first);
132     gen.writeObject(second);
133     gen.writeEndObject();
134   }
135 
136   public static LogAttribute<Object> fromJson(final CharSequence jsonStr) {
137     try {
138       JsonParser parser = Json.FACTORY.createParser(CharSequences.reader(jsonStr));
139       parser.setCodec(Json.MAPPER);
140       Map<String, Object> val = parser.readValueAs(Map.class);
141       return fromMap(val);
142     } catch (IOException ex) {
143       throw new UncheckedIOException(ex);
144     }
145   }
146 
147   public static LogAttribute<Object> fromMap(final Map<String, Object> val) {
148     if (val.size() != 1) {
149       throw new IllegalArgumentException("No Log Attribute: " + val);
150     }
151     Map.Entry<String, Object> entry = val.entrySet().iterator().next();
152     Object value = entry.getValue();
153     return LogAttribute.of(entry.getKey(), value);
154   }
155 
156   @Override
157   public void add(final Marker reference) {
158     throw new UnsupportedOperationException();
159   }
160 
161   @Override
162   public boolean remove(final Marker reference) {
163     return false;
164   }
165 
166   @Override
167   public boolean hasChildren() {
168     return false;
169   }
170 
171   @Override
172   public boolean hasReferences() {
173     return false;
174   }
175 
176   @Override
177   public Iterator<Marker> iterator() {
178     return Collections.emptyListIterator();
179   }
180 
181   @Override
182   public boolean contains(final Marker other) {
183     return false;
184   }
185 
186   @Override
187   public boolean contains(final String name) {
188     return false;
189   }
190 
191   private Object writeReplace()
192           throws java.io.ObjectStreamException {
193     StringBuilder sb = new StringBuilder(32);
194     writeJsonTo(sb);
195     return new AttrProxy(sb);
196   }
197 
198   private static final class AttrProxy implements Serializable {
199 
200     private static final long serialVersionUID = 1L;
201     private StringBuilder json;
202 
203     AttrProxy(final StringBuilder json) {
204       this.json = json;
205     }
206 
207     private Object readResolve() {
208       return LogAttribute.fromJson(json);
209     }
210 
211   }
212 
213 }