Class LoggerOddities

java.lang.Object
edu.umd.cs.findbugs.visitclass.BetterVisitor
edu.umd.cs.findbugs.visitclass.PreorderVisitor
edu.umd.cs.findbugs.visitclass.AnnotationVisitor
edu.umd.cs.findbugs.visitclass.DismantleBytecode
edu.umd.cs.findbugs.BytecodeScanningDetector
com.mebigfatguy.fbcontrib.detect.LoggerOddities
All Implemented Interfaces:
edu.umd.cs.findbugs.Detector, edu.umd.cs.findbugs.Priorities, org.apache.bcel.classfile.Visitor

@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 
     
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private static final Pattern
     
    private static final Pattern
     
    private final edu.umd.cs.findbugs.BugReporter
     
    private static final String
     
    private static final Pattern
     
    private Set<String>
     
    private boolean
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final Set<String>
     
    private String
     
    private static final Pattern
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private static final String
     
    private edu.umd.cs.findbugs.OpcodeStack
     
    private org.apache.bcel.classfile.JavaClass
     

    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 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

    Modifier and Type
    Method
    Description
    private void
    looks for slf4j calls where an exception is passed as a logger parameter, expecting to be substituted for a {} marker.
    private void
    looks for a variety of logging issues with log statements
    private void
     
    private void
     
    private void
     
    private static int
    countAnchors(String formatString)
    returns the number of anchors {} in a string
    private String
     
    private int
    returns the number of parameters slf4j or log4j2 is expecting to inject into the format string
    private boolean
    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(String fieldClsName, String fieldName, String fieldSig)
    looks to see if this field is a logger, and declared non privately
    private void
    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

    getAnnotationParameterAsEnum, 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, getSurroundingCaughtExceptionTypes, getSurroundingTryBlock, getSurroundingTryBlock, getThisClass, getXClass, getXField, getXMethod, hasInterestingClass, hasInterestingMethod, isVisitMethodsInCallOrder, setupVisitorForClass, setVisitMethodsInCallOrder, shouldVisit, toString, visitAfter, visitAfter, visitAnnotationDefault, visitAnnotationEntry, visitBootstrapMethods, visitConstantInvokeDynamic, visitConstantMethodHandle, visitConstantMethodType, visitConstantModule, visitConstantPackage, visitConstantPool, visitEnclosingMethod, visitingField, visitingMethod, visitInnerClasses, visitJavaClass, visitLineNumberTable, visitLocalVariableTable, visitMethodParameters, visitParameterAnnotationEntry, visitStackMap, visitStackMapEntry

    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, visitSynthetic, visitUnknown

    Methods inherited from class java.lang.Object

    equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

    Methods inherited from interface org.apache.bcel.classfile.Visitor

    visitConstantDynamic, visitMethodParameter, visitModule, visitModuleExports, visitModuleMainClass, visitModuleOpens, visitModulePackages, visitModuleProvides, visitModuleRequires, visitNestHost, visitNestMembers, visitRecord, visitRecordComponent, visitStackMapType
  • Field Details

    • LOGGER_METHODS

      private static final Set<String> LOGGER_METHODS
    • COMMONS_LOGGER

      private static final String COMMONS_LOGGER
      See Also:
    • LOG4J_LOGGER

      private static final String LOG4J_LOGGER
      See Also:
    • LOG4J2_LOGGER

      private static final String LOG4J2_LOGGER
      See Also:
    • LOG4J2_LOGMANAGER

      private static final String LOG4J2_LOGMANAGER
      See Also:
    • SLF4J_LOGGER

      private static final String SLF4J_LOGGER
      See Also:
    • SIG_STRING_AND_TWO_OBJECTS_TO_VOID

      private static final String SIG_STRING_AND_TWO_OBJECTS_TO_VOID
    • SIG_STRING_AND_OBJECT_ARRAY_TO_VOID

      private static final String SIG_STRING_AND_OBJECT_ARRAY_TO_VOID
    • SIG_OBJECT_AND_THROWABLE_TO_VOID

      private static final String SIG_OBJECT_AND_THROWABLE_TO_VOID
    • SIG_STRING_AND_THROWABLE_TO_VOID

      private static final String SIG_STRING_AND_THROWABLE_TO_VOID
    • SIG_CLASS_TO_COMMONS_LOGGER

      private static final String SIG_CLASS_TO_COMMONS_LOGGER
    • SIG_CLASS_TO_LOG4J_LOGGER

      private static final String SIG_CLASS_TO_LOG4J_LOGGER
    • SIG_CLASS_TO_LOG4J2_LOGGER

      private static final String SIG_CLASS_TO_LOG4J2_LOGGER
    • SIG_CLASS_TO_SLF4J_LOGGER

      private static final String SIG_CLASS_TO_SLF4J_LOGGER
    • SIG_STRING_TO_COMMONS_LOGGER

      private static final String SIG_STRING_TO_COMMONS_LOGGER
    • SIG_STRING_TO_LOG4J_LOGGER

      private static final String SIG_STRING_TO_LOG4J_LOGGER
    • SIG_STRING_TO_LOG4J2_LOGGER

      private static final String SIG_STRING_TO_LOG4J2_LOGGER
    • SIG_STRING_TO_SLF4J_LOGGER

      private static final String SIG_STRING_TO_SLF4J_LOGGER
    • SIG_STRING_AND_FACTORY_TO_LOG4J_LOGGER

      private static final String SIG_STRING_AND_FACTORY_TO_LOG4J_LOGGER
    • BAD_FORMATTING_ANCHOR

      private static final Pattern BAD_FORMATTING_ANCHOR
    • BAD_STRING_FORMAT_PATTERN

      private static final Pattern BAD_STRING_FORMAT_PATTERN
    • FORMATTER_ANCHOR

      private static final Pattern FORMATTER_ANCHOR
    • NON_SIMPLE_FORMAT

      private static final Pattern NON_SIMPLE_FORMAT
    • bugReporter

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

      private Set<String> formatterLoggers
    • throwableClass

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

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

      private String nameOfThisClass
    • isStaticInitializer

      private boolean isStaticInitializer
  • Constructor Details

    • 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 Details

    • 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 String fieldClsName, String fieldName, 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 ClassNotFoundException
      looks for a variety of logging issues with log statements
      Throws:
      ClassNotFoundException - if the exception class, or a parent class can't be found
    • checkForProblemsWithLoggerThrowableMethods

      private void checkForProblemsWithLoggerThrowableMethods()
    • checkForProblemsWithLoggerSingleArgumentMethod

      private void checkForProblemsWithLoggerSingleArgumentMethod() throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • checkForProblemsWithLoggerParameterisedMethods

      private void checkForProblemsWithLoggerParameterisedMethods(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 String getLoggingClassNameFromStackValue()
    • countAnchors

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

      private int getVarArgsParmCount(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