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

Commit 1dc78a8

Browse files
authored
Exporter/Jaeger: Use configurations and add deadline. (#1884)
1 parent 7c524f5 commit 1dc78a8

7 files changed

Lines changed: 334 additions & 35 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ break behaviors for applications that rely on this to be always enabled.
55
- Provide a `Deadline` option to Stackdriver Stats exporter. Default value is 10 seconds.
66
Also provide a `MetricServiceStub` option so that advanced users can use a custom Stackdriver
77
Monitoring client to make RPCs.
8+
- Use `JaegerExporterConfiguration` for creating `JaegerTraceExporter`. Provide a `Deadline` option
9+
with default value 10 seconds.
810

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

exporters/trace/jaeger/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ description = 'OpenCensus Trace Jaeger Exporter'
66
}
77

88
dependencies {
9+
compileOnly libraries.auto_value
10+
911
compile project(':opencensus-api'),
1012
libraries.guava
1113

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
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.jaeger;
18+
19+
import com.google.auto.value.AutoValue;
20+
import com.google.common.annotations.VisibleForTesting;
21+
import com.google.common.base.Preconditions;
22+
import io.jaegertracing.thrift.internal.senders.ThriftSender;
23+
import io.opencensus.common.Duration;
24+
import javax.annotation.Nullable;
25+
import javax.annotation.concurrent.Immutable;
26+
27+
/**
28+
* Configurations for {@link JaegerTraceExporter}.
29+
*
30+
* @since 0.22
31+
*/
32+
@AutoValue
33+
@Immutable
34+
public abstract class JaegerExporterConfiguration {
35+
36+
@VisibleForTesting static final Duration DEFAULT_DEADLINE = Duration.create(10, 0);
37+
38+
JaegerExporterConfiguration() {}
39+
40+
/**
41+
* Returns the service name.
42+
*
43+
* @return the service name.
44+
* @since 0.22
45+
*/
46+
public abstract String getServiceName();
47+
48+
/**
49+
* Returns the Thrift endpoint of your Jaeger instance.
50+
*
51+
* @return the Thrift endpoint.
52+
* @since 0.22
53+
*/
54+
public abstract String getThriftEndpoint();
55+
56+
/**
57+
* Returns the Thrift sender.
58+
*
59+
* @return the Thrift sender.
60+
* @since 0.22
61+
*/
62+
@Nullable
63+
public abstract ThriftSender getThriftSender();
64+
65+
/**
66+
* Returns the deadline for exporting to Jaeger.
67+
*
68+
* <p>Default value is 10 seconds.
69+
*
70+
* @return the export deadline.
71+
* @since 0.22
72+
*/
73+
public abstract Duration getDeadline();
74+
75+
/**
76+
* Returns a new {@link Builder}.
77+
*
78+
* @return a {@code Builder}.
79+
* @since 0.22
80+
*/
81+
public static Builder builder() {
82+
return new AutoValue_JaegerExporterConfiguration.Builder()
83+
.setThriftEndpoint("")
84+
.setDeadline(DEFAULT_DEADLINE);
85+
}
86+
87+
/**
88+
* Builder for {@link JaegerExporterConfiguration}.
89+
*
90+
* @since 0.22
91+
*/
92+
@AutoValue.Builder
93+
public abstract static class Builder {
94+
95+
@VisibleForTesting static final Duration ZERO = Duration.fromMillis(0);
96+
97+
Builder() {}
98+
99+
/**
100+
* Sets the service name.
101+
*
102+
* @param serviceName the service name.
103+
* @return this.
104+
* @since 0.22
105+
*/
106+
public abstract Builder setServiceName(String serviceName);
107+
108+
/**
109+
* Sets the Thrift endpoint of your Jaeger instance. e.g.: "http://127.0.0.1:14268/api/traces".
110+
*
111+
* <p>At least one of {@code ThriftEndpoint} and {@code ThriftSender} needs to be specified. If
112+
* both {@code ThriftEndpoint} and {@code ThriftSender} are set, {@code ThriftSender} takes
113+
* precedence.
114+
*
115+
* @param thriftEndpoint the Thrift endpoint.
116+
* @return this.
117+
* @since 0.22
118+
*/
119+
public abstract Builder setThriftEndpoint(String thriftEndpoint);
120+
121+
/**
122+
* Sets the Thrift sender.
123+
*
124+
* <p>At least one of {@code ThriftEndpoint} and {@code ThriftSender} needs to be specified. If
125+
* both {@code ThriftEndpoint} and {@code ThriftSender} are set, {@code ThriftSender} takes
126+
* precedence.
127+
*
128+
* @param sender the Thrift sender.
129+
* @return this.
130+
* @since 0.22
131+
*/
132+
public abstract Builder setThriftSender(ThriftSender sender);
133+
134+
/**
135+
* Sets the deadline for exporting to Jaeger.
136+
*
137+
* @param deadline the export deadline.
138+
* @return this
139+
* @since 0.22
140+
*/
141+
public abstract Builder setDeadline(Duration deadline);
142+
143+
abstract Duration getDeadline();
144+
145+
abstract String getThriftEndpoint();
146+
147+
@Nullable
148+
abstract ThriftSender getThriftSender();
149+
150+
abstract JaegerExporterConfiguration autoBuild();
151+
152+
/**
153+
* Builds a {@link JaegerExporterConfiguration}.
154+
*
155+
* @return a {@code JaegerExporterConfiguration}.
156+
* @since 0.22
157+
*/
158+
public JaegerExporterConfiguration build() {
159+
Preconditions.checkArgument(getDeadline().compareTo(ZERO) > 0, "Deadline must be positive.");
160+
Preconditions.checkArgument(
161+
!getThriftEndpoint().isEmpty() || getThriftSender() != null,
162+
"Neither Thrift endpoint nor Thrift sender is specified.");
163+
return autoBuild();
164+
}
165+
}
166+
}

exporters/trace/jaeger/src/main/java/io/opencensus/exporter/trace/jaeger/JaegerExporterHandler.java

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import com.google.common.collect.Lists;
2525
import com.google.common.primitives.Ints;
2626
import com.google.common.primitives.Longs;
27+
import com.google.common.util.concurrent.SimpleTimeLimiter;
28+
import com.google.common.util.concurrent.TimeLimiter;
2729
import com.google.errorprone.annotations.MustBeClosed;
2830
import io.jaegertracing.internal.exceptions.SenderException;
2931
import io.jaegertracing.thrift.internal.senders.ThriftSender;
@@ -34,6 +36,7 @@
3436
import io.jaegertracing.thriftjava.SpanRefType;
3537
import io.jaegertracing.thriftjava.Tag;
3638
import io.jaegertracing.thriftjava.TagType;
39+
import io.opencensus.common.Duration;
3740
import io.opencensus.common.Function;
3841
import io.opencensus.common.Scope;
3942
import io.opencensus.common.Timestamp;
@@ -57,6 +60,10 @@
5760
import java.util.Collection;
5861
import java.util.List;
5962
import java.util.Map;
63+
import java.util.concurrent.Callable;
64+
import java.util.concurrent.Executors;
65+
import java.util.concurrent.TimeUnit;
66+
import java.util.concurrent.TimeoutException;
6067
import java.util.logging.Level;
6168
import java.util.logging.Logger;
6269
import javax.annotation.Nullable;
@@ -152,27 +159,47 @@ public Tag apply(final Object value) {
152159

153160
private final ThriftSender sender;
154161
private final Process process;
162+
private final Duration deadline;
155163

156-
JaegerExporterHandler(final ThriftSender sender, final Process process) {
164+
JaegerExporterHandler(final ThriftSender sender, final Process process, Duration deadline) {
157165
this.sender = checkNotNull(sender, "Jaeger sender must NOT be null.");
158166
this.process = checkNotNull(process, "Process sending traces must NOT be null.");
167+
this.deadline = deadline;
159168
}
160169

161170
@Override
162171
public void export(final Collection<SpanData> spanDataList) {
163172
final Scope exportScope = newExportScope();
164173
try {
165-
doExport(spanDataList);
166-
} catch (SenderException e) {
167-
tracer
168-
.getCurrentSpan() // exportScope above.
169-
.setStatus(Status.UNKNOWN.withDescription(getMessageOrDefault(e)));
170-
logger.log(Level.WARNING, "Failed to export traces to Jaeger: " + e);
174+
TimeLimiter timeLimiter = SimpleTimeLimiter.create(Executors.newSingleThreadExecutor());
175+
timeLimiter.callWithTimeout(
176+
new Callable<Void>() {
177+
@Override
178+
public Void call() throws Exception {
179+
doExport(spanDataList);
180+
return null;
181+
}
182+
},
183+
deadline.toMillis(),
184+
TimeUnit.MILLISECONDS);
185+
} catch (TimeoutException e) {
186+
handleException(getMessageOrDefault(e), "Timeout when exporting traces to Jaeger: " + e);
187+
} catch (InterruptedException e) {
188+
handleException(getMessageOrDefault(e), "Interrupted when exporting traces to Jaeger: " + e);
189+
} catch (Exception e) {
190+
handleException(getMessageOrDefault(e), "Failed to export traces to Jaeger: " + e);
171191
} finally {
172192
exportScope.close();
173193
}
174194
}
175195

196+
private static void handleException(String description, String logMessage) {
197+
tracer
198+
.getCurrentSpan() // exportScope above.
199+
.setStatus(Status.UNKNOWN.withDescription(description));
200+
logger.log(Level.WARNING, logMessage);
201+
}
202+
176203
@MustBeClosed
177204
private static Scope newExportScope() {
178205
// Start a new span with explicit sampler (with low probability) to avoid the case when user
@@ -186,7 +213,7 @@ private void doExport(final Collection<SpanData> spanDataList) throws SenderExce
186213
sender.send(process, spans);
187214
}
188215

189-
private static String getMessageOrDefault(final SenderException e) {
216+
private static String getMessageOrDefault(final Exception e) {
190217
return e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage();
191218
}
192219

exporters/trace/jaeger/src/main/java/io/opencensus/exporter/trace/jaeger/JaegerTraceExporter.java

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@
3232
*
3333
* <pre>{@code
3434
* public static void main(String[] args) {
35-
* JaegerTraceExporter.createAndRegister("http://127.0.0.1:14268/api/traces", "myservicename");
35+
* JaegerTraceExporter.createAndRegister(
36+
* JaegerExporterConfiguration.builder().
37+
* .setThriftEndpoint("http://127.0.0.1:14268/api/traces")
38+
* .setServiceName("myservicename")
39+
* .build());
3640
* ... // Do work.
3741
* }
3842
* }</pre>
@@ -50,6 +54,29 @@ public final class JaegerTraceExporter {
5054
// Make constructor private to hide it from the API and therefore avoid users calling it.
5155
private JaegerTraceExporter() {}
5256

57+
/**
58+
* Creates and registers the Jaeger Trace exporter to the OpenCensus library using the provided
59+
* configurations.
60+
*
61+
* @param configuration configurations for this exporter.
62+
* @throws IllegalStateException if a Jaeger exporter is already registered.
63+
* @since 0.22
64+
*/
65+
public static void createAndRegister(JaegerExporterConfiguration configuration) {
66+
synchronized (monitor) {
67+
checkState(handler == null, "Jaeger exporter is already registered.");
68+
ThriftSender sender = configuration.getThriftSender();
69+
if (sender == null) {
70+
sender = new HttpSender.Builder(configuration.getThriftEndpoint()).build();
71+
}
72+
Process process = new Process(configuration.getServiceName());
73+
SpanExporter.Handler newHandler =
74+
new JaegerExporterHandler(sender, process, configuration.getDeadline());
75+
JaegerTraceExporter.handler = newHandler;
76+
register(Tracing.getExportComponent().getSpanExporter(), newHandler);
77+
}
78+
}
79+
5380
/**
5481
* Creates and registers the Jaeger Trace exporter to the OpenCensus library. Only one Jaeger
5582
* exporter can be registered at any point.
@@ -59,14 +86,15 @@ private JaegerTraceExporter() {}
5986
* @param serviceName the local service name of the process.
6087
* @throws IllegalStateException if a Jaeger exporter is already registered.
6188
* @since 0.13
89+
* @deprecated in favor of {@link #createAndRegister(JaegerExporterConfiguration)}.
6290
*/
91+
@Deprecated
6392
public static void createAndRegister(final String thriftEndpoint, final String serviceName) {
64-
synchronized (monitor) {
65-
checkState(handler == null, "Jaeger exporter is already registered.");
66-
final SpanExporter.Handler newHandler = newHandler(thriftEndpoint, serviceName);
67-
JaegerTraceExporter.handler = newHandler;
68-
register(Tracing.getExportComponent().getSpanExporter(), newHandler);
69-
}
93+
createAndRegister(
94+
JaegerExporterConfiguration.builder()
95+
.setThriftEndpoint(thriftEndpoint)
96+
.setServiceName(serviceName)
97+
.build());
7098
}
7199

72100
/**
@@ -77,27 +105,15 @@ public static void createAndRegister(final String thriftEndpoint, final String s
77105
* @param serviceName the local service name of the process.
78106
* @throws IllegalStateException if a Jaeger exporter is already registered.
79107
* @since 0.17
108+
* @deprecated in favor of {@link #createAndRegister(JaegerExporterConfiguration)}.
80109
*/
110+
@Deprecated
81111
public static void createWithSender(final ThriftSender sender, final String serviceName) {
82-
synchronized (monitor) {
83-
checkState(handler == null, "Jaeger exporter is already registered.");
84-
final SpanExporter.Handler newHandler = newHandlerWithSender(sender, serviceName);
85-
JaegerTraceExporter.handler = newHandler;
86-
register(Tracing.getExportComponent().getSpanExporter(), newHandler);
87-
}
88-
}
89-
90-
private static SpanExporter.Handler newHandler(
91-
final String thriftEndpoint, final String serviceName) {
92-
final HttpSender sender = new HttpSender.Builder(thriftEndpoint).build();
93-
final Process process = new Process(serviceName);
94-
return new JaegerExporterHandler(sender, process);
95-
}
96-
97-
private static SpanExporter.Handler newHandlerWithSender(
98-
final ThriftSender sender, final String serviceName) {
99-
final Process process = new Process(serviceName);
100-
return new JaegerExporterHandler(sender, process);
112+
createAndRegister(
113+
JaegerExporterConfiguration.builder()
114+
.setThriftSender(sender)
115+
.setServiceName(serviceName)
116+
.build());
101117
}
102118

103119
/**

0 commit comments

Comments
 (0)