1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
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 }