1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml"> 4 5 <head> 6 <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> 7 <title>SLF4J FAQ</title> 8 <link rel="stylesheet" type="text/css" media="screen" href="css/site.css" /> 9 <link rel="stylesheet" type="text/css" href="css/prettify.css" /> 10 </head> 11 <body onload="prettyPrint(); decorate();"> 12 13 <script type="text/javascript" src="js/prettify.js"></script> 14 <script type="text/javascript">prefix='';</script> 15 16 <script type="text/javascript" src="templates/header.js"></script> 17 <script type="text/javascript" src="js/jquery-min.js"></script> 18 <script type="text/javascript" src="js/decorator.js"></script> 19 20 <div id="left"> 21 <script src="templates/left.js" type="text/javascript"></script> 22 </div> 23 24 <div id="content"> 25 26 <h2><a name="top">Frequently Asked Questions about SLF4J</a></h2> 27 28 <p><b>Generalities</b></p> 29 30 <ol type="1"> 31 <li><a href="#what_is">What is SLF4J?</a></li> 32 33 <li><a href="#when">When should SLF4J be used?</a></li> 34 35 <li><a href="#yet_another_facade"> Is SLF4J yet another loggingfacade?</a></li> 36 37 <li><a href="#why_new_project"> If SLF4J fixes JCL, then why 38 wasn't the fix made in JCL instead of creating a new project? 39 </a> 40 </li> 41 42 <li><a href="#need_to_recompile"> When using SLF4J, do I have to 43 recompile my application to switch to a different logging 44 system? 45 </a> 46 </li> 47 48 <li><a href="#requirements">What are SLF4J's requirements?</a></li> 49 50 <li><a href="#compatibility">Are SLF4J versions backward 51 compatible?</a></li> 52 53 <li><a href="#IllegalAccessError">I am getting 54 <code>IllegalAccessError</code> exceptions when using SLF4J. Why 55 is that?</a></li> 56 57 58 <li> 59 <a href="#license">Why is SLF4J licensed under X11 type 60 license instead of the Apache Software License? 61 </a> 62 </li> 63 64 <li> 65 <a href="#where_is_binding">Where can I get a particular 66 SLF4J binding? 67 </a> 68 </li> 69 70 <li> 71 <a href="#configure_logging">Should my library attempt to 72 configure logging? 73 </a> 74 </li> 75 76 <li> 77 <a href="#optional_dependency">In order to reduce the number of 78 dependencies of our software we would like to make SLF4J an 79 optional dependency. Is that a good idea? 80 </a> 81 </li> 82 83 <li> 84 <a href="#maven2">What about Maven transitive 85 dependencies? 86 </a> 87 </li> 88 89 <li> 90 <a href="#excludingJCL">How do I exclude commons-logging as a 91 Maven dependency? 92 </a> 93 </li> 94 </ol> 95 96 97 <b>About the SLF4J API</b> 98 99 <ol type="1"> 100 101 <li> 102 <a href="#string_or_object"> Why don't the printing methods 103 in the Logger interface accept message of type Object, but only 104 messages of type String? 105 </a> 106 </li> 107 108 <li> 109 <a href="#exception_message"> 110 Can I log an exception without an accompanying message? 111 </a> 112 </li> 113 114 115 <li> 116 <a href="#logging_performance"> What is the fastest way of 117 (not) logging? 118 </a> 119 </li> 120 121 <li> 122 <a href="#string_contents"> How can I log the string contents 123 of a single (possibly complex) object? 124 </a> 125 </li> 126 127 128 <li><a href="#fatal"> Why doesn't the 129 <code>org.slf4j.Logger</code> interface have methods for the 130 FATAL level? </a></li> 131 132 <li><a href="#trace">Why was the TRACE level introduced only in 133 SLF4J version 1.4.0? </a></li> 134 135 <li><a href="#i18n">Does the SLF4J logging API support I18N 136 (internationalization)? </a></li> 137 138 139 <li><a href="#noLoggerFactory">Is it possible to retrieve loggers 140 without going through the static methods in 141 <code>LoggerFactory</code>? </a></li> 142 143 <li><a href="#paramException">In the presence of an 144 exception/throwable, is it possible to parameterize a logging 145 statement?</a></li> 146 147 </ol> 148 149 150 151 <b>Implementing the SLF4J API</b> 152 153 <ol type="1"> 154 155 <li><a href="#slf4j_compatible">How do I make my logging 156 framework SLF4J compatible? </a></li> 157 158 <li><a href="#marker_interface">How can my logging system add 159 support for the <code>Marker</code> interface? </a></li> 160 161 <li><a href="#version_checks">How does SLF4J's version check 162 mechanism work? </a></li> 163 164 165 </ol> 166 167 168 <b>General questions about logging</b> 169 170 171 <ol type="1"> 172 173 <li><a href="#declared_static"> Should Logger members of a class 174 be declared as static? </a></li> 175 176 177 <li><a href="#declaration_pattern">Is there a recommended idiom 178 for declaring a loggers in a class?</a></li> 179 180 </ol> 181 182 <h2>Generalities</h2> 183 184 <dl> 185 <dt class="doAnchor" name="what_is">What is SLF4J?</dt> 186 <dd> 187 <p>SLF4J is a simple facade for logging systems allowing the 188 end-user to plug-in the desired logging system at deployment 189 time. 190 </p> 191 </dd> 192 193 <dt class="doAnchor" name="when">When should SLF4J be used?</dt> 194 195 <dd> 196 <p>In short, libraries and other embedded components should 197 consider SLF4J for their logging needs because libraries cannot 198 afford to impose their choice of logging framework on the 199 end-user. On the other hand, it does not necessarily make sense 200 for stand-alone applications to use SLF4J. Stand-alone 201 applications can invoke the logging framework of their choice 202 directly. In the case of logback, the question is moot because 203 logback exposes its logger API via SLF4J. 204 </p> 205 206 <p>SLF4J is only a facade, meaning that it does not provide a 207 complete logging solution. Operations such as configuring 208 appenders or setting logging levels cannot be performed with 209 SLF4J. Thus, at some point in time, any non-trivial 210 application will need to directly invoke the underlying 211 logging system. In other words, complete independence from the 212 API underlying logging system is not possible for a 213 stand-alone application. Nevertheless, SLF4J reduces the 214 impact of this dependence to near-painless levels. 215 </p> 216 217 <p>Suppose that your CRM application uses log4j for its 218 logging. However, one of your important clients request that 219 logging be performed through JDK 1.4 logging. If your 220 application is riddled with thousands of direct log4j calls, 221 migration to JDK 1.4 would be a relatively lengthy and 222 error-prone process. Even worse, you would potentially need to 223 maintain two versions of your CRM software. Had you been 224 invoking SLF4J API instead of log4j, the migration could be 225 completed in a matter of minutes by replacing one jar file with 226 another. 227 </p> 228 229 <p>SLF4J lets component developers to defer the choice of the 230 logging system to the end-user but eventually a choice needs 231 to be made. 232 </p> 233 234 235 236 </dd> 237 238 <dt class="doAnchor" name="yet_another_facade">Is SLF4J yet 239 another logging facade?</dt> 240 241 <dd> 242 <p>SLF4J is conceptually very similar to JCL. As such, it can 243 be thought of as yet another logging facade. However, SLF4J is 244 much simpler in design and arguably more robust. In a 245 nutshell, SLF4J avoid the class loader issues that plague JCL. 246 </p> 247 248 249 250 </dd> 251 <dt class="doAnchor" name="why_new_project">If SLF4J fixes JCL, 252 then why wasn't the fix made in JCL instead of creating a new 253 project? 254 </dt> 255 256 <dd> 257 <p>This is a very good question. First, SLF4J static binding 258 approach is very simple, perhaps even laughably so. It was 259 not easy to convince developers of the validity of that 260 approach. It is only after SLF4J was released and started to 261 become accepted did it gain respectability in the relevant 262 community. 263 </p> 264 265 <p>Second, SLF4J offers two enhancements which tend to be 266 underestimated. Parameterized log messages solve an important 267 problem associated with logging performance, in a pragmatic 268 way. Marker objects, which are supported by the 269 <code>org.slf4j.Logger</code> interface, pave the way for 270 adoption of advanced logging systems and still leave the door 271 open to switching back to more traditional logging systems if 272 need be. 273 </p> 274 275 276 </dd> 277 278 <dt class="doAnchor" name="need_to_recompile">When using SLF4J, do 279 I have to recompile my application to switch to a different 280 logging system? 281 </dt> 282 283 <dd> 284 <p>No, you do not need to recompile your application. You can 285 switch to a different logging system by removing the previous 286 SLF4J binding and replacing it with the binding of your choice. 287 </p> 288 289 <p>For example, if you were using the NOP implementation and 290 would like to switch to log4j version 1.2, simply replace 291 <em>slf4j-nop.jar</em> with <em>slf4j-log4j12.jar</em> on 292 your class path but do not forget to add log4j-1.2.x.jar as 293 well. Want to switch to JDK 1.4 logging? Just replace 294 <em>slf4j-log4j12.jar</em> with <em>slf4j-jdk14.jar</em>. 295 </p> 296 297 298 </dd> 299 300 <dt class="doAnchor" name="requirements">What are SLF4J's 301 requirements? 302 </dt> 303 304 <dd> 305 306 <p>As of version 1.7.0, SLF4J requires JDK 1.5 or later. Earlier 307 SLF4J versions, namely SLF4J 1.4, 1.5. and 1.6, required JDK 308 1.4. 309 </p> 310 311 <p> </p> 312 313 <table class="bodyTable striped"> 314 <tr align="left"> 315 <th>Binding</th> 316 <th>Requirements</th> 317 </tr> 318 319 <tr> 320 <td>slf4j-nop</td> 321 <td>JDK 1.5</td> 322 </tr> 323 <tr> 324 <td>slf4j-simple</td> 325 <td>JDK 1.5</td> 326 </tr> 327 328 <tr> 329 <td>slf4j-log4j12</td> 330 <td align="left">JDK 1.5, plus any other library 331 dependencies required by the log4j appenders in use</td> 332 </tr> 333 <tr> 334 <td>slf4j-jdk14</td> 335 <td>JDK 1.5 or later</td> 336 </tr> 337 <tr> 338 <td>logback-classic</td> 339 <td>JDK 1.5 or later, plus any other library dependencies 340 required by the logback appenders in use</td> 341 </tr> 342 343 </table> 344 345 346 </dd> 347 348 <!-- ==================================================== --> 349 <!-- entry has order dependees --> 350 351 <dt class="doAnchor" name="compatibility">Are SLF4J versions 352 backward compatible? 353 </dt> 354 355 <dd> 356 <p>From the clients perspective, the SLF4J API is backward 357 compatible for all versions. This means than you can upgrade 358 from SLF4J version 1.0 to any later version without 359 problems. Code compiled with <em>slf4j-api-versionN.jar</em> 360 will work with <em>slf4j-api-versionM.jar</em> for any versionN 361 and any versionM. <b>To date, binary compatibility in slf4j-api 362 has never been broken.</b></p> 363 364 <p>However, while the SLF4J API is very stable from the client's 365 perspective, SLF4J bindings, e.g. slf4j-simple.jar or 366 slf4j-log4j12.jar, may require a specific version of slf4j-api. 367 Mixing different versions of slf4j artifacts can be problematic 368 and is strongly discouraged. For instance, if you are using 369 slf4j-api-1.5.6.jar, then you should also use 370 slf4j-simple-1.5.6.jar, using slf4j-simple-1.4.2.jar will not 371 work. 372 </p> 373 374 <p>At initialization time, if SLF4J suspects that there may be a 375 version mismatch problem, it emits a warning about the said 376 mismatch. 377 </p> 378 379 380 </dd> 381 382 <!-- ==================================================== --> 383 384 <dt class="doAnchor" name="IllegalAccessError">I am getting 385 <code>IllegalAccessError</code> exceptions when using SLF4J. Why 386 is that? 387 </dt> 388 389 <dd> 390 391 <p>Here are the exception details.</p> 392 393 <pre class="source">Exception in thread "main" java.lang.IllegalAccessError: tried to access field 394org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory 395 at org.slf4j.LoggerFactory.<clinit>(LoggerFactory.java:60)</pre> 396 397 <p>This error is caused by the static initializer of the 398 <code>LoggerFactory</code> class attempting to directly access 399 the SINGLETON field of 400 <code>org.slf4j.impl.StaticLoggerBinder</code>. While this was 401 allowed in SLF4J 1.5.5 and earlier, in 1.5.6 and later the 402 SINGLETON field has been marked as private access. 403 </p> 404 405 406 <p>If you get the exception shown above, then you are using an 407 older version of slf4j-api, e.g. 1.4.3, with a new version of a 408 slf4j binding, e.g. 1.5.6. Typically, this occurs when your 409 Maven <em>pom.ml</em> file incorporates hibernate 3.3.0 which 410 declares a dependency on slf4j-api version 1.4.2. If your 411 <em>pom.xml</em> declares a dependency on an slf4j binding, say 412 slf4j-log4j12 version 1.5.6, then you will get illegal access 413 errors. 414 </p> 415 416 <p>To see which version of slf4j-api is pulled in by Maven, use 417 the maven dependency plugin as follows.</p> 418 419 <p class="source">mvn dependency:tree</p> 420 421 <p>If you are using Eclipse, please do not rely on the dependency 422 tree shown by <a 423 href="http://m2eclipse.codehaus.org/">m2eclipse</a>.</p> 424 425 <p>In your <em>pom.xml</em> file, explicitly declaring a 426 dependency on slf4j-api matching the version of the declared 427 binding will make the problem go away. 428 </p> 429 430 <p>Please also read the FAQ entry on <a 431 href="#compatibility">backward compatibility</a> for a more 432 general explanation.</p> 433 434 435 </dd> 436 437 438 <!-- ==================================================== --> 439 440 <dt class="doAnchor" name="license">Why is SLF4J licensed under 441 X11 type license instead of the Apache Software License? 442 </dt> 443 444 <dd> 445 <p>SLF4J is licensed under a permissive X11 type license 446 instead of the <a 447 href="http://www.apache.org/licenses/">ASL</a> or the <a 448 href="http://www.gnu.org/copyleft/lesser.html">LGPL</a> 449 because the X11 license is deemed by both the Apache Software 450 Foundation as well as the Free Software Foundation as 451 compatible with their respective licenses. 452 </p> 453 454 455 </dd> 456 457 <!-- ==================================================== --> 458 <dt class="doAnchor" name="where_is_binding">Where can I get a 459 particular SLF4J binding? 460 </dt> 461 462 <dd> 463 464 <p>SLF4J bindings for <a 465 href="api/org/slf4j/impl/SimpleLogger.html">SimpleLogger</a>, 466 <a href="api/org/slf4j/impl/NOPLogger.html">NOPLogger</a>, <a 467 href="api/org/slf4j/impl/Log4jLoggerAdapter.html">Log4jLoggerAdapter</a> 468 and <a 469 href="api/org/slf4j/impl/JDK14LoggerAdapter.html">JDK14LoggerAdapter</a> 470 are contained within the files <em>slf4j-nop.jar</em>, 471 <em>slf4j-simple.jar</em>, <em>slf4j-log4j12.jar</em>, and 472 <em>slf4j-jdk14.jar</em>. These files ship with the <a 473 href="download.html">official SLF4J distribution</a>. Please 474 note that all bindings depend on <em>slf4j-api.jar</em>. 475 </p> 476 477 <p>The binding for logback-classic ships with the <a 478 href="http://logback.qos.ch/download.html">logback 479 distribution</a>. However, as with all other bindings, the 480 logback-classic binding requires <em>slf4j-api.jar</em>. 481 </p> 482 483 484 </dd> 485 486 <dt class="doAnchor" name="configure_logging">Should my library 487 attempt to configure logging? 488 </dt> 489 490 <dd> 491 <p><b>Embedded components such as libraries not only do not need 492 to configure the underlying logging framework, they really 493 should not do so</b>. They should invoke SLF4J to log but should 494 let the end-user configure the logging environment. When 495 embedded components try to configure logging on their own, they 496 often override the end-user's wishes. At the end of the day, it 497 is the end-user who has to read the logs and process them. She 498 should be the person to decide how she wants her logging 499 configured. 500 </p> 501 502 503 </dd> 504 505 <!-- ======================================================= --> 506 507 <dt class="doAnchor" name="optional_dependency">In order to reduce 508 the number of dependencies of our software we would like to make 509 SLF4J an optional dependency. Is that a good idea? 510 </dt> 511 512 <dd> 513 <p><a 514 href="http://stackoverflow.com/questions/978670/is-it-worth-wrapping-a-logging-framework-in-an-additional-layer">This 515 question pops up</a> whenever a software project reaches a point 516 where it needs to devise a logging strategy. 517 </p> 518 519 <p>Let Wombat be a software library with very few 520 dependencies. If SLF4J is chosen as Wombat's logging API, then a 521 new dependency on <em>slf4j-api.jar</em> will be added to 522 Wombat's list of dependencies. Given that writing a logging 523 wrapper does not seem that hard, some developers will be tempted 524 to wrap SLF4J and link with it only if it is already present on 525 the classpath, making SLF4J an optional dependency of Wombat. In 526 addition to solving the dependency problem, the wrapper will 527 isolate Wombat from SLF4J's API ensuring that logging in Wombat 528 is future-proof. 529 </p> 530 531 <p>On the other hand, any SLF4J-wrapper by definition depends on 532 SLF4J. It is bound to have the same general API. If in the 533 future a new and significantly different logging API comes 534 along, code that uses the wrapper will be equally difficult to 535 migrate to the new API as code that used SLF4J directly. Thus, 536 the wrapper is not likely to future-proof your code, but to make 537 it more complex by adding an additional indirection on top of 538 SLF4J, which is an indirection in itself. 539 </p> 540 541 <p><span class="label">increased vulnerability</span> It is 542 actually worse than that. Wrappers will need to depend on 543 certain internal SLF4J interfaces which change from time to 544 time, contrary to the client-facing API which never 545 changes. Thus, wrappers are usually dependent on the major 546 version they were compiled with. A wrapper compiled against 547 SLF4J version 1.5.x will not work with SLF4J 1.6 whereas client 548 code using <code>org.slf4j.Logger</code>, 549 <code>LoggerFactory</code>, <code>MarkerFactory</code>, 550 <code>org.slf4j.Marker</code>, and <code>MDC</code> will work 551 fine with any SLF4J version from version 1.0 and onwards. 552 </p> 553 554 <p>It is reasonable to assume that in most projects Wombat will 555 be one dependency among many. If each library had its own 556 logging wrapper, then each wrapper would presumably need to be 557 configured separately. Thus, instead of having to deal with one 558 logging framework, namely SLF4J, the user of Wombat would have 559 to detail with Wombat's logging wrapper as well. The problem 560 will be compounded by each framework that comes up with its own 561 wrapper in order to make SLF4J optional. (Configuring or 562 dealing with the intricacies of five different logging wrappers 563 is not exactly exciting nor endearing.) 564 </p> 565 566 <p>The <a 567 href="http://velocity.apache.org/engine/devel/developer-guide.html#Configuring_Logging">logging 568 strategy adopted by the Velocity project</a> is a good example 569 of the "custom logging abstraction" anti-pattern. By adopting an 570 independent logging abstraction strategy, Velocity developers 571 have made life harder for themselves, but more importantly, they 572 made life harder for their users. 573 </p> 574 575 <p>Some projects try to detect the presence of SLF4J on the 576 class path and switch to it if present. While this approach 577 seems transparent enough, it will result in erroneous location 578 information. Underlying logging frameworks will print the 579 location (class name and line number) of the wrapper instead of 580 the real caller. Then there is the question of API coverage as 581 SLF4J support MDC and markers in addition to parameterized 582 logging. While one can come up with a seemingly working 583 SLF4J-wrapper within hours, many technical issues will emerge 584 over time which Wombat developers will have to deal with. Note 585 that SLF4J has evolved over several years and has 260 bug 586 reports filed against it.</p> 587 588 <p>For the above reasons, developers of frameworks should resist 589 the temptation to write their own logging wrapper. Not only is 590 it a waste of time of the developer, it will actually make life 591 more difficult for the users of said frameworks and make logging 592 code paradoxically more vulnerable to change. 593 </p> 594 </dd> 595 596 597 <!-- ======================================================= --> 598 599 <dt class="doAnchor" name="maven2">What about Maven transitive 600 dependencies? 601 </dt> 602 603 <dd> 604 <p>As an author of a library built with Maven, you might want to 605 test your application using a binding, say slf4j-log4j12 or 606 logback-classic, without forcing log4j or logback-classic as a 607 dependency upon your users. This is rather easy to accomplish. 608 </p> 609 610 <p>Given that your library's code depends on the SLF4J API, you 611 will need to declare slf4j-api as a compile-time (default scope) 612 dependency. 613 </p> 614 <pre class="prettyprint source"><dependency> 615 <groupId>org.slf4j</groupId> 616 <artifactId>slf4j-api</artifactId> 617 <version>${project.version}</version> 618</dependency></pre> 619 620 <p>Limiting the transitivity of the SLF4J binding used in your 621 tests can be accomplished by declaring the scope of the 622 SLF4J-binding dependency as "test". Here is an example:</p> 623 624 <pre class="prettyprint source"><dependency> 625 <groupId>org.slf4j</groupId> 626 <artifactId>slf4j-log4j12</artifactId> 627 <version>${project.version}</version> 628 <b><scope>test</scope></b> 629</dependency></pre> 630 631 <p>Thus, as far as your users are concerned you are exporting 632 slf4j-api as a transitive dependency of your library, but not 633 any SLF4J-binding or any underlying logging system. 634 </p> 635 636 <p>Note that as of SLF4J version 1.6, in the absence of an SLF4J 637 binding, slf4j-api will default to a no-operation 638 implementation. 639 </p> 640 641 642 643 </dd> 644 645 <!-- ====================================================== --> 646 <dt class="doAnchor" name="excludingJCL">How do I exclude 647 commons-logging as a Maven dependency? 648 </dt> 649 650 <dd> 651 <p><b>alternative 1) explicit exclusion</b></p> 652 653 <p>Many software projects using Maven declare commons-logging as 654 a dependency. Therefore, if you wish to migrate to SLF4J or use 655 jcl-over-slf4j, you would need to exclude commons-logging in all 656 of your project's dependencies which transitively depend on 657 commons-logging. <a 658 href="http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html">Dependency 659 exclusion</a> is described in the Maven documentation. Excluding 660 commons-logging explicitly for multiple dependencies distributed 661 on several <em>pom.xml</em> files can be a cumbersome and a 662 relatively error prone process. 663 </p> 664 665 <p><b>alternative 2) provided scope</b></p> 666 667 <p>Commons-logging can be rather simply and conveniently 668 excluded as a dependency by declaring it in the 669 <em>provided</em> scope within the pom.xml file of your 670 project. The actual commons-logging classes would be provided by 671 jcl-over-slf4j. This translates into the following pom file 672 snippet:</p> 673 674 <pre class="prettyprint source"><dependency> 675 <groupId>commons-logging</groupId> 676 <artifactId>commons-logging</artifactId> 677 <version>1.1.1</version> 678 <scope>provided</scope> 679</dependency> 680 681<dependency> 682 <groupId>org.slf4j</groupId> 683 <artifactId>jcl-over-slf4j</artifactId> 684 <version>${project.version}</version> 685</dependency></pre> 686 687 <p>The first dependency declaration essentially states that 688 commons-logging will be "somehow" provided by your 689 environment. The second declaration includes jcl-over-slf4j into 690 your project. As jcl-over-slf4j is a perfect binary-compatible 691 replacement for commons-logging, the first assertion becomes 692 true. 693 </p> 694 695 <p>Unfortunately, while declaring commons-logging in the 696 provided scope gets the job done, your IDE, e.g. Eclipse, will 697 still place <em>commons-logging.jar</em> on your project's class 698 path as seen by your IDE. You would need to make sure that 699 <em>jcl-over-slf4j.jar</em> is visible before 700 <em>commons-logging.jar</em> by your IDE. 701 </p> 702 703 <p><b>alternative 3) empty artifacts</b></p> 704 705 <p>An alternative approach is to depend on an <b>empty</b> 706 <em>commons-logging.jar</em> artifact. This clever <a 707 href="http://day-to-day-stuff.blogspot.com/2007/10/announcement-version-99-does-not-exist.html">approach 708 first was imagined</a> and initially supported by Erik van 709 Oosten. 710 </p> 711 712 <p>The empty artifact is available from a <a 713 href="http://version99.qos.ch">http://version99.qos.ch</a> a 714 high-availability Maven repository, replicated on several hosts 715 located in different geographical regions.</p> 716 717 <p>The following declaration adds the version99 repository to 718 the set of remote repositories searched by Maven. This 719 repository contains empty artifacts for commons-logging and 720 log4j. By the way, if you use the version99 repository, please 721 drop us a line at <version99 AT qos.ch>. 722 </p> 723 724 <pre class="prettyprint source"><repositories> 725 <repository> 726 <id>version99</id> 727 <!-- highly available repository serving empty artifacts --> 728 <url>http://version99.qos.ch/</url> 729 </repository> 730</repositories></pre> 731 732 <p>Declaring version 99-empty of commons-logging in the 733 <code><dependencyManagement></code> section of your project 734 will direct all transitive dependencies for commons-logging to 735 import version 99-empty, thus nicely addressing the 736 commons-logging exclusion problem. The classes for commons-logging 737 will be provided by jcl-over-slf4j. The following lines declare 738 commons-logging version 99-empty (in the dependency management 739 section) and declare jcl-over-slf4j as a dependency. 740 </p> 741 742<pre class="prettyprint source"><dependencyManagement> 743 <dependencies> 744 <dependency> 745 <groupId>commons-logging</groupId> 746 <artifactId>commons-logging</artifactId> 747 <version><b>99-empty</b></version> 748 </dependency> 749 ... other declarations... 750 </dependencies> 751</dependencyManagement> 752 753<!-- Do not forget to declare a dependency on jcl-over-slf4j in the --> 754<!-- dependencies section. Note that the dependency on commons-logging --> 755<!-- will be imported transitively. You don't have to declare it yourself. --> 756<dependencies> 757 <dependency> 758 <groupId>org.slf4j</groupId> 759 <artifactId>jcl-over-slf4j</artifactId> 760 <version>${project.version}</version> 761 </dependency> 762 ... other dependency declarations 763</dependencies> 764</pre> 765 766 767 </dd> 768 769 770 771 </dl> 772 773 774 <h2>About the SLF4J API</h2> 775 776 <dl> 777 778 <dt class="doAnchor" name="string_or_object">Why don't the 779 printing methods in the Logger interface accept message of type 780 Object, but only messages of type String? 781 </dt> 782 783 <dd> 784 785 <p>In SLF4J 1.0beta4, the printing methods such as debug(), 786 info(), warn(), error() in the <a 787 href="api/org/slf4j/Logger.html">Logger interface</a> were 788 modified so as to accept only messages of type String 789 instead of Object. 790 </p> 791 792 <p>Thus, the set of printing methods for the DEBUG level 793 became:</p> 794 795 <pre class="prettyprint source">debug(String msg); 796debug(String format, Object arg); 797debug(String format, Object arg1, Object arg2); 798debug(String msg, Throwable t);</pre> 799 800 <p>Previously, the first argument in the above methods was of 801 type <code>Object</code>.</p> 802 803 <p>This change enforces the notion that logging systems are 804 about decorating and handling messages of type String, and not 805 any arbitrary type (Object). 806 </p> 807 808 <p>Just as importantly, the new set of method signatures offer 809 a clearer differentiation between the overloaded methods 810 whereas previously the choice of the invoked method due to 811 Java overloading rules were not always easy to follow.</p> 812 813 <p>It was also easy to make mistakes. For example, previously 814 it was legal to write:</p> 815 816 <pre class="prettyprint source">logger.debug(new Exception("some error"));</pre> 817 818 <p>Unfortunately, the above call did not print the stack trace 819 of the exception. Thus, a potentially crucial piece of 820 information could be lost. When the first parameter is 821 restricted to be of type String, then only the method 822 </p> 823 824 <pre class="prettyprint source">debug(String msg, Throwable t);</pre> 825 826 <p>can be used to log exceptions. Note that this method 827 ensures that every logged exception is accompanied with a 828 descriptive message.</p> 829 830 831 </dd> 832 833 <!-- ====================================================== --> 834 835 <dt class="doAnchor" name="exception_message">Can I log an 836 exception without an accompanying message? 837 </dt> 838 839 <dd> 840 <p>In short, no.</p> 841 842 <p>If <code>e</code> is an <code>Exception</code>, and you 843 would like to log an exception at the ERROR level, you must 844 add an accompanying message. For example,</p> 845 846 <pre class="prettyprint source">logger.error("some accompanying message", e);</pre> 847 848 <p>You might legitimately argue that not all exceptions have a 849 meaningful message to accompany them. Moreover, a good exception 850 should already contain a self explanatory description. The 851 accompanying message may therefore be considered redundant. 852 </p> 853 854 855 <p>While these are valid arguments, there are three opposing 856 arguments also worth considering. First, on many, albeit not 857 all occasions, the accompanying message can convey useful 858 information nicely complementing the description contained 859 in the exception. Frequently, at the point where the 860 exception is logged, the developer has access to more 861 contextual information than at the point where the exception 862 is thrown. Second, it is not difficult to imagine more or 863 less generic messages, e.g. "Exception caught", "Exception 864 follows", that can be used as the first argument for 865 <code>error(String msg, Throwable t)</code> invocations. 866 Third, most log output formats display the message on a 867 line, followed by the exception on a separate line. Thus, 868 the message line would look inconsistent without a message. 869 </p> 870 871 <p>In short, if the user were allowed to log an exception 872 without an accompanying message, it would be the job of the 873 logging system to invent a message. This is actually what 874 the <a href="http://tinyurl.com/cr9kg">throwing(String 875 sourceClass, String sourceMethod, Throwable thrown)</a> 876 method in java.util.logging package does. (It decides on its 877 own that accompanying message is the string "THROW".) 878 </p> 879 880 <p>It may initially appear strange to require an accompanying 881 message to log an exception. Nevertheless, this is common 882 practice in <em>all</em> log4j derived systems such as 883 java.util.logging, logkit, etc. and of course log4j itself. It 884 seems that the current consensus considers requiring an 885 accompanying message as a good a thing (TM). 886 </p> 887 888 </dd> 889 890 <!-- ====================================================== --> 891 892 893 <dt class="doAnchor" name="logging_performance">What is the 894 fastest way of (not) logging? 895 </dt> 896 897 <dd> 898 <p>SLF4J supports an advanced feature called parameterized 899 logging which can significantly boost logging performance for 900 <em>disabled</em> logging statement.</p> 901 902 <p> For some Logger <code>logger</code>, writing,</p> 903 <pre class="prettyprint source">logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));</pre> 904 905 <p>incurs the cost of constructing the message parameter, that 906 is converting both integer <code>i</code> and 907 <code>entry[i]</code> to a String, and concatenating 908 intermediate strings. This, regardless of whether the message 909 will be logged or not. 910 </p> 911 912 <p>One possible way to avoid the cost of parameter 913 construction is by surrounding the log statement with a 914 test. Here is an example.</p> 915 916 <pre class="prettyprint source">if(logger.isDebugEnabled()) { 917 logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i])); 918}</pre> 919 920 921 <p>This way you will not incur the cost of parameter 922 construction if debugging is disabled for 923 <code>logger</code>. On the other hand, if the logger is 924 enabled for the DEBUG level, you will incur the cost of 925 evaluating whether the logger is enabled or not, twice: once in 926 <code>debugEnabled</code> and once in <code>debug</code>. This 927 is an insignificant overhead because evaluating a logger takes 928 less than 1% of the time it takes to actually log a statement. 929 </p> 930 931 <p><b>Better yet, use parameterized messages</b></p> 932 933 <p>There exists a very convenient alternative based on message 934 formats. Assuming <code>entry</code> is an object, you can write: 935 </p> 936 937 938 <pre class="prettyprint source">Object entry = new SomeObject(); 939logger.debug("The entry is {}.", entry);</pre> 940 941 <p>After evaluating whether to log or not, and only if the 942 decision is affirmative, will the logger implementation format 943 the message and replace the '{}' pair with the string value of 944 <code>entry</code>. In other words, this form does not incur 945 the cost of parameter construction in case the log statement is 946 disabled. 947 </p> 948 949 <p>The following two lines will yield the exact same 950 output. However, the second form will outperform the first 951 form by a factor of at least 30, in case of a 952 <em>disabled</em> logging statement. 953 </p> 954 955 <pre class="prettyprint source">logger.debug("The new entry is "+entry+"."); 956logger.debug("The new entry is {}.", entry);</pre> 957 958 959 <p>A <a 960 href="apidocs/org/slf4j/Logger.html#debug(java.lang.String,%20java.lang.Object%2C%20java.lang.Object)">two 961 argument</a> variant is also available. For example, you can 962 write:</p> 963 964 965 <pre class="prettyprint source">logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);</pre> 966 967 <p>If three or more arguments need to be passed, you can make 968 use of the <a 969 href="apidocs/org/slf4j/Logger.html#debug(java.lang.String%2C%20java.lang.Object...)"><code>Object...</code> 970 variant</a> of the printing methods. For example, you can 971 write:</p> 972 973 <pre class="prettyprint source">logger.debug("Value {} was inserted between {} and {}.", newVal, below, above);</pre> 974 975 <p>This form incurs the hidden cost of construction of an 976 Object[] (object array) which is usually very small. The one and 977 two argument variants do not incur this hidden cost and exist 978 solely for this reason (efficiency). The slf4j-api would be 979 smaller/cleaner with only the Object... variant.</p> 980 981 982 <p>Array type arguments, including multi-dimensional arrays, 983 are also supported.</p> 984 985 <p>SLF4J uses its own message formatting implementation which 986 differs from that of the Java platform. This is justified by 987 the fact that SLF4J's implementation performs about 10 times 988 faster but at the cost of being non-standard and less 989 flexible. 990 </p> 991 992 <p><b>Escaping the "{}" pair</b></p> 993 994 <p>The "{}" pair is called the <em>formatting anchor</em>. It 995 serves to designate the location where arguments need to be 996 substituted within the message pattern. 997 </p> 998 999 <p>SLF4J only cares about the <em>formatting anchor</em>, that 1000 is the '{' character immediately followed by '}'. Thus, in 1001 case your message contains the '{' or the '}' character, you 1002 do not have to do anything special unless the '}' character 1003 immediately follows '}'. For example, 1004 </p> 1005 1006 <pre class="prettyprint source">logger.debug("Set {1,2} differs from {}", "3");</pre> 1007 1008 <p>which will print as "Set {1,2} differs from 3". </p> 1009 1010 <p>You could have even written,</p> 1011 <pre class="prettyprint source">logger.debug("Set {1,2} differs from {{}}", "3");</pre> 1012 <p>which would have printed as "Set {1,2} differs from {3}". </p> 1013 1014 <p>In the extremely rare case where the the "{}" pair occurs 1015 naturally within your text and you wish to disable the special 1016 meaning of the formatting anchor, then you need to escape the 1017 '{' character with '\', that is the backslash character. Only 1018 the '{' character should be escaped. There is no need to 1019 escape the '}' character. For example, 1020 </p> 1021 1022 <pre class="prettyprint source">logger.debug("Set \\{} differs from {}", "3");</pre> 1023 1024 <p>will print as "Set {} differs from 3". Note that within 1025 Java code, the backslash character needs to be written as 1026 '\\'.</p> 1027 1028 <p>In the rare case where the "\{}" occurs naturally in the 1029 message, you can double escape the formatting anchor so that 1030 it retains its original meaning. For example,</p> 1031 1032 1033 <pre class="prettyprint source">logger.debug("File name is C:\\\\{}.", "file.zip");</pre> 1034 <p>will print as "File name is C:\file.zip".</p> 1035 1036 </dd> 1037 1038 <!-- ================================================= --> 1039 1040 <dt class="doAnchor" name="string_contents">How can I log the 1041 string contents of a single (possibly complex) object?</dt> 1042 1043 <dd> 1044 <p> In relatively rare cases where the message to be logged 1045 is the string form of an object, then the parameterized 1046 printing method of the appropriate level can be 1047 used. Assuming <code>complexObject</code> is an object of 1048 certain complexity, for a log statement of level DEBUG, you 1049 can write: 1050 </p> 1051 1052 <pre class="prettyprint source">logger.debug("{}", complexObject);</pre> 1053 1054 1055 <p>The logging system will invoke 1056 <code>complexObject.toString()</code> method only after it 1057 has ascertained that the log statement was 1058 enabled. Otherwise, the cost of 1059 <code>complexObject.toString()</code> conversion will be 1060 advantageously avoided. 1061 </p> 1062 1063 1064 1065 </dd> 1066 1067 <!-- ================================================= --> 1068 1069 1070 <dt class="doAnchor" name="fatal">Why doesn't the 1071 <code>org.slf4j.Logger</code> interface have methods for the FATAL 1072 level? 1073 </dt> 1074 1075 <dd> 1076 <p>The <a href="apidocs/org/slf4j/Marker.html">Marker</a> 1077 interface, part of the <code>org.slf4j</code> package, renders 1078 the FATAL level largely redundant. If a given error requires 1079 attention beyond that allocated for ordinary errors, simply mark 1080 the logging statement with a specially designated marker which 1081 can be named "FATAL" or any other name to your liking. 1082 </p> 1083 1084 <p>Here is an example,</p> 1085 1086<pre class="prettyprint">import org.slf4j.Logger; 1087import org.slf4j.LoggerFactory; 1088import org.slf4j.Marker; 1089import org.slf4j.MarkerFactory; 1090 1091class Bar { 1092 void foo() { 1093 <b>Marker fatal = MarkerFactory.getMarker("FATAL");</b> 1094 Logger logger = LoggerFactory.getLogger("aLogger"); 1095 1096 try { 1097 ... obtain a JDBC connection 1098 } catch (JDBException e) { 1099 logger.error(<b>fatal</b>, "Failed to obtain JDBC connection", e); 1100 } 1101 } 1102}</pre> 1103 1104 1105 <p>While markers are part of the SLF4J API, only logback 1106 supports markers off the shelf. For example, if you add the 1107 <code>%marker</code> conversion word to its pattern, logback's 1108 <code>PatternLayout</code> will add marker data to its 1109 output. Marker data can be used to <a 1110 href="http://logback.qos.ch/manual/filters.html">filter 1111 messages</a> or even <a 1112 href="http://logback.qos.ch/manual/appenders.html#OnMarkerEvaluator">trigger</a> 1113 an outgoing email <a 1114 href="http://logback.qos.ch/recipes/emailPerTransaction.html">at 1115 the end of an individual transaction</a>. 1116 </p> 1117 1118 <p>In combination with logging frameworks such as log4j and 1119 java.util.logging which do not support markers, marker data will 1120 be silently ignored.</p> 1121 1122 <p>Markers add a new dimension with infinite possible values for 1123 processing log statements compared to five values, namely ERROR, 1124 WARN, INFO, DEBUG and TRACE, allowed by levels. At present time, 1125 only logback supports marker data. However, nothing prevents 1126 other logging frameworks from making use of marker data. 1127 </p> 1128 1129 </dd> 1130 1131 <!-- ======================================================= --> 1132 <dt class="doAnchor" name="trace">Why was the TRACE level 1133 introduced only in SLF4J version 1.4.0?</dt> 1134 1135 <dd> 1136 1137 <p>The addition of the TRACE level has been frequently and 1138 hotly debated request. By studying various projects, we 1139 observed that the TRACE level was used to disable logging 1140 output from certain classes <em>without</em> needing to 1141 configure logging for those classes. Indeed, the TRACE level 1142 is by default disabled in log4j and logback as well most other 1143 logging systems. The same result can be achieved by adding the 1144 appropriate directives in configuration files. 1145 </p> 1146 1147 <p>Thus, in many of cases the TRACE level carried the same 1148 semantic meaning as DEBUG. In such cases, the TRACE level 1149 merely saves a few configuration directives. In other, more 1150 interesting occasions, where TRACE carries a different meaning 1151 than DEBUG, <a href="api/org/slf4j/Marker.html">Marker</a> 1152 objects can be put to use to convey the desired 1153 meaning. However, if you can't be bothered with markers and 1154 wish to use a logging level lower than DEBUG, the TRACE level 1155 can get the job done. 1156 </p> 1157 1158 <p>Note that while the cost of evaluating a disabled log 1159 request is in the order of a few <code>nanoseconds</code>, the 1160 use of the TRACE level (or any other level for that matter) is 1161 discouraged in tight loops where the log request might be 1162 evaluated millions of times. If the log request is enabled, 1163 then it will overwhelm the target destination with massive 1164 output. If the request is disabled, it will waste resources. 1165 </p> 1166 1167 <p>In short, although we still discourage the use of the TRACE 1168 level because alternatives exist or because in many cases log 1169 requests of level TRACE are wasteful, given that people kept 1170 asking for it, we decided to bow to popular demand. 1171 </p> 1172 1173 1174 </dd> 1175 1176 <!-- ================================================= --> 1177 <dt class="doAnchor" name="i18n">Does the SLF4J logging API 1178 support I18N (internationalization)? 1179 </dt> 1180 1181 <dd> 1182 <p>Yes, as of version 1.5.9, SLF4J ships with a package called 1183 <code>org.slf4j.cal10n</code> which adds <a 1184 href="localization.html">localized/internationalized logging</a> 1185 support as a thin layer built upon the <a 1186 href="http://cal10n.qos.ch">CAL10N API</a>.</p> 1187 1188 1189 </dd> 1190 1191 <!-- ================================================= --> 1192 1193 <dt class="doAnchor" name="noLoggerFactory">Is it possible to 1194 retrieve loggers without going through the static methods in 1195 <code>LoggerFactory</code>? 1196 </dt> 1197 1198 <dd> 1199 1200 <p>Yes. <code>LoggerFactory</code> is essentially a wrapper 1201 around an <a 1202 href="xref/org/slf4j/ILoggerFactory.html"><code>ILoggerFactory</code></a> 1203 instance. The <code>ILoggerFactory</code> instance in use is 1204 determined according to the static binding conventions of the 1205 SLF4J framework. See the <a 1206 href="xref/org/slf4j/LoggerFactory.html#217">getSingleton()</a> 1207 method in <code>LoggerFactory</code> for details. 1208 </p> 1209 1210 <p>However, nothing prevents you from using your own 1211 <code>ILoggerFactory</code> instance. Note that you can also 1212 obtain a reference to the <code>ILoggerFactory</code> that the 1213 <code>LoggerFactory</code> class is using by invoking the <a 1214 href="apidocs/org/slf4j/LoggerFactory.html#getILoggerFactory()"> 1215 <code>LoggerFactory.getILoggerFactory()</code></a> method. 1216 </p> 1217 1218 <p>Thus, if SLF4J binding conventions do not fit your needs, or 1219 if you need additional flexibility, then do consider using the 1220 <code>ILoggerFactory</code> interface as an alternative to 1221 inventing your own logging API.</p> 1222 </dd> 1223 1224 <!-- ================================================= --> 1225 1226 <dt class="doAnchor" name="paramException">In the presence of an 1227 exception/throwable, is it possible to parameterize a logging 1228 statement?</dt> 1229 1230 1231 <dd> 1232 <p>Yes, as of SLF4J 1.6.0, but not in previous versions. The 1233 SLF4J API supports parametrization in the presence of an 1234 exception, assuming the exception is the last parameter. Thus, 1235 </p> 1236 <pre class="prettyprint">String s = "Hello world"; 1237try { 1238 Integer i = Integer.valueOf(s); 1239} catch (NumberFormatException e) { 1240 logger.error("Failed to format {}", s, e); 1241}</pre> 1242 1243 <p>will print the <code>NumberFormatException</code> with its 1244 stack trace as expected. The java compiler will invoke the <a 1245 href="http://www.slf4j.org/apidocs/org/slf4j/Logger.html#error%28java.lang.String,%20java.lang.Object,%20java.lang.Object%29">error 1246 method taking a String and two Object arguments</a>. SLF4J, in 1247 accordance with the programmer's most probable intention, will 1248 interpret <code>NumberFormatException</code> instance as a 1249 throwable instead of an unused <code>Object</code> parameter. In 1250 SLF4J versions prior to 1.6.0, the 1251 <code>NumberFormatException</code> instance was simply ignored. 1252 </p> 1253 1254 <p>If the exception is not the last argument, it will be treated 1255 as a plain object and its stack trace will NOT be printed. 1256 However, such situations should not occur in practice. 1257 </p> 1258 1259 </dd> 1260 </dl> 1261 1262 1263 1264 <h2>Implementing the SLF4J API</h2> 1265 1266 <dl> 1267 1268 <!-- ============================================================= --> 1269 1270 <dt class="doAnchor" name="slf4j_compatible">How do I make my 1271 logging framework SLF4J compatible? 1272 </dt> 1273 1274 1275 <dd> 1276 1277 <p>Adding supporting for the SLF4J is surprisingly 1278 easy. Essentially, you coping an existing binding and tailoring 1279 it a little (as explained below) does the trick. 1280 </p> 1281 1282 <p>Assuming your logging system has notion of a 1283 logger, called say <code>MyLogger</code>, you need to provide 1284 an adapter for <code>MyLogger</code> to 1285 <code>org.slf4j.Logger</code> interface. Refer to slf4j-jcl, 1286 slf4j-jdk14, and slf4j-log4j12 modules for examples of 1287 adapters. 1288 </p> 1289 1290 <p>Once you have written an appropriate adapter, say 1291 <code>MyLoggerAdapter</code>, you need to provide a factory 1292 class implementing the <code>org.slf4j.ILoggerFactory</code> 1293 interface. This factory should return instances 1294 <code>MyLoggerAdapter</code>. Let <code>MyLoggerFactory</code> 1295 be the name of your factory class. 1296 </p> 1297 1298 <p>Once you have the adapter, namely 1299 <code>MyLoggerAdapter</code>, and a factory, namely 1300 <code>MyLoggerFactory</code>, the last remaining step is to 1301 modify the <code>StaticLoggerBinder</code> class so that it 1302 returns an new instance of <code>MyLoggerFactory</code>. You 1303 will also need to modify the 1304 <code>loggerFactoryClassStr</code> variable. 1305 </p> 1306 1307 <p>For Marker or MDC support, you could use the one of the 1308 existing NOP implementations. 1309 </p> 1310 1311 <p>In summary, to create an SLF4J binding for your logging 1312 system, follow these steps:</p> 1313 1314 <ol> 1315 <li>start with a copy of an existing module,</li> 1316 <li>create an adapter between your logging system and 1317 <code>org.slf4j.Logger</code> interface 1318 </li> 1319 <li>create a factory for the adapter created in the previous step,</li> 1320 <li>modify <code>StaticLoggerBinder</code> class to use the 1321 factory you created in the previous step</li> 1322 </ol> 1323 1324 1325 </dd> 1326 1327 <!-- ============================================================= --> 1328 1329 <dt class="doAnchor" name="marker_interface">How can my logging 1330 system add support for the <code>Marker</code> interface? 1331 </dt> 1332 <dd> 1333 1334 <p>Markers constitute a revolutionary concept which is 1335 supported by logback but not other existing logging 1336 systems. Consequently, SLF4J conforming logging systems are 1337 allowed to ignore marker data passed by the user. 1338 </p> 1339 1340 <p>However, even though marker data may be ignored, the user 1341 must still be allowed to specify marker data. Otherwise, users 1342 would not be able to switch between logging systems that 1343 support markers and those that do not. 1344 </p> 1345 1346 <p>The <code>MarkerIgnoringBase</code> class can serve as a 1347 base for adapters or native implementations of logging 1348 systems lacking marker support. In 1349 <code>MarkerIgnoringBase</code>, methods taking marker data 1350 simply invoke the corresponding method without the Marker 1351 argument, discarding any Marker data passed as 1352 argument. Your SLF4J adapters can extend 1353 <code>MarkerIgnoringBase</code> to quickly implement the 1354 methods in <code>org.slf4j.Logger</code> which take a 1355 <code>Marker</code> as the first argument. 1356 </p> 1357 1358 1359 </dd> 1360 1361 <!-- ============================================================= --> 1362 1363 <dt class="doAnchor" name="version_checks">How does SLF4J's 1364 version check mechanism work? 1365 </dt> 1366 1367 <dd> 1368 <p>The version check performed by SLF4J API during its 1369 initialization is an <em>elective</em> process. Conforming SLF4J 1370 implementations may choose <em>not</em> to participate, in which 1371 case, no version check will be performed. 1372 </p> 1373 1374 <p>However, if an SLF4J implementation decides to participate, 1375 than it needs to declare a variable called 1376 REQUESTED_API_VERSION within its copy of the 1377 <code>StaticLoggerBinder</code> class. The value of this 1378 variable should be equal to the version of the slf4j-api.jar 1379 it is compiled with. If the implementation is upgraded to a 1380 newer version of slf4j-api, than you also need to update the 1381 value of REQUESTED_API_VERSION. 1382 </p> 1383 1384 <p>For each version, SLF4J API maintains a list of compatible 1385 versions. SLF4J will emit a version mismatch warning only if 1386 the requested version is not found in the compatibility 1387 list. So even if your SLF4J binding has a different release 1388 schedule than SLF4J, assuming you update the SLF4J version you 1389 use every 6 to 12 months, you can still participate in the 1390 version check without incurring a mismatch warning. For 1391 example, logback has a different release schedule but still 1392 participates in version checks.</p> 1393 1394 <p><b>As of SLF4J 1.5.5</b>, all bindings shipped within the 1395 SLF4J distribution, e.g. slf4j-log4j12, slf4j-simple and 1396 slf4j-jdk14, declare the REQUESTED_API_VERSION field with a 1397 value equal to their SLF4J version. It follows that, for example 1398 if slf4j-simple-1.5.8.jar is mixed with slf4j-api-1.6.0.jar, 1399 given that 1.5.8 is not on the compatibility list of SLF4J 1400 version 1.6.x, a version mismatch warning will be issued. 1401 </p> 1402 1403 <p>Note that SLF4J versions prior to 1.5.5 did not have a 1404 version check mechanism. Only slf4j-api-1.5.5.jar and later can 1405 emit version mismatch warnings. 1406 </p> 1407 1408 1409 </dd> 1410 1411 </dl> 1412 1413 <h2>General questions about logging</h2> 1414 1415 1416 1417 <dl> 1418 1419 <!-- ============================================================= --> 1420 <dt class="doAnchor" name="declared_static">Should Logger members 1421 of a class be declared as static? 1422 </dt> 1423 <dd> 1424 1425 <p>We <code>used</code> to recommend that loggers members be 1426 declared as instance variables instead of static. After further 1427 analysis, <b>we no longer recommend one approach over the 1428 other.</b> 1429 </p> 1430 1431 <p>Here is a summary of the pros and cons of each approach. 1432 </p> 1433 1434 <table class="bodyTable"> 1435 <tr valign="top"> 1436 <th width="50%">Advantages for declaring loggers as static</th> 1437 <th width="50%">Disadvantages for declaring loggers as static</th> 1438 </tr> 1439 <tr valign="top" class="alt"> 1440 <td> 1441 <ol> 1442 <li>common and well-established idiom</li> 1443 <li>less CPU overhead: loggers are retrieved and 1444 assigned only once, at hosting class 1445 initialization</li> 1446 <li>less memory overhead: logger declaration will 1447 consume one reference per class</li> 1448 </ol> 1449 </td> 1450 1451 <td> <!-- static con --> 1452 <ol> 1453 <li>For libraries shared between applications, not 1454 possible to take advantage of repository selectors. It 1455 should be noted that if the SLF4J binding and the 1456 underlying API ships with each application (not shared 1457 between applications), then each application will still 1458 have its own logging environment. 1459 </li> 1460 <li>not IOC-friendly</li> 1461 </ol> 1462 </td> 1463 </tr> 1464 1465 <tr> 1466 <th width="50%">Advantages for declaring loggers as instance variables</th> 1467 <th width="50%">Disadvantages for declaring loggers as 1468 instance variables</th> 1469 </tr> 1470 1471 <tr class="alt" valign="top"> 1472 <td> <!-- instance pros --> 1473 <ol> 1474 <li>Possible to take advantage of repository selectors 1475 even for libraries shared between applications. However, 1476 repository selectors only work if the underlying logging 1477 system is logback-classic. Repository selectors do not 1478 work for the SLF4J+log4j combination. 1479 </li> 1480 <li>IOC-friendly</li> 1481 </ol> 1482 </td> 1483 1484 <td> <!-- instance cons --> 1485 <ol> 1486 <li>Less common idiom than declaring loggers as static 1487 variables</li> 1488 1489 <li>higher CPU overhead: loggers are retrieved and 1490 assigned for each instance of the hosting class</li> 1491 1492 <li>higher memory overhead: logger declaration will 1493 consume one reference per instance of the hosting class</li> 1494 </ol> 1495 </td> 1496 </tr> 1497 </table> 1498 1499 1500 <h3>Explanation</h3> 1501 1502 <p>Static logger members cost a single variable reference for 1503 all instances of the class whereas an instance logger member 1504 will cost a variable reference for every instance of the 1505 class. For simple classes instantiated thousands of times 1506 there might be a noticeable difference. 1507 </p> 1508 1509 <p>However, more recent logging systems, e.g log4j or logback, 1510 support a distinct logger context for each application running 1511 in the application server. Thus, even if a single copy of 1512 <em>log4j.jar</em> or <em>logback-classic.jar</em> is deployed 1513 in the server, the logging system will be able to differentiate 1514 between applications and offer a distinct logging environment 1515 for each application. 1516 </p> 1517 1518 <p>More specifically, each time a logger is retrieved by 1519 invoking <code>LoggerFactory.getLogger()</code> method, the 1520 underlying logging system will return an instance appropriate 1521 for the current application. Please note that within the 1522 <em>same</em> application retrieving a logger by a given name 1523 will always return the same logger. For a given name, a 1524 different logger will be returned only for different 1525 applications. 1526 </p> 1527 1528 <p>If the logger is static, then it will only be retrieved once 1529 when the hosting class is loaded into memory. If the hosting 1530 class is used in only in one application, there is not much to 1531 be concerned about. However, if the hosting class is shared 1532 between several applications, then all instances of the shared 1533 class will log into the context of the application which 1534 happened to first load the shared class into memory - hardly the 1535 behavior expected by the user. 1536 </p> 1537 1538 <p>Unfortunately, for non-native implementations of the SLF4J 1539 API, namely with slf4j-log4j12, log4j's repository selector will 1540 not be able to do its job properly because slf4j-log4j12, a 1541 non-native SLF4J binding, will store logger instances in a map, 1542 short-circuiting context-dependent logger retrieval. For native 1543 SLF4J implementations, such as logback-classic, repository 1544 selectors will work as expected. 1545 </p> 1546 1547 <p>The Apache Commons wiki contains an <a 1548 href="http://wiki.apache.org/jakarta-commons/Logging/StaticLog">informative 1549 article</a> covering the same question.</p> 1550 1551 <p><b>Logger serialization</b></p> 1552 1553 <p>Contrary to static variables, instance variables are 1554 serialized by default. As of SLF4J version 1.5.3, logger 1555 instances survive serialization. Thus, serialization of the host 1556 class no longer requires any special action, even when loggers 1557 are declared as instance variables. In previous versions, logger 1558 instances needed to be declared as <code>transient</code> in the 1559 host class. </p> 1560 1561 <p><b>Summary</b></p> 1562 1563 <p>In summary, declaring logger members as static variables 1564 requires less CPU time and have a slightly smaller memory 1565 footprint. On the other hand, declaring logger members as 1566 instance variables requires more CPU time and have a slightly 1567 higher memory overhead. However, instance variables make it 1568 possible to create a distinct logger environment for each 1569 application, even for loggers declared in shared 1570 libraries. Perhaps more important than previously mentioned 1571 considerations, instance variables are IOC-friendly whereas 1572 static variables are not. 1573 </p> 1574 1575 <p>See also <a 1576 href="http://wiki.apache.org/jakarta-commons/Logging/StaticLog">related 1577 discussion</a> in the commons-logging wiki. 1578 </p> 1579 1580 </dd> 1581 </dl> 1582 1583 <!-- ============================================================= --> 1584 <dl> 1585 <dt class="doAnchor" name="declaration_pattern">Is there a 1586 recommended idiom for declaring a logger in a class? 1587 </dt> 1588 1589 <dd> 1590 <p>The following is the recommended logger declaration 1591 idiom. For reasons <a href="#declared_static">explained 1592 above</a>, it is left to the user to determine whether loggers 1593 are declared as static variables or not.</p> 1594 1595 <pre class="prettyprint source">package some.package; 1596import org.slf4j.Logger; 1597import org.slf4j.LoggerFactory; 1598 1599public class MyClass { 1600 <b>final (static) Logger logger = LoggerFactory.getLogger(MyClass.class);</b> 1601 ... etc 1602}</pre> 1603 1604 <p>Unfortunately, give that the name of the hosting class is 1605 part of the logger declaration, the above logger declaration 1606 idiom is not is <em>not</em> resistant to cut-and-pasting 1607 between classes. 1608 </p> 1609 </dd> 1610 </dl> 1611 1612 <script src="templates/footer.js" type="text/javascript"></script> 1613</div> 1614</body> 1615</html> 1616