View Javadoc
1   /*
2    * Copyright 2018 SPF4J.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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  //CHECKSTYLE:OFF
27  import sun.misc.Contended;
28  //CHECKSTYLE:ON
29  
30  /**
31   * @author Zoltan Farkas
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") //its a private class
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 }