2017-10-19 109 views
0

我想用AOP实现一个日志记录概念,但打印日志时我需要给我自己的方法名称而不是默认值。在Logback中覆盖方法名称(%M转换说明符)

更新(基于@glitch评论):

  • 我使用%M转换符告诉的logback包括在每个日志事件的方法名称。

  • 我想回报某些 logback派生方法名称spicifically;用于由我的AOP连接点发出的日志事件。

  • 我不想在日志事件的其他地方写'实际方法名'我想要使​​用的方法名称是正确的,即表示原始方法而不是拦截方法。

+0

你指的“默认”,这是否意味着你使用的是'%M'转换说明在你的logback模式让的logback推导方法的名字吗?您是否想将其替换为所有日志事件或仅针对选定的日志事件?是否必须替换它,或者在日志消息的其他位置写入其他方法名称是否足够? – glytching

+0

我在两种方式使用日志记录,一种是正常的日志记录方法和aspectj AOP。对于正常的日志记录方法名称是正确打印,但对于最终的Logger logger = LoggerFactory.getLogger(pjp.getSignature()。getDeclaringTypeName());这个记录器打印aop方法而不是确切的方法,我使用'ProceedingJoinPoint' –

+0

在这里我可以得到确切的方法名称与pjp.getSignature()。getName(),但记录器需要打印此方法名称而不是aop方法名称,如果这不是possbile我可以用这个方法名称覆盖%M –

回答

1

%M转换说明符由ch.qos.logback.classic.pattern.MethodOfCallerConverter实现。实现相当简单:

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

所以,你可以提供自己的实现。像这样的事情也许......

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

...它使用MDC从您的连接点通过实际的方法名。在您的连接点上,您可以在调用记录器之前放置MDC值,例如

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

但是... Logback不提供任何方式让您声明自己的自定义转换器。 Logback使用的转换器在 ch.qos.logback.classic.PatternLayout的静态初始化器中声明,并且这不可扩展/可覆盖。所以,我觉得你的选择是:

  1. 在自己的代码库,即用自己的logback取代自己MethodOfCallerConverter创建ch.qos.logback.classic.pattern.MethodOfCallerConverter类。您可以使用的例子,我的上方,并 - 只要你把MDC的CUSTOM_METHOD_NAME_KEY值调用的记录之前 - 它会做你想要什么

  2. 继续使用%M符,但对于AOP拦截方法添加附加的MDC属性显示实际的方法名称。这会导致Logback方法名称出现在所有日志输出中,同时出现actula方法名称(如果可用)。例如:

    // 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. 停止使用%M符和记录通过MDC所有方法名。这将导致正确的方法名称出现,但它会要求您在每种方法中更新MDC(这听起来很尴尬)。例如:

    // 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 
    
+0

谢谢你是一个天才,现在一切都像一个cham –

+0

由于Logback提供没有注册自己的'%M'转换说明符的钩子,你'扩展'通过模仿它的'MethodOfCallerConverter'进行Logback。这种方法有效,但它不是标准的,可能很脆弱;如果未来的Logback版本更改了“MethodOfCallerConverter”的名称或命名空间,那么您也必须更改“MethodOfCallerConverter”的版本。只是要记住一些事情.... – glytching