001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.classic; 015 016import java.io.ObjectStreamException; 017import java.io.Serializable; 018import java.util.Collections; 019import java.util.Iterator; 020import java.util.List; 021import java.util.concurrent.CopyOnWriteArrayList; 022 023import org.slf4j.LoggerFactory; 024import org.slf4j.Marker; 025import org.slf4j.spi.DefaultLoggingEventBuilder; 026import org.slf4j.spi.LocationAwareLogger; 027import org.slf4j.spi.LoggingEventAware; 028import org.slf4j.spi.LoggingEventBuilder; 029 030import ch.qos.logback.classic.spi.ILoggingEvent; 031import ch.qos.logback.classic.spi.LoggingEvent; 032import ch.qos.logback.classic.util.LoggerNameUtil; 033import ch.qos.logback.core.Appender; 034import ch.qos.logback.core.CoreConstants; 035import ch.qos.logback.core.spi.AppenderAttachable; 036import ch.qos.logback.core.spi.AppenderAttachableImpl; 037import ch.qos.logback.core.spi.FilterReply; 038 039public final class Logger 040 implements org.slf4j.Logger, LocationAwareLogger, LoggingEventAware, AppenderAttachable<ILoggingEvent>, Serializable { 041 042 private static final long serialVersionUID = 5454405123156820674L; // 8745934908040027998L; 043 044 /** 045 * The fully qualified name of this class. Used in gathering caller information. 046 */ 047 public static final String FQCN = ch.qos.logback.classic.Logger.class.getName(); 048 049 /** 050 * The name of this logger 051 */ 052 private String name; 053 054 // The assigned levelInt of this logger. Can be null. 055 transient private Level level; 056 057 // The effective levelInt is the assigned levelInt and if null, a levelInt is 058 // inherited form a parent. 059 transient private int effectiveLevelInt; 060 061 /** 062 * The parent of this category. All categories have at least one ancestor which 063 * is the root category. 064 */ 065 transient private Logger parent; 066 067 /** 068 * The children of this logger. A logger may have zero or more children. 069 */ 070 transient private List<Logger> childrenList; 071 072 /** 073 * It is assumed that once the 'aai' variable is set to a non-null value, it 074 * will never be reset to null. it is further assumed that only place where the 075 * 'aai variable is set is within the addAppender method. This method is 076 * synchronized on 'this' (Logger) protecting against simultaneous 077 * re-configuration of this logger (a very unlikely scenario). 078 * 079 * <p> 080 * It is further assumed that the AppenderAttachableImpl is responsible for its 081 * internal synchronization and thread safety. Thus, we can get away with *not* 082 * synchronizing on the 'aai' (check null/ read) because 083 * <p> 084 * 1) the 'aai' variable is immutable once set to non-null 085 * <p> 086 * 2) 'aai' is getAndSet only within addAppender which is synchronized 087 * <p> 088 * 3) all the other methods check whether 'aai' is null 089 * <p> 090 * 4) AppenderAttachableImpl is thread safe 091 */ 092 transient private AppenderAttachableImpl<ILoggingEvent> aai; 093 /** 094 * Additivity is set to true by default, that is children inherit the appenders 095 * of their ancestors by default. If this variable is set to <code>false</code> 096 * then the appenders located in the ancestors of this logger will not be used. 097 * However, the children of this logger will inherit its appenders, unless the 098 * children have their additivity flag set to <code>false</code> too. See the 099 * user manual for more details. 100 */ 101 transient private boolean additive = true; 102 103 final transient LoggerContext loggerContext; 104 105 Logger(String name, Logger parent, LoggerContext loggerContext) { 106 this.name = name; 107 this.parent = parent; 108 this.loggerContext = loggerContext; 109 } 110 111 public Level getEffectiveLevel() { 112 return Level.toLevel(effectiveLevelInt); 113 } 114 115 int getEffectiveLevelInt() { 116 return effectiveLevelInt; 117 } 118 119 public Level getLevel() { 120 return level; 121 } 122 123 public String getName() { 124 return name; 125 } 126 127 private boolean isRootLogger() { 128 // only the root logger has a null parent 129 return parent == null; 130 } 131 132 Logger getChildByName(final String childName) { 133 if (childrenList == null) { 134 return null; 135 } else { 136 int len = this.childrenList.size(); 137 for (int i = 0; i < len; i++) { 138 final Logger childLogger_i = (Logger) childrenList.get(i); 139 final String childName_i = childLogger_i.getName(); 140 141 if (childName.equals(childName_i)) { 142 return childLogger_i; 143 } 144 } 145 // no child found 146 return null; 147 } 148 } 149 150 public synchronized void setLevel(Level newLevel) { 151 if (level == newLevel) { 152 // nothing to do; 153 return; 154 } 155 if (newLevel == null && isRootLogger()) { 156 throw new IllegalArgumentException("The level of the root logger cannot be set to null"); 157 } 158 159 level = newLevel; 160 if (newLevel == null) { 161 effectiveLevelInt = parent.effectiveLevelInt; 162 newLevel = parent.getEffectiveLevel(); 163 } else { 164 effectiveLevelInt = newLevel.levelInt; 165 } 166 167 if (childrenList != null) { 168 int len = childrenList.size(); 169 for (int i = 0; i < len; i++) { 170 Logger child = (Logger) childrenList.get(i); 171 // tell child to handle parent levelInt change 172 child.handleParentLevelChange(effectiveLevelInt); 173 } 174 } 175 // inform listeners 176 loggerContext.fireOnLevelChange(this, newLevel); 177 } 178 179 /** 180 * This method is invoked by parent logger to let this logger know that the 181 * prent's levelInt changed. 182 * 183 * @param newParentLevelInt 184 */ 185 private synchronized void handleParentLevelChange(int newParentLevelInt) { 186 // changes in the parent levelInt affect children only if their levelInt is 187 // null 188 if (level == null) { 189 effectiveLevelInt = newParentLevelInt; 190 191 // propagate the parent levelInt change to this logger's children 192 if (childrenList != null) { 193 int len = childrenList.size(); 194 for (int i = 0; i < len; i++) { 195 Logger child = (Logger) childrenList.get(i); 196 child.handleParentLevelChange(newParentLevelInt); 197 } 198 } 199 } 200 } 201 202 /** 203 * Remove all previously added appenders from this logger instance. 204 * <p/> 205 * This is useful when re-reading configuration information. 206 */ 207 public void detachAndStopAllAppenders() { 208 if (aai != null) { 209 aai.detachAndStopAllAppenders(); 210 } 211 } 212 213 public boolean detachAppender(String name) { 214 if (aai == null) { 215 return false; 216 } 217 return aai.detachAppender(name); 218 } 219 220 // this method MUST be synchronized. See comments on 'aai' field for further 221 // details. 222 public synchronized void addAppender(Appender<ILoggingEvent> newAppender) { 223 if (aai == null) { 224 aai = new AppenderAttachableImpl<ILoggingEvent>(); 225 } 226 aai.addAppender(newAppender); 227 } 228 229 public boolean isAttached(Appender<ILoggingEvent> appender) { 230 if (aai == null) { 231 return false; 232 } 233 return aai.isAttached(appender); 234 } 235 236 @SuppressWarnings("unchecked") 237 public Iterator<Appender<ILoggingEvent>> iteratorForAppenders() { 238 if (aai == null) { 239 return Collections.EMPTY_LIST.iterator(); 240 } 241 return aai.iteratorForAppenders(); 242 } 243 244 public Appender<ILoggingEvent> getAppender(String name) { 245 if (aai == null) { 246 return null; 247 } 248 return aai.getAppender(name); 249 } 250 251 /** 252 * Invoke all the appenders of this logger. 253 * 254 * @param event The event to log 255 */ 256 public void callAppenders(ILoggingEvent event) { 257 int writes = 0; 258 for (Logger l = this; l != null; l = l.parent) { 259 writes += l.appendLoopOnAppenders(event); 260 if (!l.additive) { 261 break; 262 } 263 } 264 // No appenders in hierarchy 265 if (writes == 0) { 266 loggerContext.noAppenderDefinedWarning(this); 267 } 268 } 269 270 private int appendLoopOnAppenders(ILoggingEvent event) { 271 if (aai != null) { 272 return aai.appendLoopOnAppenders(event); 273 } else { 274 return 0; 275 } 276 } 277 278 /** 279 * Remove the appender passed as parameter form the list of appenders. 280 */ 281 public boolean detachAppender(Appender<ILoggingEvent> appender) { 282 if (aai == null) { 283 return false; 284 } 285 return aai.detachAppender(appender); 286 } 287 288 /** 289 * Create a child of this logger by suffix, that is, the part of the name 290 * extending this logger. For example, if this logger is named "x.y" and the 291 * lastPart is "z", then the created child logger will be named "x.y.z". 292 * 293 * <p> 294 * IMPORTANT: Calls to this method must be within a synchronized block on this 295 * logger. 296 * 297 * @param lastPart the suffix (i.e. last part) of the child logger name. This 298 * parameter may not include dots, i.e. the logger separator 299 * character. 300 * @return 301 */ 302 Logger createChildByLastNamePart(final String lastPart) { 303 int i_index = LoggerNameUtil.getFirstSeparatorIndexOf(lastPart); 304 if (i_index != -1) { 305 throw new IllegalArgumentException( 306 "Child name [" + lastPart + " passed as parameter, may not include [" + CoreConstants.DOT + "]"); 307 } 308 309 if (childrenList == null) { 310 childrenList = new CopyOnWriteArrayList<Logger>(); 311 } 312 Logger childLogger; 313 if (this.isRootLogger()) { 314 childLogger = new Logger(lastPart, this, this.loggerContext); 315 } else { 316 childLogger = new Logger(name + CoreConstants.DOT + lastPart, this, this.loggerContext); 317 } 318 childrenList.add(childLogger); 319 childLogger.effectiveLevelInt = this.effectiveLevelInt; 320 return childLogger; 321 } 322 323 private void localLevelReset() { 324 effectiveLevelInt = Level.DEBUG_INT; 325 if (isRootLogger()) { 326 level = Level.DEBUG; 327 } else { 328 level = null; 329 } 330 } 331 332 void recursiveReset() { 333 detachAndStopAllAppenders(); 334 localLevelReset(); 335 additive = true; 336 if (childrenList == null) { 337 return; 338 } 339 for (Logger childLogger : childrenList) { 340 childLogger.recursiveReset(); 341 } 342 } 343 344 /** 345 * The default size of child list arrays. The JDK 1.5 default is 10. We use a 346 * smaller value to save a little space. 347 */ 348 349 Logger createChildByName(final String childName) { 350 int i_index = LoggerNameUtil.getSeparatorIndexOf(childName, this.name.length() + 1); 351 if (i_index != -1) { 352 throw new IllegalArgumentException("For logger [" + this.name + "] child name [" + childName 353 + " passed as parameter, may not include '.' after index" + (this.name.length() + 1)); 354 } 355 356 if (childrenList == null) { 357 childrenList = new CopyOnWriteArrayList<Logger>(); 358 } 359 Logger childLogger; 360 childLogger = new Logger(childName, this, this.loggerContext); 361 childrenList.add(childLogger); 362 childLogger.effectiveLevelInt = this.effectiveLevelInt; 363 return childLogger; 364 } 365 366 /** 367 * The next methods are not merged into one because of the time we gain by not 368 * creating a new Object[] with the params. This reduces the cost of not logging 369 * by about 20 nanoseconds. 370 */ 371 372 private void filterAndLog_0_Or3Plus(final String localFQCN, final Marker marker, final Level level, 373 final String msg, final Object[] params, final Throwable t) { 374 375 final FilterReply decision = loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, msg, 376 params, t); 377 378 if (decision == FilterReply.NEUTRAL) { 379 if (effectiveLevelInt > level.levelInt) { 380 return; 381 } 382 } else if (decision == FilterReply.DENY) { 383 return; 384 } 385 386 buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t); 387 } 388 389 private void filterAndLog_1(final String localFQCN, final Marker marker, final Level level, final String msg, 390 final Object param, final Throwable t) { 391 392 final FilterReply decision = loggerContext.getTurboFilterChainDecision_1(marker, this, level, msg, param, t); 393 394 if (decision == FilterReply.NEUTRAL) { 395 if (effectiveLevelInt > level.levelInt) { 396 return; 397 } 398 } else if (decision == FilterReply.DENY) { 399 return; 400 } 401 402 buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[] { param }, t); 403 } 404 405 private void filterAndLog_2(final String localFQCN, final Marker marker, final Level level, final String msg, 406 final Object param1, final Object param2, final Throwable t) { 407 408 final FilterReply decision = loggerContext.getTurboFilterChainDecision_2(marker, this, level, msg, param1, 409 param2, t); 410 411 if (decision == FilterReply.NEUTRAL) { 412 if (effectiveLevelInt > level.levelInt) { 413 return; 414 } 415 } else if (decision == FilterReply.DENY) { 416 return; 417 } 418 419 buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[] { param1, param2 }, t); 420 } 421 422 private void buildLoggingEventAndAppend(final String localFQCN, final Marker marker, final Level level, 423 final String msg, final Object[] params, final Throwable t) { 424 LoggingEvent le = new LoggingEvent(localFQCN, this, level, msg, t, params); 425 le.addMarker(marker); 426 callAppenders(le); 427 } 428 429 public void trace(String msg) { 430 filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, null); 431 } 432 433 public void trace(String format, Object arg) { 434 filterAndLog_1(FQCN, null, Level.TRACE, format, arg, null); 435 } 436 437 public void trace(String format, Object arg1, Object arg2) { 438 filterAndLog_2(FQCN, null, Level.TRACE, format, arg1, arg2, null); 439 } 440 441 public void trace(String format, Object... argArray) { 442 filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, format, argArray, null); 443 } 444 445 public void trace(String msg, Throwable t) { 446 filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, t); 447 } 448 449 public void trace(Marker marker, String msg) { 450 filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, null); 451 } 452 453 public void trace(Marker marker, String format, Object arg) { 454 filterAndLog_1(FQCN, marker, Level.TRACE, format, arg, null); 455 } 456 457 public void trace(Marker marker, String format, Object arg1, Object arg2) { 458 filterAndLog_2(FQCN, marker, Level.TRACE, format, arg1, arg2, null); 459 } 460 461 public void trace(Marker marker, String format, Object... argArray) { 462 filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, format, argArray, null); 463 } 464 465 public void trace(Marker marker, String msg, Throwable t) { 466 filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, t); 467 } 468 469 public boolean isDebugEnabled() { 470 return isDebugEnabled(null); 471 } 472 473 public boolean isDebugEnabled(Marker marker) { 474 final FilterReply decision = callTurboFilters(marker, Level.DEBUG); 475 if (decision == FilterReply.NEUTRAL) { 476 return effectiveLevelInt <= Level.DEBUG_INT; 477 } else if (decision == FilterReply.DENY) { 478 return false; 479 } else if (decision == FilterReply.ACCEPT) { 480 return true; 481 } else { 482 throw new IllegalStateException("Unknown FilterReply value: " + decision); 483 } 484 } 485 486 public void debug(String msg) { 487 filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, null); 488 } 489 490 public void debug(String format, Object arg) { 491 filterAndLog_1(FQCN, null, Level.DEBUG, format, arg, null); 492 } 493 494 public void debug(String format, Object arg1, Object arg2) { 495 filterAndLog_2(FQCN, null, Level.DEBUG, format, arg1, arg2, null); 496 } 497 498 public void debug(String format, Object... argArray) { 499 filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, format, argArray, null); 500 } 501 502 public void debug(String msg, Throwable t) { 503 filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, t); 504 } 505 506 public void debug(Marker marker, String msg) { 507 filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, null); 508 } 509 510 public void debug(Marker marker, String format, Object arg) { 511 filterAndLog_1(FQCN, marker, Level.DEBUG, format, arg, null); 512 } 513 514 public void debug(Marker marker, String format, Object arg1, Object arg2) { 515 filterAndLog_2(FQCN, marker, Level.DEBUG, format, arg1, arg2, null); 516 } 517 518 public void debug(Marker marker, String format, Object... argArray) { 519 filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, format, argArray, null); 520 } 521 522 public void debug(Marker marker, String msg, Throwable t) { 523 filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, t); 524 } 525 526 public void error(String msg) { 527 filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, null); 528 } 529 530 public void error(String format, Object arg) { 531 filterAndLog_1(FQCN, null, Level.ERROR, format, arg, null); 532 } 533 534 public void error(String format, Object arg1, Object arg2) { 535 filterAndLog_2(FQCN, null, Level.ERROR, format, arg1, arg2, null); 536 } 537 538 public void error(String format, Object... argArray) { 539 filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, format, argArray, null); 540 } 541 542 public void error(String msg, Throwable t) { 543 filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, t); 544 } 545 546 public void error(Marker marker, String msg) { 547 filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, null); 548 } 549 550 public void error(Marker marker, String format, Object arg) { 551 filterAndLog_1(FQCN, marker, Level.ERROR, format, arg, null); 552 } 553 554 public void error(Marker marker, String format, Object arg1, Object arg2) { 555 filterAndLog_2(FQCN, marker, Level.ERROR, format, arg1, arg2, null); 556 } 557 558 public void error(Marker marker, String format, Object... argArray) { 559 filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, format, argArray, null); 560 } 561 562 public void error(Marker marker, String msg, Throwable t) { 563 filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, t); 564 } 565 566 public boolean isInfoEnabled() { 567 return isInfoEnabled(null); 568 } 569 570 public boolean isInfoEnabled(Marker marker) { 571 FilterReply decision = callTurboFilters(marker, Level.INFO); 572 if (decision == FilterReply.NEUTRAL) { 573 return effectiveLevelInt <= Level.INFO_INT; 574 } else if (decision == FilterReply.DENY) { 575 return false; 576 } else if (decision == FilterReply.ACCEPT) { 577 return true; 578 } else { 579 throw new IllegalStateException("Unknown FilterReply value: " + decision); 580 } 581 } 582 583 public void info(String msg) { 584 filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, null); 585 } 586 587 public void info(String format, Object arg) { 588 filterAndLog_1(FQCN, null, Level.INFO, format, arg, null); 589 } 590 591 public void info(String format, Object arg1, Object arg2) { 592 filterAndLog_2(FQCN, null, Level.INFO, format, arg1, arg2, null); 593 } 594 595 public void info(String format, Object... argArray) { 596 filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, format, argArray, null); 597 } 598 599 public void info(String msg, Throwable t) { 600 filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, t); 601 } 602 603 public void info(Marker marker, String msg) { 604 filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, null); 605 } 606 607 public void info(Marker marker, String format, Object arg) { 608 filterAndLog_1(FQCN, marker, Level.INFO, format, arg, null); 609 } 610 611 public void info(Marker marker, String format, Object arg1, Object arg2) { 612 filterAndLog_2(FQCN, marker, Level.INFO, format, arg1, arg2, null); 613 } 614 615 public void info(Marker marker, String format, Object... argArray) { 616 filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, format, argArray, null); 617 } 618 619 public void info(Marker marker, String msg, Throwable t) { 620 filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, t); 621 } 622 623 public boolean isTraceEnabled() { 624 return isTraceEnabled(null); 625 } 626 627 public boolean isTraceEnabled(Marker marker) { 628 final FilterReply decision = callTurboFilters(marker, Level.TRACE); 629 if (decision == FilterReply.NEUTRAL) { 630 return effectiveLevelInt <= Level.TRACE_INT; 631 } else if (decision == FilterReply.DENY) { 632 return false; 633 } else if (decision == FilterReply.ACCEPT) { 634 return true; 635 } else { 636 throw new IllegalStateException("Unknown FilterReply value: " + decision); 637 } 638 } 639 640 public boolean isErrorEnabled() { 641 return isErrorEnabled(null); 642 } 643 644 public boolean isErrorEnabled(Marker marker) { 645 FilterReply decision = callTurboFilters(marker, Level.ERROR); 646 if (decision == FilterReply.NEUTRAL) { 647 return effectiveLevelInt <= Level.ERROR_INT; 648 } else if (decision == FilterReply.DENY) { 649 return false; 650 } else if (decision == FilterReply.ACCEPT) { 651 return true; 652 } else { 653 throw new IllegalStateException("Unknown FilterReply value: " + decision); 654 } 655 } 656 657 public boolean isWarnEnabled() { 658 return isWarnEnabled(null); 659 } 660 661 public boolean isWarnEnabled(Marker marker) { 662 FilterReply decision = callTurboFilters(marker, Level.WARN); 663 if (decision == FilterReply.NEUTRAL) { 664 return effectiveLevelInt <= Level.WARN_INT; 665 } else if (decision == FilterReply.DENY) { 666 return false; 667 } else if (decision == FilterReply.ACCEPT) { 668 return true; 669 } else { 670 throw new IllegalStateException("Unknown FilterReply value: " + decision); 671 } 672 673 } 674 675 public boolean isEnabledFor(Marker marker, Level level) { 676 FilterReply decision = callTurboFilters(marker, level); 677 if (decision == FilterReply.NEUTRAL) { 678 return effectiveLevelInt <= level.levelInt; 679 } else if (decision == FilterReply.DENY) { 680 return false; 681 } else if (decision == FilterReply.ACCEPT) { 682 return true; 683 } else { 684 throw new IllegalStateException("Unknown FilterReply value: " + decision); 685 } 686 } 687 688 public boolean isEnabledFor(Level level) { 689 return isEnabledFor(null, level); 690 } 691 692 public void warn(String msg) { 693 filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, null); 694 } 695 696 public void warn(String msg, Throwable t) { 697 filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, t); 698 } 699 700 public void warn(String format, Object arg) { 701 filterAndLog_1(FQCN, null, Level.WARN, format, arg, null); 702 } 703 704 public void warn(String format, Object arg1, Object arg2) { 705 filterAndLog_2(FQCN, null, Level.WARN, format, arg1, arg2, null); 706 } 707 708 public void warn(String format, Object... argArray) { 709 filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, format, argArray, null); 710 } 711 712 public void warn(Marker marker, String msg) { 713 filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, null); 714 } 715 716 public void warn(Marker marker, String format, Object arg) { 717 filterAndLog_1(FQCN, marker, Level.WARN, format, arg, null); 718 } 719 720 public void warn(Marker marker, String format, Object... argArray) { 721 filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, format, argArray, null); 722 } 723 724 public void warn(Marker marker, String format, Object arg1, Object arg2) { 725 filterAndLog_2(FQCN, marker, Level.WARN, format, arg1, arg2, null); 726 } 727 728 public void warn(Marker marker, String msg, Throwable t) { 729 filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, t); 730 } 731 732 public boolean isAdditive() { 733 return additive; 734 } 735 736 public void setAdditive(boolean additive) { 737 this.additive = additive; 738 } 739 740 public String toString() { 741 return "Logger[" + name + "]"; 742 } 743 744 /** 745 * Method that calls the attached TurboFilter objects based on the logger and 746 * the level. 747 * 748 * It is used by isYYYEnabled() methods. 749 * 750 * It returns the typical FilterReply values: ACCEPT, NEUTRAL or DENY. 751 * 752 * @param level 753 * @return the reply given by the TurboFilters 754 */ 755 private FilterReply callTurboFilters(Marker marker, Level level) { 756 return loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, null, null, null); 757 } 758 759 /** 760 * Return the context for this logger. 761 * 762 * @return the context 763 */ 764 public LoggerContext getLoggerContext() { 765 return loggerContext; 766 } 767 768 /** 769 * Creates a {@link LoggingEventBuilder} of type {@link DefaultLoggingEventBuilder}. 770 * 771 * @since 1.3 772 */ 773 @Override 774 public LoggingEventBuilder makeLoggingEventBuilder(org.slf4j.event.Level level) { 775 return new DefaultLoggingEventBuilder(this, level); 776 } 777 778 public void log(Marker marker, String fqcn, int levelInt, String message, Object[] argArray, Throwable t) { 779 Level level = Level.fromLocationAwareLoggerInteger(levelInt); 780 filterAndLog_0_Or3Plus(fqcn, marker, level, message, argArray, t); 781 } 782 783 /** 784 * Support SLF4J interception during initialization as introduced in SLF4J 785 * version 1.7.15 786 * 787 * @since 1.1.4 788 * @param slf4jEvent 789 */ 790 public void log(org.slf4j.event.LoggingEvent slf4jEvent) { 791 org.slf4j.event.Level slf4jLevel = slf4jEvent.getLevel(); 792 Level logbackLevel = Level.convertAnSLF4JLevel(slf4jLevel); 793 794 // By default, assume this class was the caller. This happens during 795 // initialization. 796 // However, it is possible that the caller is some other library, e.g. 797 // slf4j-jdk-platform-logging 798 799 String callerBoundary = slf4jEvent.getCallerBoundary(); 800 if (callerBoundary == null) { 801 callerBoundary = FQCN; 802 } 803 804 LoggingEvent lle = new LoggingEvent(callerBoundary, this, logbackLevel, slf4jEvent.getMessage(), 805 slf4jEvent.getThrowable(), slf4jEvent.getArgumentArray()); 806 List<Marker> markers = slf4jEvent.getMarkers(); 807 808 if (markers != null) { 809 markers.forEach(m -> lle.addMarker(m)); 810 } 811 812 lle.setKeyValuePairs(slf4jEvent.getKeyValuePairs()); 813 814 // Note that at this point, any calls made with a logger disabled 815 // for a given level, will be already filtered out/in. TurboFilters cannot 816 // act at this point in the process. 817 this.callAppenders(lle); 818 } 819 820 /** 821 * After serialization, the logger instance does not know its LoggerContext. The 822 * best we can do here, is to return a logger with the same name returned by 823 * org.slf4j.LoggerFactory. 824 * 825 * @return Logger instance with the same name 826 * @throws ObjectStreamException 827 */ 828 protected Object readResolve() throws ObjectStreamException { 829 return LoggerFactory.getLogger(getName()); 830 } 831}