/* * Copyright 2017 NAVER Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.navercorp.pinpoint.profiler.context; import com.navercorp.pinpoint.bootstrap.context.AsyncState; import com.navercorp.pinpoint.bootstrap.context.AsyncTraceId; import com.navercorp.pinpoint.bootstrap.context.Trace; import com.navercorp.pinpoint.bootstrap.context.TraceId; import com.navercorp.pinpoint.bootstrap.sampler.Sampler; import com.navercorp.pinpoint.common.annotations.InterfaceAudience; import com.navercorp.pinpoint.profiler.context.id.AsyncIdGenerator; import com.navercorp.pinpoint.profiler.context.id.AtomicIdGenerator; import com.navercorp.pinpoint.profiler.context.id.IdGenerator; import com.navercorp.pinpoint.profiler.context.id.ListenableAsyncState; import com.navercorp.pinpoint.profiler.context.id.TraceIdFactory; import com.navercorp.pinpoint.profiler.context.recorder.RecorderFactory; import com.navercorp.pinpoint.profiler.context.storage.AsyncStorage; import com.navercorp.pinpoint.profiler.context.storage.Storage; import com.navercorp.pinpoint.profiler.context.storage.StorageFactory; /** * @author emeroad * @author Taejin Koo */ public class DefaultBaseTraceFactory implements BaseTraceFactory { private final CallStackFactory callStackFactory; private final StorageFactory storageFactory; private final Sampler sampler; private final IdGenerator idGenerator; private final AsyncIdGenerator asyncIdGenerator; private final TraceIdFactory traceIdFactory; private final SpanFactory spanFactory; private final RecorderFactory recorderFactory; public DefaultBaseTraceFactory(CallStackFactory callStackFactory, StorageFactory storageFactory, Sampler sampler, TraceIdFactory traceIdFactory, IdGenerator idGenerator, AsyncIdGenerator asyncIdGenerator, SpanFactory spanFactory, RecorderFactory recorderFactory) { if (callStackFactory == null) { throw new NullPointerException("callStackFactory must not be null"); } if (storageFactory == null) { throw new NullPointerException("storageFactory must not be null"); } if (sampler == null) { throw new NullPointerException("sampler must not be null"); } if (idGenerator == null) { throw new NullPointerException("idGenerator must not be null"); } if (traceIdFactory == null) { throw new NullPointerException("traceIdFactory must not be null"); } if (asyncIdGenerator == null) { throw new NullPointerException("asyncIdGenerator must not be null"); } if (spanFactory == null) { throw new NullPointerException("spanFactory must not be null"); } if (recorderFactory == null) { throw new NullPointerException("recorderFactory must not be null"); } this.callStackFactory = callStackFactory; this.storageFactory = storageFactory; this.sampler = sampler; this.traceIdFactory = traceIdFactory; this.idGenerator = idGenerator; this.asyncIdGenerator = asyncIdGenerator; this.spanFactory = spanFactory; this.recorderFactory = recorderFactory; } // continue to trace the request that has been determined to be sampled on previous nodes @Override public Trace continueTraceObject(final TraceId traceId) { // TODO need to modify how to bind a datasender // always set true because the decision of sampling has been made on previous nodes // TODO need to consider as a target to sample in case Trace object has a sampling flag (true) marked on previous node. final Storage storage = storageFactory.createStorage(); final long localTransactionId = this.idGenerator.nextContinuedTransactionId(); final Trace trace = new DefaultTrace(callStackFactory, storage, traceId, localTransactionId, asyncIdGenerator, true, spanFactory, recorderFactory); return trace; } @Override public Trace continueTraceObject(Trace trace) { return trace; } @Override public Trace newTraceObject() { // TODO need to modify how to inject a datasender final boolean sampling = sampler.isSampling(); if (sampling) { final Storage storage = storageFactory.createStorage(); final TraceId traceId = traceIdFactory.newTraceId(); final long localTransactionId = traceId.getTransactionSequence(); final Trace trace = new DefaultTrace(callStackFactory, storage, traceId, localTransactionId, asyncIdGenerator, true, spanFactory, recorderFactory); return trace; } else { return newDisableTrace(); } } // internal async trace. @Override public Trace continueAsyncTraceObject(AsyncTraceId traceId, int asyncId, long startTime) { final TraceId parentTraceId = traceId.getParentTraceId(); final Storage storage = storageFactory.createStorage(); final Storage asyncStorage = new AsyncStorage(storage); final Trace trace = new DefaultTrace(callStackFactory, asyncStorage, parentTraceId, AtomicIdGenerator.UNTRACKED_ID, asyncIdGenerator, true, spanFactory, recorderFactory); final AsyncTrace asyncTrace = new AsyncTrace(trace, asyncId, traceId.nextAsyncSequence(), startTime); return asyncTrace; } // entry point async trace. @InterfaceAudience.LimitedPrivate("vert.x") @Override public Trace continueAsyncTraceObject(final TraceId traceId) { final Storage storage = storageFactory.createStorage(); final long localTransactionId = this.idGenerator.nextContinuedTransactionId(); final DefaultTrace trace = new DefaultTrace(callStackFactory, storage, traceId, localTransactionId, asyncIdGenerator, true, spanFactory, recorderFactory); final SpanAsyncStateListener asyncStateListener = new SpanAsyncStateListener(trace.getSpan(), storageFactory.createStorage()); final ListenableAsyncState stateListener = new ListenableAsyncState(asyncStateListener); final AsyncTrace asyncTrace = new AsyncTrace(trace, stateListener); return asyncTrace; } // entry point async trace. @InterfaceAudience.LimitedPrivate("vert.x") @Override public Trace newAsyncTraceObject() { final boolean sampling = sampler.isSampling(); if (sampling) { final Storage storage = storageFactory.createStorage(); final TraceId traceId = traceIdFactory.newTraceId(); final long localTransactionId = traceId.getTransactionSequence(); final DefaultTrace trace = new DefaultTrace(callStackFactory, storage, traceId, localTransactionId, asyncIdGenerator, true, spanFactory, recorderFactory); final SpanAsyncStateListener asyncStateListener = new SpanAsyncStateListener(trace.getSpan(), storageFactory.createStorage()); final AsyncState closer = new ListenableAsyncState(asyncStateListener); final AsyncTrace asyncTrace = new AsyncTrace(trace, closer); return asyncTrace; } else { return newDisableTrace(); } } private Trace newDisableTrace() { final long nextDisabledId = this.idGenerator.nextDisabledId(); final Trace disableTrace = new DisableTrace(nextDisabledId); return disableTrace; } @Override public Trace disableSampling() { final long nextContinuedDisabledId = this.idGenerator.nextContinuedDisabledId(); final Trace trace = new DisableTrace(nextContinuedDisabledId); return trace; } }