aboutsummaryrefslogtreecommitdiff
path: root/impl_core/src/main/java/io/opencensus/implcore/trace/StartEndHandlerImpl.java
blob: 6adaa2003dcdb20551f890c1e8c8da48c595e562 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * Copyright 2017, OpenCensus Authors
 *
 * 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 io.opencensus.implcore.trace;

import io.opencensus.implcore.internal.EventQueue;
import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler;
import io.opencensus.implcore.trace.export.RunningSpanStoreImpl;
import io.opencensus.implcore.trace.export.SampledSpanStoreImpl;
import io.opencensus.implcore.trace.export.SpanExporterImpl;
import io.opencensus.trace.Span.Options;
import io.opencensus.trace.export.SpanData;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;

/**
 * Uses the provided {@link EventQueue} to defer processing/exporting of the {@link SpanData} to
 * avoid impacting the critical path.
 */
@ThreadSafe
public final class StartEndHandlerImpl implements StartEndHandler {
  private final SpanExporterImpl spanExporter;
  @Nullable private final RunningSpanStoreImpl runningSpanStore;
  @Nullable private final SampledSpanStoreImpl sampledSpanStore;
  private final EventQueue eventQueue;
  // true if any of (runningSpanStore OR sampledSpanStore) are different than null, which
  // means the spans with RECORD_EVENTS should be enqueued in the queue.
  private final boolean enqueueEventForNonSampledSpans;

  /**
   * Constructs a new {@code StartEndHandlerImpl}.
   *
   * @param spanExporter the {@code SpanExporter} implementation.
   * @param runningSpanStore the {@code RunningSpanStore} implementation.
   * @param sampledSpanStore the {@code SampledSpanStore} implementation.
   * @param eventQueue the event queue where all the events are enqueued.
   */
  public StartEndHandlerImpl(
      SpanExporterImpl spanExporter,
      @Nullable RunningSpanStoreImpl runningSpanStore,
      @Nullable SampledSpanStoreImpl sampledSpanStore,
      EventQueue eventQueue) {
    this.spanExporter = spanExporter;
    this.runningSpanStore = runningSpanStore;
    this.sampledSpanStore = sampledSpanStore;
    this.enqueueEventForNonSampledSpans = runningSpanStore != null || sampledSpanStore != null;
    this.eventQueue = eventQueue;
  }

  @Override
  public void onStart(RecordEventsSpanImpl span) {
    if (span.getOptions().contains(Options.RECORD_EVENTS) && enqueueEventForNonSampledSpans) {
      eventQueue.enqueue(new SpanStartEvent(span, runningSpanStore));
    }
  }

  @Override
  public void onEnd(RecordEventsSpanImpl span) {
    if ((span.getOptions().contains(Options.RECORD_EVENTS) && enqueueEventForNonSampledSpans)
        || span.getContext().getTraceOptions().isSampled()) {
      eventQueue.enqueue(new SpanEndEvent(span, spanExporter, runningSpanStore, sampledSpanStore));
    }
  }

  // An EventQueue entry that records the start of the span event.
  private static final class SpanStartEvent implements EventQueue.Entry {
    private final RecordEventsSpanImpl span;
    @Nullable private final RunningSpanStoreImpl activeSpansExporter;

    SpanStartEvent(RecordEventsSpanImpl span, @Nullable RunningSpanStoreImpl activeSpansExporter) {
      this.span = span;
      this.activeSpansExporter = activeSpansExporter;
    }

    @Override
    public void process() {
      if (activeSpansExporter != null) {
        activeSpansExporter.onStart(span);
      }
    }
  }

  // An EventQueue entry that records the end of the span event.
  private static final class SpanEndEvent implements EventQueue.Entry {
    private final RecordEventsSpanImpl span;
    @Nullable private final RunningSpanStoreImpl runningSpanStore;
    private final SpanExporterImpl spanExporter;
    @Nullable private final SampledSpanStoreImpl sampledSpanStore;

    SpanEndEvent(
        RecordEventsSpanImpl span,
        SpanExporterImpl spanExporter,
        @Nullable RunningSpanStoreImpl runningSpanStore,
        @Nullable SampledSpanStoreImpl sampledSpanStore) {
      this.span = span;
      this.runningSpanStore = runningSpanStore;
      this.spanExporter = spanExporter;
      this.sampledSpanStore = sampledSpanStore;
    }

    @Override
    public void process() {
      if (span.getContext().getTraceOptions().isSampled()) {
        spanExporter.addSpan(span);
      }
      if (runningSpanStore != null) {
        runningSpanStore.onEnd(span);
      }
      if (sampledSpanStore != null) {
        sampledSpanStore.considerForSampling(span);
      }
    }
  }
}