1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.spf4j.test.log;
17
18 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19 import java.util.EnumMap;
20 import java.util.Map;
21 import java.util.function.Supplier;
22 import javax.annotation.concurrent.ThreadSafe;
23 import org.slf4j.Logger;
24 import org.slf4j.Marker;
25 import org.spf4j.log.Level;
26
27 import sun.misc.Contended;
28
29
30
31
32
33 @ThreadSafe
34 public final class TestLogger implements Logger {
35
36 private final String name;
37
38 private final Supplier<LogConfig> cfgSource;
39
40 private final Map<Level, Supplier<LogConsumer>> consumers;
41
42
43 private static final class LogConfigConsumer {
44
45 private static final LogConfigConsumer NULL = new LogConfigConsumer(null, null);
46
47 private final LogConfig cfg;
48
49 private final LogConsumer consumer;
50
51 LogConfigConsumer(final LogConfig cfg, final LogConsumer consumer) {
52 this.cfg = cfg;
53 this.consumer = consumer;
54 }
55
56 }
57
58 @ThreadSafe
59 private final class ConsumerSupplier implements Supplier<LogConsumer> {
60
61 private final Level level;
62
63 @Contended
64 private volatile LogConfigConsumer cfgConsumer;
65
66 ConsumerSupplier(final Level level) {
67 this.level = level;
68 this.cfgConsumer = LogConfigConsumer.NULL;
69 }
70
71 @Override
72 @SuppressFBWarnings("NOS_NON_OWNED_SYNCHRONIZATION")
73 public LogConsumer get() {
74 LogConfig nCfg = cfgSource.get();
75 LogConfigConsumer curCfgConsumer = cfgConsumer;
76 if (nCfg == curCfgConsumer.cfg) {
77 return curCfgConsumer.consumer;
78 } else {
79 synchronized (this) {
80 nCfg = cfgSource.get();
81 curCfgConsumer = cfgConsumer;
82 if (nCfg == curCfgConsumer.cfg) {
83 return curCfgConsumer.consumer;
84 } else {
85 LogConsumer nCons = nCfg.getLogConsumer(name, level);
86 cfgConsumer = new LogConfigConsumer(nCfg, nCons);
87 return nCons;
88 }
89 }
90 }
91 }
92
93 }
94
95 public TestLogger(final String name, final Supplier<LogConfig> configSource) {
96 this.name = name;
97 this.cfgSource = configSource;
98 this.consumers = new EnumMap<>(Level.class);
99 for (Level level : Level.values()) {
100 consumers.put(level, new ConsumerSupplier(level));
101 }
102 }
103
104 @Override
105 public String getName() {
106 return name;
107 }
108
109 public void log(final Level level, final Marker marker, final String msg, final Object... args) {
110 LogConsumer consumer = consumers.get(level).get();
111 if (consumer != null) {
112 consumer.accept(new TestLogRecordImpl(name, level, marker, msg, args));
113 }
114 }
115
116 @Override
117 public boolean isTraceEnabled() {
118 return consumers.get(Level.TRACE).get() != null;
119 }
120
121 @Override
122 public void trace(final String msg) {
123 log(Level.TRACE, null, msg);
124 }
125
126
127 @Override
128 public void trace(final String format, final Object arg) {
129 log(Level.TRACE, null, format, arg);
130 }
131
132 @Override
133 public void trace(final String format, final Object arg1, final Object arg2) {
134 log(Level.TRACE, null, format, arg1, arg2);
135 }
136
137 @Override
138 public void trace(final String format, final Object... arguments) {
139 log(Level.TRACE, null, format, arguments);
140 }
141
142 @Override
143 public void trace(final String msg, final Throwable t) {
144 log(Level.TRACE, null, msg, t);
145 }
146
147 @Override
148 public boolean isTraceEnabled(final Marker marker) {
149 return isTraceEnabled();
150 }
151
152 @Override
153 public void trace(final Marker marker, final String msg) {
154 log(Level.TRACE, marker, msg);
155 }
156
157 @Override
158 public void trace(final Marker marker, final String format, final Object arg) {
159 log(Level.TRACE, marker, format, arg);
160 }
161
162 @Override
163 public void trace(final Marker marker, final String format, final Object arg1, final Object arg2) {
164 log(Level.TRACE, marker, format, arg1, arg2);
165 }
166
167 @Override
168 public void trace(final Marker marker, final String format, final Object... argArray) {
169 log(Level.TRACE, marker, format, argArray);
170 }
171
172 @Override
173 public void trace(final Marker marker, final String msg, final Throwable t) {
174 log(Level.TRACE, marker, msg, t);
175 }
176
177 @Override
178 public boolean isDebugEnabled() {
179 return consumers.get(Level.DEBUG).get() != null;
180 }
181
182 @Override
183 public void debug(final String msg) {
184 log(Level.DEBUG, null, msg);
185 }
186
187 @Override
188 public void debug(final String format, final Object arg) {
189 log(Level.DEBUG, null, format, arg);
190 }
191
192 @Override
193 public void debug(final String format, final Object arg1, final Object arg2) {
194 log(Level.DEBUG, null, format, arg1, arg2);
195 }
196
197 @Override
198 public void debug(final String format, final Object... arguments) {
199 log(Level.DEBUG, null, format, arguments);
200 }
201
202 @Override
203 public void debug(final String msg, final Throwable t) {
204 log(Level.DEBUG, null, msg, t);
205 }
206
207 @Override
208 public boolean isDebugEnabled(final Marker marker) {
209 return isDebugEnabled();
210 }
211
212 @Override
213 public void debug(final Marker marker, final String msg) {
214 log(Level.DEBUG, marker, msg);
215 }
216
217 @Override
218 public void debug(final Marker marker, final String format, final Object arg) {
219 log(Level.DEBUG, marker, format, arg);
220 }
221
222 @Override
223 public void debug(final Marker marker, final String format, final Object arg1, final Object arg2) {
224 log(Level.DEBUG, marker, format, arg1, arg2);
225 }
226
227 @Override
228 public void debug(final Marker marker, final String format, final Object... arguments) {
229 log(Level.DEBUG, marker, format, arguments);
230 }
231
232 @Override
233 public void debug(final Marker marker, final String msg, final Throwable t) {
234 log(Level.DEBUG, marker, msg, t);
235 }
236
237 @Override
238 public boolean isInfoEnabled() {
239 return consumers.get(Level.INFO).get() != null;
240 }
241
242 @Override
243 public void info(final String msg) {
244 log(Level.INFO, null, msg);
245 }
246
247 @Override
248 public void info(final String format, final Object arg) {
249 log(Level.INFO, null, format, arg);
250 }
251
252 @Override
253 public void info(final String format, final Object arg1, final Object arg2) {
254 log(Level.INFO, null, format, arg1, arg2);
255 }
256
257 @Override
258 public void info(final String format, final Object... arguments) {
259 log(Level.INFO, null, format, arguments);
260 }
261
262 @Override
263 public void info(final String msg, final Throwable t) {
264 log(Level.INFO, null, msg, t);
265 }
266
267 @Override
268 public boolean isInfoEnabled(final Marker marker) {
269 return isInfoEnabled();
270 }
271
272 @Override
273 public void info(final Marker marker, final String msg) {
274 log(Level.INFO, marker, msg);
275 }
276
277 @Override
278 public void info(final Marker marker, final String format, final Object arg) {
279 log(Level.INFO, marker, format, arg);
280 }
281
282 @Override
283 public void info(final Marker marker, final String format, final Object arg1, final Object arg2) {
284 log(Level.INFO, marker, format, arg1, arg2);
285 }
286
287 @Override
288 public void info(final Marker marker, final String format, final Object... arguments) {
289 log(Level.INFO, marker, format, arguments);
290 }
291
292 @Override
293 public void info(final Marker marker, final String msg, final Throwable t) {
294 log(Level.INFO, marker, msg, t);
295 }
296
297 @Override
298 public boolean isWarnEnabled() {
299 return consumers.get(Level.WARN).get() != null;
300 }
301
302 @Override
303 public void warn(final String msg) {
304 log(Level.WARN, null, msg);
305 }
306
307 @Override
308 public void warn(final String format, final Object arg) {
309 log(Level.WARN, null, format, arg);
310 }
311
312 @Override
313 public void warn(final String format, final Object... arguments) {
314 log(Level.WARN, null, format, arguments);
315 }
316
317 @Override
318 public void warn(final String format, final Object arg1, final Object arg2) {
319 log(Level.WARN, null, format, arg1, arg2);
320 }
321
322 @Override
323 public void warn(final String msg, final Throwable t) {
324 log(Level.WARN, null, msg, t);
325 }
326
327 @Override
328 public boolean isWarnEnabled(final Marker marker) {
329 return isWarnEnabled();
330 }
331
332 @Override
333 public void warn(final Marker marker, final String msg) {
334 log(Level.WARN, marker, msg);
335 }
336
337 @Override
338 public void warn(final Marker marker, final String format, final Object arg) {
339 log(Level.WARN, marker, format, arg);
340 }
341
342 @Override
343 public void warn(final Marker marker, final String format, final Object arg1, final Object arg2) {
344 log(Level.WARN, marker, format, arg1, arg2);
345 }
346
347 @Override
348 public void warn(final Marker marker, final String format, final Object... arguments) {
349 log(Level.WARN, marker, format, arguments);
350 }
351
352 @Override
353 public void warn(final Marker marker, final String msg, final Throwable t) {
354 log(Level.WARN, marker, msg, t);
355 }
356
357 @Override
358 public boolean isErrorEnabled() {
359 return consumers.get(Level.ERROR).get() != null;
360 }
361
362 @Override
363 public void error(final String msg) {
364 log(Level.ERROR, null, msg);
365 }
366
367 @Override
368 public void error(final String format, final Object arg) {
369 log(Level.ERROR, null, format, arg);
370 }
371
372 @Override
373 public void error(final String format, final Object arg1, final Object arg2) {
374 log(Level.ERROR, null, format, arg1, arg2);
375 }
376
377 @Override
378 public void error(final String format, final Object... arguments) {
379 log(Level.ERROR, null, format, arguments);
380 }
381
382 @Override
383 public void error(final String msg, final Throwable t) {
384 log(Level.ERROR, null, msg, t);
385 }
386
387 @Override
388 public boolean isErrorEnabled(final Marker marker) {
389 return isErrorEnabled();
390 }
391
392 @Override
393 public void error(final Marker marker, final String msg) {
394 log(Level.ERROR, marker, msg);
395 }
396
397 @Override
398 public void error(final Marker marker, final String format, final Object arg) {
399 log(Level.ERROR, marker, format, arg);
400 }
401
402 @Override
403 public void error(final Marker marker, final String format, final Object arg1, final Object arg2) {
404 log(Level.ERROR, marker, format, arg1, arg2);
405 }
406
407 @Override
408 public void error(final Marker marker, final String format, final Object... arguments) {
409 log(Level.ERROR, marker, format, arguments);
410 }
411
412 @Override
413 public void error(final Marker marker, final String msg, final Throwable t) {
414 log(Level.ERROR, marker, msg, t);
415 }
416
417 @Override
418 public String toString() {
419 return "TestLogger{" + "name=" + name + '}';
420 }
421
422 }