Class LoggerOddities

  • All Implemented Interfaces:
    edu.umd.cs.findbugs.Detector, edu.umd.cs.findbugs.Priorities, edu.umd.cs.findbugs.visitclass.Constants2, org.apache.bcel.classfile.Visitor, org.apache.bcel.Constants

    @CustomUserValue
    public class LoggerOddities
    extends edu.umd.cs.findbugs.BytecodeScanningDetector
    looks for uses of log4j or slf4j where the class specified when creating the logger is not the same as the class in which this logger is used. Also looks for using concatenation with slf4j logging rather than using the parameterized interface.
    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      (package private) static class  LoggerOddities.LOUserValue<T>  
    • Field Summary

      Fields 
      Modifier and Type Field Description
      private static java.util.regex.Pattern BAD_FORMATTING_ANCHOR  
      private static java.util.regex.Pattern BAD_STRING_FORMAT_PATTERN  
      private edu.umd.cs.findbugs.BugReporter bugReporter  
      private static java.lang.String COMMONS_LOGGER  
      private static java.util.regex.Pattern FORMATTER_ANCHOR  
      private java.util.Set<java.lang.String> formatterLoggers  
      private boolean isStaticInitializer  
      private static java.lang.String LOG4J_LOGGER  
      private static java.lang.String LOG4J2_LOGGER  
      private static java.lang.String LOG4J2_LOGMANAGER  
      private static java.util.Set<java.lang.String> LOGGER_METHODS  
      private java.lang.String nameOfThisClass  
      private static java.util.regex.Pattern NON_SIMPLE_FORMAT  
      private static java.lang.String SIG_CLASS_TO_COMMONS_LOGGER  
      private static java.lang.String SIG_CLASS_TO_LOG4J_LOGGER  
      private static java.lang.String SIG_CLASS_TO_LOG4J2_LOGGER  
      private static java.lang.String SIG_CLASS_TO_SLF4J_LOGGER  
      private static java.lang.String SIG_OBJECT_AND_THROWABLE_TO_VOID  
      private static java.lang.String SIG_STRING_AND_FACTORY_TO_LOG4J_LOGGER  
      private static java.lang.String SIG_STRING_AND_OBJECT_ARRAY_TO_VOID  
      private static java.lang.String SIG_STRING_AND_THROWABLE_TO_VOID  
      private static java.lang.String SIG_STRING_AND_TWO_OBJECTS_TO_VOID  
      private static java.lang.String SIG_STRING_TO_COMMONS_LOGGER  
      private static java.lang.String SIG_STRING_TO_LOG4J_LOGGER  
      private static java.lang.String SIG_STRING_TO_LOG4J2_LOGGER  
      private static java.lang.String SIG_STRING_TO_SLF4J_LOGGER  
      private static java.lang.String SLF4J_LOGGER  
      private edu.umd.cs.findbugs.OpcodeStack stack  
      private org.apache.bcel.classfile.JavaClass throwableClass  
      • Fields inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode

        codeBytes, lineNumberTable, M_BR, M_CP, M_INT, M_PAD, M_R, M_UINT
      • Fields inherited from interface org.apache.bcel.Constants

        AALOAD, AASTORE, ACC_ABSTRACT, ACC_ANNOTATION, ACC_BRIDGE, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_NATIVE, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_STATIC, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_SYPER, ACC_TRANSIENT, ACC_VARARGS, ACC_VOLATILE, ACCESS_NAMES, ACONST_NULL, ALOAD, ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3, ANEWARRAY, ANEWARRAY_QUICK, APPEND_FRAME, APPEND_FRAME_MAX, ARETURN, ARRAYLENGTH, ASTORE, ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3, ATHROW, ATTR_ANNOTATION_DEFAULT, ATTR_CODE, ATTR_CONSTANT_VALUE, ATTR_DEPRECATED, ATTR_ENCLOSING_METHOD, ATTR_EXCEPTIONS, ATTR_INNER_CLASSES, ATTR_LINE_NUMBER_TABLE, ATTR_LOCAL_VARIABLE_TABLE, ATTR_LOCAL_VARIABLE_TYPE_TABLE, ATTR_PMG, ATTR_RUNTIME_VISIBLE_ANNOTATIONS, ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS, ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS, ATTR_SIGNATURE, ATTR_SOURCE_FILE, ATTR_STACK_MAP, ATTR_STACK_MAP_TABLE, ATTR_SYNTHETIC, ATTR_UNKNOWN, ATTRIBUTE_NAMES, BALOAD, BASTORE, BIPUSH, BREAKPOINT, CALOAD, CASTORE, CHECKCAST, CHECKCAST_QUICK, CHOP_FRAME, CHOP_FRAME_MAX, CLASS_TYPE_NAMES, CONSTANT_Class, CONSTANT_Double, CONSTANT_Fieldref, CONSTANT_Float, CONSTANT_Integer, CONSTANT_InterfaceMethodref, CONSTANT_InvokeDynamic, CONSTANT_Long, CONSTANT_MethodHandle, CONSTANT_Methodref, CONSTANT_MethodType, CONSTANT_NameAndType, CONSTANT_NAMES, CONSTANT_String, CONSTANT_Utf8, CONSTRUCTOR_NAME, CONSUME_STACK, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3, DMUL, DNEG, DREM, DRETURN, DSTORE, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3, FMUL, FNEG, FREM, FRETURN, FSTORE, FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3, FSUB, FULL_FRAME, GETFIELD, GETFIELD_QUICK, GETFIELD_QUICK_W, GETFIELD2_QUICK, GETSTATIC, GETSTATIC_QUICK, GETSTATIC2_QUICK, GOTO, GOTO_W, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILLEGAL_OPCODE, ILLEGAL_TYPE, ILOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, IMPDEP1, IMPDEP2, IMUL, INEG, INSTANCEOF, INSTANCEOF_QUICK, INT2BYTE, INT2CHAR, INT2SHORT, INTERFACES_IMPLEMENTED_BY_ARRAYS, INVOKEDYNAMIC, INVOKEINTERFACE, INVOKEINTERFACE_QUICK, INVOKENONVIRTUAL, INVOKENONVIRTUAL_QUICK, INVOKESPECIAL, INVOKESTATIC, INVOKESTATIC_QUICK, INVOKESUPER_QUICK, INVOKEVIRTUAL, INVOKEVIRTUAL_QUICK, INVOKEVIRTUAL_QUICK_W, INVOKEVIRTUALOBJECT_QUICK, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3, ISUB, ITEM_Bogus, ITEM_Double, ITEM_Float, ITEM_InitObject, ITEM_Integer, ITEM_Long, ITEM_NAMES, ITEM_NewObject, ITEM_Null, ITEM_Object, IUSHR, IXOR, JSR, JSR_W, KNOWN_ATTRIBUTES, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDC_QUICK, LDC_W, LDC_W_QUICK, LDC2_W, LDC2_W_QUICK, LDIV, LLOAD, LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3, LMUL, LNEG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3, LSUB, LUSHR, LXOR, MAJOR, MAJOR_1_1, MAJOR_1_2, MAJOR_1_3, MAJOR_1_4, MAJOR_1_5, MAJOR_1_6, MAJOR_1_7, MAJOR_1_8, MAX_ACC_FLAG, MAX_BYTE, MAX_CODE_SIZE, MAX_CP_ENTRIES, MAX_SHORT, MINOR, MINOR_1_1, MINOR_1_2, MINOR_1_3, MINOR_1_4, MINOR_1_5, MINOR_1_6, MINOR_1_7, MINOR_1_8, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, MULTIANEWARRAY_QUICK, NEW, NEW_QUICK, NEWARRAY, NO_OF_OPERANDS, NOP, OPCODE_NAMES, POP, POP2, PRODUCE_STACK, PUSH, PUTFIELD, PUTFIELD_QUICK, PUTFIELD_QUICK_W, PUTFIELD2_QUICK, PUTSTATIC, PUTSTATIC_QUICK, PUTSTATIC2_QUICK, RESERVED, RET, RETURN, SALOAD, SAME_FRAME, SAME_FRAME_EXTENDED, SAME_FRAME_MAX, SAME_LOCALS_1_STACK_ITEM_FRAME, SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED, SAME_LOCALS_1_STACK_ITEM_FRAME_MAX, SASTORE, SHORT_TYPE_NAMES, SIPUSH, STATIC_INITIALIZER_NAME, SWAP, SWITCH, T_ADDRESS, T_ARRAY, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_OBJECT, T_REFERENCE, T_SHORT, T_UNKNOWN, T_VOID, TABLESWITCH, TYPE_NAMES, TYPE_OF_OPERANDS, UNDEFINED, UNPREDICTABLE, WIDE
      • Fields inherited from interface edu.umd.cs.findbugs.Priorities

        EXP_PRIORITY, HIGH_PRIORITY, IGNORE_PRIORITY, LOW_PRIORITY, NORMAL_PRIORITY
    • Constructor Summary

      Constructors 
      Constructor Description
      LoggerOddities​(edu.umd.cs.findbugs.BugReporter bugReporter)
      constructs a LO detector given the reporter to report bugs on.
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      private void checkForLoggerParam()
      looks for slf4j calls where an exception is passed as a logger parameter, expecting to be substituted for a {} marker.
      private void checkForProblemsWithLoggerMethods()
      looks for a variety of logging issues with log statements
      private void checkForProblemsWithLoggerParameterisedMethods​(java.lang.String sig)  
      private void checkForProblemsWithLoggerSingleArgumentMethod()  
      private void checkForProblemsWithLoggerThrowableMethods()  
      private static int countAnchors​(java.lang.String formatString)
      returns the number of anchors {} in a string
      private java.lang.String getLoggingClassNameFromStackValue()  
      private int getVarArgsParmCount​(java.lang.String signature)
      returns the number of parameters slf4j or log4j2 is expecting to inject into the format string
      private boolean hasExceptionOnStack()
      returns whether an exception object is on the stack slf4j will find this, and not include it in the parm list so i we find one, just don't report
      private boolean isLoggerWithClassParm​(edu.umd.cs.findbugs.ba.XMethod m)
      returns whether this method class is a standard logger instantiation that takes a java/lang/Class parameter
      private boolean isNonPrivateLogField​(java.lang.String fieldClsName, java.lang.String fieldName, java.lang.String fieldSig)
      looks to see if this field is a logger, and declared non privately
      private void lookForSuspectClasses()
      looks for instantiation of a logger with what looks like a class name that isn't the same as the class in which it exists.
      void sawOpcode​(int seen)
      implements the visitor to look for calls to Logger.getLogger with the wrong class name
      void visitClassContext​(edu.umd.cs.findbugs.ba.ClassContext classContext)
      implements the visitor to discover what the class name is if it is a normal class, or the owning class, if the class is an anonymous class.
      void visitCode​(org.apache.bcel.classfile.Code obj)
      implements the visitor to reset the stack
      • Methods inherited from class edu.umd.cs.findbugs.BytecodeScanningDetector

        getClassContext, report, shouldVisitCode
      • Methods inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode

        afterOpcode, areOppositeBranches, atCatchBlock, beforeOpcode, getBranchFallThrough, getBranchOffset, getBranchTarget, getClassConstantOperand, getClassDescriptorOperand, getCodeByte, getConstantRefOperand, getDefaultSwitchOffset, getDottedClassConstantOperand, getFieldDescriptorOperand, getIntConstant, getLongConstant, getMaxPC, getMethodDescriptorOperand, getNameConstantOperand, getNextCodeByte, getNextOpcode, getNextPC, getOpcode, getPC, getPrevOpcode, getRefConstantOperand, getRefFieldIsStatic, getRegisterOperand, getSigConstantOperand, getStringConstantOperand, getSwitchLabels, getSwitchOffsets, getXClassOperand, getXFieldOperand, getXMethodOperand, isBranch, isMethodCall, isRegisterLoad, isRegisterStore, isRegisterStore, isReturn, isShift, isSwitch, isWideOpcode, printOpCode, sawBranchTo, sawClass, sawDouble, sawField, sawFloat, sawIMethod, sawInt, sawLong, sawMethod, sawRegister, sawString, visit
      • Methods inherited from class edu.umd.cs.findbugs.visitclass.AnnotationVisitor

        getAnnotationParameterAsString, getAnnotationParameterAsStringArray, visitAnnotation, visitAnnotation, visitParameterAnnotation, visitParameterAnnotation, visitSyntheticParameterAnnotation
      • Methods inherited from class edu.umd.cs.findbugs.visitclass.PreorderVisitor

        amVisitingMainMethod, asUnsignedByte, doVisitMethod, getClassDescriptor, getClassName, getCode, getConstantPool, getDottedClassName, getDottedFieldSig, getDottedMethodSig, getDottedSuperclassName, getField, getFieldDescriptor, getFieldIsStatic, getFieldName, getFieldSig, getFullyQualifiedFieldName, getFullyQualifiedMethodName, getMethod, getMethodDescriptor, getMethodName, getMethodSig, getMethodVisitOrder, getNumberArguments, getNumberMethodArguments, getPackageName, getSizeOfSurroundingTryBlock, getSizeOfSurroundingTryBlock, getSourceFile, getStringFromIndex, getSuperclassName, getSurroundingCaughtExceptions, getSurroundingCaughtExceptions, getSurroundingTryBlock, getSurroundingTryBlock, getThisClass, getXClass, getXField, getXMethod, hasInterestingClass, hasInterestingMethod, isVisitMethodsInCallOrder, setupVisitorForClass, setVisitMethodsInCallOrder, shouldVisit, toString, visitAfter, visitAfter, visitAnnotationDefault, visitAnnotationEntry, visitConstantPool, visitEnclosingMethod, visitingField, visitingMethod, visitInnerClasses, visitJavaClass, visitLineNumberTable, visitLocalVariableTable, visitStackMapTable, visitStackMapTableEntry
      • Methods inherited from class edu.umd.cs.findbugs.visitclass.BetterVisitor

        clone, report, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visitCodeException, visitConstantClass, visitConstantDouble, visitConstantFieldref, visitConstantFloat, visitConstantInteger, visitConstantInterfaceMethodref, visitConstantLong, visitConstantMethodref, visitConstantNameAndType, visitConstantString, visitConstantUtf8, visitConstantValue, visitDeprecated, visitExceptionTable, visitField, visitInnerClass, visitLineNumber, visitLocalVariable, visitLocalVariableTypeTable, visitMethod, visitSignature, visitSourceFile, visitStackMap, visitStackMapEntry, visitSynthetic, visitUnknown
      • Methods inherited from class java.lang.Object

        equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Field Detail

      • LOGGER_METHODS

        private static final java.util.Set<java.lang.String> LOGGER_METHODS
      • LOG4J2_LOGMANAGER

        private static final java.lang.String LOG4J2_LOGMANAGER
        See Also:
        Constant Field Values
      • SIG_STRING_AND_TWO_OBJECTS_TO_VOID

        private static final java.lang.String SIG_STRING_AND_TWO_OBJECTS_TO_VOID
      • SIG_STRING_AND_OBJECT_ARRAY_TO_VOID

        private static final java.lang.String SIG_STRING_AND_OBJECT_ARRAY_TO_VOID
      • SIG_OBJECT_AND_THROWABLE_TO_VOID

        private static final java.lang.String SIG_OBJECT_AND_THROWABLE_TO_VOID
      • SIG_STRING_AND_THROWABLE_TO_VOID

        private static final java.lang.String SIG_STRING_AND_THROWABLE_TO_VOID
      • SIG_CLASS_TO_COMMONS_LOGGER

        private static final java.lang.String SIG_CLASS_TO_COMMONS_LOGGER
      • SIG_CLASS_TO_LOG4J_LOGGER

        private static final java.lang.String SIG_CLASS_TO_LOG4J_LOGGER
      • SIG_CLASS_TO_LOG4J2_LOGGER

        private static final java.lang.String SIG_CLASS_TO_LOG4J2_LOGGER
      • SIG_CLASS_TO_SLF4J_LOGGER

        private static final java.lang.String SIG_CLASS_TO_SLF4J_LOGGER
      • SIG_STRING_TO_COMMONS_LOGGER

        private static final java.lang.String SIG_STRING_TO_COMMONS_LOGGER
      • SIG_STRING_TO_LOG4J_LOGGER

        private static final java.lang.String SIG_STRING_TO_LOG4J_LOGGER
      • SIG_STRING_TO_LOG4J2_LOGGER

        private static final java.lang.String SIG_STRING_TO_LOG4J2_LOGGER
      • SIG_STRING_TO_SLF4J_LOGGER

        private static final java.lang.String SIG_STRING_TO_SLF4J_LOGGER
      • SIG_STRING_AND_FACTORY_TO_LOG4J_LOGGER

        private static final java.lang.String SIG_STRING_AND_FACTORY_TO_LOG4J_LOGGER
      • BAD_FORMATTING_ANCHOR

        private static final java.util.regex.Pattern BAD_FORMATTING_ANCHOR
      • BAD_STRING_FORMAT_PATTERN

        private static final java.util.regex.Pattern BAD_STRING_FORMAT_PATTERN
      • FORMATTER_ANCHOR

        private static final java.util.regex.Pattern FORMATTER_ANCHOR
      • NON_SIMPLE_FORMAT

        private static final java.util.regex.Pattern NON_SIMPLE_FORMAT
      • bugReporter

        private final edu.umd.cs.findbugs.BugReporter bugReporter
      • formatterLoggers

        private java.util.Set<java.lang.String> formatterLoggers
      • throwableClass

        private org.apache.bcel.classfile.JavaClass throwableClass
      • stack

        private edu.umd.cs.findbugs.OpcodeStack stack
      • nameOfThisClass

        private java.lang.String nameOfThisClass
      • isStaticInitializer

        private boolean isStaticInitializer
    • Constructor Detail

      • LoggerOddities

        public LoggerOddities​(edu.umd.cs.findbugs.BugReporter bugReporter)
        constructs a LO detector given the reporter to report bugs on.
        Parameters:
        bugReporter - the sync of bug reports
    • Method Detail

      • visitClassContext

        public void visitClassContext​(edu.umd.cs.findbugs.ba.ClassContext classContext)
        implements the visitor to discover what the class name is if it is a normal class, or the owning class, if the class is an anonymous class.
        Specified by:
        visitClassContext in interface edu.umd.cs.findbugs.Detector
        Overrides:
        visitClassContext in class edu.umd.cs.findbugs.BytecodeScanningDetector
        Parameters:
        classContext - the context object of the currently parsed class
      • visitCode

        public void visitCode​(org.apache.bcel.classfile.Code obj)
        implements the visitor to reset the stack
        Specified by:
        visitCode in interface org.apache.bcel.classfile.Visitor
        Overrides:
        visitCode in class edu.umd.cs.findbugs.visitclass.PreorderVisitor
        Parameters:
        obj - the context object of the currently parsed code block
      • sawOpcode

        public void sawOpcode​(int seen)
        implements the visitor to look for calls to Logger.getLogger with the wrong class name
        Overrides:
        sawOpcode in class edu.umd.cs.findbugs.visitclass.DismantleBytecode
        Parameters:
        seen - the opcode of the currently parsed instruction
      • isNonPrivateLogField

        private boolean isNonPrivateLogField​(@SlashedClassName
                                             java.lang.String fieldClsName,
                                             java.lang.String fieldName,
                                             java.lang.String fieldSig)
        looks to see if this field is a logger, and declared non privately
        Parameters:
        fieldClsName - the owning class type of the field
        fieldName - the name of the field
        fieldSig - the signature of the field
        Returns:
        if the field is a logger and not private
      • isLoggerWithClassParm

        private boolean isLoggerWithClassParm​(edu.umd.cs.findbugs.ba.XMethod m)
        returns whether this method class is a standard logger instantiation that takes a java/lang/Class parameter
        Parameters:
        m - the method to check
        Returns:
        if the method is a logger factory method that takes a Class object
      • checkForProblemsWithLoggerMethods

        private void checkForProblemsWithLoggerMethods()
                                                throws java.lang.ClassNotFoundException
        looks for a variety of logging issues with log statements
        Throws:
        java.lang.ClassNotFoundException - if the exception class, or a parent class can't be found
      • checkForProblemsWithLoggerThrowableMethods

        private void checkForProblemsWithLoggerThrowableMethods()
      • checkForProblemsWithLoggerSingleArgumentMethod

        private void checkForProblemsWithLoggerSingleArgumentMethod()
                                                             throws java.lang.ClassNotFoundException
        Throws:
        java.lang.ClassNotFoundException
      • checkForProblemsWithLoggerParameterisedMethods

        private void checkForProblemsWithLoggerParameterisedMethods​(java.lang.String sig)
      • checkForLoggerParam

        private void checkForLoggerParam()
        looks for slf4j calls where an exception is passed as a logger parameter, expecting to be substituted for a {} marker. As slf4j just passes the exception down to the message generation itself, the {} marker will go unpopulated.
      • lookForSuspectClasses

        private void lookForSuspectClasses()
        looks for instantiation of a logger with what looks like a class name that isn't the same as the class in which it exists. There are some cases where a 'classname-like' string is presented purposely different than this class, and an attempt is made to ignore those.
      • getLoggingClassNameFromStackValue

        @Nullable
        private java.lang.String getLoggingClassNameFromStackValue()
      • countAnchors

        private static int countAnchors​(java.lang.String formatString)
        returns the number of anchors {} in a string
        Parameters:
        formatString - the format string
        Returns:
        the number of anchors
      • getVarArgsParmCount

        private int getVarArgsParmCount​(java.lang.String signature)
        returns the number of parameters slf4j or log4j2 is expecting to inject into the format string
        Parameters:
        signature - the method signature of the error, warn, info, debug statement
        Returns:
        the number of expected parameters
      • hasExceptionOnStack

        private boolean hasExceptionOnStack()
        returns whether an exception object is on the stack slf4j will find this, and not include it in the parm list so i we find one, just don't report
        Returns:
        whether or not an exception i present