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

Commit ab23a9d

Browse files
authored
Exporter/Trace: Extract timeout logic to a common util artifact. (#1887)
* Exporter/Trace: Extract timeout logic to a common util artifact. * Add Android compatibility signature. * Fix a typo.
1 parent 7362691 commit ab23a9d

7 files changed

Lines changed: 171 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ with default value 10 seconds.
1010
- Use `ZipkinExporterConfiguration` for creating `ZipkinTraceExporter`. Provide a `Deadline` option
1111
with default value 10 seconds.
1212
- Provide a `Deadline` option to Datadog and Elasticsearch exporter. Default value is 10 seconds.
13+
- Extract the common timeout logic of Trace exporters to `opencensus-exporter-trace-util`.
1314

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

all/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def subprojects = [
3131
project(':opencensus-exporter-trace-stackdriver'),
3232
project(':opencensus-exporter-trace-zipkin'),
3333
project(':opencensus-exporter-trace-jaeger'),
34+
project(':opencensus-exporter-trace-util'),
3435
project(':opencensus-exporter-stats-signalfx'),
3536
project(':opencensus-exporter-stats-stackdriver'),
3637
project(':opencensus-exporter-stats-prometheus'),
@@ -64,6 +65,7 @@ def subprojects_javadoc = [
6465
project(':opencensus-exporter-trace-stackdriver'),
6566
project(':opencensus-exporter-trace-zipkin'),
6667
project(':opencensus-exporter-trace-jaeger'),
68+
project(':opencensus-exporter-trace-util'),
6769
project(':opencensus-exporter-stats-signalfx'),
6870
project(':opencensus-exporter-stats-stackdriver'),
6971
project(':opencensus-exporter-stats-prometheus'),

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ subprojects {
450450
'opencensus-exporter-trace-stackdriver',
451451
'opencensus-exporter-trace-zipkin',
452452
'opencensus-exporter-trace-jaeger',
453+
'opencensus-exporter-trace-util',
453454
'opencensus-impl-core',
454455
'opencensus-impl-lite',
455456
'opencensus-impl',

exporters/trace/util/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# OpenCensus Java Trace Exporter Util
2+
3+
The *OpenCensus Trace Exporter Util* is the Java helper package for all trace exporters.
4+
5+
## Quickstart
6+
7+
### Add the dependencies to your project
8+
9+
For Maven add to your `pom.xml`:
10+
```xml
11+
<dependencies>
12+
<dependency>
13+
<groupId>io.opencensus</groupId>
14+
<artifactId>opencensus-api</artifactId>
15+
<version>0.22.0</version>
16+
</dependency>
17+
<dependency>
18+
<groupId>io.opencensus</groupId>
19+
<artifactId>opencensus-exporter-trace-util</artifactId>
20+
<version>0.22.0</version>
21+
</dependency>
22+
</dependencies>
23+
```
24+
25+
For Gradle add to your dependencies:
26+
```groovy
27+
compile 'io.opencensus:opencensus-api:0.22.0'
28+
compile 'io.opencensus:opencensus-exporter-trace-util:0.22.0'
29+
```

exporters/trace/util/build.gradle

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
description = 'OpenCensus Java Trace Exporter Utils'
2+
3+
[compileJava, compileTestJava].each() {
4+
it.sourceCompatibility = 1.6
5+
it.targetCompatibility = 1.6
6+
}
7+
8+
dependencies {
9+
compileOnly libraries.auto_value
10+
11+
compile project(':opencensus-api'),
12+
libraries.guava
13+
14+
signature "org.codehaus.mojo.signature:java17:1.0@signature"
15+
signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature"
16+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
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.exporter.trace.util;
18+
19+
import com.google.common.util.concurrent.SimpleTimeLimiter;
20+
import com.google.common.util.concurrent.TimeLimiter;
21+
import com.google.errorprone.annotations.MustBeClosed;
22+
import io.opencensus.common.Duration;
23+
import io.opencensus.common.Scope;
24+
import io.opencensus.trace.Sampler;
25+
import io.opencensus.trace.Span;
26+
import io.opencensus.trace.Status;
27+
import io.opencensus.trace.TraceOptions;
28+
import io.opencensus.trace.Tracer;
29+
import io.opencensus.trace.Tracing;
30+
import io.opencensus.trace.export.SpanData;
31+
import io.opencensus.trace.export.SpanExporter;
32+
import io.opencensus.trace.export.SpanExporter.Handler;
33+
import io.opencensus.trace.samplers.Samplers;
34+
import java.util.Collection;
35+
import java.util.concurrent.Callable;
36+
import java.util.concurrent.Executors;
37+
import java.util.concurrent.TimeUnit;
38+
import java.util.concurrent.TimeoutException;
39+
import java.util.logging.Level;
40+
import java.util.logging.Logger;
41+
42+
/**
43+
* An abstract class that allows different tracing services to export recorded data for sampled
44+
* spans in their own format within a given time frame. If export does not complete within the time
45+
* frame, spans will be dropped and no retries will be performed.
46+
*
47+
* <p>Only extend this class if the client APIs don't support timeout natively. If there is a
48+
* timeout option in the client APIs (for example Stackdriver Trace V2 API allows you to set
49+
* timeout), use that instead.
50+
*
51+
* <p>To export data this MUST be register to to the ExportComponent using {@link
52+
* SpanExporter#registerHandler(String, Handler)}.
53+
*
54+
* @since 0.22
55+
*/
56+
public abstract class TimeLimitedHandler extends SpanExporter.Handler {
57+
58+
private static final Logger logger = Logger.getLogger(TimeLimitedHandler.class.getName());
59+
private static final Tracer tracer = Tracing.getTracer();
60+
private static final Sampler lowProbabilitySampler = Samplers.probabilitySampler(0.0001);
61+
62+
private final Duration deadline;
63+
private final String exportSpanName;
64+
65+
protected TimeLimitedHandler(Duration deadline, String exportSpanName) {
66+
this.deadline = deadline;
67+
this.exportSpanName = exportSpanName;
68+
}
69+
70+
/**
71+
* Exports a list of sampled (see {@link TraceOptions#isSampled()}) {@link Span}s using the
72+
* immutable representation {@link SpanData}, within the given {@code deadline} of this {@link
73+
* TimeLimitedHandler}.
74+
*
75+
* @param spanDataList a list of {@code SpanData} objects to be exported.
76+
* @since 0.22
77+
*/
78+
public abstract void timeLimitedExport(Collection<SpanData> spanDataList);
79+
80+
@Override
81+
public void export(final Collection<SpanData> spanDataList) {
82+
final Scope exportScope = newExportScope();
83+
try {
84+
TimeLimiter timeLimiter = SimpleTimeLimiter.create(Executors.newSingleThreadExecutor());
85+
timeLimiter.callWithTimeout(
86+
new Callable<Void>() {
87+
@Override
88+
public Void call() throws Exception {
89+
timeLimitedExport(spanDataList);
90+
return null;
91+
}
92+
},
93+
deadline.toMillis(),
94+
TimeUnit.MILLISECONDS);
95+
} catch (TimeoutException e) {
96+
handleException(e, "Timeout when exporting traces: " + e);
97+
} catch (InterruptedException e) {
98+
handleException(e, "Interrupted when exporting traces: " + e);
99+
} catch (Exception e) {
100+
handleException(e, "Failed to export traces: " + e);
101+
} finally {
102+
exportScope.close();
103+
}
104+
}
105+
106+
@MustBeClosed
107+
private Scope newExportScope() {
108+
return tracer.spanBuilder(exportSpanName).setSampler(lowProbabilitySampler).startScopedSpan();
109+
}
110+
111+
private static void handleException(Exception e, String logMessage) {
112+
Status status = e instanceof TimeoutException ? Status.DEADLINE_EXCEEDED : Status.UNKNOWN;
113+
tracer
114+
.getCurrentSpan()
115+
.setStatus(
116+
status.withDescription(
117+
e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage()));
118+
logger.log(Level.WARNING, logMessage);
119+
}
120+
}

settings.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ include ":opencensus-exporter-trace-ocagent"
1717
include ":opencensus-exporter-trace-stackdriver"
1818
include ":opencensus-exporter-trace-zipkin"
1919
include ":opencensus-exporter-trace-jaeger"
20+
include ":opencensus-exporter-trace-util"
2021
include ":opencensus-exporter-stats-signalfx"
2122
include ":opencensus-exporter-stats-stackdriver"
2223
include ":opencensus-exporter-stats-prometheus"
@@ -91,3 +92,4 @@ project(':opencensus-exporter-trace-stackdriver').projectDir =
9192
"$rootDir/exporters/trace/stackdriver" as File
9293
project(':opencensus-exporter-trace-zipkin').projectDir = "$rootDir/exporters/trace/zipkin" as File
9394
project(':opencensus-exporter-trace-jaeger').projectDir = "$rootDir/exporters/trace/jaeger" as File
95+
project(':opencensus-exporter-trace-util').projectDir = "$rootDir/exporters/trace/util" as File

0 commit comments

Comments
 (0)