【问题标题】:logstash-logback-encoder display stacktrace in multiple lineslogstash-logback-encoder 在多行中显示堆栈跟踪
【发布时间】:2017-12-09 20:50:20
【问题描述】:

logstash-logback-encoder 将堆栈跟踪的输出显示在一个字符串中,例如

"stack_trace": "java.lang.RuntimeException: null\n\tat com.ideasforsharing.demo.controllers.SleuthController.helloSleuth(SleuthController.java:24)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n"

这很难读。如何格式化堆栈跟踪的显示以将其显示在多行上,也许使用 json 数组?

"stack_trace" : [
    "java.lang.RuntimeException: null",
      "com.ideasforsharing.demo.controllers.SleuthController.helloSleuth(SleuthController.java:24)",
        "at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
        "at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)"
]

【问题讨论】:

    标签: java json logstash logstash-logback-encoder


    【解决方案1】:

    我做了某事

    <provider class="com.ac.log.CustomStackTraceJsonProvider">
        <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
            <maxDepthPerThrowable>full</maxDepthPerThrowable>
            <maxLength>full</maxLength>
            <shortenedClassNameLength>20</shortenedClassNameLength>
            <exclusions>${STE_EXCLUSIONS}</exclusions>
            <rootCauseFirst>true</rootCauseFirst>
        </throwableConverter>
    </provider>
    

    这个类看起来像

    import java.io.IOException;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import com.fasterxml.jackson.core.JsonGenerator;
    
    import ch.qos.logback.classic.spi.ILoggingEvent;
    import ch.qos.logback.classic.spi.IThrowableProxy;
    import net.logstash.logback.composite.JsonWritingUtils;
    import net.logstash.logback.composite.loggingevent.StackTraceJsonProvider;
    
    public class CustomStackTraceJsonProvider extends StackTraceJsonProvider {
    
      public CustomStackTraceJsonProvider() {
        super();
      }
    
      @Override
      public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException {
        IThrowableProxy throwableProxy = event.getThrowableProxy();
        if (throwableProxy != null) {
          String msg = getThrowableConverter().convert(event);
          String[] lines = msg.split("\\n\\t");
          Map<String, String> lineMap = new LinkedHashMap<>();
          for(int i = 0; i < lines.length; i++){
            lineMap.put(String.valueOf(i+1), lines[i]);
          }
          JsonWritingUtils.writeMapStringFields(generator, getFieldName(), lineMap);
        }
      }
    }
    

    输出格式为

    {
      l_t : "2018-04-14T20:00:25.066-07:00",
      l_l : "ERROR",
      l_m : "Error while validating field existence",
      service : "com.ac.api.client.product.ProductService",
      method : "fetchProduct",
      value : "p-j0ednf7f6wd8l6rss",
      l_th : "http-nio-8080-exec-5",
      stack_hash : "26c1547b",
      l_c : "com.ac.core.validation.ExistsByStringFieldValidator:isValid:34",
      stack_trace : {
        1 : "c.i.c.a.c.e.RemoteServiceException: error code: 1002, user msg: remote.service.objectNotFound, parameters: [(identifier: p-j0ednf7f6wd8l6rss)]",
        2 : "at c.i.c.a.c.p.ProductServiceImpl.toProduct(ProductServiceImpl.java:69)",
        3 : "at c.i.c.a.c.p.ProductServiceImpl.fetchProductInternal(ProductServiceImpl.java:44)",
        4 : "at c.i.c.a.c.p.ProductServiceImpl.fetchProduct(ProductServiceImpl.java:33)",
        5 : "at c.i.c.a.c.p.ProductServiceImpl$$FastClassBySpringCGLIB$$5ee58445.invoke(<generated>)",
        6 : "at o.s.c.p.MethodProxy.invoke(MethodProxy.java:204)",
        7 : "at o.s.a.f.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)",
        8 : "at o.s.a.f.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)",
        9 : "at o.s.c.j.i.JCacheInterceptor$1.invoke(JCacheInterceptor.java:52)",
        10 : "at o.s.c.j.i.JCacheAspectSupport.invokeOperation(JCacheAspectSupport.java:153)",
        11 : "at o.s.c.j.i.JCacheAspectSupport$CacheOperationInvokerAdapter.invoke(JCacheAspectSupport.java:167)",
        12 : "at o.s.c.j.i.CacheResultInterceptor.invoke(CacheResultInterceptor.java:62)",
        13 : "at o.s.c.j.i.JCacheAspectSupport.execute(JCacheAspectSupport.java:123)",
        14 : "at o.s.c.j.i.JCacheAspectSupport.execute(JCacheAspectSupport.java:102)",
        15 : "at o.s.c.j.i.JCacheInterceptor.invoke(JCacheInterceptor.java:61)",
        16 : "at o.s.a.f.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)",
        17 : "at o.s.a.f.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)",
        18 : "at c.i.c.a.c.p.ProductServiceImpl$$EnhancerBySpringCGLIB$$f315262.fetchProduct(<generated>)",
        19 : "... 124 common frames omitted\nWrapped by: j.l.r.InvocationTargetException: null",
        20 : "at s.r.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java)",
        21 : "at s.r.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
        22 : "at s.r.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
        23 : "at j.l.reflect.Method.invoke(Method.java:498)",
        24 : "at c.i.c.c.v.ExistsByStringFieldValidator.isValid(ExistsByStringFieldValidator.java:29)",
        25 : "at c.i.c.c.v.ExistsByStringFieldValidator.isValid(ExistsByStringFieldValidator.java:12)",
        26 : "at o.h.v.i.e.c.ConstraintTree.validateSingleConstraint(ConstraintTree.java:448)",
        27 : "at o.h.v.i.e.c.ConstraintTree.validateConstraints(ConstraintTree.java:127)",
        28 : "at o.h.v.i.e.c.ConstraintTree.validateComposingConstraints(ConstraintTree.java:398)",
        29 : "at o.h.v.i.e.c.ConstraintTree.validateConstraints(ConstraintTree.java:98)",
        30 : "at o.h.v.i.e.c.ConstraintTree.validateConstraints(ConstraintTree.java:87)",
        31 : "at o.h.v.i.m.c.MetaConstraint.validateConstraint(MetaConstraint.java:73)",
        32 : "at o.h.v.i.e.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:621)",
        33 : "at o.h.v.i.e.ValidatorImpl.validateConstraint(ValidatorImpl.java:584)",
        34 : "at o.h.v.i.e.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:528)",
        35 : "at o.h.v.i.e.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:496)",
        36 : "at o.h.v.i.e.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:461)",
        37 : "at o.h.v.i.e.ValidatorImpl.validateInContext(ValidatorImpl.java:411)",
        38 : "at o.h.v.i.e.ValidatorImpl.validateCascadedConstraint(ValidatorImpl.java:762)",
        39 : "at o.h.v.i.e.ValidatorImpl.validateCascadedConstraints(ValidatorImpl.java:685)",
        40 : "at o.h.v.i.e.ValidatorImpl.validateParametersInContext(ValidatorImpl.java:1126)",
        41 : "at o.h.v.i.e.ValidatorImpl.validateParameters(ValidatorImpl.java:302)",
        42 : "at o.h.v.i.e.ValidatorImpl.validateParameters(ValidatorImpl.java:256)",
        43 : "at s.r.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java)",
        44 : "at s.r.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
        45 : "... 99 frames truncated\n"
      }
    }
    

    【讨论】:

    • 这是一个很好的解决方案,但是当我实现它时,我看到了两个stack_trace 属性——原始的不可读的一个和一个转换为可读性的地图。你有没有找到一种方法来禁用原来无法读取的stack_trace 属性?
    • 我最终忽略了encoder 中的stackTrace fieldName,而是写信给fieldName stacktrace。我还将split 正则表达式切换为\\n(\\t)? 以覆盖没有制表符的换行符。您还可以使用 generator.writeFieldName("stacktrace");generator.writeObject(lines); 写出数组而不是映射 - 但是这将要求您编写自己的 CustomPrettyPrintingJsonGeneratorDecorator 以便在其自己的行上打印每个数组条目(例如,@987654335 @)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-06
    相关资源
    最近更新 更多