Add cutom opentracing trace in Java project for Elastic stack

Opentracing is one of the open protocol for distribute tracing between microservices. With APM, it helps to identify service dependency and target bottom-neck during performance tuning. Even it merged to OpenTelmetry in recent years but it still popular for APM.

This demo will show how to add custom trace in Java project. It will add to Aspect to fire in each method.

Prerequisites

  1. Project has been connected to APM;

  2. Check opentracing dependencies added in project.

    dependencies {
        implementation 'co.elastic.apm:apm-opentracing:1.+'
        implementation 'io.opentracing:opentracing-api:0.+'
    }

Steps

  1. Add custom trace.
    Add code in method required to block in span.

    import co.elastic.apm.opentracing.ElasticApmTracer;
    import io.opentracing.Scope;
    import io.opentracing.Span;
    import io.opentracing.Tracer;
    import io.opentracing.log.Fields;
    import io.opentracing.tag.Tags;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    
    import java.util.HashMap;
    import java.util.Map;
    
    @Aspect
    @Component
    public class LoggingAspect {
        private static final int LOG_LEVEL_WARNING_THRESHOLD =5000;
    
        private Tracer tracer = new ElasticApmTracer();
    
        @Around("execution(*!execution(* org.jooq..*(..))")
        public Object profileAllMethods(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
    
            //Get intercepted method details
            String className = methodSignature.getDeclaringType().getSimpleName();
            String methodName = methodSignature.getName();
            String methodFullName=className+"."+methodName;
    
            Object result=null;
    
            Span span= tracer.buildSpan(className+"#"+methodName).start();
            try (Scope scope = tracer.scopeManager().activate(span)) {
                result = proceedingJoinPoint.proceed();
            } catch(Exception ex) {
                Tags.ERROR.set(span, true);
                Map<String, Object> spanErrorLog=createErrorSpan(ex);
                span.log(spanErrorLog);
            } finally {
                span.finish();
            }
            return result;
        }
    
        private Map<String, Object> createErrorSpan(Exception ex) {
            Map<String, Object> spanErrorLog=new HashMap<>();
            spanErrorLog.put(Fields.EVENT, "Error");
            spanErrorLog.put(Fields.ERROR_OBJECT, ex);
            spanErrorLog.put(Fields.MESSAGE, ex.getMessage());
            return spanErrorLog;
        }
    }
  2. Test
    Open project in debug mode and call related code. Open APM and find related transaction. Expected it will show span which added.
About C.H. Ling 260 Articles
a .net / Java developer from Hong Kong and currently located in United Kingdom. Thanks for Google because it solve many technical problems so I build this blog as return. Besides coding and trying advance technology, hiking and traveling is other favorite to me, so I will write down something what I see and what I feel during it. Happy reading!!!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


This site uses Akismet to reduce spam. Learn how your comment data is processed.