1

I am trying to implement a logging concept with AOP but while printing the log I need give my own method name instead of the default.

Update (based on the comments from @glitch):

  • I am using the %M conversion specifier to tell Logback to include the method name in each log event.

  • I want to replce the Logback derived method name for some log events, spcifically; for the log events emitted by my AOP joinpoint.

  • I do not want to write the 'actual method name' somewhere else in the log event; I want the method name to be used and to be correct i.e. to represent the original method rather than the interception method.

Ashok Kumar N
  • 573
  • 6
  • 23
  • You refer to "the default", does this mean that you are using the `%M` conversion specifier in your logback pattern to let Logback derive the method name? Do you want to replace this for all log events or only for selected log events? Does it have to be replaced or would an additional method name written somewhere else in the log message suffice? – glytching Oct 19 '17 at 16:23
  • i am using logging in two ways one is like normal logging inside method and through aspectj AOP. for normal logging method name is printing properly but for aop `final Logger logger = LoggerFactory.getLogger(pjp.getSignature().getDeclaringTypeName()); logger.info(AppConstants.METHOD_START_DEBUG_MSG);` this logger printing the aop method instead of exact method , i am using `ProceedingJoinPoint` – Ashok Kumar N Oct 20 '17 at 07:06
  • here i can get the exact method name with pjp.getSignature().getName() , but the logger need to print this method name instead of the aop method name if this is not possbile can i able to override the %M with this method name – Ashok Kumar N Oct 20 '17 at 07:12
  • 1
    Re my three questions, I think the answers are: _are you using the %M conversion specifier in your logback pattern- - YES; _Do you want to replace this for all log events or only for selected log events_ - SELECTED LOG EVENTS; _Does it have to be replaced or would an additional method name written somewhere else in the log message suffice_ - NO ANSWER YET. – glytching Oct 20 '17 at 07:16
  • @glitch thanks for the reply and patience , this is what i exactly need . for the 3rd question - answer is i need to replace the method name in %M – Ashok Kumar N Oct 20 '17 at 07:19

1 Answers1

2

The %M conversion specifier is implemented by ch.qos.logback.classic.pattern.MethodOfCallerConverter. The implementation is quite simple:

public String convert(ILoggingEvent le) {
    StackTraceElement[] cda = le.getCallerData();
    if (cda != null && cda.length > 0) {
        return cda[0].getMethodName();
    } else {
        return CallerData.NA;
    }
}

So, you could provide your own implementation. Something like this perhaps ...

public class CustomMethodOfCallerConverter extends ClassicConverter {

    public String convert(ILoggingEvent le) {
        StackTraceElement[] cda = le.getCallerData();
        if (cda != null && cda.length > 0) {
            if (le.getMDCPropertyMap().containsKey("CUSTOM_METHOD_NAME_KEY")) {
                String methodName = le.getMDCPropertyMap().get("CUSTOM_METHOD_NAME_KEY");
                // remove the MDC entry since we are only using MDC to pass the custom method name into this converter
                le.getMDCPropertyMap().remove("CUSTOM_METHOD_NAME_KEY");
                return methodName;
            } else {
                return cda[0].getMethodName();
            }
        } else {
            return CallerData.NA;
        }
    }
}

... which uses MDC to pass the actual method name from your joinpoint. In your joinpoint you would put the MDC value before invoking on the logger e.g.

MDC.put("CUSTOM_METHOD_NAME_KEY", pjp.getSignature().getName()));

But ... Logback does not provide any way for you to declare your own custom converter. The converters in use by Logback are declared in a static initializer on ch.qos.logback.classic.PatternLayout and this is not extensible/overrideable. So, I think your options are:

  1. Create a ch.qos.logback.classic.pattern.MethodOfCallerConverter class in your own code base i.e. replace Logback's own MethodOfCallerConverter with your own. You could use the example I provided above and - as long as you put the CUSTOM_METHOD_NAME_KEY value in MDC before invoking on the logger - it will do what you want

  2. Continue to use the %M specifier but for AOP intercepted methods add an additional MDC attribute to display the actual method name. This would result in the Logback method name appearing in all log output with the actula method name appearing too (when available). For example:

    // put the actual method name in MDC
    MDC.put("actualMethodName", pjp.getSignature().getName());
    
    // specify your pattern - in logback.xml - to include the actual method name
    %d{yyyy-MM-dd HH:mm:ss}|[%thread]|%-5level|%logger{36}|%M%X{actualMethodName:-}|%msg%n
    
  3. Stop using the %M specifier and log all method names via MDC. This would result in the correct method name appearing but it would require you to update MDC in every method (which sounds quite awkward). For example:

    // put the actual method name in MDC
    MDC.put("actualMethodName", pjp.getSignature().getName());
    
    // specify your pattern - in logback.xml - to include the actual method name
    %d{yyyy-MM-dd HH:mm:ss}|[%thread]|%-5level|%logger{36}|%X{actualMethodName}|%msg%n
    
glytching
  • 44,936
  • 9
  • 114
  • 120
  • Since Logback provides no hook for registering your own `%M` conversion specifier you are 'extending' Logback by mimicing its `MethodOfCallerConverter`. This approach works but it is non standard and may be brittle; if a future verison of Logback changes the name or namespace for `MethodOfCallerConverter` then you'll have to change your version of `MethodOfCallerConverter` too. Just something to bear in mind .... – glytching Oct 20 '17 at 13:08