From 37f901afbc8cdbab112fe4b6dd822e2d9b4d0040 Mon Sep 17 00:00:00 2001 From: jack-berg <34418638+jack-berg@users.noreply.github.com> Date: Wed, 9 Aug 2023 13:39:38 -0500 Subject: [PATCH] Add toString to OTLP exporters (#5686) Co-authored-by: Mateusz Rzeszutek --- .../opentelemetry-exporter-otlp.txt | 6 ++ .../internal/grpc/GrpcExporterBuilder.java | 31 ++++++++++ .../internal/http/HttpExporterBuilder.java | 31 ++++++++++ .../http/logs/OtlpHttpLogRecordExporter.java | 5 ++ .../http/metrics/OtlpHttpMetricExporter.java | 5 ++ .../otlp/http/trace/OtlpHttpSpanExporter.java | 5 ++ .../otlp/logs/OtlpGrpcLogRecordExporter.java | 5 ++ .../otlp/metrics/OtlpGrpcMetricExporter.java | 5 ++ .../otlp/trace/OtlpGrpcSpanExporter.java | 5 ++ .../AbstractGrpcTelemetryExporterTest.java | 62 +++++++++++++++++++ .../AbstractHttpTelemetryExporterTest.java | 59 ++++++++++++++++++ ...anagedChannelTelemetryExporterBuilder.java | 5 ++ 12 files changed, 224 insertions(+) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt index c9ed6d05776..67aeae99e2f 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt @@ -2,18 +2,24 @@ Comparing source compatibility of against *** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter (not serializable) === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder toBuilder() + +++ NEW METHOD: PUBLIC(+) java.lang.String toString() *** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter (not serializable) === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder toBuilder() + +++ NEW METHOD: PUBLIC(+) java.lang.String toString() *** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter (not serializable) === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder toBuilder() + +++ NEW METHOD: PUBLIC(+) java.lang.String toString() *** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter (not serializable) === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporterBuilder toBuilder() + +++ NEW METHOD: PUBLIC(+) java.lang.String toString() *** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter (not serializable) === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder toBuilder() + +++ NEW METHOD: PUBLIC(+) java.lang.String toString() *** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter (not serializable) === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder toBuilder() + +++ NEW METHOD: PUBLIC(+) java.lang.String toString() diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilder.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilder.java index 4220cd024ea..8845c381cf2 100644 --- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilder.java +++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilder.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.StringJoiner; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.function.Supplier; @@ -202,6 +203,36 @@ public GrpcExporter build() { compressionEnabled); } + public String toString(boolean includePrefixAndSuffix) { + StringJoiner joiner = + includePrefixAndSuffix + ? new StringJoiner(", ", "GrpcExporterBuilder{", "}") + : new StringJoiner(", "); + joiner.add("exporterName=" + exporterName); + joiner.add("type=" + type); + joiner.add("endpoint=" + endpoint.toString()); + joiner.add("endpointPath=" + grpcEndpointPath); + joiner.add("timeoutNanos=" + timeoutNanos); + joiner.add("compressionEnabled=" + compressionEnabled); + StringJoiner headersJoiner = new StringJoiner(", ", "Headers{", "}"); + headers.forEach((key, value) -> headersJoiner.add(key + "=OBFUSCATED")); + joiner.add("headers=" + headersJoiner); + if (retryPolicy != null) { + joiner.add("retryPolicy=" + retryPolicy); + } + if (grpcChannel != null) { + joiner.add("grpcChannel=" + grpcChannel); + } + // Note: omit tlsConfigHelper because we can't log the configuration in any readable way + // Note: omit meterProviderSupplier because we can't log the configuration in any readable way + return joiner.toString(); + } + + @Override + public String toString() { + return toString(true); + } + // Use an inner class to ensure GrpcExporterBuilder does not have classloading dependencies on // upstream gRPC. private class UpstreamGrpcExporterFactory { diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilder.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilder.java index ed3970238bb..5227a760eb5 100644 --- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilder.java +++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilder.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.Map; import java.util.ServiceLoader; +import java.util.StringJoiner; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import java.util.logging.Level; @@ -166,6 +167,36 @@ public HttpExporter build() { return new HttpExporter<>(exporterName, type, httpSender, meterProviderSupplier, exportAsJson); } + public String toString(boolean includePrefixAndSuffix) { + StringJoiner joiner = + includePrefixAndSuffix + ? new StringJoiner(", ", "HttpExporterBuilder{", "}") + : new StringJoiner(", "); + joiner.add("exporterName=" + exporterName); + joiner.add("type=" + type); + joiner.add("endpoint=" + endpoint); + joiner.add("timeoutNanos=" + timeoutNanos); + joiner.add("compressionEnabled=" + compressionEnabled); + joiner.add("exportAsJson=" + exportAsJson); + if (headers != null) { + StringJoiner headersJoiner = new StringJoiner(", ", "Headers{", "}"); + headers.forEach((key, value) -> headersJoiner.add(key + "=OBFUSCATED")); + joiner.add("headers=" + headersJoiner); + } + if (retryPolicy != null) { + joiner.add("retryPolicy=" + retryPolicy); + } + // Note: omit tlsConfigHelper because we can't log the configuration in any readable way + // Note: omit meterProviderSupplier because we can't log the configuration in any readable way + // Note: omit authenticator because we can't log the configuration in any readable way + return joiner.toString(); + } + + @Override + public String toString() { + return toString(true); + } + /** * Resolve the {@link HttpSenderProvider}. * diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java index 791d6399ebe..a4ce261c4ba 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java @@ -84,4 +84,9 @@ public CompletableResultCode flush() { public CompletableResultCode shutdown() { return delegate.shutdown(); } + + @Override + public String toString() { + return "OtlpHttpLogRecordExporter{" + builder.toString(false) + "}"; + } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java index 9f209be9b58..262462da0df 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java @@ -110,4 +110,9 @@ public CompletableResultCode flush() { public CompletableResultCode shutdown() { return delegate.shutdown(); } + + @Override + public String toString() { + return "OtlpHttpMetricExporter{" + builder.toString(false) + "}"; + } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java index 409fd85d102..7e77d18e5d3 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java @@ -89,4 +89,9 @@ public CompletableResultCode flush() { public CompletableResultCode shutdown() { return delegate.shutdown(); } + + @Override + public String toString() { + return "OtlpHttpSpanExporter{" + builder.toString(false) + "}"; + } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java index 1c555f3465b..c454803f8e3 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java @@ -87,4 +87,9 @@ public CompletableResultCode flush() { public CompletableResultCode shutdown() { return delegate.shutdown(); } + + @Override + public String toString() { + return "OtlpGrpcLogRecordExporter{" + builder.toString(false) + "}"; + } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java index 4c932f59aa0..bd0d059e9a3 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java @@ -114,4 +114,9 @@ public CompletableResultCode flush() { public CompletableResultCode shutdown() { return delegate.shutdown(); } + + @Override + public String toString() { + return "OtlpGrpcMetricExporter{" + builder.toString(false) + "}"; + } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java index f8caef8027f..91b42fac1d6 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java @@ -89,4 +89,9 @@ public CompletableResultCode flush() { public CompletableResultCode shutdown() { return delegate.shutdown(); } + + @Override + public String toString() { + return "OtlpGrpcSpanExporter{" + builder.toString(false) + "}"; + } } diff --git a/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractGrpcTelemetryExporterTest.java b/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractGrpcTelemetryExporterTest.java index 832dd3afd03..d6bc2774c1e 100644 --- a/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractGrpcTelemetryExporterTest.java +++ b/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractGrpcTelemetryExporterTest.java @@ -783,6 +783,68 @@ void toBuilderEquality() } } + @Test + void stringRepresentation() throws IOException, CertificateEncodingException { + TelemetryExporter telemetryExporter = + exporterBuilder().setEndpoint("http://localhost:4317").build(); + try { + assertThat(telemetryExporter.unwrap().toString()) + .matches( + "OtlpGrpc[a-zA-Z]*Exporter\\{" + + "exporterName=otlp, " + + "type=[a-zA_Z]*, " + + "endpoint=http://localhost:4317, " + + "endpointPath=.*, " + + "timeoutNanos=" + + TimeUnit.SECONDS.toNanos(10) + + ", " + + "compressionEnabled=false, " + + "headers=Headers\\{User-Agent=OBFUSCATED\\}" + + ".*" // Maybe additional grpcChannel field + + "\\}"); + } finally { + telemetryExporter.shutdown(); + } + + telemetryExporter = + exporterBuilder() + .setTimeout(Duration.ofSeconds(5)) + .setEndpoint("http://example:4317") + .setCompression("gzip") + .addHeader("foo", "bar") + .setTrustedCertificates(certificate.certificate().getEncoded()) + .setClientTls( + Files.readAllBytes(clientCertificate.privateKeyFile().toPath()), + Files.readAllBytes(clientCertificate.certificateFile().toPath())) + .setRetryPolicy( + RetryPolicy.builder() + .setMaxAttempts(2) + .setMaxBackoff(Duration.ofSeconds(3)) + .setInitialBackoff(Duration.ofMillis(50)) + .setBackoffMultiplier(1.3) + .build()) + .build(); + try { + assertThat(telemetryExporter.unwrap().toString()) + .matches( + "OtlpGrpc[a-zA-Z]*Exporter\\{" + + "exporterName=otlp, " + + "type=[a-zA_Z]*, " + + "endpoint=http://example:4317, " + + "endpointPath=.*, " + + "timeoutNanos=" + + TimeUnit.SECONDS.toNanos(5) + + ", " + + "compressionEnabled=true, " + + "headers=Headers\\{.*foo=OBFUSCATED.*\\}, " + + "retryPolicy=RetryPolicy\\{maxAttempts=2, initialBackoff=PT0\\.05S, maxBackoff=PT3S, backoffMultiplier=1\\.3\\}" + + ".*" // Maybe additional grpcChannel field + + "\\}"); + } finally { + telemetryExporter.shutdown(); + } + } + protected abstract TelemetryExporterBuilder exporterBuilder(); protected abstract TelemetryExporterBuilder toBuilder(TelemetryExporter exporter); diff --git a/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractHttpTelemetryExporterTest.java b/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractHttpTelemetryExporterTest.java index d49e4a58cd5..662b58ab397 100644 --- a/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractHttpTelemetryExporterTest.java +++ b/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractHttpTelemetryExporterTest.java @@ -715,6 +715,65 @@ void toBuilderEquality() } } + @Test + void stringRepresentation() throws IOException, CertificateEncodingException { + TelemetryExporter telemetryExporter = exporterBuilder().build(); + try { + assertThat(telemetryExporter.unwrap().toString()) + .matches( + "OtlpHttp[a-zA-Z]*Exporter\\{" + + "exporterName=otlp, " + + "type=[a-zA_Z]*, " + + "endpoint=http://localhost:4318/v1/[a-zA-Z]*, " + + "timeoutNanos=" + + TimeUnit.SECONDS.toNanos(10) + + ", " + + "compressionEnabled=false, " + + "exportAsJson=false, " + + "headers=Headers\\{User-Agent=OBFUSCATED\\}" + + "\\}"); + } finally { + telemetryExporter.shutdown(); + } + + telemetryExporter = + exporterBuilder() + .setTimeout(Duration.ofSeconds(5)) + .setEndpoint("http://example:4318/v1/logs") + .setCompression("gzip") + .addHeader("foo", "bar") + .setTrustedCertificates(certificate.certificate().getEncoded()) + .setClientTls( + Files.readAllBytes(clientCertificate.privateKeyFile().toPath()), + Files.readAllBytes(clientCertificate.certificateFile().toPath())) + .setRetryPolicy( + RetryPolicy.builder() + .setMaxAttempts(2) + .setMaxBackoff(Duration.ofSeconds(3)) + .setInitialBackoff(Duration.ofMillis(50)) + .setBackoffMultiplier(1.3) + .build()) + .build(); + try { + assertThat(telemetryExporter.unwrap().toString()) + .matches( + "OtlpHttp[a-zA-Z]*Exporter\\{" + + "exporterName=otlp, " + + "type=[a-zA_Z]*, " + + "endpoint=http://example:4318/v1/[a-zA-Z]*, " + + "timeoutNanos=" + + TimeUnit.SECONDS.toNanos(5) + + ", " + + "compressionEnabled=true, " + + "exportAsJson=false, " + + "headers=Headers\\{.*foo=OBFUSCATED.*\\}, " + + "retryPolicy=RetryPolicy\\{maxAttempts=2, initialBackoff=PT0\\.05S, maxBackoff=PT3S, backoffMultiplier=1\\.3\\}" + + "\\}"); + } finally { + telemetryExporter.shutdown(); + } + } + protected abstract TelemetryExporterBuilder exporterBuilder(); protected abstract TelemetryExporterBuilder toBuilder(TelemetryExporter exporter); diff --git a/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/ManagedChannelTelemetryExporterBuilder.java b/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/ManagedChannelTelemetryExporterBuilder.java index 476a51e7645..5560335ba06 100644 --- a/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/ManagedChannelTelemetryExporterBuilder.java +++ b/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/ManagedChannelTelemetryExporterBuilder.java @@ -90,6 +90,7 @@ public TelemetryExporterBuilder addHeader(String key, String value) { @Override public TelemetryExporterBuilder setAuthenticator(Authenticator authenticator) { + delegate.setAuthenticator(authenticator); return this; } @@ -99,18 +100,21 @@ public TelemetryExporterBuilder setAuthenticator(Authenticator authenticator) @Override public TelemetryExporterBuilder setTrustedCertificates(byte[] certificates) { + delegate.setTrustedCertificates(certificates); tlsConfigHelper.setTrustManagerFromCerts(certificates); return this; } @Override public TelemetryExporterBuilder setClientTls(byte[] privateKeyPem, byte[] certificatePem) { + delegate.setClientTls(privateKeyPem, certificatePem); tlsConfigHelper.setKeyManagerFromCerts(privateKeyPem, certificatePem); return this; } @Override public TelemetryExporterBuilder setRetryPolicy(RetryPolicy retryPolicy) { + delegate.setRetryPolicy(retryPolicy); String grpcServiceName; if (delegate instanceof GrpcLogRecordExporterBuilderWrapper) { grpcServiceName = "opentelemetry.proto.collector.logs.v1.LogsService"; @@ -167,6 +171,7 @@ public CompletableResultCode shutdown() { @Override public TelemetryExporterBuilder setSslContext( SSLContext sslContext, X509TrustManager trustManager) { + delegate.setSslContext(sslContext, trustManager); tlsConfigHelper.setSslContext(sslContext, trustManager); return this; }