View Javadoc
1   package org.opentrafficsim.core.logger;
2   
3   import java.util.Set;
4   
5   import org.opentrafficsim.base.logger.CategoryLogger;
6   import org.opentrafficsim.base.logger.LogCategory;
7   import org.pmw.tinylog.Level;
8   import org.pmw.tinylog.LogEntryForwarder;
9   import org.pmw.tinylog.writers.Writer;
10  
11  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
12  
13  /**
14   * SimLogger, "extends" the CategoryLogger to be simulator aware and able to print the simulator time as part of the log
15   * message. <br>
16   * <br>
17   * Copyright (c) 2003-2018 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
18   * for project information <a href="https://www.simulation.tudelft.nl/" target="_blank">www.simulation.tudelft.nl</a>. The
19   * source code and binary code of this software is proprietary information of Delft University of Technology.
20   * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
21   */
22  @SuppressWarnings({ "checkstyle:finalclass", "checkstyle:needbraces" })
23  public class SimLogger extends CategoryLogger
24  {
25      /** The simulator of which to include the time in the log messages. */
26      private static SimulatorInterface<?, ?, ?> simulator = null;
27  
28      /** The delegate logger instance that does the actual logging work, after a positive filter outcome. */
29      private static DelegateSimLogger delegateSimLogger = new DelegateSimLogger();
30  
31      /** */
32      private SimLogger()
33      {
34          // Utility class.
35      }
36  
37      static
38      {
39          create();
40      }
41  
42      /**
43       * Create a new logger for the system console. Note that this REPLACES current loggers, so create this class before ANY
44       * other loggers are created. Note that the initial LogCategory is LogCategory.ALL, so all categories will be logged. This
45       * category has to be explicitly removed (or new categories have to be set) to log a limited set of categories.
46       */
47      protected static void create()
48      {
49          // nothing to add for now. The CategoryLogger.create() is called with its static initializer.
50      }
51  
52      /**
53       * Set the simulator of which to include the time in the log messages.
54       * @param newSimulator the simulator to set
55       */
56      public static final void setSimulator(final SimulatorInterface<?, ?, ?> newSimulator)
57      {
58          simulator = newSimulator;
59      }
60  
61      /**
62       * Set a new logging format for the message lines of all writers. The default message format is:<br>
63       * {class_name}.{method}:{line} {message|indent=4}<br>
64       * <br>
65       * A few popular placeholders that can be used:<br>
66       * - {class} Fully-qualified class name where the logging request is issued<br>
67       * - {class_name} Class name (without package) where the logging request is issued<br>
68       * - {date} Date and time of the logging request, e.g. {date:yyyy-MM-dd HH:mm:ss} [SimpleDateFormat]<br>
69       * - {level} Logging level of the created log entry<br>
70       * - {line} Line number from where the logging request is issued<br>
71       * - {message} Associated message of the created log entry<br>
72       * - {method} Method name from where the logging request is issued<br>
73       * - {package} Package where the logging request is issued<br>
74       * @see <a href="https://tinylog.org/configuration#format">https://tinylog.org/configuration</a>
75       * @param newMessageFormat the new formatting pattern to use for all registered writers
76       */
77      public static void setAllLogMessageFormat(final String newMessageFormat)
78      {
79          CategoryLogger.setAllLogMessageFormat(newMessageFormat);
80      }
81  
82      /**
83       * Set a new logging level for all registered writers.
84       * @param newLevel the new log level for all registered writers
85       */
86      public static void setAllLogLevel(final Level newLevel)
87      {
88          CategoryLogger.setAllLogLevel(newLevel);
89      }
90  
91      /**
92       * Set a new logging format for the message lines of a writer. The default message format is:<br>
93       * {class_name}.{method}:{line} {message|indent=4}<br>
94       * <br>
95       * A few popular placeholders that can be used:<br>
96       * - {class} Fully-qualified class name where the logging request is issued<br>
97       * - {class_name} Class name (without package) where the logging request is issued<br>
98       * - {date} Date and time of the logging request, e.g. {date:yyyy-MM-dd HH:mm:ss} [SimpleDateFormat]<br>
99       * - {level} Logging level of the created log entry<br>
100      * - {line} Line number from where the logging request is issued<br>
101      * - {message} Associated message of the created log entry<br>
102      * - {method} Method name from where the logging request is issued<br>
103      * - {package} Package where the logging request is issued<br>
104      * @see <a href="https://tinylog.org/configuration#format">https://tinylog.org/configuration</a>
105      * @param writer the writer to change the mesage format for
106      * @param newMessageFormat the new formatting pattern to use for all registered writers
107      */
108     public static void setLogMessageFormat(final Writer writer, final String newMessageFormat)
109     {
110         CategoryLogger.setLogMessageFormat(writer, newMessageFormat);
111     }
112 
113     /**
114      * Set a new logging level for one of the registered writers.
115      * @param writer the writer to change the log level for
116      * @param newLevel the new log level for the writer
117      */
118     public static void setLogLevel(final Writer writer, final Level newLevel)
119     {
120         CategoryLogger.setLogLevel(writer, newLevel);
121     }
122 
123     /**
124      * Add a category to be logged to the Writers.
125      * @param logCategory the LogCategory to add
126      */
127     public static void addLogCategory(final LogCategory logCategory)
128     {
129         CategoryLogger.addLogCategory(logCategory);
130     }
131 
132     /**
133      * Remove a category to be logged to the Writers.
134      * @param logCategory the LogCategory to remove
135      */
136     public static void removeLogCategory(final LogCategory logCategory)
137     {
138         CategoryLogger.removeLogCategory(logCategory);
139     }
140 
141     /**
142      * Set the categories to be logged to the Writers.
143      * @param newLogCategories the LogCategories to set, replacing the previous ones
144      */
145     public static void setLogCategories(final LogCategory... newLogCategories)
146     {
147         CategoryLogger.setLogCategories(newLogCategories);
148     }
149 
150     /* ****************************************** FILTER ******************************************/
151 
152     /**
153      * The "pass" filter that will result in always trying to log.
154      * @return the logger that tries to execute logging (delegateLogger)
155      */
156     public static DelegateLogger always()
157     {
158         return delegateLogger;
159     }
160 
161     /**
162      * Check whether the provided category needs to be logged. Note that when LogCategory.ALL is contained in the categories,
163      * filter will return true.
164      * @param logCategory the category to check for.
165      * @return the logger that either tries to log (delegateLogger), or returns without logging (noLogger)
166      */
167     public static DelegateLogger filter(final LogCategory logCategory)
168     {
169         if (categories.contains(LogCategory.ALL))
170             return delegateSimLogger;
171         if (categories.contains(logCategory))
172             return delegateSimLogger;
173         return noLogger;
174     }
175 
176     /**
177      * Check whether the provided categories contain one or more categories that need to be logged. Note that when
178      * LogCategory.ALL is contained in the categories, filter will return true.
179      * @param logCategories LogCategory...; elements or array with the categories to check for
180      * @return the logger that either tries to log (delegateLogger), or returns without logging (noLogger)
181      */
182     public static DelegateLogger filter(final LogCategory... logCategories)
183     {
184         if (categories.contains(LogCategory.ALL))
185             return delegateSimLogger;
186         for (LogCategory logCategory : logCategories)
187         {
188             if (categories.contains(logCategory))
189                 return delegateSimLogger;
190         }
191         return noLogger;
192     }
193 
194     /**
195      * Check whether the provided categories contain one or more categories that need to be logged. Note that when
196      * LogCategory.ALL is contained in the categories, filter will return true.
197      * @param logCategories Set&lt;LogCategory&gt;; the categories to check for
198      * @return the logger that either tries to log (delegateLogger), or returns without logging (noLogger)
199      */
200     public static DelegateLogger filter(final Set<LogCategory> logCategories)
201     {
202         if (categories.contains(LogCategory.ALL))
203             return delegateSimLogger;
204         for (LogCategory logCategory : logCategories)
205         {
206             if (categories.contains(logCategory))
207                 return delegateSimLogger;
208         }
209         return noLogger;
210     }
211 
212     /**
213      * Insert the simulator time into the message.
214      * @param message the original message
215      * @return the message with the simulator time at the front
216      */
217     static String insertSimTime(final String message)
218     {
219         if (simulator == null)
220             return message;
221         return simulator.getSimulatorTime() + " - " + message;
222     }
223 
224     /**
225      * DelegateSimLogger class that takes care of actually logging the message and/or exception. The methods take care of
226      * inserting the simulation time in the message.<br>
227      * <br>
228      * Copyright (c) 2003-2018 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved.
229      * See for project information <a href="https://www.simulation.tudelft.nl/" target="_blank">www.simulation.tudelft.nl</a>.
230      * The source code and binary code of this software is proprietary information of Delft University of Technology.
231      * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
232      */
233     public static class DelegateSimLogger extends DelegateLogger
234     {
235         /**
236          * Create an instance of the DelegateSimLogger that takes care of actually logging the message and/or exception.
237          */
238         public DelegateSimLogger()
239         {
240             super(true);
241         }
242 
243         /* ****************************************** TRACE ******************************************/
244 
245         /** {@inheritDoc} */
246         @Override
247         public void trace(final Object object)
248         {
249             LogEntryForwarder.forward(1, Level.TRACE, insertSimTime(object.toString()));
250         }
251 
252         /** {@inheritDoc} */
253         @Override
254         public void trace(final String message)
255         {
256             LogEntryForwarder.forward(1, Level.TRACE, insertSimTime(message));
257         }
258 
259         /** {@inheritDoc} */
260         @Override
261         public void trace(final String message, final Object... arguments)
262         {
263             LogEntryForwarder.forward(1, Level.TRACE, insertSimTime(message), arguments);
264         }
265 
266         /** {@inheritDoc} */
267         @Override
268         public void trace(final Throwable exception)
269         {
270             LogEntryForwarder.forward(1, Level.TRACE, exception, insertSimTime(exception.getMessage()));
271         }
272 
273         /** {@inheritDoc} */
274         @Override
275         public void trace(final Throwable exception, final String message)
276         {
277             LogEntryForwarder.forward(1, Level.TRACE, exception, insertSimTime(message));
278         }
279 
280         /** {@inheritDoc} */
281         @Override
282         public void trace(final Throwable exception, final String message, final Object... arguments)
283         {
284             LogEntryForwarder.forward(1, Level.TRACE, exception, insertSimTime(message), arguments);
285         }
286 
287         /* ****************************************** DEBUG ******************************************/
288 
289         /** {@inheritDoc} */
290         @Override
291         public void debug(final Object object)
292         {
293             LogEntryForwarder.forward(1, Level.DEBUG, insertSimTime(object.toString()));
294         }
295 
296         /** {@inheritDoc} */
297         @Override
298         public void debug(final String message)
299         {
300             LogEntryForwarder.forward(1, Level.DEBUG, insertSimTime(message));
301         }
302 
303         /** {@inheritDoc} */
304         @Override
305         public void debug(final String message, final Object... arguments)
306         {
307             LogEntryForwarder.forward(1, Level.DEBUG, insertSimTime(message), arguments);
308         }
309 
310         /** {@inheritDoc} */
311         @Override
312         public void debug(final Throwable exception)
313         {
314             LogEntryForwarder.forward(1, Level.DEBUG, exception, insertSimTime(exception.getMessage()));
315         }
316 
317         /** {@inheritDoc} */
318         @Override
319         public void debug(final Throwable exception, final String message)
320         {
321             LogEntryForwarder.forward(1, Level.DEBUG, exception, insertSimTime(message));
322         }
323 
324         /** {@inheritDoc} */
325         @Override
326         public void debug(final Throwable exception, final String message, final Object... arguments)
327         {
328             LogEntryForwarder.forward(1, Level.DEBUG, exception, insertSimTime(message), arguments);
329         }
330 
331         /* ****************************************** INFO ******************************************/
332 
333         /** {@inheritDoc} */
334         @Override
335         public void info(final Object object)
336         {
337             LogEntryForwarder.forward(1, Level.INFO, insertSimTime(object.toString()));
338         }
339 
340         /** {@inheritDoc} */
341         @Override
342         public void info(final String message)
343         {
344             LogEntryForwarder.forward(1, Level.INFO, insertSimTime(message));
345         }
346 
347         /** {@inheritDoc} */
348         @Override
349         public void info(final String message, final Object... arguments)
350         {
351             LogEntryForwarder.forward(1, Level.INFO, insertSimTime(message), arguments);
352         }
353 
354         /** {@inheritDoc} */
355         @Override
356         public void info(final Throwable exception)
357         {
358             LogEntryForwarder.forward(1, Level.INFO, exception, insertSimTime(exception.getMessage()));
359         }
360 
361         /** {@inheritDoc} */
362         @Override
363         public void info(final Throwable exception, final String message)
364         {
365             LogEntryForwarder.forward(1, Level.INFO, exception, insertSimTime(message));
366         }
367 
368         /** {@inheritDoc} */
369         @Override
370         public void info(final Throwable exception, final String message, final Object... arguments)
371         {
372             LogEntryForwarder.forward(1, Level.INFO, exception, insertSimTime(message), arguments);
373         }
374 
375         /* ****************************************** WARN ******************************************/
376 
377         /** {@inheritDoc} */
378         @Override
379         public void warn(final Object object)
380         {
381             LogEntryForwarder.forward(1, Level.WARNING, insertSimTime(object.toString()));
382         }
383 
384         /** {@inheritDoc} */
385         @Override
386         public void warn(final String message)
387         {
388             LogEntryForwarder.forward(1, Level.WARNING, insertSimTime(message));
389         }
390 
391         /** {@inheritDoc} */
392         @Override
393         public void warn(final String message, final Object... arguments)
394         {
395             LogEntryForwarder.forward(1, Level.WARNING, insertSimTime(message), arguments);
396         }
397 
398         /** {@inheritDoc} */
399         @Override
400         public void warn(final Throwable exception)
401         {
402             LogEntryForwarder.forward(1, Level.WARNING, exception, insertSimTime(exception.getMessage()));
403         }
404 
405         /** {@inheritDoc} */
406         @Override
407         public void warn(final Throwable exception, final String message)
408         {
409             LogEntryForwarder.forward(1, Level.WARNING, exception, insertSimTime(message));
410         }
411 
412         /** {@inheritDoc} */
413         @Override
414         public void warn(final Throwable exception, final String message, final Object... arguments)
415         {
416             LogEntryForwarder.forward(1, Level.WARNING, exception, insertSimTime(message), arguments);
417         }
418 
419         /* ****************************************** ERROR ******************************************/
420 
421         /** {@inheritDoc} */
422         @Override
423         public void error(final Object object)
424         {
425             LogEntryForwarder.forward(1, Level.ERROR, insertSimTime(object.toString()));
426         }
427 
428         /** {@inheritDoc} */
429         @Override
430         public void error(final String message)
431         {
432             LogEntryForwarder.forward(1, Level.ERROR, insertSimTime(message));
433         }
434 
435         /** {@inheritDoc} */
436         @Override
437         public void error(final String message, final Object... arguments)
438         {
439             LogEntryForwarder.forward(1, Level.ERROR, insertSimTime(message), arguments);
440         }
441 
442         /** {@inheritDoc} */
443         @Override
444         public void error(final Throwable exception)
445         {
446             LogEntryForwarder.forward(1, Level.ERROR, exception, insertSimTime(exception.getMessage()));
447         }
448 
449         /** {@inheritDoc} */
450         @Override
451         public void error(final Throwable exception, final String message)
452         {
453             LogEntryForwarder.forward(1, Level.ERROR, exception, insertSimTime(message));
454         }
455 
456         /** {@inheritDoc} */
457         @Override
458         public void error(final Throwable exception, final String message, final Object... arguments)
459         {
460             LogEntryForwarder.forward(1, Level.ERROR, exception, insertSimTime(message), arguments);
461         }
462 
463     }
464 }