wuxingye commented on issue #3365: add logstash logback plugin
URL: https://github.com/apache/skywalking/pull/3365#issuecomment-525988229
 
 
   # Add logstash logback plugin
   
   ## 1.user guide
   
   - Dependency the toolkit, such as using maven or gradle
   
   ```xml
   <dependency>
       <groupId>org.apache.skywalking</groupId>
       <artifactId>apm-toolkit-logback-1.x</artifactId>
       <version>${skywalking.version}</version>
   </dependency>
   ```
   
   - set `LogstashEncoder` of logback.xml
   
   ```xml
   <encoder charset="UTF-8" 
class="net.logstash.logback.encoder.LogstashEncoder">
       <provider 
class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.logstash.TraceIdJsonProvider">
       </provider>
       <customFields>{"app_id":"${app_id}"}</customFields>
   </encoder>
   ```
   
   
   
   ## 2.why it works
   
   - extension of logstash-logback-encoder provider, [official 
guide](https://github.com/logstash/logstash-logback-encoder#custom-json-provider)
   - Custom LogstashEncoder JSON Provider like this:
   
   ```xml
   <encoder class="net.logstash.logback.encoder.LogstashEncoder">
       ...
       <provider class="your.provider.YourJsonProvider">
           <!-- Any properties exposed by your provider can be set here -->
       </provider>
       ...
   </encoder>
   ```
   
   - TraceIdJsonProvider analyze
   
   ```java
   public class TraceIdJsonProvider extends 
AbstractFieldJsonProvider<ILoggingEvent> implements 
FieldNamesAware<LogstashFieldNames> {
   
       public static final String TRACING_ID = "TID";
   
       @Override
       public void writeTo(JsonGenerator generator, ILoggingEvent event) throws 
IOException {
           Map<String, String> map = 
event.getLoggerContextVO().getPropertyMap();
           JsonWritingUtils.writeStringField(generator, getFieldName(), 
map.get(TRACING_ID));
       }
   
       @Override
       public void setFieldNames(LogstashFieldNames fieldNames) {
           setFieldName(TRACING_ID);
       }
   }
   ```
   
   1. the setFieldNames method will add a json field named `TID`
   2. the writeTo method will set the `TID` value, for `propertyMap` is always 
not null, it at least contains `destination` of logstash, so the code will not 
throw `NPE`
   
   - TcpSocketAppenderActivation analyze
   
   ```java
   public class TcpSocketAppenderActivation extends 
ClassInstanceMethodsEnhancePluginDefine {
   
       public static final String INTERCEPT_CLASS = 
"org.apache.skywalking.apm.toolkit.activation.log.logback.v1.x.logstash.TcpSocketAppenderInterceptor";
       public static final String ENHANCE_CLASS = 
"net.logstash.logback.appender.LogstashTcpSocketAppender";
       public static final String ENHANCE_METHOD = 
"prepareForDeferredProcessing";
   
       /**
        * @return the target class, which needs active.
        */
       @Override
       protected ClassMatch enhanceClass() {
           return byName(ENHANCE_CLASS);
       }
   
       /**
        * @return null, no need to intercept constructor of enhance class.
        */
       @Override
       public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
           return null;
       }
   
       /**
        * @return the collection of {@link StaticMethodsInterceptPoint}, 
represent the intercepted methods and their
        * interceptors.
        */
       @Override
       public InstanceMethodsInterceptPoint[] 
getInstanceMethodsInterceptPoints() {
           return new InstanceMethodsInterceptPoint[] {
               new InstanceMethodsInterceptPoint() {
                   @Override
                   public ElementMatcher<MethodDescription> getMethodsMatcher() 
{
                       return 
named(ENHANCE_METHOD).and(takesArgumentWithType(0, 
"ch.qos.logback.classic.spi.ILoggingEvent"));
                   }
   
                   @Override
                   public String getMethodsInterceptor() {
                       return INTERCEPT_CLASS;
                   }
   
                   @Override public boolean isOverrideArgs() {
                       return false;
                   }
               }
           };
       }
   }
   
   ```
   
   1. net.logstash.logback.appender.`LogstashTcpSocketAppender` is logstash 
appender, contains a method:
   
   ```java
       @Override
       protected void prepareForDeferredProcessing(final ILoggingEvent event) {
           super.prepareForDeferredProcessing(event);
           if (includeCallerData) {
               event.getCallerData();
           }
       }
   ```
   
   2. so we enhance it by the `beforeMethod` of `TcpSocketAppenderInterceptor` :
   
   ```java
       @Override public void beforeMethod(EnhancedInstance objInst, Method 
method, Object[] allArguments,
           Class<?>[] argumentsTypes, MethodInterceptResult result) throws 
Throwable {
           ILoggingEvent event = (ILoggingEvent)allArguments[0];
           if (event != null && event.getLoggerContextVO() != null && 
event.getLoggerContextVO().getPropertyMap() != null) {
               event.getLoggerContextVO().getPropertyMap().put("TID", 
ContextManager.getGlobalTraceId());
           }
       }
   ```
   
   3. it put a key value of `(TID, ContextManager.getGlobalTraceId())` to the 
`ILoggingEvent`, so we can get it in the `writeTo` method of 
`TraceIdJsonProvider` 
   4. the method `prepareForDeferredProcessing` of `LogstashTcpSocketAppender` 
works on the worker thread, but others works on the logstash thread, because 
`logstash-logback-encoder` if a async plugin, so we enhance it by this way
   
   ## 3.related pictures
   
   - ConsoleAppender plugin
   
   
![image](https://user-images.githubusercontent.com/9107702/63904127-889aa800-ca42-11e9-9202-f3f832eaea6f.png)
   
   - logstash logback plugin
   
   
![image](https://user-images.githubusercontent.com/9107702/63904142-97815a80-ca42-11e9-8c95-0128891759e8.png)
   
   - skywalking ui
   
   
![image](https://user-images.githubusercontent.com/9107702/63904152-a10ac280-ca42-11e9-9e49-ca719b4dfabe.png)
   
   - before add `TID`
   
   
![image](https://user-images.githubusercontent.com/9107702/63904167-ac5dee00-ca42-11e9-8641-609f6ec6fedc.png)
   
   - after add `TID`
   
   
![image](https://user-images.githubusercontent.com/9107702/63904181-b253cf00-ca42-11e9-83e3-ed6135ab7bad.png)
   
   

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to