1 package org.djutils.logger; 2 3 import java.util.Arrays; 4 import java.util.HashMap; 5 import java.util.HashSet; 6 import java.util.Map; 7 import java.util.Set; 8 import java.util.function.BooleanSupplier; 9 10 import org.pmw.tinylog.Configurator; 11 import org.pmw.tinylog.Level; 12 import org.pmw.tinylog.LogEntryForwarder; 13 import org.pmw.tinylog.writers.ConsoleWriter; 14 import org.pmw.tinylog.writers.Writer; 15 16 /** 17 * The CategoryLogger can log for specific Categories. The way to call the logger for messages that always need to be logged, 18 * such as an error with an exception is: 19 * 20 * <pre> 21 * CategoryLogger.always().error(exception, "Parameter {} did not initialize correctly", param1.toString()); 22 * </pre> 23 * 24 * It is also possible to indicate the category / categories for the message, which will only be logged if at least one of the 25 * indicated categories is turned on with addLogCategory() or setLogCategories(), or if one of the added or set LogCategories is 26 * LogCategory.ALL: 27 * 28 * <pre> 29 * CategoryLogger.filter(Cat.BASE).debug("Parameter {} initialized correctly", param1.toString()); 30 * </pre> 31 * <p> 32 * Copyright (c) 2018-2019 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See 33 * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is 34 * distributed under a three-clause BSD-style license, which can be found at 35 * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>. 36 * </p> 37 * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank"> Alexander Verbraeck</a> 38 */ 39 @SuppressWarnings({"checkstyle:visibilitymodifier", "checkstyle:finalclass", "checkstyle:needbraces"}) 40 public class CategoryLogger 41 { 42 /** The default message format. */ 43 public static final String DEFAULT_MESSAGE_FORMAT = "{class_name}.{method}:{line} {message|indent=4}"; 44 45 /** The current message format. */ 46 private static String defaultMessageFormat = DEFAULT_MESSAGE_FORMAT; 47 48 /** The current logging level. */ 49 private static Level defaultLevel = Level.INFO; 50 51 /** The writers registered with this CategoryLogger. */ 52 private static Set<Writer> writers = new HashSet<>(); 53 54 /** The log level per Writer. */ 55 private static Map<Writer, Level> writerLevels = new HashMap<>(); 56 57 /** The message format per Writer. */ 58 private static Map<Writer, String> writerFormats = new HashMap<>(); 59 60 /** The categories to log. */ 61 protected static Set<LogCategory> categories = new HashSet<>(256); 62 63 /** The console writer, replacing the default one. */ 64 private static Writer consoleWriter; 65 66 /** The conditional logger works on the basis of a true condition. */ 67 protected static ConditionalLogger conditionalLogger = new ConditionalLogger(true); 68 69 /** The conditional logger works on the basis of a condition, failing the condition. */ 70 protected static ConditionalLogger conditionalNoLogger = new ConditionalLogger(false); 71 72 /** The delegate logger instance that does the actual logging work, after a positive filter outcome. */ 73 protected static DelegateLogger delegateLogger = new DelegateLogger(true); 74 75 /** The delegate logger that returns immediately after a negative filter outcome. */ 76 protected static DelegateLogger noLogger = new DelegateLogger(false); 77 78 /** */ 79 protected CategoryLogger() 80 { 81 // Utility class. 82 } 83 84 static 85 { 86 create(); 87 } 88 89 /** 90 * Create a new logger for the system console. Note that this REPLACES current writers. Note that the initial LogCategory is 91 * LogCategory.ALL, so all categories will be logged. This category has to be explicitly removed (or new categories have to 92 * be set) to log a limited set of categories. 93 */ 94 protected static void create() 95 { 96 consoleWriter = new ConsoleWriter(); 97 writers.add(consoleWriter); 98 Configurator.currentConfig().writer(consoleWriter, defaultLevel, defaultMessageFormat).activate(); 99 categories.add(LogCategory.ALL); 100 } 101 102 /** 103 * Set a new logging format for the message lines of all writers. The default message format is:<br> 104 * {class_name}.{method}:{line} {message|indent=4}<br> 105 * <br> 106 * A few popular placeholders that can be used:<br> 107 * - {class} Fully-qualified class name where the logging request is issued<br> 108 * - {class_name} Class name (without package) where the logging request is issued<br> 109 * - {date} Date and time of the logging request, e.g. {date:yyyy-MM-dd HH:mm:ss} [SimpleDateFormat]<br> 110 * - {level} Logging level of the created log entry<br> 111 * - {line} Line number from where the logging request is issued<br> 112 * - {message} Associated message of the created log entry<br> 113 * - {method} Method name from where the logging request is issued<br> 114 * - {package} Package where the logging request is issued<br> 115 * @see <a href="https://tinylog.org/configuration#format">https://tinylog.org/configuration</a> 116 * @param newMessageFormat String; the new formatting pattern to use for all registered writers 117 */ 118 public static void setAllLogMessageFormat(final String newMessageFormat) 119 { 120 for (Writer writer : writers) 121 { 122 Configurator.currentConfig().removeWriter(writer).activate(); 123 defaultMessageFormat = newMessageFormat; 124 writerFormats.put(writer, newMessageFormat); 125 Configurator.currentConfig().addWriter(writer, defaultLevel, defaultMessageFormat).activate(); 126 } 127 } 128 129 /** 130 * Set a new logging level for all registered writers. 131 * @param newLevel Level; the new log level for all registered writers 132 */ 133 public static void setAllLogLevel(final Level newLevel) 134 { 135 for (Writer writer : writers) 136 { 137 Configurator.currentConfig().removeWriter(writer).activate(); 138 defaultLevel = newLevel; 139 writerLevels.put(writer, newLevel); 140 Configurator.currentConfig().addWriter(writer, defaultLevel, defaultMessageFormat).activate(); 141 } 142 } 143 144 /** 145 * Set a new logging format for the message lines of a writer. The default message format is:<br> 146 * {class_name}.{method}:{line} {message|indent=4}<br> 147 * <br> 148 * A few popular placeholders that can be used:<br> 149 * - {class} Fully-qualified class name where the logging request is issued<br> 150 * - {class_name} Class name (without package) where the logging request is issued<br> 151 * - {date} Date and time of the logging request, e.g. {date:yyyy-MM-dd HH:mm:ss} [SimpleDateFormat]<br> 152 * - {level} Logging level of the created log entry<br> 153 * - {line} Line number from where the logging request is issued<br> 154 * - {message} Associated message of the created log entry<br> 155 * - {method} Method name from where the logging request is issued<br> 156 * - {package} Package where the logging request is issued<br> 157 * @see <a href="https://tinylog.org/configuration#format">https://tinylog.org/configuration</a> 158 * @param writer Writer; the writer to change the message format for 159 * @param newMessageFormat String; the new formatting pattern to use for all registered writers 160 */ 161 public static void setLogMessageFormat(final Writer writer, final String newMessageFormat) 162 { 163 Configurator.currentConfig().removeWriter(writer).activate(); 164 writerFormats.put(writer, newMessageFormat); 165 Configurator.currentConfig().addWriter(writer, writerLevels.get(writer), newMessageFormat).activate(); 166 } 167 168 /** 169 * Set a new logging level for one of the registered writers. 170 * @param writer Writer; the writer to change the log level for 171 * @param newLevel Level; the new log level for the writer 172 */ 173 public static void setLogLevel(final Writer writer, final Level newLevel) 174 { 175 Configurator.currentConfig().removeWriter(writer).activate(); 176 writerLevels.put(writer, newLevel); 177 Configurator.currentConfig().addWriter(writer, newLevel, writerFormats.get(writer)).activate(); 178 } 179 180 /** 181 * Add a category to be logged to the Writers. 182 * @param logCategory LogCategory; the LogCategory to add 183 */ 184 public static void addLogCategory(final LogCategory logCategory) 185 { 186 categories.add(logCategory); 187 } 188 189 /** 190 * Remove a category to be logged to the Writers. 191 * @param logCategory LogCategory; the LogCategory to remove 192 */ 193 public static void removeLogCategory(final LogCategory logCategory) 194 { 195 categories.remove(logCategory); 196 } 197 198 /** 199 * Set the categories to be logged to the Writers. 200 * @param newLogCategories LogCategory...; the LogCategories to set, replacing the previous ones 201 */ 202 public static void setLogCategories(final LogCategory... newLogCategories) 203 { 204 categories.clear(); 205 categories.addAll(Arrays.asList(newLogCategories)); 206 } 207 208 /* ****************************************** FILTER ******************************************/ 209 210 /** 211 * The "pass" filter that will result in always trying to log. 212 * @return the logger that tries to execute logging (delegateLogger) 213 */ 214 public static DelegateLogger always() 215 { 216 return delegateLogger; 217 } 218 219 /** 220 * Check whether the provided category needs to be logged. Note that when LogCategory.ALL is contained in the categories, 221 * filter will return true. 222 * @param logCategory LogCategory; the category to check for. 223 * @return the logger that either tries to log (delegateLogger), or returns without logging (noLogger) 224 */ 225 public static DelegateLogger filter(final LogCategory logCategory) 226 { 227 if (categories.contains(LogCategory.ALL)) 228 return delegateLogger; 229 if (categories.contains(logCategory)) 230 return delegateLogger; 231 return noLogger; 232 } 233 234 /** 235 * Check whether the provided categories contain one or more categories that need to be logged. Note that when 236 * LogCategory.ALL is contained in the categories, filter will return true. 237 * @param logCategories LogCategory...; elements or array with the categories to check for 238 * @return the logger that either tries to log (delegateLogger), or returns without logging (noLogger) 239 */ 240 public static DelegateLogger filter(final LogCategory... logCategories) 241 { 242 if (categories.contains(LogCategory.ALL)) 243 return delegateLogger; 244 for (LogCategory logCategory : logCategories) 245 { 246 if (categories.contains(logCategory)) 247 return delegateLogger; 248 } 249 return noLogger; 250 } 251 252 /** 253 * Check whether the provided categories contain one or more categories that need to be logged. Note that when 254 * LogCategory.ALL is contained in the categories, filter will return true. 255 * @param logCategories Set<LogCategory>; the categories to check for 256 * @return the logger that either tries to log (delegateLogger), or returns without logging (noLogger) 257 */ 258 public static DelegateLogger filter(final Set<LogCategory> logCategories) 259 { 260 if (categories.contains(LogCategory.ALL)) 261 return delegateLogger; 262 for (LogCategory logCategory : logCategories) 263 { 264 if (categories.contains(logCategory)) 265 return delegateLogger; 266 } 267 return noLogger; 268 } 269 270 /** 271 * The conditional filter that will result in the usage of a ConditionalLogger. 272 * @param condition boolean; the condition that should be evaluated 273 * @return the logger that further processes logging (ConditionalLogger) 274 */ 275 public static ConditionalLogger when(final boolean condition) 276 { 277 if (condition) 278 return conditionalLogger; 279 return conditionalNoLogger; 280 } 281 282 /** 283 * The conditional filter that will result in the usage of a ConditionalLogger. 284 * @param supplier BooleanSupplier; the function evaluating the condition 285 * @return the logger that further processes logging (ConditionalLogger) 286 */ 287 public static ConditionalLogger when(final BooleanSupplier supplier) 288 { 289 if (supplier.getAsBoolean()) 290 return conditionalLogger; 291 return conditionalNoLogger; 292 } 293 294 /* *********************************** CONDITIONAL LOGGER *************************************/ 295 296 /** 297 * ConditionalLogger class that takes care of filtering based on a condition. <br> 298 * <br> 299 * Copyright (c) 2003-2019 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. 300 * See for project information <a href="https://www.simulation.tudelft.nl/" target="_blank"> www.simulation.tudelft.nl</a>. 301 * The source code and binary code of this software is proprietary information of Delft University of Technology. 302 * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank"> Alexander Verbraeck</a> 303 */ 304 public static class ConditionalLogger 305 { 306 /** Should we try to log or not? */ 307 private final boolean log; 308 309 /** 310 * @param log boolean; indicate whether we should log or not. 311 */ 312 public ConditionalLogger(final boolean log) 313 { 314 super(); 315 this.log = log; 316 } 317 318 /** 319 * The "pass" filter that will result in always trying to log. 320 * @return the logger that tries to execute logging (delegateLogger) 321 */ 322 public DelegateLogger always() 323 { 324 if (this.log) 325 return delegateLogger; 326 return noLogger; 327 } 328 329 /** 330 * Check whether the provided category needs to be logged. Note that when LogCategory.ALL is contained in the 331 * categories, filter will return true. 332 * @param logCategory LogCategory; the category to check for. 333 * @return the logger that either tries to log (delegateLogger), or returns without logging (noLogger) 334 */ 335 public DelegateLogger filter(final LogCategory logCategory) 336 { 337 if (this.log) 338 { 339 if (categories.contains(LogCategory.ALL)) 340 return delegateLogger; 341 if (categories.contains(logCategory)) 342 return delegateLogger; 343 } 344 return noLogger; 345 } 346 347 /** 348 * Check whether the provided categories contain one or more categories that need to be logged. Note that when 349 * LogCategory.ALL is contained in the categories, filter will return true. 350 * @param logCategories LogCategory...; elements or array with the categories to check for 351 * @return the logger that either tries to log (delegateLogger), or returns without logging (noLogger) 352 */ 353 public DelegateLogger filter(final LogCategory... logCategories) 354 { 355 if (this.log) 356 { 357 if (categories.contains(LogCategory.ALL)) 358 return delegateLogger; 359 for (LogCategory logCategory : logCategories) 360 { 361 if (categories.contains(logCategory)) 362 return delegateLogger; 363 } 364 } 365 return noLogger; 366 } 367 } 368 369 /* ************************************ DELEGATE LOGGER ***************************************/ 370 371 /** 372 * DelegateLogger class that takes care of actually logging the message and/or exception. <br> 373 * <br> 374 * Copyright (c) 2003-2019 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. 375 * See for project information <a href="https://www.simulation.tudelft.nl/" target="_blank"> www.simulation.tudelft.nl</a>. 376 * The source code and binary code of this software is proprietary information of Delft University of Technology. 377 * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank"> Alexander Verbraeck</a> 378 */ 379 public static class DelegateLogger 380 { 381 /** Should we try to log or not? */ 382 private final boolean log; 383 384 /** 385 * @param log boolean; indicate whether we should log or not. 386 */ 387 public DelegateLogger(final boolean log) 388 { 389 super(); 390 this.log = log; 391 } 392 393 /* ****************************************** TRACE ******************************************/ 394 395 /** 396 * Create a trace log entry that will always be output, independent of LogCategory settings. 397 * @param object Object; the result of the <code>toString()</code> method of <code>object</code> will be logged 398 */ 399 public void trace(final Object object) 400 { 401 if (this.log) 402 LogEntryForwarder.forward(1, Level.TRACE, object); 403 } 404 405 /** 406 * Create a trace log entry that will always be output, independent of LogCategory settings. 407 * @param message String; the message to log 408 */ 409 public void trace(final String message) 410 { 411 if (this.log) 412 LogEntryForwarder.forward(1, Level.TRACE, message); 413 } 414 415 /** 416 * Create a trace log entry that will always be output, independent of LogCategory settings. 417 * @param message String; the message to be logged, where {} entries will be replaced by arguments 418 * @param arguments Object...; the arguments to substitute for the {} entries in the message string 419 */ 420 public void trace(final String message, final Object... arguments) 421 { 422 if (this.log) 423 LogEntryForwarder.forward(1, Level.TRACE, message, arguments); 424 } 425 426 /** 427 * Create a trace log entry that will always be output, independent of LogCategory settings. 428 * @param exception Throwable; the exception to log 429 */ 430 public void trace(final Throwable exception) 431 { 432 if (this.log) 433 LogEntryForwarder.forward(1, Level.TRACE, exception); 434 } 435 436 /** 437 * Create a trace log entry that will always be output, independent of LogCategory settings. 438 * @param exception Throwable; the exception to log 439 * @param message String; the message to log 440 */ 441 public void trace(final Throwable exception, final String message) 442 { 443 if (this.log) 444 LogEntryForwarder.forward(1, Level.TRACE, exception, message); 445 } 446 447 /** 448 * Create a trace log entry that will always be output, independent of LogCategory settings. 449 * @param exception Throwable; the exception to log 450 * @param message String; the message to log, where {} entries will be replaced by arguments 451 * @param arguments Object...; the arguments to substitute for the {} entries in the message string 452 */ 453 public void trace(final Throwable exception, final String message, final Object... arguments) 454 { 455 if (this.log) 456 LogEntryForwarder.forward(1, Level.TRACE, exception, message, arguments); 457 } 458 459 /* ****************************************** DEBUG ******************************************/ 460 461 /** 462 * Create a debug log entry that will always be output, independent of LogCategory settings. 463 * @param object Object; the result of the <code>toString()</code> method of <code>object</code> will be logged 464 */ 465 public void debug(final Object object) 466 { 467 if (this.log) 468 LogEntryForwarder.forward(1, Level.DEBUG, object); 469 } 470 471 /** 472 * Create a debug log entry that will always be output, independent of LogCategory settings. 473 * @param message String; the message to log 474 */ 475 public void debug(final String message) 476 { 477 if (this.log) 478 LogEntryForwarder.forward(1, Level.DEBUG, message); 479 } 480 481 /** 482 * Create a debug log entry that will always be output, independent of LogCategory settings. 483 * @param message String; the message to be logged, where {} entries will be replaced by arguments 484 * @param arguments Object...; the arguments to substitute for the {} entries in the message string 485 */ 486 public void debug(final String message, final Object... arguments) 487 { 488 if (this.log) 489 LogEntryForwarder.forward(1, Level.DEBUG, message, arguments); 490 } 491 492 /** 493 * Create a debug log entry that will always be output, independent of LogCategory settings. 494 * @param exception Throwable; the exception to log 495 */ 496 public void debug(final Throwable exception) 497 { 498 if (this.log) 499 LogEntryForwarder.forward(1, Level.DEBUG, exception); 500 } 501 502 /** 503 * Create a debug log entry that will always be output, independent of LogCategory settings. 504 * @param exception Throwable; the exception to log 505 * @param message String; the message to log 506 */ 507 public void debug(final Throwable exception, final String message) 508 { 509 if (this.log) 510 LogEntryForwarder.forward(1, Level.DEBUG, exception, message); 511 } 512 513 /** 514 * Create a debug log entry that will always be output, independent of LogCategory settings. 515 * @param exception Throwable; the exception to log 516 * @param message String; the message to log, where {} entries will be replaced by arguments 517 * @param arguments Object...; the arguments to substitute for the {} entries in the message string 518 */ 519 public void debug(final Throwable exception, final String message, final Object... arguments) 520 { 521 if (this.log) 522 LogEntryForwarder.forward(1, Level.DEBUG, exception, message, arguments); 523 } 524 525 /* ****************************************** INFO ******************************************/ 526 527 /** 528 * Create a info log entry that will always be output, independent of LogCategory settings. 529 * @param object Object; the result of the <code>toString()</code> method of <code>object</code> will be logged 530 */ 531 public void info(final Object object) 532 { 533 if (this.log) 534 LogEntryForwarder.forward(1, Level.INFO, object); 535 } 536 537 /** 538 * Create a info log entry that will always be output, independent of LogCategory settings. 539 * @param message String; the message to log 540 */ 541 public void info(final String message) 542 { 543 if (this.log) 544 LogEntryForwarder.forward(1, Level.INFO, message); 545 } 546 547 /** 548 * Create a info log entry that will always be output, independent of LogCategory settings. 549 * @param message String; the message to be logged, where {} entries will be replaced by arguments 550 * @param arguments Object...; the arguments to substitute for the {} entries in the message string 551 */ 552 public void info(final String message, final Object... arguments) 553 { 554 if (this.log) 555 LogEntryForwarder.forward(1, Level.INFO, message, arguments); 556 } 557 558 /** 559 * Create a info log entry that will always be output, independent of LogCategory settings. 560 * @param exception Throwable; the exception to log 561 */ 562 public void info(final Throwable exception) 563 { 564 if (this.log) 565 LogEntryForwarder.forward(1, Level.INFO, exception); 566 } 567 568 /** 569 * Create a info log entry that will always be output, independent of LogCategory settings. 570 * @param exception Throwable; the exception to log 571 * @param message String; the message to log 572 */ 573 public void info(final Throwable exception, final String message) 574 { 575 if (this.log) 576 LogEntryForwarder.forward(1, Level.INFO, exception, message); 577 } 578 579 /** 580 * Create a info log entry that will always be output, independent of LogCategory settings. 581 * @param exception Throwable; the exception to log 582 * @param message String; the message to log, where {} entries will be replaced by arguments 583 * @param arguments Object...; the arguments to substitute for the {} entries in the message string 584 */ 585 public void info(final Throwable exception, final String message, final Object... arguments) 586 { 587 if (this.log) 588 LogEntryForwarder.forward(1, Level.INFO, exception, message, arguments); 589 } 590 591 /* ****************************************** WARN ******************************************/ 592 593 /** 594 * Create a warn log entry that will always be output, independent of LogCategory settings. 595 * @param object Object; the result of the <code>toString()</code> method of <code>object</code> will be logged 596 */ 597 public void warn(final Object object) 598 { 599 if (this.log) 600 LogEntryForwarder.forward(1, Level.WARNING, object); 601 } 602 603 /** 604 * Create a warn log entry that will always be output, independent of LogCategory settings. 605 * @param message String; the message to log 606 */ 607 public void warn(final String message) 608 { 609 if (this.log) 610 LogEntryForwarder.forward(1, Level.WARNING, message); 611 } 612 613 /** 614 * Create a warn log entry that will always be output, independent of LogCategory settings. 615 * @param message String; the message to be logged, where {} entries will be replaced by arguments 616 * @param arguments Object...; the arguments to substitute for the {} entries in the message string 617 */ 618 public void warn(final String message, final Object... arguments) 619 { 620 if (this.log) 621 LogEntryForwarder.forward(1, Level.WARNING, message, arguments); 622 } 623 624 /** 625 * Create a warn log entry that will always be output, independent of LogCategory settings. 626 * @param exception Throwable; the exception to log 627 */ 628 public void warn(final Throwable exception) 629 { 630 if (this.log) 631 LogEntryForwarder.forward(1, Level.WARNING, exception); 632 } 633 634 /** 635 * Create a warn log entry that will always be output, independent of LogCategory settings. 636 * @param exception Throwable; the exception to log 637 * @param message String; the message to log 638 */ 639 public void warn(final Throwable exception, final String message) 640 { 641 if (this.log) 642 LogEntryForwarder.forward(1, Level.WARNING, exception, message); 643 } 644 645 /** 646 * Create a warn log entry that will always be output, independent of LogCategory settings. 647 * @param exception Throwable; the exception to log 648 * @param message String; the message to log, where {} entries will be replaced by arguments 649 * @param arguments Object...; the arguments to substitute for the {} entries in the message string 650 */ 651 public void warn(final Throwable exception, final String message, final Object... arguments) 652 { 653 if (this.log) 654 LogEntryForwarder.forward(1, Level.WARNING, exception, message, arguments); 655 } 656 657 /* ****************************************** ERROR ******************************************/ 658 659 /** 660 * Create a error log entry that will always be output, independent of LogCategory settings. 661 * @param object Object; the result of the <code>toString()</code> method of <code>object</code> will be logged 662 */ 663 public void error(final Object object) 664 { 665 if (this.log) 666 LogEntryForwarder.forward(1, Level.ERROR, object); 667 } 668 669 /** 670 * Create a error log entry that will always be output, independent of LogCategory settings. 671 * @param message String; the message to log 672 */ 673 public void error(final String message) 674 { 675 if (this.log) 676 LogEntryForwarder.forward(1, Level.ERROR, message); 677 } 678 679 /** 680 * Create a error log entry that will always be output, independent of LogCategory settings. 681 * @param message String; the message to be logged, where {} entries will be replaced by arguments 682 * @param arguments Object...; the arguments to substitute for the {} entries in the message string 683 */ 684 public void error(final String message, final Object... arguments) 685 { 686 if (this.log) 687 LogEntryForwarder.forward(1, Level.ERROR, message, arguments); 688 } 689 690 /** 691 * Create a error log entry that will always be output, independent of LogCategory settings. 692 * @param exception Throwable; the exception to log 693 */ 694 public void error(final Throwable exception) 695 { 696 if (this.log) 697 LogEntryForwarder.forward(1, Level.ERROR, exception); 698 } 699 700 /** 701 * Create a error log entry that will always be output, independent of LogCategory settings. 702 * @param exception Throwable; the exception to log 703 * @param message String; the message to log 704 */ 705 public void error(final Throwable exception, final String message) 706 { 707 if (this.log) 708 LogEntryForwarder.forward(1, Level.ERROR, exception, message); 709 } 710 711 /** 712 * Create a error log entry that will always be output, independent of LogCategory settings. 713 * @param exception Throwable; the exception to log 714 * @param message String; the message to log, where {} entries will be replaced by arguments 715 * @param arguments Object...; the arguments to substitute for the {} entries in the message string 716 */ 717 public void error(final Throwable exception, final String message, final Object... arguments) 718 { 719 if (this.log) 720 LogEntryForwarder.forward(1, Level.ERROR, exception, message, arguments); 721 } 722 } 723 }