Delete jaeger exporters (#6119)
This commit is contained in:
parent
9c3af76ab9
commit
30c75b4715
|
@ -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--> | [](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--> | [](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--> | [](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--> | [](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--> | [](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--> | [](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--> | [](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--> | [](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--> | [](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--> | [](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 |
|
||||
|
|
|
@ -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_")
|
||||
},
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
# OpenTelemetry - Jaeger Proto (DEPRECATED)
|
||||
|
||||
> **NOTICE**: External use of this artifact is deprecated.
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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"))
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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() {}
|
||||
}
|
|
@ -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;
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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"))
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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() {}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
package io.opentelemetry.exporter.jaeger;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
@ -1 +0,0 @@
|
|||
Non-empty folder required for wire proto compiler.
|
|
@ -1 +0,0 @@
|
|||
io.opentelemetry.exporter.jaeger.internal.JaegerGrpcSpanExporterProvider
|
|
@ -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.");
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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"))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue