Skip to content
This repository was archived by the owner on Dec 23, 2023. It is now read-only.

Commit 68e19ed

Browse files
authored
Disable by default RunningSpanStore, and enable if Zpages are initialized. (#1875)
* Disable by default RunningSpanStore, and enable if Zpages are initialized. * Change to allow configuration of max spans. * Update Changelog.
1 parent 409b451 commit 68e19ed

16 files changed

Lines changed: 384 additions & 227 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
## Unreleased
2+
- Disable RunningSpanStore by default unless the z-pages contrib is linked and initialized. This may
3+
break behaviors for applications that rely on this to be always enabled.
24

35
## 0.21.0 - 2019-04-30
46
- Add HTTP text format serializer to Tag propagation component.

api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,17 @@ static RunningSpanStore getNoopRunningSpanStore() {
6767
*/
6868
public abstract Collection<SpanData> getRunningSpans(Filter filter);
6969

70+
/**
71+
* Sets the maximum number of Spans in th {@code RunningSpanStore}.
72+
*
73+
* <p>{@code 0} means disabled, by default the {@code RunningSpanStore} is disabled.
74+
*
75+
* @param maxNumberOfSpans the maximum number of Spans in th {@code RunningSpanStore}.
76+
* @throws IllegalArgumentException if {@code maxNumberOfSpans} is negative.
77+
* @since 0.22
78+
*/
79+
public abstract void setMaxNumberOfSpans(int maxNumberOfSpans);
80+
7081
/**
7182
* The summary of all available data.
7283
*
@@ -197,5 +208,10 @@ public Collection<SpanData> getRunningSpans(Filter filter) {
197208
Utils.checkNotNull(filter, "filter");
198209
return Collections.<SpanData>emptyList();
199210
}
211+
212+
@Override
213+
public void setMaxNumberOfSpans(int maxNumberOfSpans) {
214+
Utils.checkArgument(maxNumberOfSpans >= 0, "Invalid negative maxNumberOfElements");
215+
}
200216
}
201217
}

contrib/zpages/src/main/java/io/opencensus/contrib/zpages/ZPageHandlers.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ public final class ZPageHandlers {
7878
private static final ZPageHandler statszZPageHandler =
7979
StatszZPageHandler.create(Stats.getViewManager());
8080

81+
static {
82+
// Sets the maximum number of elements as Integer.MAX_VALUE.
83+
Tracing.getExportComponent().getRunningSpanStore().setMaxNumberOfSpans(Integer.MAX_VALUE);
84+
}
85+
8186
private static final Object monitor = new Object();
8287

8388
@GuardedBy("monitor")

impl_core/src/main/java/io/opencensus/implcore/trace/StartEndHandlerImpl.java

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import io.opencensus.implcore.internal.EventQueue;
2020
import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler;
21-
import io.opencensus.implcore.trace.export.RunningSpanStoreImpl;
21+
import io.opencensus.implcore.trace.export.InProcessRunningSpanStore;
2222
import io.opencensus.implcore.trace.export.SampledSpanStoreImpl;
2323
import io.opencensus.implcore.trace.export.SpanExporterImpl;
2424
import io.opencensus.trace.Span.Options;
@@ -33,80 +33,77 @@
3333
@ThreadSafe
3434
public final class StartEndHandlerImpl implements StartEndHandler {
3535
private final SpanExporterImpl spanExporter;
36-
@Nullable private final RunningSpanStoreImpl runningSpanStore;
37-
@Nullable private final SampledSpanStoreImpl sampledSpanStore;
36+
private final InProcessRunningSpanStore inProcessRunningSpanStore;
37+
private final SampledSpanStoreImpl sampledSpanStore;
3838
private final EventQueue eventQueue;
39-
// true if any of (runningSpanStore OR sampledSpanStore) are different than null, which
40-
// means the spans with RECORD_EVENTS should be enqueued in the queue.
41-
private final boolean enqueueEventForNonSampledSpans;
4239

4340
/**
4441
* Constructs a new {@code StartEndHandlerImpl}.
4542
*
4643
* @param spanExporter the {@code SpanExporter} implementation.
47-
* @param runningSpanStore the {@code RunningSpanStore} implementation.
44+
* @param inProcessRunningSpanStore the {@code RunningSpanStore} implementation.
4845
* @param sampledSpanStore the {@code SampledSpanStore} implementation.
4946
* @param eventQueue the event queue where all the events are enqueued.
5047
*/
5148
public StartEndHandlerImpl(
5249
SpanExporterImpl spanExporter,
53-
@Nullable RunningSpanStoreImpl runningSpanStore,
54-
@Nullable SampledSpanStoreImpl sampledSpanStore,
50+
InProcessRunningSpanStore inProcessRunningSpanStore,
51+
SampledSpanStoreImpl sampledSpanStore,
5552
EventQueue eventQueue) {
5653
this.spanExporter = spanExporter;
57-
this.runningSpanStore = runningSpanStore;
54+
this.inProcessRunningSpanStore = inProcessRunningSpanStore;
5855
this.sampledSpanStore = sampledSpanStore;
59-
this.enqueueEventForNonSampledSpans = runningSpanStore != null || sampledSpanStore != null;
6056
this.eventQueue = eventQueue;
6157
}
6258

6359
@Override
6460
public void onStart(RecordEventsSpanImpl span) {
65-
if (span.getOptions().contains(Options.RECORD_EVENTS) && enqueueEventForNonSampledSpans) {
66-
eventQueue.enqueue(new SpanStartEvent(span, runningSpanStore));
61+
if (span.getOptions().contains(Options.RECORD_EVENTS)
62+
&& inProcessRunningSpanStore.getEnabled()) {
63+
eventQueue.enqueue(new SpanStartEvent(span, inProcessRunningSpanStore));
6764
}
6865
}
6966

7067
@Override
7168
public void onEnd(RecordEventsSpanImpl span) {
72-
if ((span.getOptions().contains(Options.RECORD_EVENTS) && enqueueEventForNonSampledSpans)
69+
if ((span.getOptions().contains(Options.RECORD_EVENTS)
70+
&& (inProcessRunningSpanStore.getEnabled() || sampledSpanStore.getEnabled()))
7371
|| span.getContext().getTraceOptions().isSampled()) {
74-
eventQueue.enqueue(new SpanEndEvent(span, spanExporter, runningSpanStore, sampledSpanStore));
72+
eventQueue.enqueue(
73+
new SpanEndEvent(span, spanExporter, inProcessRunningSpanStore, sampledSpanStore));
7574
}
7675
}
7776

7877
// An EventQueue entry that records the start of the span event.
7978
private static final class SpanStartEvent implements EventQueue.Entry {
8079
private final RecordEventsSpanImpl span;
81-
@Nullable private final RunningSpanStoreImpl activeSpansExporter;
80+
private final InProcessRunningSpanStore inProcessRunningSpanStore;
8281

83-
SpanStartEvent(RecordEventsSpanImpl span, @Nullable RunningSpanStoreImpl activeSpansExporter) {
82+
SpanStartEvent(RecordEventsSpanImpl span, InProcessRunningSpanStore inProcessRunningSpanStore) {
8483
this.span = span;
85-
this.activeSpansExporter = activeSpansExporter;
84+
this.inProcessRunningSpanStore = inProcessRunningSpanStore;
8685
}
8786

8887
@Override
8988
public void process() {
90-
if (activeSpansExporter != null) {
91-
activeSpansExporter.onStart(span);
92-
}
89+
inProcessRunningSpanStore.onStart(span);
9390
}
9491
}
9592

9693
// An EventQueue entry that records the end of the span event.
9794
private static final class SpanEndEvent implements EventQueue.Entry {
9895
private final RecordEventsSpanImpl span;
99-
@Nullable private final RunningSpanStoreImpl runningSpanStore;
96+
private final InProcessRunningSpanStore inProcessRunningSpanStore;
10097
private final SpanExporterImpl spanExporter;
10198
@Nullable private final SampledSpanStoreImpl sampledSpanStore;
10299

103100
SpanEndEvent(
104101
RecordEventsSpanImpl span,
105102
SpanExporterImpl spanExporter,
106-
@Nullable RunningSpanStoreImpl runningSpanStore,
103+
InProcessRunningSpanStore inProcessRunningSpanStore,
107104
@Nullable SampledSpanStoreImpl sampledSpanStore) {
108105
this.span = span;
109-
this.runningSpanStore = runningSpanStore;
106+
this.inProcessRunningSpanStore = inProcessRunningSpanStore;
110107
this.spanExporter = spanExporter;
111108
this.sampledSpanStore = sampledSpanStore;
112109
}
@@ -116,9 +113,7 @@ public void process() {
116113
if (span.getContext().getTraceOptions().isSampled()) {
117114
spanExporter.addSpan(span);
118115
}
119-
if (runningSpanStore != null) {
120-
runningSpanStore.onEnd(span);
121-
}
116+
inProcessRunningSpanStore.onEnd(span);
122117
if (sampledSpanStore != null) {
123118
sampledSpanStore.considerForSampling(span);
124119
}

impl_core/src/main/java/io/opencensus/implcore/trace/export/ExportComponentImpl.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public final class ExportComponentImpl extends ExportComponent {
2929
private static final Duration EXPORTER_SCHEDULE_DELAY = Duration.create(5, 0);
3030

3131
private final SpanExporterImpl spanExporter;
32-
private final RunningSpanStoreImpl runningSpanStore;
32+
private final InProcessRunningSpanStore inProcessRunningSpanStore;
3333
private final SampledSpanStoreImpl sampledSpanStore;
3434

3535
@Override
@@ -38,8 +38,8 @@ public SpanExporterImpl getSpanExporter() {
3838
}
3939

4040
@Override
41-
public RunningSpanStoreImpl getRunningSpanStore() {
42-
return runningSpanStore;
41+
public InProcessRunningSpanStore getRunningSpanStore() {
42+
return inProcessRunningSpanStore;
4343
}
4444

4545
@Override
@@ -81,10 +81,7 @@ public static ExportComponentImpl createWithoutInProcessStores(EventQueue eventQ
8181
*/
8282
private ExportComponentImpl(boolean supportInProcessStores, EventQueue eventQueue) {
8383
this.spanExporter = SpanExporterImpl.create(EXPORTER_BUFFER_SIZE, EXPORTER_SCHEDULE_DELAY);
84-
this.runningSpanStore =
85-
supportInProcessStores
86-
? new InProcessRunningSpanStoreImpl()
87-
: RunningSpanStoreImpl.getNoopRunningSpanStoreImpl();
84+
this.inProcessRunningSpanStore = InProcessRunningSpanStore.create();
8885
this.sampledSpanStore =
8986
supportInProcessStores
9087
? new InProcessSampledSpanStoreImpl(eventQueue)
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* Copyright 2019, OpenCensus Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.opencensus.implcore.trace.export;
18+
19+
import static com.google.common.base.Preconditions.checkArgument;
20+
21+
import io.opencensus.implcore.trace.RecordEventsSpanImpl;
22+
import io.opencensus.implcore.trace.internal.ConcurrentIntrusiveList;
23+
import io.opencensus.trace.export.RunningSpanStore;
24+
import io.opencensus.trace.export.SpanData;
25+
import java.util.ArrayList;
26+
import java.util.Collection;
27+
import java.util.Collections;
28+
import java.util.HashMap;
29+
import java.util.List;
30+
import java.util.Map;
31+
import javax.annotation.Nullable;
32+
import javax.annotation.concurrent.ThreadSafe;
33+
34+
/** In-process implementation of the {@link RunningSpanStore}. */
35+
@ThreadSafe
36+
public final class InProcessRunningSpanStore extends RunningSpanStore {
37+
private static final Summary EMPTY_SUMMARY =
38+
RunningSpanStore.Summary.create(Collections.<String, PerSpanNameSummary>emptyMap());
39+
40+
@Nullable private volatile InProcessRunningSpanStoreImpl impl = null;
41+
42+
static InProcessRunningSpanStore create() {
43+
return new InProcessRunningSpanStore();
44+
}
45+
46+
/**
47+
* Adds the {@code Span} into the running spans list when the {@code Span} starts.
48+
*
49+
* @param span the {@code Span} that started.
50+
*/
51+
public void onStart(RecordEventsSpanImpl span) {
52+
InProcessRunningSpanStoreImpl impl = this.impl;
53+
if (impl != null) {
54+
impl.onStart(span);
55+
}
56+
}
57+
58+
/**
59+
* Removes the {@code Span} from the running spans list when the {@code Span} ends.
60+
*
61+
* @param span the {@code Span} that ended.
62+
*/
63+
public void onEnd(RecordEventsSpanImpl span) {
64+
InProcessRunningSpanStoreImpl impl = this.impl;
65+
if (impl != null) {
66+
impl.onEnd(span);
67+
}
68+
}
69+
70+
/**
71+
* Returns {@code true} if the RunningSpanStore is enabled.
72+
*
73+
* @return {@code true} if the RunningSpanStore is enabled.
74+
*/
75+
public boolean getEnabled() {
76+
return this.impl != null;
77+
}
78+
79+
@Override
80+
public Summary getSummary() {
81+
InProcessRunningSpanStoreImpl impl = this.impl;
82+
if (impl != null) {
83+
return impl.getSummary();
84+
}
85+
return EMPTY_SUMMARY;
86+
}
87+
88+
@Override
89+
public Collection<SpanData> getRunningSpans(Filter filter) {
90+
InProcessRunningSpanStoreImpl impl = this.impl;
91+
if (impl != null) {
92+
return impl.getRunningSpans(filter);
93+
}
94+
return Collections.emptyList();
95+
}
96+
97+
@Override
98+
public void setMaxNumberOfSpans(int maxNumberOfSpans) {
99+
checkArgument(maxNumberOfSpans >= 0, "Invalid negative maxNumberOfElements");
100+
synchronized (this) {
101+
InProcessRunningSpanStoreImpl currentImpl = this.impl;
102+
if (currentImpl != null) {
103+
currentImpl.clear();
104+
}
105+
this.impl = null;
106+
if (maxNumberOfSpans > 0) {
107+
impl = new InProcessRunningSpanStoreImpl(maxNumberOfSpans);
108+
}
109+
}
110+
}
111+
112+
private static final class InProcessRunningSpanStoreImpl {
113+
private final ConcurrentIntrusiveList<RecordEventsSpanImpl> runningSpans;
114+
115+
private InProcessRunningSpanStoreImpl(int maxNumberOfElements) {
116+
runningSpans = new ConcurrentIntrusiveList<>(maxNumberOfElements);
117+
}
118+
119+
private void onStart(RecordEventsSpanImpl span) {
120+
runningSpans.addElement(span);
121+
}
122+
123+
private void onEnd(RecordEventsSpanImpl span) {
124+
// TODO: Count and display when try to remove span that was not present.
125+
runningSpans.removeElement(span);
126+
}
127+
128+
private Summary getSummary() {
129+
Collection<RecordEventsSpanImpl> allRunningSpans = runningSpans.getAll();
130+
Map<String, Integer> numSpansPerName = new HashMap<String, Integer>();
131+
for (RecordEventsSpanImpl span : allRunningSpans) {
132+
Integer prevValue = numSpansPerName.get(span.getName());
133+
numSpansPerName.put(span.getName(), prevValue != null ? prevValue + 1 : 1);
134+
}
135+
Map<String, PerSpanNameSummary> perSpanNameSummary =
136+
new HashMap<String, PerSpanNameSummary>();
137+
for (Map.Entry<String, Integer> it : numSpansPerName.entrySet()) {
138+
perSpanNameSummary.put(it.getKey(), PerSpanNameSummary.create(it.getValue()));
139+
}
140+
return Summary.create(perSpanNameSummary);
141+
}
142+
143+
private Collection<SpanData> getRunningSpans(Filter filter) {
144+
Collection<RecordEventsSpanImpl> allRunningSpans = runningSpans.getAll();
145+
int maxSpansToReturn =
146+
filter.getMaxSpansToReturn() == 0 ? allRunningSpans.size() : filter.getMaxSpansToReturn();
147+
List<SpanData> ret = new ArrayList<SpanData>(maxSpansToReturn);
148+
for (RecordEventsSpanImpl span : allRunningSpans) {
149+
if (ret.size() == maxSpansToReturn) {
150+
break;
151+
}
152+
if (span.getName().equals(filter.getSpanName())) {
153+
ret.add(span.toSpanData());
154+
}
155+
}
156+
return ret;
157+
}
158+
159+
private void clear() {
160+
runningSpans.clear();
161+
}
162+
}
163+
}

0 commit comments

Comments
 (0)