Delete jaeger exporters (#6119)

This commit is contained in:
jack-berg 2024-01-12 16:52:32 -06:00 committed by GitHub
parent 9c3af76ab9
commit 30c75b4715
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 4 additions and 3761 deletions

View File

@ -265,8 +265,6 @@ dependency as follows, replacing `{{artifact-id}}` with the value from the "Arti
| [OTLP Exporters](./exporters/otlp/all) | OTLP gRPC & HTTP exporters, including traces, metrics, and logs | `opentelemetry-exporter-otlp` | <!--VERSION_STABLE-->1.34.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-otlp.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-otlp) |
| [OTLP Logging Exporters](./exporters/logging-otlp) | Logging exporters in OTLP JSON encoding, including traces, metrics, and logs | `opentelemetry-exporter-logging-otlp` | <!--VERSION_STABLE-->1.34.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-logging-otlp.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-logging-otlp) |
| [OTLP Common](./exporters/otlp/common) | Shared OTLP components (internal) | `opentelemetry-exporter-otlp-common` | <!--VERSION_STABLE-->1.34.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-otlp-common.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-otlp-common) |
| [Jaeger gRPC Exporter](./exporters/jaeger) | Jaeger gRPC trace exporter (deprecated [1]) | `opentelemetry-exporter-jaeger` | <!--VERSION_STABLE-->1.34.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-jaeger.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-jaeger) |
| [Jaeger Thrift Exporter](./exporters/jaeger-thrift) | Jaeger thrift trace exporter (deprecated [1]) | `opentelemetry-exporter-jaeger-thift` | <!--VERSION_STABLE-->1.34.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-jaeger-thrift.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-jaeger-thrift) |
| [Logging Exporter](./exporters/logging) | Logging exporters, including metrics, traces, and logs | `opentelemetry-exporter-logging` | <!--VERSION_STABLE-->1.34.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-logging.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-logging) |
| [Zipkin Exporter](./exporters/zipkin) | Zipkin trace exporter | `opentelemetry-exporter-zipkin` | <!--VERSION_STABLE-->1.34.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-zipkin.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-zipkin) |
| [Prometheus Exporter](./exporters/prometheus) | Prometheus metric exporter | `opentelemetry-exporter-prometheus` | <!--VERSION_UNSTABLE-->1.34.0-alpha<!--/VERSION_UNSTABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-prometheus.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-prometheus) |
@ -275,13 +273,6 @@ dependency as follows, replacing `{{artifact-id}}` with the value from the "Arti
| [JDK Sender](./exporters/sender/okhttp) | Java 11+ native HttpClient implementation of HttpSender (internal) | `opentelemetry-exporter-sender-jdk` | <!--VERSION_UNSTABLE-->1.34.0-alpha<!--/VERSION_UNSTABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-sender-jdk.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-sender-jdk) | |
| [gRPC ManagedChannel Sender](./exporters/sender/grpc-managed-channel) | gRPC ManagedChannel implementation of GrpcSender (internal) | `opentelemetry-exporter-sender-grpc-managed-channel` | <!--VERSION_STABLE-->1.34.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-sender-grpc-managed-channel.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-sender-grpc-managed-channel) | |
**[1]**: Jaeger now
has [native support for OTLP](https://opentelemetry.io/blog/2022/jaeger-native-otlp/) and jaeger
exporters are now deprecated. `opentelemetry-exporter-jaeger-thrift` will continue to be published
until 1.34.0 (January 2024) but no new PRs will be accepted except security related bugfixes. After
1.34.0, `io.opentelemetry:opentelemetry-bom` will reference the last published version, but no
additional versions will be published.
### SDK Extensions
| Component | Description | Artifact ID | Version | Javadoc |

View File

@ -98,9 +98,6 @@ tasks.named<JacocoReport>("jacocoTestReport") {
// Exclude mrjar (jacoco complains), shaded, and generated code
!it.absolutePath.contains("META-INF/versions/") &&
!it.absolutePath.contains("/internal/shaded/") &&
!it.absolutePath.contains("io/opentelemetry/proto/") &&
!it.absolutePath.contains("io/opentelemetry/exporter/jaeger/proto/") &&
!it.absolutePath.contains("io/opentelemetry/exporter/jaeger/internal/protobuf/") &&
!it.absolutePath.contains("io/opentelemetry/sdk/extension/trace/jaeger/proto/") &&
!it.absolutePath.contains("AutoValue_")
},

View File

@ -14,3 +14,5 @@ otelBom.addFallback("opentelemetry-extension-annotations", "1.18.0")
otelBom.addFallback("opentelemetry-sdk-extension-resources", "1.19.0")
otelBom.addFallback("opentelemetry-sdk-extension-aws", "1.19.0")
otelBom.addFallback("opentelemetry-extension-aws", "1.20.1")
// NOTE: opentelemetry-exporter-jaeger and opentelemetry-exporter-jaeger-thift are omitted because
// they contain dependencies on internal classes, which may have breaking API changes preventing compilation.

View File

@ -1,3 +0,0 @@
# OpenTelemetry - Jaeger Proto (DEPRECATED)
> **NOTICE**: External use of this artifact is deprecated.

View File

@ -1,25 +0,0 @@
plugins {
id("otel.protobuf-conventions")
id("otel.animalsniffer-conventions")
}
description = "OpenTelemetry - Jaeger Exporter Proto (Internal Use Only)"
otelJava.moduleName.set("io.opentelemetry.exporter.jaeger.proto")
dependencies {
api("com.google.protobuf:protobuf-java")
compileOnly("io.grpc:grpc-api")
compileOnly("io.grpc:grpc-protobuf")
compileOnly("io.grpc:grpc-stub")
}
tasks {
compileJava {
with(options) {
// Generated code so can't control serialization.
compilerArgs.add("-Xlint:-serial")
}
}
}

View File

@ -1,23 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
syntax="proto3";
package jaeger.api_v2;
import "jaeger/api_v2/model.proto";
option java_package = "io.opentelemetry.exporter.jaeger.proto.api_v2";
message PostSpansRequest {
Batch batch = 1;
}
message PostSpansResponse {
}
service CollectorService {
rpc PostSpans(PostSpansRequest) returns (PostSpansResponse) {}
}

View File

@ -1,89 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
syntax="proto3";
package jaeger.api_v2;
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
option java_package = "io.opentelemetry.exporter.jaeger.proto.api_v2";
enum ValueType {
STRING = 0;
BOOL = 1;
INT64 = 2;
FLOAT64 = 3;
BINARY = 4;
};
message Log {
google.protobuf.Timestamp timestamp = 1;
repeated KeyValue fields = 2;
}
message KeyValue {
string key = 1;
ValueType v_type = 2;
string v_str = 3;
bool v_bool = 4;
int64 v_int64 = 5;
double v_float64 = 6;
bytes v_binary = 7;
}
enum SpanRefType {
CHILD_OF = 0;
FOLLOWS_FROM = 1;
};
message SpanRef {
bytes trace_id = 1;
bytes span_id = 2;
SpanRefType ref_type = 3;
}
message Process {
string service_name = 1;
repeated KeyValue tags = 2;
}
message Span {
bytes trace_id = 1;
bytes span_id = 2;
string operation_name = 3;
repeated SpanRef references = 4;
uint32 flags = 5;
google.protobuf.Timestamp start_time = 6;
google.protobuf.Duration duration = 7;
repeated KeyValue tags = 8;
repeated Log logs = 9;
Process process = 10;
string process_id = 11;
repeated string warnings = 12;
}
message Trace {
message ProcessMapping {
string process_id = 1;
Process process = 2;
}
repeated Span spans = 1;
repeated ProcessMapping process_map = 2;
repeated string warnings = 3;
}
message Batch {
repeated Span spans = 1;
Process process = 2;
}
message DependencyLink {
string parent = 1;
string child = 2;
uint64 call_count = 3;
string source = 4;
}

View File

@ -1,58 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
// Includes work from:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package io.opentelemetry.internal;
option java_package = "io.opentelemetry.exporter.jaeger.internal.protobuf";
option java_outer_classname = "TimeProto";
option java_multiple_files = true;
// Copied from google.protobuf.Timestamp to provide access to the wire format.
message Time {
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
int64 seconds = 1;
// Non-negative fractions of a second at nanosecond resolution. Negative
// second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999
// inclusive.
int32 nanos = 2;
}

View File

@ -1,27 +0,0 @@
plugins {
id("otel.java-conventions")
id("otel.publish-conventions")
id("otel.animalsniffer-conventions")
}
description = "OpenTelemetry - Jaeger Thrift Exporter"
otelJava.moduleName.set("io.opentelemetry.exporter.jaeger.thrift")
dependencies {
api(project(":sdk:all"))
implementation(project(":sdk:all"))
implementation("com.fasterxml.jackson.jr:jackson-jr-objects")
implementation("io.jaegertracing:jaeger-client") {
exclude("com.google.code.gson", "gson")
}
testImplementation("com.fasterxml.jackson.jr:jackson-jr-stree")
testImplementation("org.testcontainers:junit-jupiter")
testImplementation("com.squareup.okhttp3:okhttp")
testImplementation("com.google.guava:guava-testlib")
testImplementation(project(":sdk:testing"))
}

View File

@ -1,277 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger.thrift;
import static io.opentelemetry.api.common.AttributeKey.booleanKey;
import com.fasterxml.jackson.jr.ob.JSON;
import io.jaegertracing.thriftjava.Log;
import io.jaegertracing.thriftjava.Span;
import io.jaegertracing.thriftjava.SpanRef;
import io.jaegertracing.thriftjava.SpanRefType;
import io.jaegertracing.thriftjava.Tag;
import io.jaegertracing.thriftjava.TagType;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.sdk.trace.data.EventData;
import io.opentelemetry.sdk.trace.data.LinkData;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.annotation.concurrent.ThreadSafe;
/** Adapts OpenTelemetry objects to Jaeger objects. */
@ThreadSafe
final class Adapter {
static final AttributeKey<Boolean> KEY_ERROR = booleanKey("error");
static final String KEY_LOG_EVENT = "event";
static final String KEY_EVENT_DROPPED_ATTRIBUTES_COUNT = "otel.event.dropped_attributes_count";
static final String KEY_DROPPED_ATTRIBUTES_COUNT = "otel.dropped_attributes_count";
static final String KEY_DROPPED_EVENTS_COUNT = "otel.dropped_events_count";
static final String KEY_SPAN_KIND = "span.kind";
static final String KEY_SPAN_STATUS_MESSAGE = "otel.status_message";
static final String KEY_SPAN_STATUS_CODE = "otel.status_code";
static final String KEY_INSTRUMENTATION_SCOPE_NAME = "otel.scope.name";
static final String KEY_INSTRUMENTATION_SCOPE_VERSION = "otel.scope.version";
static final String KEY_INSTRUMENTATION_LIBRARY_NAME = "otel.library.name";
static final String KEY_INSTRUMENTATION_LIBRARY_VERSION = "otel.library.version";
private Adapter() {}
/**
* Converts a list of {@link SpanData} into a collection of Jaeger's {@link Span}.
*
* @param spans the list of spans to be converted
* @return the collection of Jaeger spans
* @see #toJaeger(SpanData)
*/
static List<Span> toJaeger(Collection<SpanData> spans) {
return spans.stream().map(Adapter::toJaeger).collect(Collectors.toList());
}
/**
* Converts a single {@link SpanData} into a Jaeger's {@link Span}.
*
* @param span the span to be converted
* @return the Jaeger span
*/
static Span toJaeger(SpanData span) {
Span target = new Span();
long traceIdHigh = traceIdAsLongHigh(span.getTraceId());
long traceIdLow = traceIdAsLongLow(span.getTraceId());
target.setTraceIdHigh(traceIdHigh);
target.setTraceIdLow(traceIdLow);
target.setSpanId(spanIdAsLong(span.getSpanId()));
target.setOperationName(span.getName());
target.setStartTime(TimeUnit.NANOSECONDS.toMicros(span.getStartEpochNanos()));
target.setDuration(
TimeUnit.NANOSECONDS.toMicros(span.getEndEpochNanos() - span.getStartEpochNanos()));
List<Tag> tags = toTags(span.getAttributes());
int droppedAttributes = span.getTotalAttributeCount() - span.getAttributes().size();
if (droppedAttributes > 0) {
tags.add(new Tag(KEY_DROPPED_ATTRIBUTES_COUNT, TagType.LONG).setVLong(droppedAttributes));
}
target.setLogs(toJaegerLogs(span.getEvents()));
int droppedEvents = span.getTotalRecordedEvents() - span.getEvents().size();
if (droppedEvents > 0) {
tags.add(new Tag(KEY_DROPPED_EVENTS_COUNT, TagType.LONG).setVLong(droppedEvents));
}
List<SpanRef> references = toSpanRefs(span.getLinks());
// add the parent span
if (span.getParentSpanContext().isValid()) {
long parentSpanId = spanIdAsLong(span.getParentSpanId());
references.add(new SpanRef(SpanRefType.CHILD_OF, traceIdLow, traceIdHigh, parentSpanId));
target.setParentSpanId(parentSpanId);
}
target.setReferences(references);
if (span.getKind() != SpanKind.INTERNAL) {
tags.add(
new Tag(KEY_SPAN_KIND, TagType.STRING)
.setVStr(span.getKind().name().toLowerCase(Locale.ROOT)));
}
if (!span.getStatus().getDescription().isEmpty()) {
tags.add(
new Tag(KEY_SPAN_STATUS_MESSAGE, TagType.STRING)
.setVStr(span.getStatus().getDescription()));
}
if (span.getStatus().getStatusCode() != StatusCode.UNSET) {
tags.add(
new Tag(KEY_SPAN_STATUS_CODE, TagType.STRING)
.setVStr(span.getStatus().getStatusCode().name()));
}
tags.add(
new Tag(KEY_INSTRUMENTATION_SCOPE_NAME, TagType.STRING)
.setVStr(span.getInstrumentationScopeInfo().getName()));
// Include instrumentation library name for backwards compatibility
tags.add(
new Tag(KEY_INSTRUMENTATION_LIBRARY_NAME, TagType.STRING)
.setVStr(span.getInstrumentationScopeInfo().getName()));
if (span.getInstrumentationScopeInfo().getVersion() != null) {
tags.add(
new Tag(KEY_INSTRUMENTATION_SCOPE_VERSION, TagType.STRING)
.setVStr(span.getInstrumentationScopeInfo().getVersion()));
// Include instrumentation library name for backwards compatibility
tags.add(
new Tag(KEY_INSTRUMENTATION_LIBRARY_VERSION, TagType.STRING)
.setVStr(span.getInstrumentationScopeInfo().getVersion()));
}
if (span.getStatus().getStatusCode() == StatusCode.ERROR) {
tags.add(toTag(KEY_ERROR, true));
}
target.setTags(tags);
return target;
}
/**
* Converts {@link EventData}s into a collection of Jaeger's {@link Log}.
*
* @param timedEvents the timed events to be converted
* @return a collection of Jaeger logs
* @see #toJaegerLog(EventData)
*/
// VisibleForTesting
static List<Log> toJaegerLogs(List<EventData> timedEvents) {
return timedEvents.stream().map(Adapter::toJaegerLog).collect(Collectors.toList());
}
/**
* Converts a {@link EventData} into Jaeger's {@link Log}.
*
* @param event the timed event to be converted
* @return a Jaeger log
*/
// VisibleForTesting
static Log toJaegerLog(EventData event) {
Log result = new Log();
result.setTimestamp(TimeUnit.NANOSECONDS.toMicros(event.getEpochNanos()));
result.addToFields(new Tag(KEY_LOG_EVENT, TagType.STRING).setVStr(event.getName()));
int droppedAttributesCount = event.getDroppedAttributesCount();
if (droppedAttributesCount > 0) {
result.addToFields(
new Tag(KEY_EVENT_DROPPED_ATTRIBUTES_COUNT, TagType.LONG)
.setVLong(droppedAttributesCount));
}
List<Tag> attributeTags = toTags(event.getAttributes());
for (Tag attributeTag : attributeTags) {
result.addToFields(attributeTag);
}
return result;
}
/**
* Converts a map of attributes into a collection of Jaeger's {@link Tag}.
*
* @param attributes the span attributes
* @return a collection of Jaeger key values
* @see #toTag
*/
static List<Tag> toTags(Attributes attributes) {
List<Tag> results = new ArrayList<>();
attributes.forEach((key, value) -> results.add(toTag(key, value)));
return results;
}
/**
* Converts the given {@link AttributeKey} and value into Jaeger's {@link Tag}.
*
* @param key the entry key as string
* @param value the entry value
* @return a Jaeger key value
*/
// VisibleForTesting
static Tag toTag(AttributeKey<?> key, Object value) {
switch (key.getType()) {
case STRING:
return new Tag(key.getKey(), TagType.STRING).setVStr((String) value);
case LONG:
return new Tag(key.getKey(), TagType.LONG).setVLong((long) value);
case BOOLEAN:
return new Tag(key.getKey(), TagType.BOOL).setVBool((boolean) value);
case DOUBLE:
return new Tag(key.getKey(), TagType.DOUBLE).setVDouble((double) value);
default:
try {
return new Tag(key.getKey(), TagType.STRING).setVStr(JSON.std.asString(value));
} catch (IOException e) {
// Can't have an exception serializing a plain Java object to a String. Add an exception
// mostly to satisfy the compiler.
throw new UncheckedIOException(
"Error serializing a plain Java object to String. "
+ "This is a bug in the OpenTelemetry library.",
e);
}
}
}
/**
* Converts {@link LinkData}s into a collection of Jaeger's {@link SpanRef}.
*
* @param links the span's links property to be converted
* @return a collection of Jaeger span references
*/
// VisibleForTesting
static List<SpanRef> toSpanRefs(List<LinkData> links) {
List<SpanRef> spanRefs = new ArrayList<>(links.size());
for (LinkData link : links) {
spanRefs.add(toSpanRef(link));
}
return spanRefs;
}
/**
* Converts a single {@link LinkData} into a Jaeger's {@link SpanRef}.
*
* @param link the OpenTelemetry link to be converted
* @return the Jaeger span reference
*/
// VisibleForTesting
static SpanRef toSpanRef(LinkData link) {
// we can assume that all links are *follows from*
// https://github.com/open-telemetry/opentelemetry-java/issues/475
// https://github.com/open-telemetry/opentelemetry-java/pull/481/files#r312577862
return new SpanRef(
SpanRefType.FOLLOWS_FROM,
traceIdAsLongLow(link.getSpanContext().getTraceId()),
traceIdAsLongHigh(link.getSpanContext().getTraceId()),
spanIdAsLong(link.getSpanContext().getSpanId()));
}
private static long traceIdAsLongHigh(String traceId) {
return new BigInteger(traceId.substring(0, 16), 16).longValue();
}
private static long traceIdAsLongLow(String traceId) {
return new BigInteger(traceId.substring(16, 32), 16).longValue();
}
private static long spanIdAsLong(String spanId) {
return new BigInteger(spanId, 16).longValue();
}
}

View File

@ -1,170 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger.thrift;
import io.jaegertracing.internal.exceptions.SenderException;
import io.jaegertracing.thrift.internal.senders.ThriftSender;
import io.jaegertracing.thriftjava.Process;
import io.jaegertracing.thriftjava.Span;
import io.jaegertracing.thriftjava.Tag;
import io.jaegertracing.thriftjava.TagType;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.internal.ThrottlingLogger;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.annotation.concurrent.ThreadSafe;
/**
* Exports spans to Jaeger via Thrift, using Jaeger's thrift model.
*
* @deprecated Use {@code OtlpGrpcSpanExporter} or {@code OtlpHttpSpanExporter} from <a
* href="https://github.com/open-telemetry/opentelemetry-java/tree/main/exporters/otlp/all">opentelemetry-exporter-otlp</a>
* instead.
*/
@ThreadSafe
@Deprecated
public final class JaegerThriftSpanExporter implements SpanExporter {
private static final AttributeKey<String> SERVICE_NAME = AttributeKey.stringKey("service.name");
static final String DEFAULT_ENDPOINT = "http://localhost:14268/api/traces";
private static final String DEFAULT_HOST_NAME = "unknown";
private static final String CLIENT_VERSION_KEY = "jaeger.version";
private static final String CLIENT_VERSION_VALUE = "opentelemetry-java";
private static final String HOSTNAME_KEY = "hostname";
private static final String IP_KEY = "ip";
private static final String IP_DEFAULT = "0.0.0.0";
private final ThrottlingLogger logger =
new ThrottlingLogger(Logger.getLogger(JaegerThriftSpanExporter.class.getName()));
private final AtomicBoolean isShutdown = new AtomicBoolean();
private final ThriftSender thriftSender;
private final Process process;
/**
* Creates a new Jaeger gRPC Span Reporter with the given name, using the given channel.
*
* @param thriftSender The sender used for sending the data.
*/
JaegerThriftSpanExporter(ThriftSender thriftSender) {
this.thriftSender = thriftSender;
String hostname;
String ipv4;
try {
hostname = InetAddress.getLocalHost().getHostName();
ipv4 = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
hostname = DEFAULT_HOST_NAME;
ipv4 = IP_DEFAULT;
}
Tag clientTag = new Tag(CLIENT_VERSION_KEY, TagType.STRING).setVStr(CLIENT_VERSION_VALUE);
Tag ipv4Tag = new Tag(IP_KEY, TagType.STRING).setVStr(ipv4);
Tag hostnameTag = new Tag(HOSTNAME_KEY, TagType.STRING).setVStr(hostname);
this.process = new Process();
this.process.addToTags(clientTag);
this.process.addToTags(ipv4Tag);
this.process.addToTags(hostnameTag);
}
/**
* Submits all the given spans in a single batch to the Jaeger collector.
*
* @param spans the list of sampled Spans to be exported.
* @return the result of the operation
*/
@Override
public CompletableResultCode export(Collection<SpanData> spans) {
if (isShutdown.get()) {
return CompletableResultCode.ofFailure();
}
Map<Process, List<Span>> batches =
spans.stream().collect(Collectors.groupingBy(SpanData::getResource)).entrySet().stream()
.collect(
Collectors.toMap(
entry -> createProcess(entry.getKey()),
entry -> Adapter.toJaeger(entry.getValue())));
List<CompletableResultCode> batchResults = new ArrayList<>(batches.size());
batches.forEach(
(process, jaegerSpans) -> {
CompletableResultCode batchResult = new CompletableResultCode();
batchResults.add(batchResult);
try {
// todo: consider making truly async
thriftSender.send(process, jaegerSpans);
batchResult.succeed();
} catch (SenderException e) {
logger.log(Level.WARNING, "Failed to export spans", e);
batchResult.fail();
}
});
return CompletableResultCode.ofAll(batchResults);
}
private Process createProcess(Resource resource) {
Process result = new Process(this.process);
String serviceName = resource.getAttribute(SERVICE_NAME);
if (serviceName == null || serviceName.isEmpty()) {
serviceName = Resource.getDefault().getAttribute(SERVICE_NAME);
}
// In practice should never be null unless the default Resource spec is changed.
if (serviceName != null) {
result.setServiceName(serviceName);
}
List<Tag> tags = Adapter.toTags(resource.getAttributes());
tags.forEach(result::addToTags);
return result;
}
/**
* The Jaeger exporter does not batch spans, so this method will immediately return with success.
*
* @return always Success
*/
@Override
public CompletableResultCode flush() {
return CompletableResultCode.ofSuccess();
}
/**
* Returns a new builder instance for this exporter.
*
* @return a new builder instance for this exporter.
*/
public static JaegerThriftSpanExporterBuilder builder() {
return new JaegerThriftSpanExporterBuilder();
}
/**
* Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately
* cancelled.
*/
@Override
public CompletableResultCode shutdown() {
if (!isShutdown.compareAndSet(false, true)) {
logger.log(Level.INFO, "Calling shutdown() multiple times.");
}
return CompletableResultCode.ofSuccess();
}
}

View File

@ -1,69 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger.thrift;
import io.jaegertracing.thrift.internal.senders.HttpSender;
import io.jaegertracing.thrift.internal.senders.ThriftSender;
import javax.annotation.Nullable;
import org.apache.thrift.transport.TTransportException;
/**
* Builder utility for this exporter.
*
* @deprecated Use {@code OtlpGrpcSpanExporter} or {@code OtlpHttpSpanExporter} from <a
* href="https://github.com/open-telemetry/opentelemetry-java/tree/main/exporters/otlp/all">opentelemetry-exporter-otlp</a>
* instead.
*/
@Deprecated
public final class JaegerThriftSpanExporterBuilder {
private String endpoint = JaegerThriftSpanExporter.DEFAULT_ENDPOINT;
@Nullable private ThriftSender thriftSender;
/**
* Explicitly set the {@link ThriftSender} instance to use for this Exporter. Will override any
* endpoint that has been set.
*
* @param thriftSender The ThriftSender to use.
* @return this.
*/
public JaegerThriftSpanExporterBuilder setThriftSender(ThriftSender thriftSender) {
this.thriftSender = thriftSender;
return this;
}
/**
* Sets the Jaeger endpoint to connect to. Needs to include the full API path for trace ingest.
*
* <p>Optional, defaults to "http://localhost:14268/api/traces".
*
* @param endpoint The Jaeger endpoint URL, ex. "https://jaegerhost:14268/api/traces".
* @return this.
*/
public JaegerThriftSpanExporterBuilder setEndpoint(String endpoint) {
this.endpoint = endpoint;
return this;
}
/**
* Constructs a new instance of the exporter based on the builder's values.
*
* @return a new exporter's instance.
*/
public JaegerThriftSpanExporter build() {
ThriftSender thriftSender = this.thriftSender;
if (thriftSender == null) {
try {
thriftSender = new HttpSender.Builder(endpoint).build();
} catch (TTransportException e) {
throw new IllegalStateException("Failed to construct a thrift HttpSender.", e);
}
}
return new JaegerThriftSpanExporter(thriftSender);
}
JaegerThriftSpanExporterBuilder() {}
}

View File

@ -1,9 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
@ParametersAreNonnullByDefault
package io.opentelemetry.exporter.jaeger.thrift;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@ -1,363 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger.thrift;
import static io.opentelemetry.api.common.AttributeKey.booleanArrayKey;
import static io.opentelemetry.api.common.AttributeKey.booleanKey;
import static io.opentelemetry.api.common.AttributeKey.doubleArrayKey;
import static io.opentelemetry.api.common.AttributeKey.doubleKey;
import static io.opentelemetry.api.common.AttributeKey.longArrayKey;
import static io.opentelemetry.api.common.AttributeKey.longKey;
import static io.opentelemetry.api.common.AttributeKey.stringArrayKey;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.common.io.BaseEncoding;
import io.jaegertracing.thriftjava.Log;
import io.jaegertracing.thriftjava.SpanRef;
import io.jaegertracing.thriftjava.SpanRefType;
import io.jaegertracing.thriftjava.Tag;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.api.trace.TraceFlags;
import io.opentelemetry.api.trace.TraceState;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.testing.trace.TestSpanData;
import io.opentelemetry.sdk.trace.data.EventData;
import io.opentelemetry.sdk.trace.data.LinkData;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.data.StatusData;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link Adapter}. */
class AdapterTest {
private static final BaseEncoding hex = BaseEncoding.base16().lowerCase();
private static final String LINK_TRACE_ID = "ff000000000000000000000000cba123";
private static final String LINK_SPAN_ID = "0000000000fed456";
private static final String TRACE_ID = "0000000000000000ff00000000abc123";
private static final String SPAN_ID = "ff00000000def456";
private static final String PARENT_SPAN_ID = "0000000000aef789";
@Test
void testThriftSpans() {
long duration = 900; // ms
long startMs = System.currentTimeMillis();
long endMs = startMs + duration;
SpanData span = getSpanData(startMs, endMs, SpanKind.SERVER);
List<SpanData> spans = Collections.singletonList(span);
List<io.jaegertracing.thriftjava.Span> jaegerSpans = Adapter.toJaeger(spans);
// the span contents are checked somewhere else
assertThat(jaegerSpans).hasSize(1);
}
@Test
void testThriftSpan() {
long duration = 900; // ms
long startMs = System.currentTimeMillis();
long endMs = startMs + duration;
SpanData span = getSpanData(startMs, endMs, SpanKind.SERVER, 2, 4);
// test
io.jaegertracing.thriftjava.Span jaegerSpan = Adapter.toJaeger(span);
String rebuildTraceId =
traceIdFromLongs(jaegerSpan.getTraceIdHigh(), jaegerSpan.getTraceIdLow());
assertThat(rebuildTraceId).isEqualTo(span.getTraceId());
assertThat(spanIdFromLong(jaegerSpan.getSpanId())).isEqualTo(span.getSpanId());
assertThat(jaegerSpan.getOperationName()).isEqualTo("GET /api/endpoint");
assertThat(jaegerSpan.getStartTime()).isEqualTo(MILLISECONDS.toMicros(startMs));
assertThat(jaegerSpan.getDuration()).isEqualTo(MILLISECONDS.toMicros(duration));
assertThat(jaegerSpan.getTagsSize()).isEqualTo(8);
assertThat(getValue(jaegerSpan.getTags(), Adapter.KEY_SPAN_KIND).getVStr()).isEqualTo("server");
assertThat(getValue(jaegerSpan.getTags(), Adapter.KEY_SPAN_STATUS_CODE).getVLong())
.isEqualTo(0);
assertThat(getValue(jaegerSpan.getTags(), Adapter.KEY_SPAN_STATUS_MESSAGE).getVStr())
.isEqualTo("ok!");
assertThat(getValue(jaegerSpan.getTags(), Adapter.KEY_DROPPED_EVENTS_COUNT).getVLong())
.isEqualTo(1);
assertThat(getValue(jaegerSpan.getTags(), Adapter.KEY_DROPPED_ATTRIBUTES_COUNT).getVLong())
.isEqualTo(3);
assertThat(jaegerSpan.getLogsSize()).isEqualTo(1);
Log log = jaegerSpan.getLogs().get(0);
assertThat(getValue(log.getFields(), Adapter.KEY_LOG_EVENT).getVStr())
.isEqualTo("the log message");
assertThat(getValue(log.getFields(), "foo").getVStr()).isEqualTo("bar");
assertThat(jaegerSpan.getReferencesSize()).isEqualTo(2);
assertHasFollowsFrom(jaegerSpan);
assertHasParent(jaegerSpan);
}
@Test
void testThriftSpan_internal() {
long duration = 900; // ms
long startMs = System.currentTimeMillis();
long endMs = startMs + duration;
SpanData span = getSpanData(startMs, endMs, SpanKind.INTERNAL);
// test
io.jaegertracing.thriftjava.Span jaegerSpan = Adapter.toJaeger(span);
assertThat(jaegerSpan.getTagsSize()).isEqualTo(5);
assertThat(getValue(jaegerSpan.getTags(), Adapter.KEY_SPAN_KIND)).isNull();
}
@Test
void testJaegerLogs() {
// prepare
EventData eventsData = getTimedEvent();
// test
Collection<Log> logs = Adapter.toJaegerLogs(Collections.singletonList(eventsData));
// verify
assertThat(logs).hasSize(1);
}
@Test
void testJaegerLog() {
// prepare
EventData event = getTimedEvent();
// test
Log log = Adapter.toJaegerLog(event);
// verify
assertThat(log.getFieldsSize()).isEqualTo(2);
assertThat(getValue(log.getFields(), Adapter.KEY_LOG_EVENT).getVStr())
.isEqualTo("the log message");
assertThat(getValue(log.getFields(), "foo").getVStr()).isEqualTo("bar");
assertThat(getValue(log.getFields(), Adapter.KEY_EVENT_DROPPED_ATTRIBUTES_COUNT)).isNull();
}
@Test
void jaegerLog_droppedAttributes() {
EventData event = getTimedEvent(3);
// test
Log log = Adapter.toJaegerLog(event);
// verify
assertThat(getValue(log.getFields(), Adapter.KEY_EVENT_DROPPED_ATTRIBUTES_COUNT).getVLong())
.isEqualTo(2);
}
@Test
void testKeyValue() {
// test
Tag kvB = Adapter.toTag(booleanKey("valueB"), true);
Tag kvD = Adapter.toTag(doubleKey("valueD"), 1.);
Tag kvI = Adapter.toTag(longKey("valueI"), 2L);
Tag kvS = Adapter.toTag(stringKey("valueS"), "foobar");
Tag kvArrayB = Adapter.toTag(booleanArrayKey("valueArrayB"), Arrays.asList(true, false));
Tag kvArrayD = Adapter.toTag(doubleArrayKey("valueArrayD"), Arrays.asList(1.2345, 6.789));
Tag kvArrayI = Adapter.toTag(longArrayKey("valueArrayI"), Arrays.asList(12345L, 67890L));
Tag kvArrayS = Adapter.toTag(stringArrayKey("valueArrayS"), Arrays.asList("foobar", "barfoo"));
// verify
assertThat(kvB.isVBool()).isTrue();
assertThat(kvD.getVDouble()).isEqualTo(1);
assertThat(kvI.getVLong()).isEqualTo(2);
assertThat(kvS.getVStr()).isEqualTo("foobar");
assertThat(kvArrayB.getVStr()).isEqualTo("[true,false]");
assertThat(kvArrayD.getVStr()).isEqualTo("[1.2345,6.789]");
assertThat(kvArrayI.getVStr()).isEqualTo("[12345,67890]");
assertThat(kvArrayS.getVStr()).isEqualTo("[\"foobar\",\"barfoo\"]");
}
@Test
void testSpanRefs() {
// prepare
LinkData link =
LinkData.create(createSpanContext("00000000000000000000000000cba123", "0000000000fed456"));
// test
Collection<SpanRef> spanRefs = Adapter.toSpanRefs(Collections.singletonList(link));
// verify
assertThat(spanRefs).hasSize(1); // the actual span ref is tested in another test
}
@Test
void testSpanRef() {
// prepare
LinkData link = LinkData.create(createSpanContext(TRACE_ID, SPAN_ID));
// test
SpanRef spanRef = Adapter.toSpanRef(link);
// verify
assertThat(spanIdFromLong(spanRef.getSpanId())).isEqualTo(SPAN_ID);
assertThat(traceIdFromLongs(spanRef.getTraceIdHigh(), spanRef.getTraceIdLow()))
.isEqualTo(TRACE_ID);
assertThat(spanRef.getRefType()).isEqualTo(SpanRefType.FOLLOWS_FROM);
}
@Test
void testStatusNotUnset() {
long startMs = System.currentTimeMillis();
long endMs = startMs + 900;
SpanData span =
TestSpanData.builder()
.setHasEnded(true)
.setSpanContext(createSpanContext(TRACE_ID, SPAN_ID))
.setName("GET /api/endpoint")
.setStartEpochNanos(MILLISECONDS.toNanos(startMs))
.setEndEpochNanos(MILLISECONDS.toNanos(endMs))
.setKind(SpanKind.SERVER)
.setStatus(StatusData.error())
.setTotalRecordedEvents(0)
.setTotalRecordedLinks(0)
.build();
assertThat(Adapter.toJaeger(span)).isNotNull();
}
@Test
void testSpanError() {
Attributes attributes =
Attributes.of(
stringKey("error.type"),
this.getClass().getName(),
stringKey("error.message"),
"server error");
long startMs = System.currentTimeMillis();
long endMs = startMs + 900;
SpanData span =
TestSpanData.builder()
.setHasEnded(true)
.setSpanContext(createSpanContext(TRACE_ID, SPAN_ID))
.setName("GET /api/endpoint")
.setStartEpochNanos(MILLISECONDS.toNanos(startMs))
.setEndEpochNanos(MILLISECONDS.toNanos(endMs))
.setKind(SpanKind.SERVER)
.setStatus(StatusData.error())
.setAttributes(attributes)
.setTotalRecordedEvents(0)
.setTotalRecordedLinks(0)
.build();
io.jaegertracing.thriftjava.Span jaegerSpan = Adapter.toJaeger(span);
assertThat(getValue(jaegerSpan.getTags(), "error.type").getVStr())
.isEqualTo(this.getClass().getName());
assertThat(getValue(jaegerSpan.getTags(), "error").isVBool()).isTrue();
}
private static EventData getTimedEvent() {
return getTimedEvent(-1);
}
private static EventData getTimedEvent(int totalAttributeCount) {
long epochNanos = MILLISECONDS.toNanos(System.currentTimeMillis());
Attributes attributes = Attributes.of(stringKey("foo"), "bar");
if (totalAttributeCount <= 0) {
totalAttributeCount = attributes.size();
}
return EventData.create(epochNanos, "the log message", attributes, totalAttributeCount);
}
private static SpanData getSpanData(long startMs, long endMs, SpanKind kind) {
return getSpanData(startMs, endMs, kind, 1, 1);
}
private static SpanData getSpanData(
long startMs, long endMs, SpanKind kind, int totalRecordedEvents, int totalAttributeCount) {
Attributes attributes = Attributes.of(booleanKey("valueB"), true);
LinkData link = LinkData.create(createSpanContext(LINK_TRACE_ID, LINK_SPAN_ID), attributes);
return TestSpanData.builder()
.setHasEnded(true)
.setSpanContext(createSpanContext(TRACE_ID, SPAN_ID))
.setParentSpanContext(
SpanContext.create(
TRACE_ID, PARENT_SPAN_ID, TraceFlags.getDefault(), TraceState.getDefault()))
.setName("GET /api/endpoint")
.setStartEpochNanos(MILLISECONDS.toNanos(startMs))
.setEndEpochNanos(MILLISECONDS.toNanos(endMs))
.setAttributes(Attributes.of(booleanKey("valueB"), true))
.setTotalAttributeCount(totalAttributeCount)
.setEvents(Collections.singletonList(getTimedEvent()))
.setTotalRecordedEvents(totalRecordedEvents)
.setLinks(Collections.singletonList(link))
.setTotalRecordedLinks(1)
.setKind(kind)
.setResource(Resource.create(Attributes.empty()))
.setStatus(StatusData.create(StatusCode.OK, "ok!"))
.build();
}
private static SpanContext createSpanContext(String traceId, String spanId) {
return SpanContext.create(traceId, spanId, TraceFlags.getDefault(), TraceState.getDefault());
}
@Nullable
private static Tag getValue(List<Tag> tagsList, String s) {
for (Tag kv : tagsList) {
if (kv.getKey().equals(s)) {
return kv;
}
}
return null;
}
private static void assertHasFollowsFrom(io.jaegertracing.thriftjava.Span jaegerSpan) {
boolean found = false;
for (SpanRef spanRef : jaegerSpan.getReferences()) {
if (SpanRefType.FOLLOWS_FROM.equals(spanRef.getRefType())) {
assertThat(traceIdFromLongs(spanRef.getTraceIdHigh(), spanRef.getTraceIdLow()))
.isEqualTo(LINK_TRACE_ID);
assertThat(spanIdFromLong(spanRef.getSpanId())).isEqualTo(LINK_SPAN_ID);
found = true;
}
}
assertThat(found).isTrue();
}
private static void assertHasParent(io.jaegertracing.thriftjava.Span jaegerSpan) {
boolean found = false;
for (SpanRef spanRef : jaegerSpan.getReferences()) {
if (SpanRefType.CHILD_OF.equals(spanRef.getRefType())) {
assertThat(traceIdFromLongs(spanRef.getTraceIdHigh(), spanRef.getTraceIdLow()))
.isEqualTo(TRACE_ID);
assertThat(spanIdFromLong(spanRef.getSpanId())).isEqualTo(PARENT_SPAN_ID);
found = true;
}
}
assertThat(found).isTrue();
assertThat(spanIdFromLong(jaegerSpan.getParentSpanId())).isEqualTo(PARENT_SPAN_ID);
}
private static String traceIdFromLongs(long high, long low) {
return hex.encode(
ByteBuffer.allocate(16).order(ByteOrder.BIG_ENDIAN).putLong(high).putLong(low).array());
}
private static String spanIdFromLong(long id) {
return hex.encode(ByteBuffer.allocate(8).order(ByteOrder.BIG_ENDIAN).putLong(id).array());
}
}

View File

@ -1,135 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger.thrift;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.jr.ob.JSON;
import com.fasterxml.jackson.jr.stree.JacksonJrsTreeCodec;
import io.jaegertracing.thrift.internal.senders.UdpSender;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import java.time.Duration;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.thrift.transport.TTransportException;
import org.awaitility.Awaitility;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.PullPolicy;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@Testcontainers(disabledWithoutDocker = true)
@SuppressWarnings("deprecation") // Testing deprecated code
class JaegerThriftIntegrationTest {
private static final OkHttpClient client = new OkHttpClient();
private static final int QUERY_PORT = 16686;
private static final int THRIFT_HTTP_PORT = 14268;
private static final int THRIFT_UDP_PORT = 6831;
private static final int HEALTH_PORT = 14269;
private static final String SERVICE_NAME = "E2E-test";
private static final String JAEGER_URL = "http://localhost";
@Container
public static final GenericContainer<?> jaegerContainer =
new GenericContainer<>("ghcr.io/open-telemetry/opentelemetry-java/jaeger:1.32")
.withImagePullPolicy(PullPolicy.alwaysPull())
.withExposedPorts(THRIFT_HTTP_PORT, THRIFT_UDP_PORT, QUERY_PORT, HEALTH_PORT)
.withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger("jaeger")))
.waitingFor(Wait.forHttp("/").forPort(HEALTH_PORT));
@ParameterizedTest
@ValueSource(booleans = {false, true})
void testJaegerIntegration(boolean udp) {
OpenTelemetry openTelemetry = initOpenTelemetry(udp);
imitateWork(openTelemetry);
Awaitility.await()
.atMost(Duration.ofSeconds(30))
.until(JaegerThriftIntegrationTest::assertJaegerHasATrace);
}
private static OpenTelemetry initOpenTelemetry(boolean udp) {
JaegerThriftSpanExporterBuilder jaegerExporter = JaegerThriftSpanExporter.builder();
if (udp) {
int mappedPort = jaegerContainer.getMappedPort(THRIFT_UDP_PORT);
try {
jaegerExporter.setThriftSender(new UdpSender("localhost", mappedPort, 0));
} catch (TTransportException e) {
throw new IllegalStateException(e);
}
} else {
int mappedPort = jaegerContainer.getMappedPort(THRIFT_HTTP_PORT);
jaegerExporter.setEndpoint(JAEGER_URL + ":" + mappedPort + "/api/traces");
}
return OpenTelemetrySdk.builder()
.setTracerProvider(
SdkTracerProvider.builder()
.addSpanProcessor(SimpleSpanProcessor.create(jaegerExporter.build()))
.setResource(
Resource.getDefault().toBuilder()
.put(stringKey("service.name"), SERVICE_NAME)
.build())
.build())
.build();
}
private void imitateWork(OpenTelemetry openTelemetry) {
Span span =
openTelemetry.getTracer(getClass().getCanonicalName()).spanBuilder("Test span").startSpan();
span.addEvent("some event");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
span.end();
}
private static boolean assertJaegerHasATrace() {
try {
Integer mappedPort = jaegerContainer.getMappedPort(QUERY_PORT);
String url =
String.format(
"%s/api/traces?service=%s",
String.format(JAEGER_URL + ":%d", mappedPort), SERVICE_NAME);
Request request =
new Request.Builder()
.url(url)
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.build();
TreeNode json;
try (Response response = client.newCall(request).execute()) {
json =
JSON.builder()
.treeCodec(new JacksonJrsTreeCodec())
.build()
.treeFrom(response.body().byteStream());
}
return json.get("data").get(0).get("traceID") != null;
} catch (Exception e) {
return false;
}
}
}

View File

@ -1,274 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger.thrift;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import io.github.netmikey.logunit.api.LogCapturer;
import io.jaegertracing.internal.exceptions.SenderException;
import io.jaegertracing.thrift.internal.senders.ThriftSender;
import io.jaegertracing.thriftjava.Process;
import io.jaegertracing.thriftjava.Span;
import io.jaegertracing.thriftjava.SpanRef;
import io.jaegertracing.thriftjava.SpanRefType;
import io.jaegertracing.thriftjava.Tag;
import io.jaegertracing.thriftjava.TagType;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.TraceFlags;
import io.opentelemetry.api.trace.TraceState;
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.testing.trace.TestSpanData;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.data.StatusData;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
@SuppressWarnings("deprecation") // Testing deprecated code
class JaegerThriftSpanExporterTest {
private static final String TRACE_ID = "a0000000000000000000000000abc123";
private static final long TRACE_ID_HIGH = 0xa000000000000000L;
private static final long TRACE_ID_LOW = 0x0000000000abc123L;
private static final String SPAN_ID = "00000f0000def456";
private static final long SPAN_ID_LONG = 0x00000f0000def456L;
private static final String SPAN_ID_2 = "00a0000000aef789";
private static final long SPAN_ID_2_LONG = 0x00a0000000aef789L;
private static final SpanContext SPAN_CONTEXT =
SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TraceState.getDefault());
private static final SpanContext SPAN_CONTEXT_2 =
SpanContext.create(TRACE_ID, SPAN_ID_2, TraceFlags.getDefault(), TraceState.getDefault());
private static final Duration DURATION = Duration.ofMillis(900);
@RegisterExtension
LogCapturer logs = LogCapturer.create().captureForType(JaegerThriftSpanExporter.class);
private JaegerThriftSpanExporter exporter;
@Mock private ThriftSender thriftSender;
@BeforeEach
void beforeEach() {
exporter = JaegerThriftSpanExporter.builder().setThriftSender(thriftSender).build();
}
@Test
void testExport() throws SenderException, UnknownHostException {
SpanData span =
testSpanData(
Resource.create(
Attributes.of(
stringKey("service.name"),
"myServiceName",
stringKey("resource-attr-key"),
"resource-attr-value")),
"GET /api/endpoint",
SPAN_CONTEXT,
SPAN_CONTEXT_2);
// test
CompletableResultCode result = exporter.export(Collections.singletonList(span));
result.join(1, TimeUnit.SECONDS);
assertThat(result.isSuccess()).isEqualTo(true);
// verify
Process expectedProcess = new Process("myServiceName");
expectedProcess.addToTags(
new Tag("jaeger.version", TagType.STRING).setVStr("opentelemetry-java"));
expectedProcess.addToTags(
new Tag("ip", TagType.STRING).setVStr(InetAddress.getLocalHost().getHostAddress()));
expectedProcess.addToTags(
new Tag("hostname", TagType.STRING).setVStr(InetAddress.getLocalHost().getHostName()));
expectedProcess.addToTags(
new Tag("resource-attr-key", TagType.STRING).setVStr("resource-attr-value"));
expectedProcess.addToTags(new Tag("service.name", TagType.STRING).setVStr("myServiceName"));
Span expectedSpan =
new Span()
.setTraceIdHigh(TRACE_ID_HIGH)
.setTraceIdLow(TRACE_ID_LOW)
.setSpanId(SPAN_ID_LONG)
.setOperationName("GET /api/endpoint")
.setReferences(
Collections.singletonList(
new SpanRef()
.setSpanId(SPAN_ID_2_LONG)
.setTraceIdHigh(TRACE_ID_HIGH)
.setTraceIdLow(TRACE_ID_LOW)
.setRefType(SpanRefType.CHILD_OF)))
.setParentSpanId(SPAN_ID_2_LONG)
.setStartTime(TimeUnit.NANOSECONDS.toMicros(span.getStartEpochNanos()))
.setDuration(DURATION.toMillis() * 1000)
.setLogs(Collections.emptyList());
expectedSpan.addToTags(new Tag("span.kind", TagType.STRING).setVStr("consumer"));
expectedSpan.addToTags(new Tag("otel.status_code", TagType.STRING).setVStr("OK"));
expectedSpan.addToTags(
new Tag("otel.scope.name", TagType.STRING).setVStr("io.opentelemetry.auto"));
expectedSpan.addToTags(
new Tag("otel.library.name", TagType.STRING).setVStr("io.opentelemetry.auto"));
expectedSpan.addToTags(new Tag("otel.scope.version", TagType.STRING).setVStr("1.0.0"));
expectedSpan.addToTags(new Tag("otel.library.version", TagType.STRING).setVStr("1.0.0"));
List<Span> expectedSpans = Collections.singletonList(expectedSpan);
verify(thriftSender).send(expectedProcess, expectedSpans);
}
@Test
void testExportMultipleResources() throws SenderException, UnknownHostException {
SpanData span =
testSpanData(
Resource.create(
Attributes.of(
stringKey("service.name"),
"myServiceName1",
stringKey("resource-attr-key-1"),
"resource-attr-value-1")),
"GET /api/endpoint/1",
SPAN_CONTEXT,
SpanContext.getInvalid());
SpanData span2 =
testSpanData(
Resource.create(
Attributes.of(
stringKey("service.name"),
"myServiceName2",
stringKey("resource-attr-key-2"),
"resource-attr-value-2")),
"GET /api/endpoint/2",
SPAN_CONTEXT_2,
SpanContext.getInvalid());
// test
CompletableResultCode result = exporter.export(Arrays.asList(span, span2));
result.join(1, TimeUnit.SECONDS);
assertThat(result.isSuccess()).isEqualTo(true);
// verify
Process expectedProcess1 = new Process("myServiceName1");
expectedProcess1.addToTags(
new Tag("jaeger.version", TagType.STRING).setVStr("opentelemetry-java"));
expectedProcess1.addToTags(
new Tag("ip", TagType.STRING).setVStr(InetAddress.getLocalHost().getHostAddress()));
expectedProcess1.addToTags(
new Tag("hostname", TagType.STRING).setVStr(InetAddress.getLocalHost().getHostName()));
expectedProcess1.addToTags(
new Tag("resource-attr-key-1", TagType.STRING).setVStr("resource-attr-value-1"));
expectedProcess1.addToTags(new Tag("service.name", TagType.STRING).setVStr("myServiceName1"));
Process expectedProcess2 = new Process("myServiceName2");
expectedProcess2.addToTags(
new Tag("jaeger.version", TagType.STRING).setVStr("opentelemetry-java"));
expectedProcess2.addToTags(
new Tag("ip", TagType.STRING).setVStr(InetAddress.getLocalHost().getHostAddress()));
expectedProcess2.addToTags(
new Tag("hostname", TagType.STRING).setVStr(InetAddress.getLocalHost().getHostName()));
expectedProcess2.addToTags(
new Tag("resource-attr-key-2", TagType.STRING).setVStr("resource-attr-value-2"));
expectedProcess2.addToTags(new Tag("service.name", TagType.STRING).setVStr("myServiceName2"));
Span expectedSpan1 =
new Span()
.setTraceIdHigh(TRACE_ID_HIGH)
.setTraceIdLow(TRACE_ID_LOW)
.setSpanId(SPAN_ID_LONG)
.setOperationName("GET /api/endpoint/1")
.setReferences(Collections.emptyList())
.setStartTime(TimeUnit.NANOSECONDS.toMicros(span.getStartEpochNanos()))
.setDuration(DURATION.toMillis() * 1000)
.setLogs(Collections.emptyList());
expectedSpan1.addToTags(new Tag("span.kind", TagType.STRING).setVStr("consumer"));
expectedSpan1.addToTags(new Tag("otel.status_code", TagType.STRING).setVStr("OK"));
expectedSpan1.addToTags(
new Tag("otel.scope.name", TagType.STRING).setVStr("io.opentelemetry.auto"));
expectedSpan1.addToTags(
new Tag("otel.library.name", TagType.STRING).setVStr("io.opentelemetry.auto"));
expectedSpan1.addToTags(new Tag("otel.scope.version", TagType.STRING).setVStr("1.0.0"));
expectedSpan1.addToTags(new Tag("otel.library.version", TagType.STRING).setVStr("1.0.0"));
Span expectedSpan2 =
new Span()
.setTraceIdHigh(TRACE_ID_HIGH)
.setTraceIdLow(TRACE_ID_LOW)
.setSpanId(SPAN_ID_2_LONG)
.setOperationName("GET /api/endpoint/2")
.setReferences(Collections.emptyList())
.setStartTime(TimeUnit.NANOSECONDS.toMicros(span2.getStartEpochNanos()))
.setDuration(DURATION.toMillis() * 1000)
.setLogs(Collections.emptyList());
expectedSpan2.addToTags(new Tag("span.kind", TagType.STRING).setVStr("consumer"));
expectedSpan2.addToTags(new Tag("otel.status_code", TagType.STRING).setVStr("OK"));
expectedSpan2.addToTags(
new Tag("otel.scope.name", TagType.STRING).setVStr("io.opentelemetry.auto"));
expectedSpan2.addToTags(
new Tag("otel.library.name", TagType.STRING).setVStr("io.opentelemetry.auto"));
expectedSpan2.addToTags(new Tag("otel.scope.version", TagType.STRING).setVStr("1.0.0"));
expectedSpan2.addToTags(new Tag("otel.library.version", TagType.STRING).setVStr("1.0.0"));
verify(thriftSender).send(expectedProcess2, Collections.singletonList(expectedSpan2));
verify(thriftSender).send(expectedProcess1, Collections.singletonList(expectedSpan1));
}
@Test
@SuppressLogger(JaegerThriftSpanExporter.class)
void shutdown() {
assertThat(exporter.shutdown().join(1, TimeUnit.SECONDS).isSuccess()).isTrue();
assertThat(logs.getEvents()).isEmpty();
assertThat(
exporter
.export(
Collections.singletonList(
testSpanData(
Resource.getDefault(),
"span name",
SPAN_CONTEXT,
SpanContext.getInvalid())))
.join(10, TimeUnit.SECONDS)
.isSuccess())
.isFalse();
assertThat(exporter.shutdown().join(1, TimeUnit.SECONDS).isSuccess()).isTrue();
logs.assertContains("Calling shutdown() multiple times.");
}
private static SpanData testSpanData(
Resource resource, String spanName, SpanContext spanContext, SpanContext parentContext) {
long startMs = System.currentTimeMillis();
long endMs = startMs + DURATION.toMillis();
return TestSpanData.builder()
.setHasEnded(true)
.setSpanContext(spanContext)
.setParentSpanContext(parentContext)
.setName(spanName)
.setStartEpochNanos(TimeUnit.MILLISECONDS.toNanos(startMs))
.setEndEpochNanos(TimeUnit.MILLISECONDS.toNanos(endMs))
.setStatus(StatusData.ok())
.setKind(SpanKind.CONSUMER)
.setLinks(Collections.emptyList())
.setTotalRecordedLinks(0)
.setTotalRecordedEvents(0)
.setInstrumentationScopeInfo(
InstrumentationScopeInfo.builder("io.opentelemetry.auto").setVersion("1.0.0").build())
.setResource(resource)
.build();
}
}

View File

@ -1,48 +0,0 @@
plugins {
id("otel.java-conventions")
id("otel.publish-conventions")
id("otel.animalsniffer-conventions")
id("com.squareup.wire")
}
description = "OpenTelemetry - Jaeger Exporter"
otelJava.moduleName.set("io.opentelemetry.exporter.jaeger")
dependencies {
api(project(":sdk:all"))
protoSource(project(":exporters:jaeger-proto"))
implementation(project(":exporters:common"))
implementation(project(":exporters:sender:okhttp"))
implementation(project(":sdk-extensions:autoconfigure-spi"))
compileOnly("io.grpc:grpc-stub")
implementation("com.fasterxml.jackson.jr:jackson-jr-objects")
testImplementation(project(":exporters:jaeger-proto"))
testImplementation("com.fasterxml.jackson.jr:jackson-jr-stree")
testImplementation("com.google.protobuf:protobuf-java-util")
testImplementation("com.linecorp.armeria:armeria-junit5")
testImplementation("com.linecorp.armeria:armeria-grpc-protocol")
testImplementation("com.squareup.okhttp3:okhttp")
testImplementation("org.testcontainers:junit-jupiter")
testImplementation(project(":sdk:testing"))
}
wire {
custom {
schemaHandlerFactoryClass = "io.opentelemetry.gradle.ProtoFieldsWireHandlerFactory"
}
}
afterEvaluate {
tasks.getByName("generateMainProtos") {
setDependsOn(configurations.getByName("protoPath"))
}
}

View File

@ -1,46 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.jaeger.proto.api_v2.internal.Batch;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.io.IOException;
import java.util.List;
final class BatchMarshaler extends MarshalerWithSize {
private final SpanMarshaler[] spans;
private final ProcessMarshaler process;
static BatchMarshaler create(List<SpanData> spans, Resource resource) {
SpanMarshaler[] spanMarshalers = SpanMarshaler.createRepeated(spans);
ProcessMarshaler processMarshaler = ProcessMarshaler.create(resource);
return new BatchMarshaler(spanMarshalers, processMarshaler);
}
BatchMarshaler(SpanMarshaler[] spans, ProcessMarshaler process) {
super(calculateSize(spans, process));
this.spans = spans;
this.process = process;
}
@Override
protected void writeTo(Serializer output) throws IOException {
output.serializeRepeatedMessage(Batch.SPANS, spans);
output.serializeMessage(Batch.PROCESS, process);
}
private static int calculateSize(SpanMarshaler[] spans, ProcessMarshaler process) {
int size = 0;
size += MarshalerUtil.sizeRepeatedMessage(Batch.SPANS, spans);
size += MarshalerUtil.sizeMessage(Batch.PROCESS, process);
return size;
}
}

View File

@ -1,124 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.exporter.internal.grpc.GrpcExporter;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.concurrent.ThreadSafe;
/**
* Exports spans to Jaeger via gRPC, using Jaeger's protobuf model.
*
* @deprecated Use {@code OtlpGrpcSpanExporter} or {@code OtlpHttpSpanExporter} from <a
* href="https://github.com/open-telemetry/opentelemetry-java/tree/main/exporters/otlp/all">opentelemetry-exporter-otlp</a>
* instead.
*/
@ThreadSafe
@Deprecated
public final class JaegerGrpcSpanExporter implements SpanExporter {
private static final String DEFAULT_HOST_NAME = "unknown";
private static final AttributeKey<String> CLIENT_VERSION_KEY =
AttributeKey.stringKey("jaeger.version");
private static final String CLIENT_VERSION_VALUE = "opentelemetry-java";
private static final AttributeKey<String> HOSTNAME_KEY = AttributeKey.stringKey("hostname");
private static final String IP_DEFAULT = "0.0.0.0";
// Visible for testing
static final AttributeKey<String> IP_KEY = AttributeKey.stringKey("ip");
private final GrpcExporter<PostSpansRequestMarshaler> delegate;
// Jaeger-specific resource information
private final Resource jaegerResource;
JaegerGrpcSpanExporter(GrpcExporter<PostSpansRequestMarshaler> delegate) {
this.delegate = delegate;
String hostname;
String ipv4;
try {
hostname = InetAddress.getLocalHost().getHostName();
ipv4 = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
hostname = DEFAULT_HOST_NAME;
ipv4 = IP_DEFAULT;
}
jaegerResource =
Resource.builder()
.put(CLIENT_VERSION_KEY, CLIENT_VERSION_VALUE)
.put(IP_KEY, ipv4)
.put(HOSTNAME_KEY, hostname)
.build();
}
/**
* Submits all the given spans in a single batch to the Jaeger collector.
*
* @param spans the list of sampled Spans to be exported.
* @return the result of the operation
*/
@Override
public CompletableResultCode export(Collection<SpanData> spans) {
List<CompletableResultCode> results = new ArrayList<>();
spans.stream()
.collect(Collectors.groupingBy(SpanData::getResource))
.forEach(
(resource, spanData) ->
results.add(delegate.export(buildRequest(resource, spanData), spanData.size())));
return CompletableResultCode.ofAll(results);
}
private PostSpansRequestMarshaler buildRequest(Resource resource, List<SpanData> spans) {
Resource mergedResource = jaegerResource.merge(resource);
return PostSpansRequestMarshaler.create(spans, mergedResource);
}
/**
* The Jaeger exporter does not batch spans, so this method will immediately return with success.
*
* @return always Success
*/
@Override
public CompletableResultCode flush() {
return CompletableResultCode.ofSuccess();
}
/**
* Returns a new builder instance for this exporter.
*
* @return a new builder instance for this exporter.
*/
public static JaegerGrpcSpanExporterBuilder builder() {
return new JaegerGrpcSpanExporterBuilder();
}
/**
* Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately
* cancelled.
*/
@Override
public CompletableResultCode shutdown() {
return delegate.shutdown();
}
// Visible for testing
Resource getJaegerResource() {
return jaegerResource;
}
}

View File

@ -1,160 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import static io.opentelemetry.api.internal.Utils.checkArgument;
import static java.util.Objects.requireNonNull;
import io.grpc.ManagedChannel;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder;
import java.net.URI;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
/**
* Builder utility for this exporter.
*
* @deprecated Use {@code OtlpGrpcSpanExporter} or {@code OtlpHttpSpanExporter} from <a
* href="https://github.com/open-telemetry/opentelemetry-java/tree/main/exporters/otlp/all">opentelemetry-exporter-otlp</a>
* instead.
*/
@Deprecated
public final class JaegerGrpcSpanExporterBuilder {
private static final String GRPC_SERVICE_NAME = "jaeger.api_v2.CollectorService";
// Visible for testing
static final String GRPC_ENDPOINT_PATH = "/" + GRPC_SERVICE_NAME + "/PostSpans";
private static final String DEFAULT_ENDPOINT_URL = "http://localhost:14250";
private static final URI DEFAULT_ENDPOINT = URI.create(DEFAULT_ENDPOINT_URL);
private static final long DEFAULT_TIMEOUT_SECS = 10;
private final GrpcExporterBuilder<PostSpansRequestMarshaler> delegate;
JaegerGrpcSpanExporterBuilder() {
delegate =
new GrpcExporterBuilder<>(
"jaeger",
"span",
DEFAULT_TIMEOUT_SECS,
DEFAULT_ENDPOINT,
() -> MarshalerCollectorServiceGrpc::newFutureStub,
GRPC_ENDPOINT_PATH);
}
/**
* Sets the managed channel to use when communicating with the backend. Takes precedence over
* {@link #setEndpoint(String)} if both are called.
*
* @param channel the channel to use.
* @return this.
* @deprecated Use {@link #setEndpoint(String)}. If you have a use case not satisfied by the
* methods on this builder, please file an issue to let us know what it is.
*/
@Deprecated
public JaegerGrpcSpanExporterBuilder setChannel(ManagedChannel channel) {
delegate.setChannel(channel);
return this;
}
/**
* Sets the Jaeger endpoint to connect to. If unset, defaults to {@value DEFAULT_ENDPOINT_URL}.
* The endpoint must start with either http:// or https://.
*/
public JaegerGrpcSpanExporterBuilder setEndpoint(String endpoint) {
requireNonNull(endpoint, "endpoint");
delegate.setEndpoint(endpoint);
return this;
}
/**
* Sets the method used to compress payloads. If unset, compression is disabled. Currently
* supported compression methods include "gzip" and "none".
*
* @since 1.20.0
*/
public JaegerGrpcSpanExporterBuilder setCompression(String compressionMethod) {
requireNonNull(compressionMethod, "compressionMethod");
checkArgument(
compressionMethod.equals("gzip") || compressionMethod.equals("none"),
"Unsupported compression method. Supported compression methods include: gzip, none.");
delegate.setCompression(compressionMethod);
return this;
}
/**
* Sets the maximum time to wait for the collector to process an exported batch of spans. If
* unset, defaults to {@value DEFAULT_TIMEOUT_SECS}s.
*/
public JaegerGrpcSpanExporterBuilder setTimeout(long timeout, TimeUnit unit) {
requireNonNull(unit, "unit");
checkArgument(timeout >= 0, "timeout must be non-negative");
delegate.setTimeout(timeout, unit);
return this;
}
/**
* Sets the maximum time to wait for the collector to process an exported batch of spans. If
* unset, defaults to {@value DEFAULT_TIMEOUT_SECS}s.
*/
public JaegerGrpcSpanExporterBuilder setTimeout(Duration timeout) {
requireNonNull(timeout, "timeout");
delegate.setTimeout(timeout);
return this;
}
/**
* Sets the certificate chain to use for verifying servers when TLS is enabled. The {@code byte[]}
* should contain an X.509 certificate collection in PEM format. If not set, TLS connections will
* use the system default trusted certificates.
*/
public JaegerGrpcSpanExporterBuilder setTrustedCertificates(byte[] trustedCertificatesPem) {
delegate.setTrustManagerFromCerts(trustedCertificatesPem);
return this;
}
/** Sets the client key and chain to use for verifying servers when mTLS is enabled. */
public JaegerGrpcSpanExporterBuilder setClientTls(byte[] privateKeyPem, byte[] certificatePem) {
delegate.setKeyManagerFromCerts(privateKeyPem, certificatePem);
return this;
}
/**
* Sets the "bring-your-own" SSLContext for use with TLS. Users should call this _or_ set raw
* certificate bytes, but not both.
*/
public JaegerGrpcSpanExporterBuilder setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
delegate.setSslContext(sslContext, trustManager);
return this;
}
/**
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, uses
* {@link GlobalOpenTelemetry#getMeterProvider()}.
*
* @since 1.15.0
*/
public JaegerGrpcSpanExporterBuilder setMeterProvider(MeterProvider meterProvider) {
requireNonNull(meterProvider, "meterProvider");
delegate.setMeterProvider(() -> meterProvider);
return this;
}
/**
* Constructs a new instance of the exporter based on the builder's values.
*
* @return a new exporter's instance.
*/
public JaegerGrpcSpanExporter build() {
return new JaegerGrpcSpanExporter(delegate.build());
}
}

View File

@ -1,132 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import com.fasterxml.jackson.jr.ob.JSON;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.ProtoEnumInfo;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.jaeger.proto.api_v2.internal.KeyValue;
import io.opentelemetry.exporter.jaeger.proto.api_v2.internal.ValueType;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings({
"checkstyle:LocalVariableName",
"checkstyle:MemberName",
"checkstyle:ParameterName",
})
final class KeyValueMarshaler extends MarshalerWithSize {
private static final byte[] EMPTY_BYTES = new byte[0];
private final byte[] keyUtf8;
private final ProtoEnumInfo valueType;
private final byte[] vStrUtf8;
private final boolean vBool;
private final long vInt64;
private final double vFloat64;
static List<KeyValueMarshaler> createRepeated(Attributes attributes) {
if (attributes.isEmpty()) {
return new ArrayList<>();
}
List<KeyValueMarshaler> marshalers = new ArrayList<>(attributes.size());
attributes.forEach((attributeKey, o) -> marshalers.add(create(attributeKey, o)));
return marshalers;
}
static KeyValueMarshaler create(AttributeKey<?> key, Object value) {
byte[] keyUtf8 = MarshalerUtil.toBytes(key.getKey());
// Default is the 0 value, string in this case
ProtoEnumInfo valueType = ValueType.STRING;
byte[] vStrUtf8 = EMPTY_BYTES;
boolean vBool = false;
long vInt64 = 0;
double vFloat64 = 0;
switch (key.getType()) {
case STRING:
valueType = ValueType.STRING;
vStrUtf8 = MarshalerUtil.toBytes(((String) value));
break;
case BOOLEAN:
valueType = ValueType.BOOL;
vBool = (boolean) value;
break;
case LONG:
valueType = ValueType.INT64;
vInt64 = (long) value;
break;
case DOUBLE:
valueType = ValueType.FLOAT64;
vFloat64 = (double) value;
break;
case STRING_ARRAY:
case BOOLEAN_ARRAY:
case LONG_ARRAY:
case DOUBLE_ARRAY:
valueType = ValueType.STRING;
try {
vStrUtf8 = JSON.std.asBytes(value);
} catch (IOException e) {
// Can't happen, just ignore it.
}
break;
}
return new KeyValueMarshaler(keyUtf8, valueType, vStrUtf8, vBool, vInt64, vFloat64);
}
KeyValueMarshaler(
byte[] keyUtf8,
ProtoEnumInfo valueType,
byte[] vStrUtf8,
boolean vBool,
long vInt64,
double vFloat64) {
super(calculateSize(keyUtf8, valueType, vStrUtf8, vBool, vInt64, vFloat64));
this.keyUtf8 = keyUtf8;
this.valueType = valueType;
this.vStrUtf8 = vStrUtf8;
this.vBool = vBool;
this.vInt64 = vInt64;
this.vFloat64 = vFloat64;
}
@Override
protected void writeTo(Serializer output) throws IOException {
output.serializeString(KeyValue.KEY, keyUtf8);
output.serializeEnum(KeyValue.V_TYPE, valueType);
output.serializeString(KeyValue.V_STR, vStrUtf8);
output.serializeBool(KeyValue.V_BOOL, vBool);
output.serializeInt64(KeyValue.V_INT64, vInt64);
output.serializeDouble(KeyValue.V_FLOAT64, vFloat64);
}
private static int calculateSize(
byte[] keyUtf8,
ProtoEnumInfo valueType,
byte[] vStrUtf8,
boolean vBool,
long vInt64,
double vFloat64) {
int size = 0;
size += MarshalerUtil.sizeBytes(KeyValue.KEY, keyUtf8);
size += MarshalerUtil.sizeEnum(KeyValue.V_TYPE, valueType);
size += MarshalerUtil.sizeBytes(KeyValue.V_STR, vStrUtf8);
size += MarshalerUtil.sizeBool(KeyValue.V_BOOL, vBool);
size += MarshalerUtil.sizeInt64(KeyValue.V_INT64, vInt64);
size += MarshalerUtil.sizeDouble(KeyValue.V_FLOAT64, vFloat64);
return size;
}
}

View File

@ -1,71 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.jaeger.proto.api_v2.internal.Log;
import io.opentelemetry.sdk.trace.data.EventData;
import java.io.IOException;
import java.util.List;
final class LogMarshaler extends MarshalerWithSize {
private static final AttributeKey<String> KEY_LOG_EVENT = AttributeKey.stringKey("event");
private static final AttributeKey<Long> KEY_EVENT_DROPPED_ATTRIBUTES_COUNT =
AttributeKey.longKey("otel.event.dropped_attributes_count");
private final TimeMarshaler timestamp;
private final List<KeyValueMarshaler> fields;
static LogMarshaler[] createRepeated(List<EventData> events) {
int len = events.size();
LogMarshaler[] marshalers = new LogMarshaler[len];
for (int i = 0; i < len; i++) {
marshalers[i] = create(events.get(i));
}
return marshalers;
}
static LogMarshaler create(EventData event) {
TimeMarshaler timestamp = TimeMarshaler.create(event.getEpochNanos());
List<KeyValueMarshaler> fields = KeyValueMarshaler.createRepeated(event.getAttributes());
// name is a top-level property in OpenTelemetry
fields.add(KeyValueMarshaler.create(KEY_LOG_EVENT, event.getName()));
int droppedAttributesCount = event.getDroppedAttributesCount();
if (droppedAttributesCount > 0) {
fields.add(
KeyValueMarshaler.create(
KEY_EVENT_DROPPED_ATTRIBUTES_COUNT, (long) droppedAttributesCount));
}
return new LogMarshaler(timestamp, fields);
}
LogMarshaler(TimeMarshaler timestamp, List<KeyValueMarshaler> fields) {
super(calculateSize(timestamp, fields));
this.timestamp = timestamp;
this.fields = fields;
}
@Override
protected void writeTo(Serializer output) throws IOException {
output.serializeMessage(Log.TIMESTAMP, timestamp);
output.serializeRepeatedMessage(Log.FIELDS, fields);
}
private static int calculateSize(TimeMarshaler timestamp, List<KeyValueMarshaler> fields) {
int size = 0;
size += MarshalerUtil.sizeMessage(Log.TIMESTAMP, timestamp);
size += MarshalerUtil.sizeRepeatedMessage(Log.FIELDS, fields);
return size;
}
}

View File

@ -1,88 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import static io.grpc.MethodDescriptor.generateFullMethodName;
import com.google.common.util.concurrent.ListenableFuture;
import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.MethodDescriptor;
import io.grpc.stub.ClientCalls;
import io.opentelemetry.exporter.internal.grpc.MarshalerInputStream;
import io.opentelemetry.exporter.internal.grpc.MarshalerServiceStub;
import java.io.InputStream;
import javax.annotation.Nullable;
// Adapted from the protoc generated code for CollectorServiceGrpc.
final class MarshalerCollectorServiceGrpc {
private static final String SERVICE_NAME = "jaeger.api_v2.CollectorService";
private static final MethodDescriptor.Marshaller<PostSpansRequestMarshaler> REQUEST_MARSHALLER =
new MethodDescriptor.Marshaller<PostSpansRequestMarshaler>() {
@Override
public InputStream stream(PostSpansRequestMarshaler value) {
return new MarshalerInputStream(value);
}
@Override
public PostSpansRequestMarshaler parse(InputStream stream) {
throw new UnsupportedOperationException("Only for serializing");
}
};
private static final MethodDescriptor.Marshaller<PostSpansResponse> RESPONSE_MARSHALER =
new MethodDescriptor.Marshaller<PostSpansResponse>() {
@Override
public InputStream stream(PostSpansResponse value) {
throw new UnsupportedOperationException("Only for parsing");
}
@Override
public PostSpansResponse parse(InputStream stream) {
return PostSpansResponse.INSTANCE;
}
};
private static final MethodDescriptor<PostSpansRequestMarshaler, PostSpansResponse>
getPostSpansMethod =
MethodDescriptor.<PostSpansRequestMarshaler, PostSpansResponse>newBuilder()
.setType(MethodDescriptor.MethodType.UNARY)
.setFullMethodName(generateFullMethodName(SERVICE_NAME, "PostSpans"))
.setRequestMarshaller(REQUEST_MARSHALLER)
.setResponseMarshaller(RESPONSE_MARSHALER)
.build();
static CollectorServiceFutureStub newFutureStub(
Channel channel, @Nullable String authorityOverride) {
return CollectorServiceFutureStub.newStub(
(c, options) -> new CollectorServiceFutureStub(c, options.withAuthority(authorityOverride)),
channel);
}
static final class CollectorServiceFutureStub
extends MarshalerServiceStub<
PostSpansRequestMarshaler, PostSpansResponse, CollectorServiceFutureStub> {
private CollectorServiceFutureStub(Channel channel, CallOptions callOptions) {
super(channel, callOptions);
}
@Override
protected MarshalerCollectorServiceGrpc.CollectorServiceFutureStub build(
Channel channel, CallOptions callOptions) {
return new MarshalerCollectorServiceGrpc.CollectorServiceFutureStub(channel, callOptions);
}
@Override
public ListenableFuture<PostSpansResponse> export(PostSpansRequestMarshaler request) {
return ClientCalls.futureUnaryCall(
getChannel().newCall(getPostSpansMethod, getCallOptions()), request);
}
}
private MarshalerCollectorServiceGrpc() {}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.jaeger.proto.api_v2.internal.PostSpansRequest;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.io.IOException;
import java.util.List;
final class PostSpansRequestMarshaler extends MarshalerWithSize {
private final BatchMarshaler batch;
static PostSpansRequestMarshaler create(List<SpanData> spans, Resource resource) {
return new PostSpansRequestMarshaler(BatchMarshaler.create(spans, resource));
}
PostSpansRequestMarshaler(BatchMarshaler batch) {
super(calculateSize(batch));
this.batch = batch;
}
@Override
protected void writeTo(Serializer output) throws IOException {
output.serializeMessage(PostSpansRequest.BATCH, batch);
}
private static int calculateSize(BatchMarshaler batch) {
int size = 0;
size += MarshalerUtil.sizeMessage(PostSpansRequest.BATCH, batch);
return size;
}
}

View File

@ -1,15 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
// A Java object to correspond to the gRPC response for the Collector.PostSpans method. If fields
// are added to the type in the future, this can be converted to an actual class.
//
// It may seem like Void could be used instead but gRPC does not allow response values to be
// null.
enum PostSpansResponse {
INSTANCE;
}

View File

@ -1,53 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.jaeger.proto.api_v2.internal.Process;
import io.opentelemetry.sdk.resources.Resource;
import java.io.IOException;
import java.util.List;
final class ProcessMarshaler extends MarshalerWithSize {
private static final AttributeKey<String> SERVICE_NAME = AttributeKey.stringKey("service.name");
private final byte[] serviceNameUtf8;
private final List<KeyValueMarshaler> tags;
static ProcessMarshaler create(Resource resource) {
String serviceName = resource.getAttribute(SERVICE_NAME);
if (serviceName == null || serviceName.isEmpty()) {
serviceName = Resource.getDefault().getAttribute(SERVICE_NAME);
}
return new ProcessMarshaler(
MarshalerUtil.toBytes(serviceName),
KeyValueMarshaler.createRepeated(resource.getAttributes()));
}
ProcessMarshaler(byte[] serviceNameUtf8, List<KeyValueMarshaler> tags) {
super(calculateSize(serviceNameUtf8, tags));
this.serviceNameUtf8 = serviceNameUtf8;
this.tags = tags;
}
@Override
protected void writeTo(Serializer output) throws IOException {
output.serializeString(Process.SERVICE_NAME, serviceNameUtf8);
output.serializeRepeatedMessage(Process.TAGS, tags);
}
private static int calculateSize(byte[] serviceNameUtf8, List<KeyValueMarshaler> tags) {
int size = 0;
size += MarshalerUtil.sizeBytes(Process.SERVICE_NAME, serviceNameUtf8);
size += MarshalerUtil.sizeRepeatedMessage(Process.TAGS, tags);
return size;
}
}

View File

@ -1,186 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import static io.opentelemetry.api.common.AttributeKey.booleanKey;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.jaeger.proto.api_v2.internal.Span;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
final class SpanMarshaler extends MarshalerWithSize {
private static final AttributeKey<Boolean> KEY_ERROR = booleanKey("error");
private static final AttributeKey<Long> KEY_DROPPED_ATTRIBUTES_COUNT =
AttributeKey.longKey("otel.dropped_attributes_count");
private static final AttributeKey<Long> KEY_DROPPED_EVENTS_COUNT =
AttributeKey.longKey("otel.dropped_events_count");
private static final AttributeKey<String> KEY_SPAN_KIND = AttributeKey.stringKey("span.kind");
private static final AttributeKey<String> KEY_SPAN_STATUS_MESSAGE =
AttributeKey.stringKey("otel.status_description");
private static final AttributeKey<String> KEY_SPAN_STATUS_CODE =
AttributeKey.stringKey("otel.status_code");
private static final AttributeKey<String> KEY_INSTRUMENTATION_SCOPE_NAME =
AttributeKey.stringKey("otel.scope.name");
private static final AttributeKey<String> KEY_INSTRUMENTATION_SCOPE_VERSION =
AttributeKey.stringKey("otel.scope.version");
private static final AttributeKey<String> KEY_INSTRUMENTATION_LIBRARY_NAME =
AttributeKey.stringKey("otel.library.name");
private static final AttributeKey<String> KEY_INSTRUMENTATION_LIBRARY_VERSION =
AttributeKey.stringKey("otel.library.version");
private final String traceId;
private final String spanId;
private final byte[] operationNameUtf8;
private final TimeMarshaler startTime;
private final TimeMarshaler duration;
private final List<KeyValueMarshaler> tags;
private final LogMarshaler[] logs;
private final List<SpanRefMarshaler> references;
static SpanMarshaler[] createRepeated(List<SpanData> spans) {
int len = spans.size();
SpanMarshaler[] marshalers = new SpanMarshaler[len];
for (int i = 0; i < len; i++) {
marshalers[i] = SpanMarshaler.create(spans.get(i));
}
return marshalers;
}
static SpanMarshaler create(SpanData span) {
String traceId = span.getSpanContext().getTraceId();
String spanId = span.getSpanContext().getSpanId();
byte[] operationNameUtf8 = MarshalerUtil.toBytes(span.getName());
TimeMarshaler startTime = TimeMarshaler.create(span.getStartEpochNanos());
TimeMarshaler duration =
TimeMarshaler.create(span.getEndEpochNanos() - span.getStartEpochNanos());
List<KeyValueMarshaler> tags = KeyValueMarshaler.createRepeated(span.getAttributes());
int droppedAttributes = span.getTotalAttributeCount() - span.getAttributes().size();
if (droppedAttributes > 0) {
tags.add(KeyValueMarshaler.create(KEY_DROPPED_ATTRIBUTES_COUNT, (long) droppedAttributes));
}
LogMarshaler[] logs = LogMarshaler.createRepeated(span.getEvents());
int droppedEvents = span.getTotalRecordedEvents() - span.getEvents().size();
if (droppedEvents > 0) {
tags.add(KeyValueMarshaler.create(KEY_DROPPED_EVENTS_COUNT, (long) droppedEvents));
}
List<SpanRefMarshaler> references = SpanRefMarshaler.createRepeated(span.getLinks());
// add the parent span
SpanContext parentSpanContext = span.getParentSpanContext();
if (parentSpanContext.isValid()) {
references.add(SpanRefMarshaler.create(parentSpanContext));
}
if (span.getKind() != SpanKind.INTERNAL) {
tags.add(
KeyValueMarshaler.create(KEY_SPAN_KIND, span.getKind().name().toLowerCase(Locale.ROOT)));
}
if (!span.getStatus().getDescription().isEmpty()) {
tags.add(
KeyValueMarshaler.create(KEY_SPAN_STATUS_MESSAGE, span.getStatus().getDescription()));
}
if (span.getStatus().getStatusCode() != StatusCode.UNSET) {
tags.add(
KeyValueMarshaler.create(KEY_SPAN_STATUS_CODE, span.getStatus().getStatusCode().name()));
}
tags.add(
KeyValueMarshaler.create(
KEY_INSTRUMENTATION_SCOPE_NAME, span.getInstrumentationScopeInfo().getName()));
// Include instrumentation library name for backwards compatibility
tags.add(
KeyValueMarshaler.create(
KEY_INSTRUMENTATION_LIBRARY_NAME, span.getInstrumentationScopeInfo().getName()));
if (span.getInstrumentationScopeInfo().getVersion() != null) {
tags.add(
KeyValueMarshaler.create(
KEY_INSTRUMENTATION_SCOPE_VERSION, span.getInstrumentationScopeInfo().getVersion()));
// Include instrumentation library name for backwards compatibility
tags.add(
KeyValueMarshaler.create(
KEY_INSTRUMENTATION_LIBRARY_VERSION,
span.getInstrumentationScopeInfo().getVersion()));
}
if (span.getStatus().getStatusCode() == StatusCode.ERROR) {
tags.add(KeyValueMarshaler.create(KEY_ERROR, true));
}
return new SpanMarshaler(
traceId, spanId, operationNameUtf8, startTime, duration, tags, logs, references);
}
SpanMarshaler(
String traceId,
String spanId,
byte[] operationNameUtf8,
TimeMarshaler startTime,
TimeMarshaler duration,
List<KeyValueMarshaler> tags,
LogMarshaler[] logs,
List<SpanRefMarshaler> references) {
super(
calculateSize(
traceId, spanId, operationNameUtf8, startTime, duration, tags, logs, references));
this.traceId = traceId;
this.spanId = spanId;
this.operationNameUtf8 = operationNameUtf8;
this.startTime = startTime;
this.duration = duration;
this.tags = tags;
this.logs = logs;
this.references = references;
}
@Override
protected void writeTo(Serializer output) throws IOException {
output.serializeTraceId(Span.TRACE_ID, traceId);
output.serializeSpanId(Span.SPAN_ID, spanId);
output.serializeString(Span.OPERATION_NAME, operationNameUtf8);
output.serializeMessage(Span.START_TIME, startTime);
output.serializeMessage(Span.DURATION, duration);
output.serializeRepeatedMessage(Span.TAGS, tags);
output.serializeRepeatedMessage(Span.LOGS, logs);
output.serializeRepeatedMessage(Span.REFERENCES, references);
}
private static int calculateSize(
String traceId,
String spanId,
byte[] operationNameUtf8,
TimeMarshaler startTime,
TimeMarshaler duration,
List<KeyValueMarshaler> tags,
LogMarshaler[] logs,
List<SpanRefMarshaler> references) {
int size = 0;
size += MarshalerUtil.sizeTraceId(Span.TRACE_ID, traceId);
size += MarshalerUtil.sizeSpanId(Span.SPAN_ID, spanId);
size += MarshalerUtil.sizeBytes(Span.OPERATION_NAME, operationNameUtf8);
size += MarshalerUtil.sizeMessage(Span.START_TIME, startTime);
size += MarshalerUtil.sizeMessage(Span.DURATION, duration);
size += MarshalerUtil.sizeRepeatedMessage(Span.TAGS, tags);
size += MarshalerUtil.sizeRepeatedMessage(Span.LOGS, logs);
size += MarshalerUtil.sizeRepeatedMessage(Span.REFERENCES, references);
return size;
}
}

View File

@ -1,71 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.ProtoEnumInfo;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.jaeger.proto.api_v2.internal.SpanRef;
import io.opentelemetry.exporter.jaeger.proto.api_v2.internal.SpanRefType;
import io.opentelemetry.sdk.trace.data.LinkData;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
final class SpanRefMarshaler extends MarshalerWithSize {
private final String traceId;
private final String spanId;
private final ProtoEnumInfo refType;
static List<SpanRefMarshaler> createRepeated(List<LinkData> links) {
List<SpanRefMarshaler> marshalers = new ArrayList<>(links.size());
for (LinkData link : links) {
// we can assume that all links are *follows from*
// https://github.com/open-telemetry/opentelemetry-java/issues/475
// https://github.com/open-telemetry/opentelemetry-java/pull/481/files#r312577862
marshalers.add(create(link));
;
}
return marshalers;
}
static SpanRefMarshaler create(SpanContext spanContext) {
return new SpanRefMarshaler(
spanContext.getTraceId(), spanContext.getSpanId(), SpanRefType.CHILD_OF);
}
static SpanRefMarshaler create(LinkData link) {
return new SpanRefMarshaler(
link.getSpanContext().getTraceId(),
link.getSpanContext().getSpanId(),
SpanRefType.FOLLOWS_FROM);
}
SpanRefMarshaler(String traceId, String spanId, ProtoEnumInfo refType) {
super(calculateSize(traceId, spanId, refType));
this.traceId = traceId;
this.spanId = spanId;
this.refType = refType;
}
@Override
protected void writeTo(Serializer output) throws IOException {
output.serializeTraceId(SpanRef.TRACE_ID, traceId);
output.serializeSpanId(SpanRef.SPAN_ID, spanId);
output.serializeEnum(SpanRef.REF_TYPE, refType);
}
private static int calculateSize(String traceId, String spanId, ProtoEnumInfo refType) {
int size = 0;
size += MarshalerUtil.sizeTraceId(SpanRef.TRACE_ID, traceId);
size += MarshalerUtil.sizeSpanId(SpanRef.SPAN_ID, spanId);
size += MarshalerUtil.sizeEnum(SpanRef.REF_TYPE, refType);
return size;
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import io.opentelemetry.exporter.internal.marshal.MarshalerUtil;
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
import io.opentelemetry.exporter.internal.marshal.Serializer;
import io.opentelemetry.exporter.jaeger.internal.protobuf.internal.Time;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
// The wire format for Timestamp and Duration are exactly the same. Just implement one Marshaler
// for them.
final class TimeMarshaler extends MarshalerWithSize {
private static final long NANOS_PER_SECOND = TimeUnit.SECONDS.toNanos(1);
private final long seconds;
private final int nanos;
static TimeMarshaler create(long timeNanos) {
long seconds = timeNanos / NANOS_PER_SECOND;
int nanos = (int) (timeNanos % NANOS_PER_SECOND);
return new TimeMarshaler(seconds, nanos);
}
TimeMarshaler(long seconds, int nanos) {
super(calculateSize(seconds, nanos));
this.seconds = seconds;
this.nanos = nanos;
}
@Override
protected void writeTo(Serializer output) throws IOException {
output.serializeInt64(Time.SECONDS, seconds);
output.serializeInt32(Time.NANOS, nanos);
}
private static int calculateSize(long seconds, int nanos) {
int size = 0;
size += MarshalerUtil.sizeInt64(Time.SECONDS, seconds);
size += MarshalerUtil.sizeInt32(Time.NANOS, nanos);
return size;
}
}

View File

@ -1,48 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger.internal;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.time.Duration;
/**
* {@link SpanExporter} SPI implementation for {@link
* io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter}.
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*
* @deprecated Use {@code OtlpGrpcSpanExporter} or {@code OtlpHttpSpanExporter} from <a
* href="https://github.com/open-telemetry/opentelemetry-java/tree/main/exporters/otlp/all">opentelemetry-exporter-otlp</a>
* instead.
*/
@Deprecated
public class JaegerGrpcSpanExporterProvider implements ConfigurableSpanExporterProvider {
@Override
public String getName() {
return "jaeger";
}
@Override
public SpanExporter createExporter(ConfigProperties config) {
io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporterBuilder builder =
io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter.builder();
String endpoint = config.getString("otel.exporter.jaeger.endpoint");
if (endpoint != null) {
builder.setEndpoint(endpoint);
}
Duration timeout = config.getDuration("otel.exporter.jaeger.timeout");
if (timeout != null) {
builder.setTimeout(timeout);
}
return builder.build();
}
}

View File

@ -1,9 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
@ParametersAreNonnullByDefault
package io.opentelemetry.exporter.jaeger;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@ -1 +0,0 @@
Non-empty folder required for wire proto compiler.

View File

@ -1 +0,0 @@
io.opentelemetry.exporter.jaeger.internal.JaegerGrpcSpanExporterProvider

View File

@ -1,422 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.fail;
import com.google.protobuf.InvalidProtocolBufferException;
import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.ServiceRequestContext;
import com.linecorp.armeria.server.grpc.protocol.AbstractUnaryGrpcService;
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
import io.github.netmikey.logunit.api.LogCapturer;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.SpanId;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.TraceFlags;
import io.opentelemetry.api.trace.TraceId;
import io.opentelemetry.api.trace.TraceState;
import io.opentelemetry.exporter.internal.TlsUtil;
import io.opentelemetry.exporter.internal.grpc.GrpcExporter;
import io.opentelemetry.exporter.jaeger.proto.api_v2.Collector;
import io.opentelemetry.exporter.jaeger.proto.api_v2.Model;
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.testing.trace.TestSpanData;
import io.opentelemetry.sdk.trace.IdGenerator;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.data.StatusData;
import java.net.InetAddress;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@SuppressWarnings("deprecation") // Testing deprecated code
class JaegerGrpcSpanExporterTest {
private static final BlockingQueue<Collector.PostSpansRequest> postedRequests =
new LinkedBlockingDeque<>();
@RegisterExtension
static final ServerExtension server =
new ServerExtension() {
@Override
protected void configure(ServerBuilder sb) {
sb.service(
JaegerGrpcSpanExporterBuilder.GRPC_ENDPOINT_PATH,
new AbstractUnaryGrpcService() {
@Override
protected CompletionStage<byte[]> handleMessage(
ServiceRequestContext ctx, byte[] message) {
try {
postedRequests.add(Collector.PostSpansRequest.parseFrom(message));
} catch (InvalidProtocolBufferException e) {
CompletableFuture<byte[]> future = new CompletableFuture<>();
future.completeExceptionally(e);
return future;
}
return CompletableFuture.completedFuture(
Collector.PostSpansResponse.getDefaultInstance().toByteArray());
}
});
}
};
@RegisterExtension LogCapturer logs = LogCapturer.create().captureForType(GrpcExporter.class);
@RegisterExtension
static final SelfSignedCertificateExtension serverTls = new SelfSignedCertificateExtension();
@RegisterExtension
static final SelfSignedCertificateExtension clientTls = new SelfSignedCertificateExtension();
private JaegerGrpcSpanExporter exporter;
@BeforeEach
void setUp() {
exporter =
JaegerGrpcSpanExporter.builder()
.setEndpoint(server.httpUri().toString())
.setMeterProvider(MeterProvider.noop())
.build();
}
@AfterEach
void tearDown() {
exporter.shutdown();
postedRequests.clear();
}
@Test
void testExport() throws Exception {
SpanData span =
testSpanData(
Resource.create(
Attributes.of(
stringKey("service.name"),
"myServiceName",
stringKey("resource-attr-key"),
"resource-attr-value")),
"GET /api/endpoint");
// test
CompletableResultCode result = exporter.export(Collections.singletonList(span));
result.join(10, TimeUnit.SECONDS);
assertThat(result.isSuccess()).isEqualTo(true);
// verify
assertThat(postedRequests).hasSize(1);
Model.Batch batch = postedRequests.poll().getBatch();
assertThat(batch.getSpans(0).getOperationName()).isEqualTo("GET /api/endpoint");
assertThat(SpanId.fromBytes(batch.getSpans(0).getSpanId().toByteArray()))
.isEqualTo(span.getSpanContext().getSpanId());
assertThat(
getTagValue(batch.getProcess().getTagsList(), "resource-attr-key")
.orElseThrow(() -> new AssertionError("resource-attr-key not found"))
.getVStr())
.isEqualTo("resource-attr-value");
verifyBatch(batch);
assertThat(batch.getProcess().getServiceName()).isEqualTo("myServiceName");
}
@Test
void testExportMultipleResources() throws Exception {
SpanData span =
testSpanData(
Resource.create(
Attributes.of(
stringKey("service.name"),
"myServiceName1",
stringKey("resource-attr-key-1"),
"resource-attr-value-1")),
"GET /api/endpoint/1");
SpanData span2 =
testSpanData(
Resource.create(
Attributes.of(
stringKey("service.name"),
"myServiceName2",
stringKey("resource-attr-key-2"),
"resource-attr-value-2")),
"GET /api/endpoint/2");
// test
CompletableResultCode result = exporter.export(Arrays.asList(span, span2));
result.join(10, TimeUnit.SECONDS);
assertThat(result.isSuccess()).isEqualTo(true);
// verify
assertThat(postedRequests).hasSize(2);
List<Collector.PostSpansRequest> requests = new ArrayList<>(postedRequests);
assertThat(requests).hasSize(2);
for (Collector.PostSpansRequest request : requests) {
Model.Batch batch = request.getBatch();
verifyBatch(batch);
Optional<Model.KeyValue> processTag =
getTagValue(batch.getProcess().getTagsList(), "resource-attr-key-1");
Optional<Model.KeyValue> processTag2 =
getTagValue(batch.getProcess().getTagsList(), "resource-attr-key-2");
if (processTag.isPresent()) {
assertThat(processTag2.isPresent()).isFalse();
assertThat(batch.getSpans(0).getOperationName()).isEqualTo("GET /api/endpoint/1");
assertThat(SpanId.fromBytes(batch.getSpans(0).getSpanId().toByteArray()))
.isEqualTo(span.getSpanContext().getSpanId());
assertThat(processTag.get().getVStr()).isEqualTo("resource-attr-value-1");
assertThat(batch.getProcess().getServiceName()).isEqualTo("myServiceName1");
} else if (processTag2.isPresent()) {
assertThat(batch.getSpans(0).getOperationName()).isEqualTo("GET /api/endpoint/2");
assertThat(SpanId.fromBytes(batch.getSpans(0).getSpanId().toByteArray()))
.isEqualTo(span2.getSpanContext().getSpanId());
assertThat(processTag2.get().getVStr()).isEqualTo("resource-attr-value-2");
assertThat(batch.getProcess().getServiceName()).isEqualTo("myServiceName2");
} else {
fail("No process tag resource-attr-key-1 or resource-attr-key-2");
}
}
}
private void verifyBatch(Model.Batch batch) throws Exception {
assertThat(batch.getSpansCount()).isEqualTo(1);
assertThat(TraceId.fromBytes(batch.getSpans(0).getTraceId().toByteArray())).isNotNull();
assertThat(batch.getProcess().getTagsCount()).isEqualTo(5);
assertThat(
getSpanTagValue(batch.getSpans(0), "otel.scope.name")
.orElseThrow(() -> new AssertionError("otel.scope.name not found"))
.getVStr())
.isEqualTo("io.opentelemetry.auto");
assertThat(
getSpanTagValue(batch.getSpans(0), "otel.library.name")
.orElseThrow(() -> new AssertionError("otel.library.name not found"))
.getVStr())
.isEqualTo("io.opentelemetry.auto");
assertThat(
getSpanTagValue(batch.getSpans(0), "otel.library.version")
.orElseThrow(() -> new AssertionError("otel.library.version not found"))
.getVStr())
.isEqualTo("1.0.0");
assertThat(
getSpanTagValue(batch.getSpans(0), "otel.scope.version")
.orElseThrow(() -> new AssertionError("otel.scope.version not found"))
.getVStr())
.isEqualTo("1.0.0");
assertThat(
getTagValue(batch.getProcess().getTagsList(), "ip")
.orElseThrow(() -> new AssertionError("ip not found"))
.getVStr())
.isEqualTo(exporter.getJaegerResource().getAttribute(JaegerGrpcSpanExporter.IP_KEY));
assertThat(
getTagValue(batch.getProcess().getTagsList(), "hostname")
.orElseThrow(() -> new AssertionError("hostname not found"))
.getVStr())
.isEqualTo(InetAddress.getLocalHost().getHostName());
assertThat(
getTagValue(batch.getProcess().getTagsList(), "jaeger.version")
.orElseThrow(() -> new AssertionError("jaeger.version not found"))
.getVStr())
.isEqualTo("opentelemetry-java");
}
private static Optional<Model.KeyValue> getSpanTagValue(Model.Span span, String tagKey) {
return getTagValue(span.getTagsList(), tagKey);
}
private static Optional<Model.KeyValue> getTagValue(List<Model.KeyValue> tags, String tagKey) {
return tags.stream().filter(kv -> kv.getKey().equals(tagKey)).findFirst();
}
private static SpanData testSpanData(Resource resource, String spanName) {
long duration = 900; // ms
long startMs = System.currentTimeMillis();
long endMs = startMs + duration;
return TestSpanData.builder()
.setHasEnded(true)
.setSpanContext(
SpanContext.create(
IdGenerator.random().generateTraceId(),
IdGenerator.random().generateSpanId(),
TraceFlags.getSampled(),
TraceState.getDefault()))
.setName(spanName)
.setStartEpochNanos(TimeUnit.MILLISECONDS.toNanos(startMs))
.setEndEpochNanos(TimeUnit.MILLISECONDS.toNanos(endMs))
.setStatus(StatusData.ok())
.setKind(SpanKind.CONSUMER)
.setLinks(Collections.emptyList())
.setTotalRecordedLinks(0)
.setTotalRecordedEvents(0)
.setInstrumentationScopeInfo(
InstrumentationScopeInfo.builder("io.opentelemetry.auto").setVersion("1.0.0").build())
.setResource(resource)
.build();
}
@Test
void validTrustedConfig() throws Exception {
assertThatCode(
() ->
JaegerGrpcSpanExporter.builder()
.setTrustedCertificates(serverTls.certificate().getEncoded()))
.doesNotThrowAnyException();
}
@Test
void validClientKeyConfig() throws Exception {
assertThatCode(
() ->
JaegerGrpcSpanExporter.builder()
.setClientTls(
clientTls.privateKey().getEncoded(), serverTls.certificate().getEncoded()))
.doesNotThrowAnyException();
}
@Test
void validSslContextConfig() throws Exception {
X509TrustManager trustManager = TlsUtil.trustManager(serverTls.certificate().getEncoded());
X509KeyManager keyManager =
TlsUtil.keyManager(
clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(new KeyManager[] {keyManager}, new TrustManager[] {trustManager}, null);
assertThatCode(() -> JaegerGrpcSpanExporter.builder().setSslContext(sslContext, trustManager))
.doesNotThrowAnyException();
}
@Test
@SuppressWarnings("PreferJavaTimeOverload")
void invalidConfig() {
assertThatThrownBy(() -> JaegerGrpcSpanExporter.builder().setTimeout(-1, TimeUnit.MILLISECONDS))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("timeout must be non-negative");
assertThatThrownBy(() -> JaegerGrpcSpanExporter.builder().setTimeout(1, null))
.isInstanceOf(NullPointerException.class)
.hasMessage("unit");
assertThatThrownBy(() -> JaegerGrpcSpanExporter.builder().setTimeout(null))
.isInstanceOf(NullPointerException.class)
.hasMessage("timeout");
assertThatThrownBy(() -> JaegerGrpcSpanExporter.builder().setEndpoint(null))
.isInstanceOf(NullPointerException.class)
.hasMessage("endpoint");
assertThatThrownBy(() -> JaegerGrpcSpanExporter.builder().setEndpoint("😺://localhost"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Invalid endpoint, must be a URL: 😺://localhost")
.hasCauseInstanceOf(URISyntaxException.class);
assertThatThrownBy(() -> JaegerGrpcSpanExporter.builder().setEndpoint("localhost"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Invalid endpoint, must start with http:// or https://: localhost");
assertThatThrownBy(() -> JaegerGrpcSpanExporter.builder().setEndpoint("gopher://localhost"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Invalid endpoint, must start with http:// or https://: gopher://localhost");
assertThatThrownBy(() -> JaegerGrpcSpanExporter.builder().setCompression(null))
.isInstanceOf(NullPointerException.class)
.hasMessage("compressionMethod");
assertThatThrownBy(() -> JaegerGrpcSpanExporter.builder().setCompression("foo"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage(
"Unsupported compression method. Supported compression methods include: gzip, none.");
}
@Test
void compressionDefault() {
JaegerGrpcSpanExporter exporter = JaegerGrpcSpanExporter.builder().build();
try {
assertThat(exporter).extracting("delegate.grpcSender.compressionEnabled").isEqualTo(false);
} finally {
exporter.shutdown();
}
}
@Test
void compressionNone() {
JaegerGrpcSpanExporter exporter =
JaegerGrpcSpanExporter.builder().setCompression("none").build();
try {
assertThat(exporter).extracting("delegate.grpcSender.compressionEnabled").isEqualTo(false);
} finally {
exporter.shutdown();
}
}
@Test
void compressionGzip() {
JaegerGrpcSpanExporter exporter =
JaegerGrpcSpanExporter.builder().setCompression("gzip").build();
try {
assertThat(exporter).extracting("delegate.grpcSender.compressionEnabled").isEqualTo(true);
} finally {
exporter.shutdown();
}
}
@Test
void compressionEnabledAndDisabled() {
JaegerGrpcSpanExporter exporter =
JaegerGrpcSpanExporter.builder().setCompression("gzip").setCompression("none").build();
try {
assertThat(exporter).extracting("delegate.grpcSender.compressionEnabled").isEqualTo(false);
} finally {
exporter.shutdown();
}
}
@Test
@SuppressLogger(GrpcExporter.class)
void shutdown() {
JaegerGrpcSpanExporter exporter =
JaegerGrpcSpanExporter.builder().setEndpoint(server.httpUri().toString()).build();
assertThat(exporter.shutdown().join(1, TimeUnit.SECONDS).isSuccess()).isTrue();
assertThat(logs.getEvents()).isEmpty();
assertThat(
exporter
.export(Collections.singletonList(testSpanData(Resource.getDefault(), "span name")))
.join(10, TimeUnit.SECONDS)
.isSuccess())
.isFalse();
assertThat(exporter.shutdown().join(1, TimeUnit.SECONDS).isSuccess()).isTrue();
logs.assertContains("Calling shutdown() multiple times.");
}
}

View File

@ -1,118 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.jr.ob.JSON;
import com.fasterxml.jackson.jr.stree.JacksonJrsTreeCodec;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.time.Duration;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.PullPolicy;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@Testcontainers(disabledWithoutDocker = true)
@SuppressWarnings("deprecation") // Testing deprecated code
class JaegerIntegrationTest {
private static final OkHttpClient client = new OkHttpClient();
private static final int QUERY_PORT = 16686;
private static final int COLLECTOR_PORT = 14250;
private static final int HEALTH_PORT = 14269;
private static final String SERVICE_NAME = "E2E-test";
private static final String JAEGER_URL = "http://localhost";
@Container
public static final GenericContainer<?> jaegerContainer =
new GenericContainer<>("ghcr.io/open-telemetry/opentelemetry-java/jaeger:1.32")
.withImagePullPolicy(PullPolicy.alwaysPull())
.withExposedPorts(COLLECTOR_PORT, QUERY_PORT, HEALTH_PORT)
.waitingFor(Wait.forHttp("/").forPort(HEALTH_PORT));
@Test
void testJaegerIntegration() {
OpenTelemetry openTelemetry = initOpenTelemetry();
imitateWork(openTelemetry);
Awaitility.await()
.atMost(Duration.ofSeconds(30))
.until(JaegerIntegrationTest::assertJaegerHaveTrace);
}
private static OpenTelemetry initOpenTelemetry() {
SpanExporter jaegerExporter =
JaegerGrpcSpanExporter.builder()
.setEndpoint("http://localhost:" + jaegerContainer.getMappedPort(COLLECTOR_PORT))
.setTimeout(Duration.ofSeconds(30))
.build();
return OpenTelemetrySdk.builder()
.setTracerProvider(
SdkTracerProvider.builder()
.addSpanProcessor(SimpleSpanProcessor.create(jaegerExporter))
.setResource(
Resource.getDefault().toBuilder()
.put(stringKey("service.name"), SERVICE_NAME)
.build())
.build())
.build();
}
private void imitateWork(OpenTelemetry openTelemetry) {
Span span =
openTelemetry.getTracer(getClass().getCanonicalName()).spanBuilder("Test span").startSpan();
span.addEvent("some event");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
span.end();
}
private static boolean assertJaegerHaveTrace() {
try {
String url =
String.format(
"%s/api/traces?service=%s",
String.format(JAEGER_URL + ":%d", jaegerContainer.getMappedPort(QUERY_PORT)),
SERVICE_NAME);
Request request =
new Request.Builder()
.url(url)
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.build();
TreeNode json;
try (Response response = client.newCall(request).execute()) {
json =
JSON.builder()
.treeCodec(new JacksonJrsTreeCodec())
.build()
.treeFrom(response.body().byteStream());
}
return json.get("data").get(0).get("traceID") != null;
} catch (Exception e) {
return false;
}
}
}

View File

@ -1,437 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger;
import static io.opentelemetry.api.common.AttributeKey.booleanArrayKey;
import static io.opentelemetry.api.common.AttributeKey.booleanKey;
import static io.opentelemetry.api.common.AttributeKey.doubleArrayKey;
import static io.opentelemetry.api.common.AttributeKey.doubleKey;
import static io.opentelemetry.api.common.AttributeKey.longArrayKey;
import static io.opentelemetry.api.common.AttributeKey.longKey;
import static io.opentelemetry.api.common.AttributeKey.stringArrayKey;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.util.Durations;
import com.google.protobuf.util.Timestamps;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.SpanId;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.TraceFlags;
import io.opentelemetry.api.trace.TraceId;
import io.opentelemetry.api.trace.TraceState;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.jaeger.proto.api_v2.Model;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.testing.trace.TestSpanData;
import io.opentelemetry.sdk.trace.data.EventData;
import io.opentelemetry.sdk.trace.data.LinkData;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.data.StatusData;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.junit.jupiter.api.Test;
class PostSpansRequestMarshalerTest {
private static final String KEY_LOG_EVENT = "event";
private static final String KEY_EVENT_DROPPED_ATTRIBUTES_COUNT =
"otel.event.dropped_attributes_count";
private static final String KEY_DROPPED_ATTRIBUTES_COUNT = "otel.dropped_attributes_count";
private static final String KEY_DROPPED_EVENTS_COUNT = "otel.dropped_events_count";
private static final String KEY_SPAN_KIND = "span.kind";
private static final String LINK_TRACE_ID = "00000000000000000000000000cba123";
private static final String LINK_SPAN_ID = "0000000000fed456";
private static final String TRACE_ID = "00000000000000000000000000abc123";
private static final String SPAN_ID = "0000000000def456";
private static final String PARENT_SPAN_ID = "0000000000aef789";
@Test
void testProtoSpans() {
long duration = 900; // ms
long startMs = System.currentTimeMillis();
long endMs = startMs + duration;
SpanData span = getSpanData(startMs, endMs, SpanKind.SERVER);
List<SpanData> spans = Collections.singletonList(span);
SpanMarshaler[] jaegerSpans = SpanMarshaler.createRepeated(spans);
// the span contents are checked somewhere else
assertThat(jaegerSpans).hasSize(1);
}
@Test
@SuppressWarnings({"ProtoTimestampGetSecondsGetNano", "ProtoDurationGetSecondsGetNano"})
void testProtoSpan() {
long duration = 900; // ms
long startMs = System.currentTimeMillis();
long endMs = startMs + duration;
SpanData span = getSpanData(startMs, endMs, SpanKind.SERVER, 2);
// test
Model.Span jaegerSpan = parse(Model.Span.getDefaultInstance(), SpanMarshaler.create(span));
assertThat(TraceId.fromBytes(jaegerSpan.getTraceId().toByteArray()))
.isEqualTo(span.getTraceId());
assertThat(SpanId.fromBytes(jaegerSpan.getSpanId().toByteArray())).isEqualTo(span.getSpanId());
assertThat(jaegerSpan.getOperationName()).isEqualTo("GET /api/endpoint");
assertThat(jaegerSpan.getStartTime()).isEqualTo(Timestamps.fromMillis(startMs));
assertThat(jaegerSpan.getDuration()).isEqualTo(Durations.fromMillis(duration));
assertThat(jaegerSpan.getTagsCount()).isEqualTo(7);
Model.KeyValue keyValue = getValue(jaegerSpan.getTagsList(), KEY_SPAN_KIND);
assertThat(keyValue).isNotNull();
assertThat(keyValue.getVStr()).isEqualTo("server");
Model.KeyValue droppedAttributes =
getValue(jaegerSpan.getTagsList(), KEY_DROPPED_ATTRIBUTES_COUNT);
assertThat(droppedAttributes)
.isEqualTo(
Model.KeyValue.newBuilder()
.setKey(KEY_DROPPED_ATTRIBUTES_COUNT)
.setVType(Model.ValueType.INT64)
.setVInt64(2)
.build());
assertThat(jaegerSpan.getLogsCount()).isEqualTo(1);
Model.KeyValue droppedEvents = getValue(jaegerSpan.getTagsList(), KEY_DROPPED_EVENTS_COUNT);
assertThat(droppedEvents)
.isEqualTo(
Model.KeyValue.newBuilder()
.setKey(KEY_DROPPED_EVENTS_COUNT)
.setVType(Model.ValueType.INT64)
.setVInt64(1)
.build());
Model.Log log = jaegerSpan.getLogs(0);
keyValue = getValue(log.getFieldsList(), KEY_LOG_EVENT);
assertThat(keyValue).isNotNull();
assertThat(keyValue.getVStr()).isEqualTo("the log message");
keyValue = getValue(log.getFieldsList(), "foo");
assertThat(keyValue).isNotNull();
assertThat(keyValue.getVStr()).isEqualTo("bar");
assertThat(jaegerSpan.getReferencesCount()).isEqualTo(2);
assertHasFollowsFrom(jaegerSpan);
assertHasParent(jaegerSpan);
}
@Test
void testProtoSpan_internal() {
long duration = 900; // ms
long startMs = System.currentTimeMillis();
long endMs = startMs + duration;
SpanData span = getSpanData(startMs, endMs, SpanKind.INTERNAL);
// test
Model.Span jaegerSpan = parse(Model.Span.getDefaultInstance(), SpanMarshaler.create(span));
Model.KeyValue keyValue = getValue(jaegerSpan.getTagsList(), KEY_SPAN_KIND);
assertThat(keyValue).isNull();
}
@Test
void testJaegerLogs() {
// prepare
EventData eventsData = getTimedEvent();
// test
LogMarshaler[] logs = LogMarshaler.createRepeated(Collections.singletonList(eventsData));
// verify
assertThat(logs).hasSize(1);
}
@Test
void testJaegerLog() {
// prepare
EventData event = getTimedEvent();
// test
Model.Log log = parse(Model.Log.getDefaultInstance(), LogMarshaler.create(event));
// verify
assertThat(log.getFieldsCount()).isEqualTo(2);
Model.KeyValue keyValue = getValue(log.getFieldsList(), KEY_LOG_EVENT);
assertThat(keyValue).isNotNull();
assertThat(keyValue.getVStr()).isEqualTo("the log message");
keyValue = getValue(log.getFieldsList(), "foo");
assertThat(keyValue).isNotNull();
assertThat(keyValue.getVStr()).isEqualTo("bar");
keyValue = getValue(log.getFieldsList(), KEY_EVENT_DROPPED_ATTRIBUTES_COUNT);
assertThat(keyValue).isNull();
// verify dropped_attributes_count
event = getTimedEvent(3);
log = parse(Model.Log.getDefaultInstance(), LogMarshaler.create(event));
keyValue = getValue(log.getFieldsList(), KEY_EVENT_DROPPED_ATTRIBUTES_COUNT);
assertThat(keyValue).isNotNull();
assertThat(keyValue.getVInt64()).isEqualTo(2);
}
@Test
void testKeyValue() {
// test
Model.KeyValue kvB =
parse(
Model.KeyValue.getDefaultInstance(),
KeyValueMarshaler.create(booleanKey("valueB"), true));
Model.KeyValue kvD =
parse(
Model.KeyValue.getDefaultInstance(), KeyValueMarshaler.create(doubleKey("valueD"), 1.));
Model.KeyValue kvI =
parse(Model.KeyValue.getDefaultInstance(), KeyValueMarshaler.create(longKey("valueI"), 2L));
Model.KeyValue kvS =
parse(
Model.KeyValue.getDefaultInstance(),
KeyValueMarshaler.create(stringKey("valueS"), "foobar"));
Model.KeyValue kvArrayB =
parse(
Model.KeyValue.getDefaultInstance(),
KeyValueMarshaler.create(booleanArrayKey("valueArrayB"), Arrays.asList(true, false)));
Model.KeyValue kvArrayD =
parse(
Model.KeyValue.getDefaultInstance(),
KeyValueMarshaler.create(doubleArrayKey("valueArrayD"), Arrays.asList(1.2345, 6.789)));
Model.KeyValue kvArrayI =
parse(
Model.KeyValue.getDefaultInstance(),
KeyValueMarshaler.create(longArrayKey("valueArrayI"), Arrays.asList(12345L, 67890L)));
Model.KeyValue kvArrayS =
parse(
Model.KeyValue.getDefaultInstance(),
KeyValueMarshaler.create(
stringArrayKey("valueArrayS"), Arrays.asList("foobar", "barfoo")));
// verify
assertThat(kvB.getVBool()).isTrue();
assertThat(kvB.getVType()).isEqualTo(Model.ValueType.BOOL);
assertThat(kvD.getVFloat64()).isEqualTo(1.);
assertThat(kvD.getVType()).isEqualTo(Model.ValueType.FLOAT64);
assertThat(kvI.getVInt64()).isEqualTo(2);
assertThat(kvI.getVType()).isEqualTo(Model.ValueType.INT64);
assertThat(kvS.getVStr()).isEqualTo("foobar");
assertThat(kvS.getVStrBytes().toStringUtf8()).isEqualTo("foobar");
assertThat(kvS.getVType()).isEqualTo(Model.ValueType.STRING);
assertThat(kvArrayB.getVStr()).isEqualTo("[true,false]");
assertThat(kvArrayB.getVStrBytes().toStringUtf8()).isEqualTo("[true,false]");
assertThat(kvArrayB.getVType()).isEqualTo(Model.ValueType.STRING);
assertThat(kvArrayD.getVStr()).isEqualTo("[1.2345,6.789]");
assertThat(kvArrayD.getVStrBytes().toStringUtf8()).isEqualTo("[1.2345,6.789]");
assertThat(kvArrayD.getVType()).isEqualTo(Model.ValueType.STRING);
assertThat(kvArrayI.getVStr()).isEqualTo("[12345,67890]");
assertThat(kvArrayI.getVStrBytes().toStringUtf8()).isEqualTo("[12345,67890]");
assertThat(kvArrayI.getVType()).isEqualTo(Model.ValueType.STRING);
assertThat(kvArrayS.getVStr()).isEqualTo("[\"foobar\",\"barfoo\"]");
assertThat(kvArrayS.getVStrBytes().toStringUtf8()).isEqualTo("[\"foobar\",\"barfoo\"]");
assertThat(kvArrayS.getVType()).isEqualTo(Model.ValueType.STRING);
}
@Test
void testSpanRefs() {
// prepare
LinkData link =
LinkData.create(createSpanContext("00000000000000000000000000cba123", "0000000000fed456"));
// test
List<SpanRefMarshaler> spanRefs =
SpanRefMarshaler.createRepeated(Collections.singletonList(link));
// verify
assertThat(spanRefs).hasSize(1); // the actual span ref is tested in another test
}
@Test
void testSpanRef() {
// prepare
LinkData link = LinkData.create(createSpanContext(TRACE_ID, SPAN_ID));
// test
Model.SpanRef spanRef =
parse(Model.SpanRef.getDefaultInstance(), SpanRefMarshaler.create(link));
// verify
assertThat(SpanId.fromBytes(spanRef.getSpanId().toByteArray())).isEqualTo(SPAN_ID);
assertThat(TraceId.fromBytes(spanRef.getTraceId().toByteArray())).isEqualTo(TRACE_ID);
assertThat(spanRef.getRefType()).isEqualTo(Model.SpanRefType.FOLLOWS_FROM);
}
@Test
void testStatusNotUnset() {
long startMs = System.currentTimeMillis();
long endMs = startMs + 900;
SpanData span =
TestSpanData.builder()
.setHasEnded(true)
.setSpanContext(createSpanContext(TRACE_ID, SPAN_ID))
.setName("GET /api/endpoint")
.setStartEpochNanos(TimeUnit.MILLISECONDS.toNanos(startMs))
.setEndEpochNanos(TimeUnit.MILLISECONDS.toNanos(endMs))
.setKind(SpanKind.SERVER)
.setStatus(StatusData.error())
.setTotalRecordedEvents(0)
.setTotalRecordedLinks(0)
.build();
assertThat(SpanMarshaler.create(span)).isNotNull();
}
@Test
void testSpanError() {
Attributes attributes =
Attributes.of(
stringKey("error.type"),
this.getClass().getName(),
stringKey("error.message"),
"server error");
long startMs = System.currentTimeMillis();
long endMs = startMs + 900;
SpanData span =
TestSpanData.builder()
.setHasEnded(true)
.setSpanContext(createSpanContext(TRACE_ID, SPAN_ID))
.setName("GET /api/endpoint")
.setStartEpochNanos(TimeUnit.MILLISECONDS.toNanos(startMs))
.setEndEpochNanos(TimeUnit.MILLISECONDS.toNanos(endMs))
.setKind(SpanKind.SERVER)
.setStatus(StatusData.error())
.setAttributes(attributes)
.setTotalRecordedEvents(0)
.setTotalRecordedLinks(0)
.build();
Model.Span jaegerSpan = parse(Model.Span.getDefaultInstance(), SpanMarshaler.create(span));
Model.KeyValue errorType = getValue(jaegerSpan.getTagsList(), "error.type");
assertThat(errorType).isNotNull();
assertThat(errorType.getVStr()).isEqualTo(this.getClass().getName());
Model.KeyValue error = getValue(jaegerSpan.getTagsList(), "error");
assertThat(error).isNotNull();
assertThat(error.getVBool()).isTrue();
}
private static EventData getTimedEvent() {
return getTimedEvent(-1);
}
private static EventData getTimedEvent(int totalAttributeCount) {
long epochNanos = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis());
Attributes attributes = Attributes.of(stringKey("foo"), "bar");
if (totalAttributeCount <= 0) {
totalAttributeCount = attributes.size();
}
return EventData.create(epochNanos, "the log message", attributes, totalAttributeCount);
}
private static SpanData getSpanData(long startMs, long endMs, SpanKind kind) {
return getSpanData(startMs, endMs, kind, 1);
}
private static SpanData getSpanData(
long startMs, long endMs, SpanKind kind, int totalRecordedEvents) {
Attributes attributes = Attributes.of(booleanKey("valueB"), true);
LinkData link = LinkData.create(createSpanContext(LINK_TRACE_ID, LINK_SPAN_ID), attributes);
return TestSpanData.builder()
.setHasEnded(true)
.setSpanContext(createSpanContext(TRACE_ID, SPAN_ID))
.setParentSpanContext(
SpanContext.create(
TRACE_ID, PARENT_SPAN_ID, TraceFlags.getDefault(), TraceState.getDefault()))
.setName("GET /api/endpoint")
.setStartEpochNanos(TimeUnit.MILLISECONDS.toNanos(startMs))
.setEndEpochNanos(TimeUnit.MILLISECONDS.toNanos(endMs))
.setAttributes(Attributes.of(booleanKey("valueB"), true))
.setTotalAttributeCount(3)
.setEvents(Collections.singletonList(getTimedEvent()))
.setTotalRecordedEvents(totalRecordedEvents)
.setLinks(Collections.singletonList(link))
.setTotalRecordedLinks(1)
.setKind(kind)
.setResource(Resource.create(Attributes.empty()))
.setStatus(StatusData.ok())
.build();
}
private static SpanContext createSpanContext(String traceId, String spanId) {
return SpanContext.create(traceId, spanId, TraceFlags.getSampled(), TraceState.getDefault());
}
@Nullable
private static Model.KeyValue getValue(List<Model.KeyValue> tagsList, String s) {
for (Model.KeyValue kv : tagsList) {
if (kv.getKey().equals(s)) {
return kv;
}
}
return null;
}
private static void assertHasFollowsFrom(Model.Span jaegerSpan) {
boolean found = false;
for (Model.SpanRef spanRef : jaegerSpan.getReferencesList()) {
if (Model.SpanRefType.FOLLOWS_FROM.equals(spanRef.getRefType())) {
assertThat(TraceId.fromBytes(spanRef.getTraceId().toByteArray())).isEqualTo(LINK_TRACE_ID);
assertThat(SpanId.fromBytes(spanRef.getSpanId().toByteArray())).isEqualTo(LINK_SPAN_ID);
found = true;
}
}
assertThat(found).withFailMessage("Should have found the follows-from reference").isTrue();
}
private static void assertHasParent(Model.Span jaegerSpan) {
boolean found = false;
for (Model.SpanRef spanRef : jaegerSpan.getReferencesList()) {
if (Model.SpanRefType.CHILD_OF.equals(spanRef.getRefType())) {
assertThat(TraceId.fromBytes(spanRef.getTraceId().toByteArray())).isEqualTo(TRACE_ID);
assertThat(SpanId.fromBytes(spanRef.getSpanId().toByteArray())).isEqualTo(PARENT_SPAN_ID);
found = true;
}
}
assertThat(found).withFailMessage("Should have found the parent reference").isTrue();
}
@SuppressWarnings("unchecked")
private static <T extends Message> T parse(T prototype, Marshaler marshaler) {
byte[] serialized = toByteArray(marshaler);
T result;
try {
result = (T) prototype.newBuilderForType().mergeFrom(serialized).build();
} catch (InvalidProtocolBufferException e) {
throw new UncheckedIOException(e);
}
// Our marshaler should produce the exact same length of serialized output (for example, field
// default values are not outputted), so we check that here. The output itself may have slightly
// different ordering, mostly due to the way we don't output oneof values in field order all the
// tieme. If the lengths are equal and the resulting protos are equal, the marshaling is
// guaranteed to be valid.
assertThat(result.getSerializedSize()).isEqualTo(serialized.length);
return result;
}
private static byte[] toByteArray(Marshaler marshaler) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
marshaler.writeBinaryTo(bos);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return bos.toByteArray();
}
}

View File

@ -1,69 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.jaeger.internal;
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import okhttp3.HttpUrl;
import org.junit.jupiter.api.Test;
@SuppressWarnings("deprecation") // Testing deprecated code
class JaegerGrpcSpanExporterProviderTest {
private static final JaegerGrpcSpanExporterProvider provider =
new JaegerGrpcSpanExporterProvider();
@Test
void getName() {
assertThat(provider.getName()).isEqualTo("jaeger");
}
@Test
void createExporter_Default() {
try (SpanExporter spanExporter =
provider.createExporter(DefaultConfigProperties.createFromMap(Collections.emptyMap()))) {
assertThat(spanExporter)
.isInstanceOf(io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter.class);
assertThat(spanExporter)
.extracting("delegate.grpcSender")
.extracting("client")
.extracting("callTimeoutMillis")
.isEqualTo(10000);
assertThat(spanExporter)
.extracting("delegate.grpcSender")
.extracting("url")
.isEqualTo(
HttpUrl.get("http://localhost:14250/jaeger.api_v2.CollectorService/PostSpans"));
}
}
@Test
void createExporter_WithConfiguration() {
Map<String, String> config = new HashMap<>();
config.put("otel.exporter.jaeger.endpoint", "http://endpoint:8080");
config.put("otel.exporter.jaeger.timeout", "1s");
try (SpanExporter spanExporter =
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
assertThat(spanExporter)
.isInstanceOf(io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter.class);
assertThat(spanExporter)
.extracting("delegate.grpcSender")
.extracting("client")
.extracting("callTimeoutMillis")
.isEqualTo(1000);
assertThat(spanExporter)
.extracting("delegate.grpcSender")
.extracting("url")
.isEqualTo(HttpUrl.get("http://endpoint:8080/jaeger.api_v2.CollectorService/PostSpans"));
}
}
}

View File

@ -1,14 +0,0 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

View File

@ -49,7 +49,6 @@ testing {
dependencies {
implementation(project(":api:events"))
implementation(project(":extensions:trace-propagators"))
implementation(project(":exporters:jaeger"))
implementation(project(":exporters:logging"))
implementation(project(":exporters:logging-otlp"))
implementation(project(":exporters:otlp:all"))

View File

@ -28,14 +28,11 @@ class SpanExporterConfigurationTest {
SpiHelper.create(SpanExporterConfigurationTest.class.getClassLoader());
@Test
@SuppressWarnings("deprecation") // Testing deprecated jaeger exporter
void configureExporter_KnownSpiExportersOnClasspath() {
NamedSpiManager<SpanExporter> spiExportersManager =
SpanExporterConfiguration.spanExporterSpiManager(
DefaultConfigProperties.createFromMap(Collections.emptyMap()), spiHelper);
assertThat(SpanExporterConfiguration.configureExporter("jaeger", spiExportersManager))
.isInstanceOf(io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter.class);
assertThat(SpanExporterConfiguration.configureExporter("logging", spiExportersManager))
.isInstanceOf(LoggingSpanExporter.class);
assertThat(SpanExporterConfiguration.configureExporter("logging-otlp", spiExportersManager))

View File

@ -39,7 +39,6 @@ dependencies {
// dependencies.
isTransitive = false
}
jmh(project(":exporters:jaeger-thrift"))
jmh(project(":exporters:otlp:all")) {
// The opentelemetry-exporter-otlp depends on this project itself. So don't pull in
// the transitive dependencies.

View File

@ -38,7 +38,6 @@ public class ExporterBenchmark {
private static final DockerImageName OTLP_COLLECTOR_IMAGE =
DockerImageName.parse("otel/opentelemetry-collector-dev:latest");
protected static final int OTLP_PORT = 5678;
protected static final int JAEGER_PORT = 14268;
private static final int HEALTH_CHECK_PORT = 13133;
protected SdkSpanBuilder sdkSpanBuilder;
@ -49,7 +48,7 @@ public class ExporterBenchmark {
// Configuring the collector test-container
GenericContainer<?> collector =
new GenericContainer<>(OTLP_COLLECTOR_IMAGE)
.withExposedPorts(OTLP_PORT, HEALTH_CHECK_PORT, JAEGER_PORT)
.withExposedPorts(OTLP_PORT, HEALTH_CHECK_PORT)
.waitingFor(Wait.forHttp("/").forPort(HEALTH_CHECK_PORT))
.withCopyFileToContainer(
MountableFile.forClasspathResource("/otel.yaml"), "/etc/otel.yaml")
@ -92,17 +91,4 @@ public class ExporterBenchmark {
.build();
}
}
@SuppressWarnings("deprecation") // Benchmarking deprecated code
public static class JaegerBenchmark extends AbstractProcessorBenchmark {
@Override
protected io.opentelemetry.exporter.jaeger.thrift.JaegerThriftSpanExporter createExporter(
GenericContainer<?> collector) {
String host = collector.getHost();
int port = collector.getMappedPort(JAEGER_PORT);
return io.opentelemetry.exporter.jaeger.thrift.JaegerThriftSpanExporter.builder()
.setEndpoint("http://" + host + ":" + port + "/api/traces")
.build();
}
}
}

View File

@ -3,9 +3,6 @@ receivers:
protocols:
grpc:
endpoint: 0.0.0.0:5678
jaeger:
protocols:
thrift_http:
processors:
batch:
@ -20,6 +17,6 @@ service:
extensions: [health_check]
pipelines:
traces:
receivers: [otlp, jaeger]
receivers: [otlp]
processors: [batch]
exporters: [logging]

View File

@ -36,9 +36,6 @@ include(":exporters:common")
include(":exporters:sender:grpc-managed-channel")
include(":exporters:sender:jdk")
include(":exporters:sender:okhttp")
include(":exporters:jaeger")
include(":exporters:jaeger-proto")
include(":exporters:jaeger-thrift")
include(":exporters:logging")
include(":exporters:logging-otlp")
include(":exporters:otlp:all")