Search in sources :

Example 1 with Trace2Dto

use of io.datarouter.instrumentation.trace.Trace2Dto in project datarouter by hotpads.

the class TraceFilter method doFilter.

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
    try {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        // get or create TraceContext
        Long traceCreated = Trace2Dto.getCurrentTimeInNs();
        String traceparentStr = request.getHeader(DatarouterHttpClientIoExceptionCircuitBreaker.TRACEPARENT);
        String tracestateStr = request.getHeader(DatarouterHttpClientIoExceptionCircuitBreaker.TRACESTATE);
        W3TraceContext traceContext = new W3TraceContext(traceparentStr, tracestateStr, traceCreated);
        String initialParentId = traceContext.getTraceparent().parentId;
        traceContext.updateParentIdAndAddTracestateMember();
        RequestAttributeTool.set(request, BaseHandler.TRACE_URL_REQUEST_ATTRIBUTE, urlBuilder.buildTraceForCurrentServer(traceContext.getTraceId(), traceContext.getParentId()));
        RequestAttributeTool.set(request, BaseHandler.TRACE_CONTEXT, traceContext.copy());
        // traceflag might be incorrect because it might have been modified during request processing
        if (traceSettings.addTraceparentHeader.get()) {
            response.setHeader(DatarouterHttpClientIoExceptionCircuitBreaker.TRACEPARENT, traceContext.getTraceparent().toString());
        }
        // bind these to all threads, even if tracing is disabled
        Tracer tracer = new DatarouterTracer(serverName.get(), null, traceContext);
        tracer.setSaveThreadCpuTime(traceSettings.saveThreadCpuTime.get());
        tracer.setSaveThreadMemoryAllocated(traceSettings.saveThreadMemoryAllocated.get());
        tracer.setSaveSpanCpuTime(traceSettings.saveSpanCpuTime.get());
        tracer.setSaveSpanMemoryAllocated(traceSettings.saveSpanMemoryAllocated.get());
        TracerThreadLocal.bindToThread(tracer);
        String requestThreadName = (request.getContextPath() + " request").trim();
        tracer.createAndStartThread(requestThreadName, Trace2Dto.getCurrentTimeInNs());
        Long threadId = Thread.currentThread().getId();
        boolean saveCpuTime = traceSettings.saveTraceCpuTime.get();
        Long cpuTimeBegin = saveCpuTime ? MxBeans.THREAD.getCurrentThreadCpuTime() : null;
        boolean saveAllocatedBytes = traceSettings.saveTraceAllocatedBytes.get();
        Long threadAllocatedBytesBegin = saveAllocatedBytes ? MxBeans.THREAD.getThreadAllocatedBytes(threadId) : null;
        boolean errored = false;
        try {
            fc.doFilter(req, res);
        } catch (Exception e) {
            errored = true;
            throw e;
        } finally {
            long ended = Trace2Dto.getCurrentTimeInNs();
            Long cpuTimeEnded = saveCpuTime ? MxBeans.THREAD.getCurrentThreadCpuTime() : null;
            Long threadAllocatedBytesEnded = saveAllocatedBytes ? MxBeans.THREAD.getThreadAllocatedBytes(threadId) : null;
            Traceparent traceparent = tracer.getTraceContext().get().getTraceparent();
            Trace2ThreadDto rootThread = null;
            if (tracer.getCurrentThreadId() != null) {
                rootThread = ((DatarouterTracer) tracer).getCurrentThread();
                rootThread.setCpuTimeEndedNs(cpuTimeEnded);
                rootThread.setMemoryAllocatedBytesEnded(threadAllocatedBytesEnded);
                rootThread.setEnded(ended);
                ((DatarouterTracer) tracer).setCurrentThread(null);
            }
            Trace2Dto trace2 = new Trace2Dto(traceparent, initialParentId, request.getContextPath(), request.getRequestURI().toString(), request.getQueryString(), traceCreated, ended, serviceName.get(), tracer.getDiscardedThreadCount(), tracer.getThreadQueue().size(), cpuTimeBegin, cpuTimeEnded, threadAllocatedBytesBegin, threadAllocatedBytesEnded);
            Long traceDurationMs = trace2.getDurationInMs();
            Long cpuTime = saveCpuTime ? TimeUnit.NANOSECONDS.toMillis(cpuTimeEnded - cpuTimeBegin) : null;
            Long threadAllocatedKB = saveAllocatedBytes ? (threadAllocatedBytesEnded - threadAllocatedBytesBegin) / 1024 : null;
            String saveReason = null;
            if (traceSettings.saveTraces.get()) {
                if (traceDurationMs > traceSettings.saveTracesOverMs.get()) {
                    saveReason = "duration";
                }
                if (RequestTool.getBoolean(request, "trace", false)) {
                    saveReason = "queryParam";
                }
                if (tracer.shouldSample()) {
                    saveReason = "traceContext";
                }
                if (errored) {
                    saveReason = "error";
                }
            }
            if (saveReason != null) {
                Counters.inc("traceSaved " + saveReason);
                List<Trace2ThreadDto> threads = new ArrayList<>(tracer.getThreadQueue());
                List<Trace2SpanDto> spans = new ArrayList<>(tracer.getSpanQueue());
                if (rootThread != null) {
                    rootThread.setTotalSpanCount(spans.size());
                    // force to save the rootThread even though the queue could be full
                    threads.add(rootThread);
                }
                String userAgent = RequestTool.getUserAgent(request);
                String userToken = currentSessionInfo.getSession(request).map(Session::getUserToken).orElse("unknown");
                HttpRequestRecordDto httpRequestRecord = buildHttpRequestRecord(errored, request, traceCreated, userToken, traceparent);
                String destination = offerTrace2(new Trace2BundleDto(trace2, threads, spans), httpRequestRecord);
                logger.warn("Trace saved to={} traceparent={} initialParentId={} durationMs={}" + " cpuTimeMs={} threadAllocatedKB={} path={} query={} userAgent=\"{}\" userToken={}", destination, traceparent, initialParentId, traceDurationMs, cpuTime, threadAllocatedKB, trace2.type, trace2.params, userAgent, userToken);
            } else if (traceDurationMs > traceSettings.logTracesOverMs.get() || TracerTool.shouldLog()) {
                // only log once
                logger.warn("Trace logged durationMs={} cpuTimeMs={} threadAllocatedKB={} path={}" + " query={}, traceparent={}", traceDurationMs, cpuTime, threadAllocatedKB, trace2.type, trace2.params, traceparent);
            }
            Optional<Class<? extends BaseHandler>> handlerClassOpt = RequestAttributeTool.get(request, BaseHandler.HANDLER_CLASS);
            Optional<Method> handlerMethodOpt = RequestAttributeTool.get(request, BaseHandler.HANDLER_METHOD);
            if (handlerClassOpt.isPresent() && handlerMethodOpt.isPresent()) {
                Class<? extends BaseHandler> handlerClass = handlerClassOpt.get();
                if (traceSettings.latencyRecordedHandlers.get().contains(handlerClass.getName())) {
                    handlerMetrics.saveMethodLatency(handlerClass, handlerMethodOpt.get(), traceDurationMs);
                }
            }
        }
    } finally {
        TracerThreadLocal.clearFromThread();
    }
}
Also used : DatarouterTracer(io.datarouter.util.tracer.DatarouterTracer) ArrayList(java.util.ArrayList) Trace2ThreadDto(io.datarouter.instrumentation.trace.Trace2ThreadDto) Traceparent(io.datarouter.instrumentation.trace.Traceparent) HttpServletRequest(javax.servlet.http.HttpServletRequest) Tracer(io.datarouter.instrumentation.trace.Tracer) DatarouterTracer(io.datarouter.util.tracer.DatarouterTracer) HttpServletResponse(javax.servlet.http.HttpServletResponse) W3TraceContext(io.datarouter.instrumentation.trace.W3TraceContext) Method(java.lang.reflect.Method) ServletException(javax.servlet.ServletException) IOException(java.io.IOException) Trace2SpanDto(io.datarouter.instrumentation.trace.Trace2SpanDto) BaseHandler(io.datarouter.web.handler.BaseHandler) HttpRequestRecordDto(io.datarouter.instrumentation.exception.HttpRequestRecordDto) Trace2BundleAndHttpRequestRecordDto(io.datarouter.instrumentation.trace.Trace2BundleAndHttpRequestRecordDto) Trace2BundleDto(io.datarouter.instrumentation.trace.Trace2BundleDto) Trace2Dto(io.datarouter.instrumentation.trace.Trace2Dto)

Aggregations

HttpRequestRecordDto (io.datarouter.instrumentation.exception.HttpRequestRecordDto)1 Trace2BundleAndHttpRequestRecordDto (io.datarouter.instrumentation.trace.Trace2BundleAndHttpRequestRecordDto)1 Trace2BundleDto (io.datarouter.instrumentation.trace.Trace2BundleDto)1 Trace2Dto (io.datarouter.instrumentation.trace.Trace2Dto)1 Trace2SpanDto (io.datarouter.instrumentation.trace.Trace2SpanDto)1 Trace2ThreadDto (io.datarouter.instrumentation.trace.Trace2ThreadDto)1 Traceparent (io.datarouter.instrumentation.trace.Traceparent)1 Tracer (io.datarouter.instrumentation.trace.Tracer)1 W3TraceContext (io.datarouter.instrumentation.trace.W3TraceContext)1 DatarouterTracer (io.datarouter.util.tracer.DatarouterTracer)1 BaseHandler (io.datarouter.web.handler.BaseHandler)1 IOException (java.io.IOException)1 Method (java.lang.reflect.Method)1 ArrayList (java.util.ArrayList)1 ServletException (javax.servlet.ServletException)1 HttpServletRequest (javax.servlet.http.HttpServletRequest)1 HttpServletResponse (javax.servlet.http.HttpServletResponse)1