All Downloads are FREE. Search and download functionalities are using the official Maven repository.

graphql.execution.instrumentation.tracing.TracingSupport Maven / Gradle / Ivy

There is a newer version: 230521-nf-execution
Show newest version
package graphql.execution.instrumentation.tracing;

import com.google.common.collect.ImmutableList;
import graphql.PublicApi;
import graphql.execution.ExecutionStepInfo;
import graphql.execution.instrumentation.InstrumentationState;
import graphql.schema.DataFetchingEnvironment;

import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;

import static graphql.schema.GraphQLTypeUtil.simplePrint;

/**
 * This creates a map of tracing information as outlined in https://github.com/apollographql/apollo-tracing
 * 

* This is a stateful object that should be instantiated and called via {@link java.lang.instrument.Instrumentation} * calls. It has been made a separate class so that you can compose this into existing * instrumentation code. */ @PublicApi public class TracingSupport implements InstrumentationState { private final Instant startRequestTime; private final long startRequestNanos; private final ConcurrentLinkedQueue> fieldData; private final Map parseMap = new LinkedHashMap<>(); private final Map validationMap = new LinkedHashMap<>(); private final boolean includeTrivialDataFetchers; /** * The timer starts as soon as you create this object * * @param includeTrivialDataFetchers whether the trace trivial data fetchers */ public TracingSupport(boolean includeTrivialDataFetchers) { this.includeTrivialDataFetchers = includeTrivialDataFetchers; startRequestNanos = System.nanoTime(); startRequestTime = Instant.now(); fieldData = new ConcurrentLinkedQueue<>(); } /** * A simple object that you need to call {@link #onEnd()} on */ public interface TracingContext { /** * Call this to end the current trace context */ void onEnd(); } /** * This should be called to start the trace of a field, with {@link TracingContext#onEnd()} being called to * end the call. * * @param dataFetchingEnvironment the data fetching that is occurring * @param trivialDataFetcher if the data fetcher is considered trivial * * @return a context to call end on */ public TracingContext beginField(DataFetchingEnvironment dataFetchingEnvironment, boolean trivialDataFetcher) { if (!includeTrivialDataFetchers && trivialDataFetcher) { return () -> { // nothing to do }; } long startFieldFetch = System.nanoTime(); return () -> { long now = System.nanoTime(); long duration = now - startFieldFetch; long startOffset = startFieldFetch - startRequestNanos; ExecutionStepInfo executionStepInfo = dataFetchingEnvironment.getExecutionStepInfo(); Map fetchMap = new LinkedHashMap<>(); fetchMap.put("path", executionStepInfo.getPath().toList()); fetchMap.put("parentType", simplePrint(executionStepInfo.getParent().getUnwrappedNonNullType())); fetchMap.put("returnType", executionStepInfo.simplePrint()); fetchMap.put("fieldName", executionStepInfo.getFieldDefinition().getName()); fetchMap.put("startOffset", startOffset); fetchMap.put("duration", duration); fieldData.add(fetchMap); }; } /** * This should be called to start the trace of query parsing, with {@link TracingContext#onEnd()} being called to * end the call. * * @return a context to call end on */ public TracingContext beginParse() { return traceToMap(parseMap); } /** * This should be called to start the trace of query validation, with {@link TracingContext#onEnd()} being called to * end the call. * * @return a context to call end on */ public TracingContext beginValidation() { return traceToMap(validationMap); } private TracingContext traceToMap(Map map) { long start = System.nanoTime(); return () -> { long now = System.nanoTime(); long duration = now - start; long startOffset = now - startRequestNanos; map.put("startOffset", startOffset); map.put("duration", duration); }; } /** * This will snapshot this tracing and return a map of the results * * @return a snapshot of the tracing data */ public Map snapshotTracingData() { Map traceMap = new LinkedHashMap<>(); traceMap.put("version", 1L); traceMap.put("startTime", rfc3339(startRequestTime)); traceMap.put("endTime", rfc3339(Instant.now())); traceMap.put("duration", System.nanoTime() - startRequestNanos); traceMap.put("parsing", copyMap(parseMap)); traceMap.put("validation", copyMap(validationMap)); traceMap.put("execution", executionData()); return traceMap; } private Object copyMap(Map map) { return new LinkedHashMap<>(map); } private Map executionData() { Map map = new LinkedHashMap<>(); List> list = ImmutableList.copyOf(fieldData); map.put("resolvers", list); return map; } private String rfc3339(Instant time) { return DateTimeFormatter.ISO_INSTANT.format(time); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy