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<LogCategory>; 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 }