7Z;6(@EK$q*Jgif00I6*^ZGV+XB5uw*1R-@23yTw&WKD{s1;HTL;dO)%5i#`dc6b7;5@^{KU%N|A-$zsYw4)7LA{3`Zp>1
z-?K9_IE&z)dayUM)wd8K^29m-l$lFhi$zj0l!u~4;VGR6Y!?MAfBC^?QD53hy6VdD
z@eUZIui}~L%#SmajaRq1J|#>
z4m=o$vZ*34=ZWK2!QMNEcp2Lbc5N1q!lEDq(bz0b;WI9;e>l=CG9^n#ro`w>_0F$Q
zfZ={2QyTkfByC&gy;x!r*NyXXbk=a%~~(#K?<
zTke0HuF5{Q+~?@!KDXR|g+43$+;ab`^flS%miup_0OUTm=nIc%d5nLP)i308PIjl_YMF6cpQ__6&$n6it8K-
z8PIjl_YMF6cpQ_!r)L8IivW`WdK8mBs6PXdjR2DYdK8nCs73=4j{uVadK8oNjwX|E
wpAeHLsTu^*Y>Trk?aBtSQ(D-o$(D8Px^?ZI-PUB?
z*1fv!{YdHme3Fc8%cR@*@zc5A_nq&2=R47Hp@$-JF4Fz*;SLw5}K^y>s-s;V!}b2i=5=M-
zComP?ju>8Fe@=H@rlwe1l`J*6BTTo`9b$zjQ@HxrAhp0D#u?M~TxGC_!?ccCHCjt|
zF*PgJf@kJB`|Ml}cmsyrAjO#Kjr^E5p29w+#>$C`Q|54BoDv$fQ9D?3n32P9LPMIzu?LjNqggOH=1@T{9bMn*u8(GI
z!;MLTtFPHal^S>VcJdiYqX0VU|Rn@A}C1xOlxCribxes0~+n2
z6qDaIA2$?e`opx3_KW!rAgbpzU)gFdjAKXh|5w``#F0R|c)Y)Du0_Ihhz^S?k^pk%
zP>9|pIDx)xHH^_~+aA=^$M!<8K~Hy(71nJGf6`HnjtS=4X4=Hk^O71oNia2V{HUCC
zoN3RSBS?mZCLw;l4W4a+D8qc)XJS`pUJ5X-f^1ytxwr`@si$lAE?{4G|o;
zO0l>`rr?;~c;{ZEFJ!!3=7=FdGJ?Q^xfNQh4A?i;IJ4}B+A?4olTK(fN++3CRBP97
ze~lG9h%oegkn)lpW-4F8o2`*WW0mZHwHez`ko@>U1_;EC_6ig|Drn@=DMV9YEUSCa
zIf$kHei3(u#zm9I!Jf(4t`Vm1lltJ&lVHy(eIXE8sy9sUpmz%I_gA#8x^Zv8%w?r2
z{GdkX1SkzRIr>prRK@rqn9j2wG|rUvf6PJbbin=yy-TAXrguvzN8jL$hUrIXzr^s5
zVM?H4;eM-QeRFr06@ifV(ocvk?_)~N@1c2ien56UjWXid6W%6ievIh)>dk|rIs##^kY67ib8Kw%#-oVFaXG7$ERyA9(NSJUvWiOA5H(!{uOpcW
zg&-?iqPhds%3%tFspHDqqr;A!e@B#iPQjHd=c>N1LoOEGRehVoPOdxJ>b6>yc#o#+
zl8s8!(|NMeqjsy@0x{8^j0d00SqRZjp{Kj)&4UHYGxG+z9b-)72I*&J70?+8e?p_@
z=>-(>l6z5vYlP~<2%DU02b!mA{7mS)NS_eLe=t)sm&+Pmk?asOEKlkPQ)EUvvfC=;4M&*|I!w}(@V_)eUKLA_t^%`o
z0PM9LV|UKTLnk|?M3u!|f2S0?UqZsEIH9*NJS-8lzu;A6-rr-ot=dg9SASoluZUkFH$7X;
zP=?kYX!K?JL-b~<#7wU;b;eS)O;@?h%sPPk{4xEBxb{!sm0AY|f9cNvx6>$3F!*0c
z75H=dy8JvTyO8}g1w{$9T$p~5en}AeSLoCF>_RT9YPMpChUjl310o*$QocjbH&
zbnwg#gssR#jDVN{uEi3n(PZ%PFZ|6J2
z5_rBf0-u>e4sFe0*Km49ATi7>Kn0f9!uc|rRMR1Dtt6m1LW8^>qFlo}h$@br=Rmpi
z;mI&>OF64Be{dVeHI8utrh)v^wsZ0jii%x8UgZ8TC%K~@I(4E};GFW&(;WVov}3%H
zH;IhRkfD^(vt^DjZz(MyHLZxv8}qzPc(%itBkBwf_fC~sDBgh<3XAv5cxxfF3<2U!
z03Xe&z`is!JDHbe;mNmfkH+_LFE*I2^mdL@7(@9DfAcP6O04V-ko;Rpgp<%Cj5r8Z
zd0`sXoIjV$j)--;jA6Zy^D5&5v$o^>e%>Q?9GLm{i~p^lAn!%ZtF$I~>39XVZxk0b
zROh^Bk9cE0AJBLozZIEmy7xG(yHWGztvfnr0(2ro1%>zsGMS^EMu+S$r=_;9
zWwZkgf7Q7`H9sLf2Go^Xy6&h~a&%s2_T@_Csf19MntF$aVFiFkvE3_hUg(B@&Xw@YJ
zpL$wNYf78=0c@!QU6_a$>CPiXT7QAGDM}7Z(0z#_ZA=fmLUj{2z7@Ypo71UDy8GHr
z-&TLKf6a5WCf@Adle3VglBt4>Z>;xF}}-S~B7<(%B;Y
z0QR55{z-buw>8ilNM3u6I+D$S%?)(p>=eBx-HpvZj{7c*_?K=d()*7q?93us}1dq%FAFYLsW8ZTQ_XZLh`P2*6(NgS}qGcfGXVWpwsp#Rs}IuKbk*`2}&)
zI^Vsk6S&Q4@oYS?dJ`NwMVBs6f57+RxdqVub#PvMu?$=^OJy5xEl0<5SLsSRy%%a0
zi}Y#1-F3m;Ieh#Y12UgW?-R)|eX>ZuF-2cc!1>~NS|XSF-6In>zBoZg+ml!6%fk7U
zw0LHcz8VQk(jOJ+Yu)|^|15ufl$KQd_1eUZZzj`aC%umU6F1&D5XVWce_wAe(qCSZ
zpX-QF4e{EmEVN9~6%bR5U*UT{eMHfcUo`jw*u?4r2s_$`}U{?NjvEm(u&<>B|%mq$Q3weshxk
z76<``8vh{+nX`@9CB6IE&z)I%IFjR^LH{s1p|eppv=x
za(g_jLU|xjWMAn-V7th$f({|LG8zzIE0g?cyW;%Dmtv%C+0@xVxPE^
zyZzi9P%JAD6ynwHptuzP`Kox7*9h7XSMonCalv;Md0i9Vb-c*!f0ubfk?&T&T}AHh
z4m8Bz{JllKcdNg?D^%a5MFQ;#1z|*}H^qHLzW)L}wp?2tY7RejtSh8<;Zw)QGJYUm
z|MbTxyj*McKlStlT9I5XlSWtQGN&-LTr2XyNU+`490rg?LYLMRnz-@oKqT1hpCGqP
zyRXt4=_Woj$%n5ee<3zhLF>5>`?m9a#xQH+Jk_+|RM8Vi;2*XbK-
zEL6sCpaGPzP>k8f4Kh|##_imt#zJMB;ir|JrMPGW`rityK1vHXMLy18%qmMQAm4WZ
zP)i30KR&5vs15)C+8dM66&$k~i|ZT;KR&5vs15)C+8dJ(sAmGPijyIz6_bsqKLSFH
zlOd=TljEpH0>h4zA*dCTK&emy#FCRCs1=i^sZ9bFmXjf<6_X39E(XY)00000#N437
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 68e8816d71c..2b189974c29 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
+distributionSha256Sum=5b9c5eb3f9fc2c94abaea57d90bd78747ca117ddbbf96c859d3741181a12bf2a
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
From 581690ecaca5b92979f0ff559a083a63b4b98590 Mon Sep 17 00:00:00 2001
From: Chung Nguyen
Date: Mon, 19 Aug 2024 20:57:08 +0200
Subject: [PATCH 08/42] supress zipkin exporters instrumentations (#6552)
---
.../exporter/zipkin/ZipkinSpanExporter.java | 24 +++++---
.../zipkin/ZipkinSpanExporterTest.java | 58 +++++++++++++++++++
2 files changed, 73 insertions(+), 9 deletions(-)
diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java
index c92f70db3f5..a76d3177fd4 100644
--- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java
+++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporter.java
@@ -5,6 +5,7 @@
package io.opentelemetry.exporter.zipkin;
+import io.opentelemetry.api.internal.InstrumentationUtil;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.ExporterMetrics;
import io.opentelemetry.sdk.common.CompletableResultCode;
@@ -75,15 +76,20 @@ public CompletableResultCode export(Collection spanDataList) {
encodedSpans.add(encoder.encode(zipkinSpan));
}
- try {
- sender.send(encodedSpans);
- exporterMetrics.addSuccess(numItems);
- return CompletableResultCode.ofSuccess();
- } catch (IOException | RuntimeException t) {
- exporterMetrics.addFailed(numItems);
- logger.log(Level.WARNING, "Failed to export spans", t);
- return CompletableResultCode.ofFailure();
- }
+ CompletableResultCode resultCode = new CompletableResultCode();
+ InstrumentationUtil.suppressInstrumentation(
+ () -> {
+ try {
+ sender.send(encodedSpans);
+ exporterMetrics.addSuccess(numItems);
+ resultCode.succeed();
+ } catch (IOException | RuntimeException e) {
+ exporterMetrics.addFailed(numItems);
+ logger.log(Level.WARNING, "Failed to export spans", e);
+ resultCode.fail();
+ }
+ });
+ return resultCode;
}
@Override
diff --git a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java
index 673855d4a8c..2c70691744c 100644
--- a/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java
+++ b/exporters/zipkin/src/test/java/io/opentelemetry/exporter/zipkin/ZipkinSpanExporterTest.java
@@ -9,12 +9,15 @@
import static io.opentelemetry.exporter.zipkin.ZipkinTestUtil.zipkinSpanBuilder;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import io.github.netmikey.logunit.api.LogCapturer;
+import io.opentelemetry.api.internal.InstrumentationUtil;
import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.context.Context;
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.testing.trace.TestSpanData;
@@ -22,7 +25,9 @@
import java.net.InetAddress;
import java.time.Duration;
import java.util.Collections;
+import java.util.List;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -244,4 +249,57 @@ void stringRepresentation() {
"ZipkinSpanExporter{endpoint=http://zipkin:9411/api/v2/spans, compressionEnabled=false, readTimeoutMillis=15000}");
}
}
+
+ @Test
+ void suppressInstrumentation() {
+ TestSpanData testSpanData = spanBuilder().build();
+
+ SuppressCatchingSender suppressCatchingSender = new SuppressCatchingSender(Encoding.JSON);
+ ZipkinSpanExporter zipkinSpanExporter =
+ new ZipkinSpanExporter(
+ new ZipkinSpanExporterBuilder(),
+ mockEncoder,
+ suppressCatchingSender,
+ MeterProvider::noop,
+ mockTransformer);
+
+ byte[] someBytes = new byte[0];
+ Span zipkinSpan =
+ zipkinSpanBuilder(Span.Kind.SERVER, localIp)
+ .putTag(OtelToZipkinSpanTransformer.OTEL_STATUS_CODE, "OK")
+ .build();
+ when(mockTransformer.generateSpan(testSpanData)).thenReturn(zipkinSpan);
+ when(mockEncoder.encode(zipkinSpan)).thenReturn(someBytes);
+
+ zipkinSpanExporter.export(Collections.singleton(testSpanData));
+
+ // Instrumentation should be suppressed on send, to avoid incidental spans related to span
+ // export.
+ assertTrue(suppressCatchingSender.sent.get());
+ assertTrue(suppressCatchingSender.suppressed.get());
+ }
+
+ static class SuppressCatchingSender extends BytesMessageSender.Base {
+
+ final AtomicBoolean sent = new AtomicBoolean();
+ final AtomicBoolean suppressed = new AtomicBoolean();
+
+ protected SuppressCatchingSender(Encoding encoding) {
+ super(encoding);
+ }
+
+ @Override
+ public int messageMaxBytes() {
+ return 1024;
+ }
+
+ @Override
+ public void send(List list) throws IOException {
+ sent.set(true);
+ suppressed.set(InstrumentationUtil.shouldSuppressInstrumentation(Context.current()));
+ }
+
+ @Override
+ public void close() throws IOException {}
+ }
}
From 023c8cc291ae4195aacef9cb5c9e0ddceb689bf7 Mon Sep 17 00:00:00 2001
From: SylvainJuge <763082+SylvainJuge@users.noreply.github.com>
Date: Mon, 19 Aug 2024 20:58:23 +0200
Subject: [PATCH 09/42] Fix broken markdown links (#6655)
---
sdk-extensions/incubator/README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sdk-extensions/incubator/README.md b/sdk-extensions/incubator/README.md
index cfc76184c31..abdb90cf9a7 100644
--- a/sdk-extensions/incubator/README.md
+++ b/sdk-extensions/incubator/README.md
@@ -4,7 +4,7 @@ This artifact contains experimental code related to the trace and metric SDKs.
## File Configuration
-Allows for YAML based file configuration of `OpenTelemetrySdk` as defined in the [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/file-configuration.md).
+Allows for YAML based file configuration of `OpenTelemetrySdk` as defined in the [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/data-model.md#file-based-configuration-model).
Usage:
@@ -18,7 +18,7 @@ try (FileInputStream yamlConfigFileInputStream = new FileInputStream("/path/to/c
```
Notes:
-* Environment variable substitution is supported as [defined in the spec](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/file-configuration.md#environment-variable-substitution)
+* Environment variable substitution is supported as [defined in the spec](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/data-model.md#environment-variable-substitution)
* Currently, there is no support for the SPIs defined in [opentelemetry-sdk-extension-autoconfigure-spi](../autoconfigure-spi). Only built in samplers, processors, exporters, etc can be configured.
* You can use file configuration with [autoconfigure](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure#file-configuration) to specify a configuration file via environment variable, e.g. `OTEL_EXPERIMENTAL_CONFIG_FILE=/path/to/config.yaml`.
From 4751c07a19af68a7df69027da398dc868fa5494f Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 19 Aug 2024 14:32:48 -0500
Subject: [PATCH 10/42] Update dependency com.google.guava:guava-bom to
v33.3.0-jre (#6653)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
dependencyManagement/build.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts
index 35343491d23..7caf4c60755 100644
--- a/dependencyManagement/build.gradle.kts
+++ b/dependencyManagement/build.gradle.kts
@@ -9,7 +9,7 @@ rootProject.extra["versions"] = dependencyVersions
val DEPENDENCY_BOMS = listOf(
"com.fasterxml.jackson:jackson-bom:2.17.2",
- "com.google.guava:guava-bom:33.2.1-jre",
+ "com.google.guava:guava-bom:33.3.0-jre",
"com.google.protobuf:protobuf-bom:3.25.4",
"com.linecorp.armeria:armeria-bom:1.30.0",
"com.squareup.okhttp3:okhttp-bom:4.12.0",
From e94c0d133b7ec011d35989f89063a3ff5249f367 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 19 Aug 2024 14:33:13 -0500
Subject: [PATCH 11/42] Update dependency
com.google.api.grpc:proto-google-common-protos to v2.43.0 (#6651)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
dependencyManagement/build.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts
index 7caf4c60755..d3d9bdd13ce 100644
--- a/dependencyManagement/build.gradle.kts
+++ b/dependencyManagement/build.gradle.kts
@@ -56,7 +56,7 @@ val DEPENDENCIES = listOf(
"io.prometheus:simpleclient_httpserver:${prometheusClientVersion}",
"javax.annotation:javax.annotation-api:1.3.2",
"com.github.stefanbirkner:system-rules:1.19.0",
- "com.google.api.grpc:proto-google-common-protos:2.42.0",
+ "com.google.api.grpc:proto-google-common-protos:2.43.0",
"com.google.code.findbugs:jsr305:3.0.2",
"com.google.guava:guava-beta-checker:1.0",
"com.sun.net.httpserver:http:20070405",
From df7bda64e66b681fd8d6a5d832c666055d969073 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 19 Aug 2024 14:33:25 -0500
Subject: [PATCH 12/42] Update dependency com.google.guava:guava to v33.3.0-jre
(#6652)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
buildSrc/build.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index cd5bb0c12d5..d85c65767de 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -55,7 +55,7 @@ dependencies {
// When updating, update above in plugins too
implementation("com.diffplug.spotless:spotless-plugin-gradle:6.25.0")
// Needed for japicmp but not automatically brought in for some reason.
- implementation("com.google.guava:guava:33.2.1-jre")
+ implementation("com.google.guava:guava:33.3.0-jre")
implementation("com.squareup:javapoet:1.13.0")
implementation("com.squareup.wire:wire-compiler")
implementation("com.squareup.wire:wire-gradle-plugin")
From d7626e32d422b5c2d931154107cfb844f35e79f0 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 19 Aug 2024 15:59:23 -0500
Subject: [PATCH 13/42] Update dependency com.uber.nullaway:nullaway to v0.11.2
(#6657)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
dependencyManagement/build.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts
index d3d9bdd13ce..9eacbb3bbfa 100644
--- a/dependencyManagement/build.gradle.kts
+++ b/dependencyManagement/build.gradle.kts
@@ -61,7 +61,7 @@ val DEPENDENCIES = listOf(
"com.google.guava:guava-beta-checker:1.0",
"com.sun.net.httpserver:http:20070405",
"com.tngtech.archunit:archunit-junit5:1.3.0",
- "com.uber.nullaway:nullaway:0.11.1",
+ "com.uber.nullaway:nullaway:0.11.2",
"edu.berkeley.cs.jqf:jqf-fuzz:1.7", // jqf-fuzz version 1.8+ requires Java 11+
"eu.rekawek.toxiproxy:toxiproxy-java:2.1.7",
"io.github.netmikey.logunit:logunit-jul:2.0.0",
From 3e8092d086967fa24a0559044651781403033313 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 19 Aug 2024 15:59:42 -0500
Subject: [PATCH 14/42] Update plugin com.gradle.develocity to v3.18 (#6656)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
settings.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 4c02af73c6f..1ad4058a096 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,7 +1,7 @@
pluginManagement {
plugins {
id("com.gradleup.shadow") version "8.3.0"
- id("com.gradle.develocity") version "3.17.6"
+ id("com.gradle.develocity") version "3.18"
id("de.undercouch.download") version "5.6.0"
id("org.jsonschema2pojo") version "1.2.1"
id("io.github.gradle-nexus.publish-plugin") version "2.0.0"
From d4b10a89a05e0bb7c017fc51dc5cfd86b7b773ea Mon Sep 17 00:00:00 2001
From: SylvainJuge <763082+SylvainJuge@users.noreply.github.com>
Date: Tue, 20 Aug 2024 19:30:20 +0200
Subject: [PATCH 15/42] add ns and us for config duration units (#6654)
Co-authored-by: Jack Berg
---
.../spi/internal/DefaultConfigProperties.java | 6 +++++-
.../spi/internal/ConfigPropertiesTest.java | 16 ++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java
index b8673993fe3..af0e4bae2bf 100644
--- a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java
+++ b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java
@@ -159,7 +159,7 @@ public Duration getDuration(String name) {
try {
long rawNumber = Long.parseLong(numberString.trim());
TimeUnit unit = getDurationUnit(unitString.trim());
- return Duration.ofMillis(TimeUnit.MILLISECONDS.convert(rawNumber, unit));
+ return Duration.ofNanos(TimeUnit.NANOSECONDS.convert(rawNumber, unit));
} catch (NumberFormatException ex) {
throw new ConfigurationException(
"Invalid duration property "
@@ -256,6 +256,10 @@ private static List filterBlanksAndNulls(String[] values) {
/** Returns the TimeUnit associated with a unit string. Defaults to milliseconds. */
private static TimeUnit getDurationUnit(String unitString) {
switch (unitString) {
+ case "us":
+ return TimeUnit.MICROSECONDS;
+ case "ns":
+ return TimeUnit.NANOSECONDS;
case "": // Fallthrough expected
case "ms":
return TimeUnit.MILLISECONDS;
diff --git a/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java b/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java
index e0fe198dc9e..78cc6806c08 100644
--- a/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java
+++ b/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java
@@ -185,8 +185,24 @@ void invalidDuration() {
.hasMessage("Invalid duration property duration=9mm. Invalid duration string, found: mm");
}
+ @Test
+ void durationNegativeParsing() {
+ assertThat(
+ DefaultConfigProperties.createFromMap(Collections.singletonMap("duration", "-41"))
+ .getDuration("duration"))
+ .isEqualTo(Duration.ofMillis(-41));
+ }
+
@Test
void durationUnitParsing() {
+ assertThat(
+ DefaultConfigProperties.createFromMap(Collections.singletonMap("duration", "3ns"))
+ .getDuration("duration"))
+ .isEqualTo(Duration.ofNanos(3));
+ assertThat(
+ DefaultConfigProperties.createFromMap(Collections.singletonMap("duration", "2us"))
+ .getDuration("duration"))
+ .isEqualTo(Duration.ofNanos(2000));
assertThat(
DefaultConfigProperties.createFromMap(Collections.singletonMap("duration", "1"))
.getDuration("duration"))
From dc4cc270091a7dae3b0a49a47761da51bb75f29f Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 20 Aug 2024 16:16:11 -0500
Subject: [PATCH 16/42] Update dependency
io.opentelemetry.semconv:opentelemetry-semconv-incubating to v1.27.0-alpha
(#6660)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
dependencyManagement/build.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts
index 9eacbb3bbfa..206bc3af84e 100644
--- a/dependencyManagement/build.gradle.kts
+++ b/dependencyManagement/build.gradle.kts
@@ -67,7 +67,7 @@ val DEPENDENCIES = listOf(
"io.github.netmikey.logunit:logunit-jul:2.0.0",
"io.jaegertracing:jaeger-client:1.8.1",
"io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:1.29.0-alpha",
- "io.opentelemetry.semconv:opentelemetry-semconv-incubating:1.26.0-alpha",
+ "io.opentelemetry.semconv:opentelemetry-semconv-incubating:1.27.0-alpha",
"io.opentelemetry.proto:opentelemetry-proto:1.3.2-alpha",
"io.opentracing:opentracing-api:0.33.0",
"io.opentracing:opentracing-noop:0.33.0",
From 97b3fa42f10d43a4f27ecdf2d809bca95fed4de3 Mon Sep 17 00:00:00 2001
From: jack-berg <34418638+jack-berg@users.noreply.github.com>
Date: Tue, 20 Aug 2024 22:05:51 -0500
Subject: [PATCH 17/42] Remove outdated ExtendedSpanBuilder javadoc example
(#6659)
---
.../api/incubator/trace/ExtendedSpanBuilder.java | 7 -------
1 file changed, 7 deletions(-)
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedSpanBuilder.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedSpanBuilder.java
index eec32904a4e..8474095f734 100644
--- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedSpanBuilder.java
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedSpanBuilder.java
@@ -29,13 +29,6 @@ public interface ExtendedSpanBuilder extends SpanBuilder {
* The span context will be extracted from the carrier
, which you usually get from
* HTTP headers of the metadata of a message you're processing.
*
- *
A typical usage would be:
- * ExtendedTracer.create(tracer)
- * .setSpanKind(SpanKind.SERVER)
- * .setParentFrom(propagators, carrier)
- * .run("my-span", () -> { ... });
- *
- *
* @param propagators provide the propagators from {@link OpenTelemetry#getPropagators()}
* @param carrier the string map where to extract the span context from
*/
From 97185c6fa09c6133c758bd62f931274e67d63a81 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 23 Aug 2024 18:39:22 -0700
Subject: [PATCH 18/42] Update dependency nl.jqno.equalsverifier:equalsverifier
to v3.16.2 (#6667)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
dependencyManagement/build.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts
index 206bc3af84e..3144535bf3e 100644
--- a/dependencyManagement/build.gradle.kts
+++ b/dependencyManagement/build.gradle.kts
@@ -73,7 +73,7 @@ val DEPENDENCIES = listOf(
"io.opentracing:opentracing-noop:0.33.0",
"io.prometheus:prometheus-metrics-exporter-httpserver:1.3.1",
"junit:junit:4.13.2",
- "nl.jqno.equalsverifier:equalsverifier:3.16.1",
+ "nl.jqno.equalsverifier:equalsverifier:3.16.2",
"org.awaitility:awaitility:4.2.2",
"org.bouncycastle:bcpkix-jdk15on:1.70",
"org.codehaus.mojo:animal-sniffer-annotations:1.24",
From c90175f1ae7d15fef6bac8eb6c95492c981daa61 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 23 Aug 2024 18:44:24 -0700
Subject: [PATCH 19/42] Update dependency
org.jetbrains.kotlin:kotlin-gradle-plugin to v2.0.20 (#6663)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
buildSrc/build.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index d85c65767de..5c2c974b841 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -65,7 +65,7 @@ dependencies {
implementation("me.champeau.jmh:jmh-gradle-plugin:0.7.2")
implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.0.1")
implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.0.0")
- implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.10")
+ implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20")
implementation("org.owasp:dependency-check-gradle:10.0.3")
implementation("ru.vyarus:gradle-animalsniffer-plugin:1.7.1")
}
From 7522bfe141524d52649b5c344c643104b57af608 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Sun, 25 Aug 2024 12:57:30 -0700
Subject: [PATCH 20/42] Update dependency checkstyle to v10.18.0 (#6670)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: John Watson
---
.../java/io/opentelemetry/api/baggage/propagation/Parser.java | 4 ++--
buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts | 2 +-
.../exporter/zipkin/LocalInetAddressSupplier.java | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Parser.java b/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Parser.java
index d6c26fcef27..c9d619c1bf3 100644
--- a/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Parser.java
+++ b/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Parser.java
@@ -12,11 +12,11 @@
/**
* Implements single-pass Baggage parsing in accordance with https://w3c.github.io/baggage/ Key /
- * value are restricted in accordance with https://www.ietf.org/rfc/rfc2616.txt
+ * value are restricted in accordance with https://www.ietf.org/rfc/rfc2616.txt.
*
* Note: following aspects are not specified in RFC: - some invalid elements (key or value) -
* parser will include valid ones, disregard invalid - empty "value" is regarded as invalid - meta -
- * anything besides element terminator (comma)
+ * anything besides element terminator (comma).
*/
class Parser {
diff --git a/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts
index f651f5c3021..929cbee6046 100644
--- a/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts
@@ -42,7 +42,7 @@ java {
checkstyle {
configDirectory.set(file("$rootDir/buildscripts/"))
- toolVersion = "10.17.0"
+ toolVersion = "10.18.0"
isIgnoreFailures = false
configProperties["rootDir"] = rootDir
}
diff --git a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/LocalInetAddressSupplier.java b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/LocalInetAddressSupplier.java
index 1ddb324edb6..a5376eb88a9 100644
--- a/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/LocalInetAddressSupplier.java
+++ b/exporters/zipkin/src/main/java/io/opentelemetry/exporter/zipkin/LocalInetAddressSupplier.java
@@ -30,7 +30,7 @@ public InetAddress get() {
return inetAddress;
}
- /** Logic borrowed from brave.internal.Platform.produceLocalEndpoint */
+ /** Logic borrowed from brave.internal.Platform.produceLocalEndpoint. */
@Nullable
private static InetAddress findLocalIp() {
try {
From 71124d2c5b0c3ae36500c82b2853f146b63f82cf Mon Sep 17 00:00:00 2001
From: Jarrod Robins
Date: Wed, 28 Aug 2024 05:49:11 +1000
Subject: [PATCH 21/42] Return status code exceptions via CompletableResultCode
in GrpcExporter and HttpExporter (#6645)
---
.../internal/FailedExportException.java | 126 ++++++++++++++++++
.../exporter/internal/grpc/GrpcExporter.java | 70 ++++++----
.../exporter/internal/http/HttpExporter.java | 6 +-
.../AbstractGrpcTelemetryExporterTest.java | 61 ++++++++-
.../AbstractHttpTelemetryExporterTest.java | 58 ++++++--
.../okhttp/internal/OkHttpGrpcSender.java | 4 +-
.../okhttp/internal/OkHttpHttpSender.java | 7 +-
7 files changed, 284 insertions(+), 48 deletions(-)
create mode 100644 exporters/common/src/main/java/io/opentelemetry/exporter/internal/FailedExportException.java
diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/FailedExportException.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/FailedExportException.java
new file mode 100644
index 00000000000..74f66dbfa1f
--- /dev/null
+++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/FailedExportException.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.exporter.internal;
+
+import io.opentelemetry.exporter.internal.grpc.GrpcResponse;
+import io.opentelemetry.exporter.internal.http.HttpSender;
+import javax.annotation.Nullable;
+
+/**
+ * Represents the failure of a gRPC or HTTP exporter.
+ *
+ * This class is internal and is hence not for public use. Its APIs are unstable and can change
+ * at any time.
+ */
+public abstract class FailedExportException extends Exception {
+
+ private static final long serialVersionUID = 6988924855140178789L;
+
+ private FailedExportException(@Nullable Throwable cause) {
+ super(cause);
+ }
+
+ /** Indicates an HTTP export failed after receiving a response from the server. */
+ public static HttpExportException httpFailedWithResponse(HttpSender.Response response) {
+ return new HttpExportException(response, null);
+ }
+
+ /** Indicates an HTTP export failed exceptionally without receiving a response from the server. */
+ public static HttpExportException httpFailedExceptionally(Throwable cause) {
+ return new HttpExportException(null, cause);
+ }
+
+ /** Indicates a gRPC export failed after receiving a response from the server. */
+ public static GrpcExportException grpcFailedWithResponse(GrpcResponse response) {
+ return new GrpcExportException(response, null);
+ }
+
+ /** Indicates a gRPC export failed exceptionally without receiving a response from the server. */
+ public static GrpcExportException grpcFailedExceptionally(Throwable cause) {
+ return new GrpcExportException(null, cause);
+ }
+
+ /** Returns true if the export failed with a response from the server. */
+ public abstract boolean failedWithResponse();
+
+ /** Represents the failure of an HTTP exporter. */
+ public static final class HttpExportException extends FailedExportException {
+
+ private static final long serialVersionUID = -6787390183017184775L;
+
+ @Nullable private final HttpSender.Response response;
+ @Nullable private final Throwable cause;
+
+ private HttpExportException(@Nullable HttpSender.Response response, @Nullable Throwable cause) {
+ super(cause);
+ this.response = response;
+ this.cause = cause;
+ }
+
+ @Override
+ public boolean failedWithResponse() {
+ return response != null;
+ }
+
+ /**
+ * Returns the response if the export failed with a response from the server, or null if the
+ * export failed exceptionally with no response.
+ */
+ @Nullable
+ public HttpSender.Response getResponse() {
+ return response;
+ }
+
+ /**
+ * Returns the exceptional cause of failure, or null if the export failed with a response from
+ * the server.
+ */
+ @Nullable
+ @Override
+ public Throwable getCause() {
+ return cause;
+ }
+ }
+
+ /** Represents the failure of a gRPC exporter. */
+ public static final class GrpcExportException extends FailedExportException {
+
+ private static final long serialVersionUID = -9157548250286695364L;
+
+ @Nullable private final GrpcResponse response;
+ @Nullable private final Throwable cause;
+
+ private GrpcExportException(@Nullable GrpcResponse response, @Nullable Throwable cause) {
+ super(cause);
+ this.response = response;
+ this.cause = cause;
+ }
+
+ @Override
+ public boolean failedWithResponse() {
+ return response != null;
+ }
+
+ /**
+ * Returns the response if the export failed with a response from the server, or null if the
+ * export failed exceptionally with no response.
+ */
+ @Nullable
+ public GrpcResponse getResponse() {
+ return response;
+ }
+
+ /**
+ * Returns the exceptional cause of failure, or null if the export failed with a response from
+ * the server.
+ */
+ @Nullable
+ @Override
+ public Throwable getCause() {
+ return cause;
+ }
+ }
+}
diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporter.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporter.java
index 6a74ba5df8a..e8101049b9f 100644
--- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporter.java
+++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporter.java
@@ -7,9 +7,11 @@
import static io.opentelemetry.exporter.internal.grpc.GrpcExporterUtil.GRPC_STATUS_UNAVAILABLE;
import static io.opentelemetry.exporter.internal.grpc.GrpcExporterUtil.GRPC_STATUS_UNIMPLEMENTED;
+import static io.opentelemetry.exporter.internal.grpc.GrpcExporterUtil.GRPC_STATUS_UNKNOWN;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.ExporterMetrics;
+import io.opentelemetry.exporter.internal.FailedExportException;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.internal.ThrottlingLogger;
@@ -66,39 +68,17 @@ public CompletableResultCode export(T exportRequest, int numItems) {
},
(response, throwable) -> {
exporterMetrics.addFailed(numItems);
+
+ logFailureMessage(response, throwable);
+
switch (response.grpcStatusValue()) {
- case GRPC_STATUS_UNIMPLEMENTED:
- if (loggedUnimplemented.compareAndSet(false, true)) {
- GrpcExporterUtil.logUnimplemented(
- internalLogger, type, response.grpcStatusDescription());
- }
- break;
- case GRPC_STATUS_UNAVAILABLE:
- logger.log(
- Level.SEVERE,
- "Failed to export "
- + type
- + "s. Server is UNAVAILABLE. "
- + "Make sure your collector is running and reachable from this network. "
- + "Full error message:"
- + response.grpcStatusDescription());
+ case GRPC_STATUS_UNKNOWN:
+ result.failExceptionally(FailedExportException.grpcFailedExceptionally(throwable));
break;
default:
- logger.log(
- Level.WARNING,
- "Failed to export "
- + type
- + "s. Server responded with gRPC status code "
- + response.grpcStatusValue()
- + ". Error message: "
- + response.grpcStatusDescription());
+ result.failExceptionally(FailedExportException.grpcFailedWithResponse(response));
break;
}
- if (logger.isLoggable(Level.FINEST)) {
- logger.log(
- Level.FINEST, "Failed to export " + type + "s. Details follow: " + throwable);
- }
- result.fail();
});
return result;
@@ -111,4 +91,38 @@ public CompletableResultCode shutdown() {
}
return grpcSender.shutdown();
}
+
+ private void logFailureMessage(GrpcResponse response, Throwable throwable) {
+ switch (response.grpcStatusValue()) {
+ case GRPC_STATUS_UNIMPLEMENTED:
+ if (loggedUnimplemented.compareAndSet(false, true)) {
+ GrpcExporterUtil.logUnimplemented(internalLogger, type, response.grpcStatusDescription());
+ }
+ break;
+ case GRPC_STATUS_UNAVAILABLE:
+ logger.log(
+ Level.SEVERE,
+ "Failed to export "
+ + type
+ + "s. Server is UNAVAILABLE. "
+ + "Make sure your collector is running and reachable from this network. "
+ + "Full error message:"
+ + response.grpcStatusDescription());
+ break;
+ default:
+ logger.log(
+ Level.WARNING,
+ "Failed to export "
+ + type
+ + "s. Server responded with gRPC status code "
+ + response.grpcStatusValue()
+ + ". Error message: "
+ + response.grpcStatusDescription());
+ break;
+ }
+
+ if (logger.isLoggable(Level.FINEST)) {
+ logger.log(Level.FINEST, "Failed to export " + type + "s. Details follow: " + throwable);
+ }
+ }
}
diff --git a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporter.java b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporter.java
index befb579d964..d0361eaecca 100644
--- a/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporter.java
+++ b/exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporter.java
@@ -7,6 +7,7 @@
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.internal.ExporterMetrics;
+import io.opentelemetry.exporter.internal.FailedExportException;
import io.opentelemetry.exporter.internal.grpc.GrpcExporterUtil;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.sdk.common.CompletableResultCode;
@@ -90,7 +91,8 @@ public CompletableResultCode export(T exportRequest, int numItems) {
+ statusCode
+ ". Error message: "
+ status);
- result.fail();
+
+ result.failExceptionally(FailedExportException.httpFailedWithResponse(httpResponse));
},
e -> {
exporterMetrics.addFailed(numItems);
@@ -101,7 +103,7 @@ public CompletableResultCode export(T exportRequest, int numItems) {
+ "s. The request could not be executed. Full error message: "
+ e.getMessage(),
e);
- result.fail();
+ result.failExceptionally(FailedExportException.httpFailedExceptionally(e));
});
return result;
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 a62911a54b0..5950d8c00aa 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
@@ -25,9 +25,11 @@
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
import io.github.netmikey.logunit.api.LogCapturer;
import io.grpc.ManagedChannel;
+import io.opentelemetry.exporter.internal.FailedExportException;
import io.opentelemetry.exporter.internal.TlsUtil;
import io.opentelemetry.exporter.internal.compression.GzipCompressor;
import io.opentelemetry.exporter.internal.grpc.GrpcExporter;
+import io.opentelemetry.exporter.internal.grpc.GrpcResponse;
import io.opentelemetry.exporter.internal.grpc.MarshalerServiceStub;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.otlp.testing.internal.compressor.Base64Compressor;
@@ -66,6 +68,7 @@
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
+import org.assertj.core.api.Assertions;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.assertj.core.api.iterable.ThrowingExtractor;
import org.junit.jupiter.api.AfterAll;
@@ -486,6 +489,7 @@ void connectTimeout() {
CompletableResultCode result =
exporter.export(Collections.singletonList(generateFakeTelemetry()));
assertThat(result.join(10, TimeUnit.SECONDS).isSuccess()).isFalse();
+
// Assert that the export request fails well before the default connect timeout of 10s
assertThat(System.currentTimeMillis() - startTimeMillis)
.isLessThan(TimeUnit.SECONDS.toMillis(1));
@@ -540,17 +544,33 @@ void doubleShutdown() {
@Test
@SuppressLogger(GrpcExporter.class)
void error() {
- addGrpcError(13, null);
+ int statusCode = 13;
+ addGrpcError(statusCode, null);
TelemetryExporter exporter = nonRetryingExporter();
try {
- assertThat(
- exporter
- .export(Collections.singletonList(generateFakeTelemetry()))
- .join(10, TimeUnit.SECONDS)
- .isSuccess())
- .isFalse();
+ CompletableResultCode result =
+ exporter
+ .export(Collections.singletonList(generateFakeTelemetry()))
+ .join(10, TimeUnit.SECONDS);
+
+ assertThat(result.isSuccess()).isFalse();
+
+ assertThat(result.getFailureThrowable())
+ .asInstanceOf(
+ InstanceOfAssertFactories.throwable(FailedExportException.GrpcExportException.class))
+ .returns(true, Assertions.from(FailedExportException::failedWithResponse))
+ .satisfies(
+ ex -> {
+ assertThat(ex.getResponse())
+ .isNotNull()
+ .extracting(GrpcResponse::grpcStatusValue)
+ .isEqualTo(statusCode);
+
+ assertThat(ex.getCause()).isNull();
+ });
+
LoggingEvent log =
logs.assertContains(
"Failed to export "
@@ -562,6 +582,33 @@ void error() {
}
}
+ @Test
+ @SuppressLogger(GrpcExporter.class)
+ void errorWithUnknownError() {
+ addGrpcError(2, null);
+
+ TelemetryExporter exporter = nonRetryingExporter();
+
+ try {
+ assertThat(
+ exporter
+ .export(Collections.singletonList(generateFakeTelemetry()))
+ .join(10, TimeUnit.SECONDS)
+ .getFailureThrowable())
+ .asInstanceOf(
+ InstanceOfAssertFactories.throwable(FailedExportException.GrpcExportException.class))
+ .returns(false, Assertions.from(FailedExportException::failedWithResponse))
+ .satisfies(
+ ex -> {
+ assertThat(ex.getResponse()).isNull();
+
+ assertThat(ex.getCause()).isNotNull();
+ });
+ } finally {
+ exporter.shutdown();
+ }
+ }
+
@Test
@SuppressLogger(GrpcExporter.class)
void errorWithMessage() {
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 befa39af5f3..7f6bfff04b3 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
@@ -26,9 +26,11 @@
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.exporter.internal.FailedExportException;
import io.opentelemetry.exporter.internal.TlsUtil;
import io.opentelemetry.exporter.internal.compression.GzipCompressor;
import io.opentelemetry.exporter.internal.http.HttpExporter;
+import io.opentelemetry.exporter.internal.http.HttpSender;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.otlp.testing.internal.compressor.Base64Compressor;
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
@@ -72,6 +74,8 @@
import okio.GzipSource;
import okio.Okio;
import okio.Source;
+import org.assertj.core.api.Assertions;
+import org.assertj.core.api.InstanceOfAssertFactories;
import org.assertj.core.api.iterable.ThrowingExtractor;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
@@ -534,8 +538,22 @@ void connectTimeout() {
try {
long startTimeMillis = System.currentTimeMillis();
CompletableResultCode result =
- exporter.export(Collections.singletonList(generateFakeTelemetry()));
- assertThat(result.join(10, TimeUnit.SECONDS).isSuccess()).isFalse();
+ exporter
+ .export(Collections.singletonList(generateFakeTelemetry()))
+ .join(10, TimeUnit.SECONDS);
+
+ assertThat(result.isSuccess()).isFalse();
+
+ assertThat(result.getFailureThrowable())
+ .asInstanceOf(
+ InstanceOfAssertFactories.throwable(FailedExportException.HttpExportException.class))
+ .returns(false, Assertions.from(FailedExportException::failedWithResponse))
+ .satisfies(
+ ex -> {
+ assertThat(ex.getResponse()).isNull();
+ assertThat(ex.getCause()).isNotNull();
+ });
+
// Assert that the export request fails well before the default connect timeout of 10s
assertThat(System.currentTimeMillis() - startTimeMillis)
.isLessThan(TimeUnit.SECONDS.toMillis(1));
@@ -590,13 +608,35 @@ void doubleShutdown() {
@Test
@SuppressLogger(HttpExporter.class)
void error() {
- addHttpError(500);
- assertThat(
- exporter
- .export(Collections.singletonList(generateFakeTelemetry()))
- .join(10, TimeUnit.SECONDS)
- .isSuccess())
- .isFalse();
+ int statusCode = 500;
+ addHttpError(statusCode);
+ CompletableResultCode result =
+ exporter
+ .export(Collections.singletonList(generateFakeTelemetry()))
+ .join(10, TimeUnit.SECONDS);
+
+ assertThat(result.isSuccess()).isFalse();
+
+ assertThat(result.getFailureThrowable())
+ .asInstanceOf(
+ InstanceOfAssertFactories.throwable(FailedExportException.HttpExportException.class))
+ .returns(true, Assertions.from(FailedExportException::failedWithResponse))
+ .satisfies(
+ ex -> {
+ assertThat(ex.getResponse())
+ .isNotNull()
+ .satisfies(
+ response -> {
+ assertThat(response)
+ .extracting(HttpSender.Response::statusCode)
+ .isEqualTo(statusCode);
+
+ assertThatCode(response::responseBody).doesNotThrowAnyException();
+ });
+
+ assertThat(ex.getCause()).isNull();
+ });
+
LoggingEvent log =
logs.assertContains(
"Failed to export "
diff --git a/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpGrpcSender.java b/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpGrpcSender.java
index 7fb04c4e513..a622d95ac6c 100644
--- a/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpGrpcSender.java
+++ b/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpGrpcSender.java
@@ -136,7 +136,9 @@ public void onFailure(Call call, IOException e) {
if (description == null) {
description = "";
}
- onError.accept(GrpcResponse.create(2 /* UNKNOWN */, description), e);
+ onError.accept(
+ GrpcResponse.create(GrpcExporterUtil.GRPC_STATUS_UNKNOWN, description),
+ e);
}
@Override
diff --git a/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpHttpSender.java b/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpHttpSender.java
index 1a0263a13de..20af7127451 100644
--- a/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpHttpSender.java
+++ b/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/OkHttpHttpSender.java
@@ -143,6 +143,8 @@ public void onResponse(Call call, okhttp3.Response response) {
try (ResponseBody body = response.body()) {
onResponse.accept(
new Response() {
+ @Nullable private byte[] bodyBytes;
+
@Override
public int statusCode() {
return response.code();
@@ -155,7 +157,10 @@ public String statusMessage() {
@Override
public byte[] responseBody() throws IOException {
- return body.bytes();
+ if (bodyBytes == null) {
+ bodyBytes = body.bytes();
+ }
+ return bodyBytes;
}
});
}
From 902c46e2a74239bc13e140f8d70a0106c8f10ee1 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 27 Aug 2024 20:25:20 -0700
Subject: [PATCH 22/42] Update gradle/actions action to v4.0.1 (#6673)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
.github/workflows/gradle-wrapper-validation.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml
index e659ca0fa97..c55680e34b8 100644
--- a/.github/workflows/gradle-wrapper-validation.yml
+++ b/.github/workflows/gradle-wrapper-validation.yml
@@ -13,4 +13,4 @@ jobs:
steps:
- uses: actions/checkout@v4
- - uses: gradle/actions/wrapper-validation@v4.0.0
+ - uses: gradle/actions/wrapper-validation@v4.0.1
From 05fe136cb3d90de26bed5f865bb7d519680e5be2 Mon Sep 17 00:00:00 2001
From: jack-berg <34418638+jack-berg@users.noreply.github.com>
Date: Wed, 28 Aug 2024 14:42:37 -0500
Subject: [PATCH 23/42] Add file configuration ComponentProvider support for
resources (#6625)
---
.../sdk/autoconfigure/internal/SpiHelper.java | 4 +-
.../incubator/fileconfig/ResourceFactory.java | 95 +++++++++++++++++--
...OpenTelemetryConfigurationFactoryTest.java | 4 +
.../fileconfig/ResourceFactoryTest.java | 17 +++-
.../component/ResourceComponentProvider.java | 27 ++++++
...ResourceOrderedFirstComponentProvider.java | 33 +++++++
...esourceOrderedSecondComponentProvider.java | 34 +++++++
...toconfigure.spi.internal.ComponentProvider | 3 +
8 files changed, 203 insertions(+), 14 deletions(-)
create mode 100644 sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceComponentProvider.java
create mode 100644 sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceOrderedFirstComponentProvider.java
create mode 100644 sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceOrderedSecondComponentProvider.java
diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/SpiHelper.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/SpiHelper.java
index bd3bfc13f04..c8c40e63e07 100644
--- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/SpiHelper.java
+++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/SpiHelper.java
@@ -81,9 +81,9 @@ public NamedSpiManager loadConfigurable(
}
/**
- * Find a registered {@link ComponentProvider} which {@link ComponentProvider#getType()} matching
+ * Find a registered {@link ComponentProvider} with {@link ComponentProvider#getType()} matching
* {@code type}, {@link ComponentProvider#getName()} matching {@code name}, and call {@link
- * ComponentProvider#create(StructuredConfigProperties)} with the given {@code model}.
+ * ComponentProvider#create(StructuredConfigProperties)} with the given {@code config}.
*
* @throws ConfigurationException if no matching providers are found, or if multiple are found
* (i.e. conflict), or if {@link ComponentProvider#create(StructuredConfigProperties)} throws
diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ResourceFactory.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ResourceFactory.java
index 04a0de2bcac..eaaf1ae98b3 100644
--- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ResourceFactory.java
+++ b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ResourceFactory.java
@@ -6,14 +6,25 @@
package io.opentelemetry.sdk.extension.incubator.fileconfig;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
+import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
+import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Attributes;
-import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Resource;
-import io.opentelemetry.sdk.resources.ResourceBuilder;
+import io.opentelemetry.sdk.resources.Resource;
import java.io.Closeable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import java.util.stream.Collectors;
-final class ResourceFactory implements Factory {
+final class ResourceFactory
+ implements Factory<
+ io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Resource, Resource> {
+ private static final StructuredConfigProperties EMPTY_CONFIG =
+ FileConfiguration.toConfigProperties(Collections.emptyMap());
private static final ResourceFactory INSTANCE = new ResourceFactory();
private ResourceFactory() {}
@@ -23,16 +34,82 @@ static ResourceFactory getInstance() {
}
@Override
- public io.opentelemetry.sdk.resources.Resource create(
- Resource model, SpiHelper spiHelper, List closeables) {
- ResourceBuilder builder = io.opentelemetry.sdk.resources.Resource.getDefault().toBuilder();
+ public Resource create(
+ io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Resource model,
+ SpiHelper spiHelper,
+ List closeables) {
+ Resource result = Resource.getDefault();
+
+ List resourceDetectorResources = loadFromResourceDetectors(spiHelper);
+ for (Resource resourceProviderResource : resourceDetectorResources) {
+ result = result.merge(resourceProviderResource);
+ }
Attributes attributesModel = model.getAttributes();
if (attributesModel != null) {
- builder.putAll(
- AttributesFactory.getInstance().create(attributesModel, spiHelper, closeables));
+ result =
+ result.toBuilder()
+ .putAll(
+ AttributesFactory.getInstance().create(attributesModel, spiHelper, closeables))
+ .build();
}
- return builder.build();
+ return result;
+ }
+
+ /**
+ * Load resources from resource detectors, in order of lowest priority to highest priority.
+ *
+ * In file configuration, a resource detector is a {@link ComponentProvider} with {@link
+ * ComponentProvider#getType()} set to {@link Resource}. Unlike other {@link ComponentProvider}s,
+ * the resource detector version does not use {@link ComponentProvider#getName()} (except for
+ * debug messages), and {@link ComponentProvider#create(StructuredConfigProperties)} is called
+ * with an empty instance. Additionally, the {@link Ordered#order()} value is respected for
+ * resource detectors which implement {@link Ordered}.
+ */
+ @SuppressWarnings("rawtypes")
+ private static List loadFromResourceDetectors(SpiHelper spiHelper) {
+ List componentProviders = spiHelper.load(ComponentProvider.class);
+ List resourceAndOrders = new ArrayList<>();
+ for (ComponentProvider> componentProvider : componentProviders) {
+ if (componentProvider.getType() != Resource.class) {
+ continue;
+ }
+ Resource resource;
+ try {
+ resource = (Resource) componentProvider.create(EMPTY_CONFIG);
+ } catch (Throwable throwable) {
+ throw new ConfigurationException(
+ "Error configuring "
+ + Resource.class.getName()
+ + " with name \""
+ + componentProvider.getName()
+ + "\"",
+ throwable);
+ }
+ int order =
+ (componentProvider instanceof Ordered) ? ((Ordered) componentProvider).order() : 0;
+ resourceAndOrders.add(new ResourceAndOrder(resource, order));
+ }
+ resourceAndOrders.sort(Comparator.comparing(ResourceAndOrder::order));
+ return resourceAndOrders.stream().map(ResourceAndOrder::resource).collect(Collectors.toList());
+ }
+
+ private static final class ResourceAndOrder {
+ private final Resource resource;
+ private final int order;
+
+ private ResourceAndOrder(Resource resource, int order) {
+ this.resource = resource;
+ this.order = order;
+ }
+
+ private Resource resource() {
+ return resource;
+ }
+
+ private int order() {
+ return order;
+ }
}
}
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/OpenTelemetryConfigurationFactoryTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/OpenTelemetryConfigurationFactoryTest.java
index da3cc7cd013..7de50047ece 100644
--- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/OpenTelemetryConfigurationFactoryTest.java
+++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/OpenTelemetryConfigurationFactoryTest.java
@@ -140,6 +140,10 @@ void create_Configured() {
io.opentelemetry.sdk.resources.Resource.getDefault().toBuilder()
.put("service.name", "my-service")
.put("key", "val")
+ // resource attributes from resource ComponentProviders
+ .put("color", "red")
+ .put("shape", "square")
+ .put("order", "second")
.build();
OpenTelemetrySdk expectedSdk =
OpenTelemetrySdk.builder()
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ResourceFactoryTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ResourceFactoryTest.java
index 37e494ee28a..584f908431c 100644
--- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ResourceFactoryTest.java
+++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ResourceFactoryTest.java
@@ -6,7 +6,7 @@
package io.opentelemetry.sdk.extension.incubator.fileconfig;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Attributes;
@@ -16,8 +16,11 @@
class ResourceFactoryTest {
+ private SpiHelper spiHelper = SpiHelper.create(MetricExporterFactoryTest.class.getClassLoader());
+
@Test
void create() {
+ spiHelper = spy(spiHelper);
assertThat(
ResourceFactory.getInstance()
.create(
@@ -26,13 +29,21 @@ void create() {
.withAttributes(
new Attributes()
.withServiceName("my-service")
- .withAdditionalProperty("key", "val")),
- mock(SpiHelper.class),
+ .withAdditionalProperty("key", "val")
+ // Should override shape attribute from ResourceComponentProvider
+ .withAdditionalProperty("shape", "circle")),
+ spiHelper,
Collections.emptyList()))
.isEqualTo(
Resource.getDefault().toBuilder()
.put("service.name", "my-service")
.put("key", "val")
+ .put("shape", "circle")
+ // From ResourceComponentProvider
+ .put("color", "red")
+ // From ResourceOrderedSecondComponentProvider, which takes priority over
+ // ResourceOrderedFirstComponentProvider
+ .put("order", "second")
.build());
}
}
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceComponentProvider.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceComponentProvider.java
new file mode 100644
index 00000000000..13b0e86c05a
--- /dev/null
+++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceComponentProvider.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.extension.incubator.fileconfig.component;
+
+import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
+import io.opentelemetry.sdk.resources.Resource;
+
+public class ResourceComponentProvider implements ComponentProvider {
+ @Override
+ public Class getType() {
+ return Resource.class;
+ }
+
+ @Override
+ public String getName() {
+ return "unused";
+ }
+
+ @Override
+ public Resource create(StructuredConfigProperties config) {
+ return Resource.builder().put("shape", "square").put("color", "red").build();
+ }
+}
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceOrderedFirstComponentProvider.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceOrderedFirstComponentProvider.java
new file mode 100644
index 00000000000..f2f41e5b955
--- /dev/null
+++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceOrderedFirstComponentProvider.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.extension.incubator.fileconfig.component;
+
+import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
+import io.opentelemetry.sdk.resources.Resource;
+
+public class ResourceOrderedFirstComponentProvider implements ComponentProvider, Ordered {
+ @Override
+ public Class getType() {
+ return Resource.class;
+ }
+
+ @Override
+ public String getName() {
+ return "unused";
+ }
+
+ @Override
+ public Resource create(StructuredConfigProperties config) {
+ return Resource.builder().put("order", "first").build();
+ }
+
+ @Override
+ public int order() {
+ return 1;
+ }
+}
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceOrderedSecondComponentProvider.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceOrderedSecondComponentProvider.java
new file mode 100644
index 00000000000..00017b2b7d4
--- /dev/null
+++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceOrderedSecondComponentProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.extension.incubator.fileconfig.component;
+
+import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
+import io.opentelemetry.sdk.resources.Resource;
+
+public class ResourceOrderedSecondComponentProvider
+ implements ComponentProvider, Ordered {
+ @Override
+ public Class getType() {
+ return Resource.class;
+ }
+
+ @Override
+ public String getName() {
+ return "unused";
+ }
+
+ @Override
+ public Resource create(StructuredConfigProperties config) {
+ return Resource.builder().put("order", "second").build();
+ }
+
+ @Override
+ public int order() {
+ return 2;
+ }
+}
diff --git a/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider b/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider
index 0dc2d209e1d..6ab8ffdecc3 100644
--- a/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider
+++ b/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider
@@ -1,3 +1,6 @@
io.opentelemetry.sdk.extension.incubator.fileconfig.component.MetricExporterComponentProvider
io.opentelemetry.sdk.extension.incubator.fileconfig.component.SpanExporterComponentProvider
io.opentelemetry.sdk.extension.incubator.fileconfig.component.LogRecordExporterComponentProvider
+io.opentelemetry.sdk.extension.incubator.fileconfig.component.ResourceComponentProvider
+io.opentelemetry.sdk.extension.incubator.fileconfig.component.ResourceOrderedFirstComponentProvider
+io.opentelemetry.sdk.extension.incubator.fileconfig.component.ResourceOrderedSecondComponentProvider
From 8495996d549a969ab2fece1f12a7d6bc0f84f17c Mon Sep 17 00:00:00 2001
From: jack-berg <34418638+jack-berg@users.noreply.github.com>
Date: Wed, 28 Aug 2024 14:59:04 -0500
Subject: [PATCH 24/42] Processor component provider (#6623)
---
.../fileconfig/LogRecordProcessorFactory.java | 24 ++++++--
.../fileconfig/SpanProcessorFactory.java | 24 ++++++--
.../LogRecordProcessorFactoryTest.java | 32 +++++++---
.../fileconfig/MetricExporterFactoryTest.java | 5 +-
.../fileconfig/SpanProcessorFactoryTest.java | 31 +++++++---
.../LogRecordProcessorComponentProvider.java | 47 ++++++++++++++
.../SpanProcessorComponentProvider.java | 61 +++++++++++++++++++
...toconfigure.spi.internal.ComponentProvider | 2 +
8 files changed, 200 insertions(+), 26 deletions(-)
create mode 100644 sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/LogRecordProcessorComponentProvider.java
create mode 100644 sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/SpanProcessorComponentProvider.java
diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/LogRecordProcessorFactory.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/LogRecordProcessorFactory.java
index 78183f19232..882db7db24f 100644
--- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/LogRecordProcessorFactory.java
+++ b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/LogRecordProcessorFactory.java
@@ -17,6 +17,7 @@
import java.io.Closeable;
import java.time.Duration;
import java.util.List;
+import java.util.Map;
final class LogRecordProcessorFactory
implements Factory<
@@ -73,11 +74,26 @@ public LogRecordProcessor create(
closeables, SimpleLogRecordProcessor.create(logRecordExporter));
}
- // TODO: add support for generic log record processors
if (!model.getAdditionalProperties().isEmpty()) {
- throw new ConfigurationException(
- "Unrecognized log record processor(s): "
- + model.getAdditionalProperties().keySet().stream().collect(joining(",", "[", "]")));
+ Map additionalProperties = model.getAdditionalProperties();
+ if (additionalProperties.size() > 1) {
+ throw new ConfigurationException(
+ "Invalid configuration - multiple log record processors set: "
+ + additionalProperties.keySet().stream().collect(joining(",", "[", "]")));
+ }
+ Map.Entry processorKeyValue =
+ additionalProperties.entrySet().stream()
+ .findFirst()
+ .orElseThrow(
+ () ->
+ new IllegalStateException("Missing processor. This is a programming error."));
+ LogRecordProcessor logRecordProcessor =
+ FileConfigUtil.loadComponent(
+ spiHelper,
+ LogRecordProcessor.class,
+ processorKeyValue.getKey(),
+ processorKeyValue.getValue());
+ return FileConfigUtil.addAndReturn(closeables, logRecordProcessor);
} else {
throw new ConfigurationException("log processor must be set");
}
diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SpanProcessorFactory.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SpanProcessorFactory.java
index d0c50ebaa61..9d2e4362078 100644
--- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SpanProcessorFactory.java
+++ b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SpanProcessorFactory.java
@@ -17,6 +17,7 @@
import java.io.Closeable;
import java.time.Duration;
import java.util.List;
+import java.util.Map;
final class SpanProcessorFactory
implements Factory<
@@ -70,11 +71,26 @@ public SpanProcessor create(
return FileConfigUtil.addAndReturn(closeables, SimpleSpanProcessor.create(spanExporter));
}
- // TODO: add support for generic span processors
if (!model.getAdditionalProperties().isEmpty()) {
- throw new ConfigurationException(
- "Unrecognized span processor(s): "
- + model.getAdditionalProperties().keySet().stream().collect(joining(",", "[", "]")));
+ Map additionalProperties = model.getAdditionalProperties();
+ if (additionalProperties.size() > 1) {
+ throw new ConfigurationException(
+ "Invalid configuration - multiple span processors set: "
+ + additionalProperties.keySet().stream().collect(joining(",", "[", "]")));
+ }
+ Map.Entry processorKeyValue =
+ additionalProperties.entrySet().stream()
+ .findFirst()
+ .orElseThrow(
+ () ->
+ new IllegalStateException("Missing processor. This is a programming error."));
+ SpanProcessor spanProcessor =
+ FileConfigUtil.loadComponent(
+ spiHelper,
+ SpanProcessor.class,
+ processorKeyValue.getKey(),
+ processorKeyValue.getValue());
+ return FileConfigUtil.addAndReturn(closeables, spanProcessor);
} else {
throw new ConfigurationException("span processor must be set");
}
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/LogRecordProcessorFactoryTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/LogRecordProcessorFactoryTest.java
index 06ad307ee06..31038580e82 100644
--- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/LogRecordProcessorFactoryTest.java
+++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/LogRecordProcessorFactoryTest.java
@@ -13,6 +13,7 @@
import io.opentelemetry.internal.testing.CleanupExtension;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
+import io.opentelemetry.sdk.extension.incubator.fileconfig.component.LogRecordProcessorComponentProvider;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchLogRecordProcessor;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordExporter;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordProcessor;
@@ -23,6 +24,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -137,19 +139,35 @@ void create_SimpleConfigured() {
}
@Test
- void create_SpiProcessor() {
- List closeables = new ArrayList<>();
-
+ void create_SpiProcessor_Unknown() {
assertThatThrownBy(
() ->
LogRecordProcessorFactory.getInstance()
.create(
new LogRecordProcessor()
- .withAdditionalProperty("test", ImmutableMap.of("key1", "value1")),
+ .withAdditionalProperty(
+ "unknown_key", ImmutableMap.of("key1", "value1")),
spiHelper,
- closeables))
+ new ArrayList<>()))
.isInstanceOf(ConfigurationException.class)
- .hasMessage("Unrecognized log record processor(s): [test]");
- cleanup.addCloseables(closeables);
+ .hasMessage(
+ "No component provider detected for io.opentelemetry.sdk.logs.LogRecordProcessor with name \"unknown_key\".");
+ }
+
+ @Test
+ void create_SpiExporter_Valid() {
+ io.opentelemetry.sdk.logs.LogRecordProcessor logRecordProcessor =
+ LogRecordProcessorFactory.getInstance()
+ .create(
+ new LogRecordProcessor()
+ .withAdditionalProperty("test", ImmutableMap.of("key1", "value1")),
+ spiHelper,
+ new ArrayList<>());
+ assertThat(logRecordProcessor)
+ .isInstanceOf(LogRecordProcessorComponentProvider.TestLogRecordProcessor.class);
+ Assertions.assertThat(
+ ((LogRecordProcessorComponentProvider.TestLogRecordProcessor) logRecordProcessor)
+ .config.getString("key1"))
+ .isEqualTo("value1");
}
}
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/MetricExporterFactoryTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/MetricExporterFactoryTest.java
index 8356339e063..64f0db469ec 100644
--- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/MetricExporterFactoryTest.java
+++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/MetricExporterFactoryTest.java
@@ -210,7 +210,7 @@ void create_PrometheusExporter() {
.MetricExporter()
.withPrometheus(new Prometheus()),
spiHelper,
- new ArrayList<>()))
+ closeables))
.isInstanceOf(ConfigurationException.class)
.hasMessage("prometheus exporter not supported in this context");
cleanup.addCloseables(closeables);
@@ -218,8 +218,6 @@ void create_PrometheusExporter() {
@Test
void create_SpiExporter_Unknown() {
- List closeables = new ArrayList<>();
-
assertThatThrownBy(
() ->
MetricExporterFactory.getInstance()
@@ -233,7 +231,6 @@ void create_SpiExporter_Unknown() {
.isInstanceOf(ConfigurationException.class)
.hasMessage(
"No component provider detected for io.opentelemetry.sdk.metrics.export.MetricExporter with name \"unknown_key\".");
- cleanup.addCloseables(closeables);
}
@Test
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SpanProcessorFactoryTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SpanProcessorFactoryTest.java
index 972e0a137f9..19426bd1244 100644
--- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SpanProcessorFactoryTest.java
+++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SpanProcessorFactoryTest.java
@@ -13,6 +13,7 @@
import io.opentelemetry.internal.testing.CleanupExtension;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
+import io.opentelemetry.sdk.extension.incubator.fileconfig.component.SpanProcessorComponentProvider;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchSpanProcessor;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Otlp;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleSpanProcessor;
@@ -23,6 +24,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -137,19 +139,34 @@ void create_SimpleConfigured() {
}
@Test
- void create_SpiProcessor() {
- List closeables = new ArrayList<>();
-
+ void create_SpiProcessor_Unknown() {
assertThatThrownBy(
() ->
SpanProcessorFactory.getInstance()
.create(
new SpanProcessor()
- .withAdditionalProperty("test", ImmutableMap.of("key1", "value1")),
+ .withAdditionalProperty(
+ "unknown_key", ImmutableMap.of("key1", "value1")),
spiHelper,
- closeables))
+ new ArrayList<>()))
.isInstanceOf(ConfigurationException.class)
- .hasMessage("Unrecognized span processor(s): [test]");
- cleanup.addCloseables(closeables);
+ .hasMessage(
+ "No component provider detected for io.opentelemetry.sdk.trace.SpanProcessor with name \"unknown_key\".");
+ }
+
+ @Test
+ void create_SpiExporter_Valid() {
+ io.opentelemetry.sdk.trace.SpanProcessor spanProcessor =
+ SpanProcessorFactory.getInstance()
+ .create(
+ new SpanProcessor()
+ .withAdditionalProperty("test", ImmutableMap.of("key1", "value1")),
+ spiHelper,
+ new ArrayList<>());
+ assertThat(spanProcessor).isInstanceOf(SpanProcessorComponentProvider.TestSpanProcessor.class);
+ Assertions.assertThat(
+ ((SpanProcessorComponentProvider.TestSpanProcessor) spanProcessor)
+ .config.getString("key1"))
+ .isEqualTo("value1");
}
}
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/LogRecordProcessorComponentProvider.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/LogRecordProcessorComponentProvider.java
new file mode 100644
index 00000000000..581f2726154
--- /dev/null
+++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/LogRecordProcessorComponentProvider.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.extension.incubator.fileconfig.component;
+
+import io.opentelemetry.context.Context;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
+import io.opentelemetry.sdk.common.CompletableResultCode;
+import io.opentelemetry.sdk.logs.LogRecordProcessor;
+import io.opentelemetry.sdk.logs.ReadWriteLogRecord;
+
+public class LogRecordProcessorComponentProvider implements ComponentProvider {
+ @Override
+ public Class getType() {
+ return LogRecordProcessor.class;
+ }
+
+ @Override
+ public String getName() {
+ return "test";
+ }
+
+ @Override
+ public LogRecordProcessor create(StructuredConfigProperties config) {
+ return new TestLogRecordProcessor(config);
+ }
+
+ public static class TestLogRecordProcessor implements LogRecordProcessor {
+
+ public final StructuredConfigProperties config;
+
+ private TestLogRecordProcessor(StructuredConfigProperties config) {
+ this.config = config;
+ }
+
+ @Override
+ public void onEmit(Context context, ReadWriteLogRecord logRecord) {}
+
+ @Override
+ public CompletableResultCode shutdown() {
+ return CompletableResultCode.ofSuccess();
+ }
+ }
+}
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/SpanProcessorComponentProvider.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/SpanProcessorComponentProvider.java
new file mode 100644
index 00000000000..7bfe0936cd9
--- /dev/null
+++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/SpanProcessorComponentProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.extension.incubator.fileconfig.component;
+
+import io.opentelemetry.context.Context;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
+import io.opentelemetry.sdk.common.CompletableResultCode;
+import io.opentelemetry.sdk.trace.ReadWriteSpan;
+import io.opentelemetry.sdk.trace.ReadableSpan;
+import io.opentelemetry.sdk.trace.SpanProcessor;
+
+public class SpanProcessorComponentProvider implements ComponentProvider {
+ @Override
+ public Class getType() {
+ return SpanProcessor.class;
+ }
+
+ @Override
+ public String getName() {
+ return "test";
+ }
+
+ @Override
+ public SpanProcessor create(StructuredConfigProperties config) {
+ return new TestSpanProcessor(config);
+ }
+
+ public static class TestSpanProcessor implements SpanProcessor {
+
+ public final StructuredConfigProperties config;
+
+ private TestSpanProcessor(StructuredConfigProperties config) {
+ this.config = config;
+ }
+
+ @Override
+ public void onStart(Context parentContext, ReadWriteSpan span) {}
+
+ @Override
+ public boolean isStartRequired() {
+ return true;
+ }
+
+ @Override
+ public void onEnd(ReadableSpan span) {}
+
+ @Override
+ public boolean isEndRequired() {
+ return true;
+ }
+
+ @Override
+ public CompletableResultCode shutdown() {
+ return CompletableResultCode.ofSuccess();
+ }
+ }
+}
diff --git a/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider b/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider
index 6ab8ffdecc3..88759776549 100644
--- a/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider
+++ b/sdk-extensions/incubator/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider
@@ -1,6 +1,8 @@
io.opentelemetry.sdk.extension.incubator.fileconfig.component.MetricExporterComponentProvider
io.opentelemetry.sdk.extension.incubator.fileconfig.component.SpanExporterComponentProvider
io.opentelemetry.sdk.extension.incubator.fileconfig.component.LogRecordExporterComponentProvider
+io.opentelemetry.sdk.extension.incubator.fileconfig.component.SpanProcessorComponentProvider
+io.opentelemetry.sdk.extension.incubator.fileconfig.component.LogRecordProcessorComponentProvider
io.opentelemetry.sdk.extension.incubator.fileconfig.component.ResourceComponentProvider
io.opentelemetry.sdk.extension.incubator.fileconfig.component.ResourceOrderedFirstComponentProvider
io.opentelemetry.sdk.extension.incubator.fileconfig.component.ResourceOrderedSecondComponentProvider
From 938b03dff65ee752802f9c131f14afff29bd01d0 Mon Sep 17 00:00:00 2001
From: jack-berg <34418638+jack-berg@users.noreply.github.com>
Date: Wed, 28 Aug 2024 15:09:36 -0500
Subject: [PATCH 25/42] Add file configuration ComponentProvider support for
samplers (#6494)
---
.../fileconfig/FileConfiguration.java | 81 +++++++++++++------
.../incubator/fileconfig/SamplerFactory.java | 79 ++++++------------
.../YamlStructuredConfigProperties.java | 31 +++++--
.../FileConfigurationCreateTest.java | 2 +-
.../fileconfig/SamplerFactoryTest.java | 27 ++++++-
.../component/SamplerComponentProvider.java | 58 +++++++++++++
...toconfigure.spi.internal.ComponentProvider | 1 +
.../jaeger-remote-sampler/build.gradle.kts | 1 +
.../JaegerRemoteSamplerComponentProvider.java | 54 +++++++++++++
...toconfigure.spi.internal.ComponentProvider | 1 +
10 files changed, 245 insertions(+), 90 deletions(-)
create mode 100644 sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/SamplerComponentProvider.java
create mode 100644 sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/internal/JaegerRemoteSamplerComponentProvider.java
create mode 100644 sdk-extensions/jaeger-remote-sampler/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider
diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfiguration.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfiguration.java
index 82888ed5735..1a28935086b 100644
--- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfiguration.java
+++ b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/FileConfiguration.java
@@ -12,8 +12,10 @@
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
+import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfiguration;
+import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Sampler;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
@@ -84,30 +86,10 @@ public static OpenTelemetrySdk parseAndCreate(InputStream inputStream) {
* @throws ConfigurationException if unable to interpret
*/
public static OpenTelemetrySdk create(OpenTelemetryConfiguration configurationModel) {
- List closeables = new ArrayList<>();
- try {
- return OpenTelemetryConfigurationFactory.getInstance()
- .create(
- configurationModel,
- SpiHelper.create(FileConfiguration.class.getClassLoader()),
- closeables);
- } catch (RuntimeException e) {
- logger.info(
- "Error encountered interpreting configuration model. Closing partially configured components.");
- for (Closeable closeable : closeables) {
- try {
- logger.fine("Closing " + closeable.getClass().getName());
- closeable.close();
- } catch (IOException ex) {
- logger.warning(
- "Error closing " + closeable.getClass().getName() + ": " + ex.getMessage());
- }
- }
- if (e instanceof ConfigurationException) {
- throw e;
- }
- throw new ConfigurationException("Unexpected configuration error", e);
- }
+ return createAndMaybeCleanup(
+ OpenTelemetryConfigurationFactory.getInstance(),
+ SpiHelper.create(FileConfiguration.class.getClassLoader()),
+ configurationModel);
}
/**
@@ -157,6 +139,57 @@ static StructuredConfigProperties toConfigProperties(Object model) {
return YamlStructuredConfigProperties.create(configurationMap);
}
+ /**
+ * Create a {@link Sampler} from the {@code samplerModel} representing the sampler config.
+ *
+ * This is used when samplers are composed, with one sampler accepting one or more additional
+ * samplers as config properties. The {@link ComponentProvider} implementation can call this to
+ * configure a delegate {@link Sampler} from the {@link StructuredConfigProperties} corresponding
+ * to a particular config property.
+ */
+ // TODO(jack-berg): add create methods for all SDK extension components supported by
+ // ComponentProvider
+ public static io.opentelemetry.sdk.trace.samplers.Sampler createSampler(
+ StructuredConfigProperties genericSamplerModel) {
+ Sampler samplerModel = convertToModel(genericSamplerModel, Sampler.class);
+ return createAndMaybeCleanup(
+ SamplerFactory.getInstance(),
+ SpiHelper.create(FileConfiguration.class.getClassLoader()),
+ samplerModel);
+ }
+
+ static T convertToModel(
+ StructuredConfigProperties structuredConfigProperties, Class modelType) {
+ if (!(structuredConfigProperties instanceof YamlStructuredConfigProperties)) {
+ throw new ConfigurationException(
+ "Only YamlStructuredConfigProperties can be converted to model");
+ }
+ return MAPPER.convertValue(
+ ((YamlStructuredConfigProperties) structuredConfigProperties).toMap(), modelType);
+ }
+
+ static R createAndMaybeCleanup(Factory factory, SpiHelper spiHelper, M model) {
+ List closeables = new ArrayList<>();
+ try {
+ return factory.create(model, spiHelper, closeables);
+ } catch (RuntimeException e) {
+ logger.info("Error encountered interpreting model. Closing partially configured components.");
+ for (Closeable closeable : closeables) {
+ try {
+ logger.fine("Closing " + closeable.getClass().getName());
+ closeable.close();
+ } catch (IOException ex) {
+ logger.warning(
+ "Error closing " + closeable.getClass().getName() + ": " + ex.getMessage());
+ }
+ }
+ if (e instanceof ConfigurationException) {
+ throw e;
+ }
+ throw new ConfigurationException("Unexpected configuration error", e);
+ }
+ }
+
/**
* {@link StandardConstructor} which substitutes environment variables.
*
diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactory.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactory.java
index f900015f8c4..2f8c3bc4520 100644
--- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactory.java
+++ b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactory.java
@@ -7,20 +7,14 @@
import static java.util.stream.Collectors.joining;
-import io.opentelemetry.sdk.autoconfigure.internal.NamedSpiManager;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
-import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
-import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
-import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.JaegerRemote;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ParentBased;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TraceIdRatioBased;
import io.opentelemetry.sdk.trace.samplers.ParentBasedSamplerBuilder;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import java.io.Closeable;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -63,70 +57,49 @@ public Sampler create(
: create(parentBasedModel.getRoot(), spiHelper, closeables);
ParentBasedSamplerBuilder builder = Sampler.parentBasedBuilder(root);
if (parentBasedModel.getRemoteParentSampled() != null) {
- builder.setRemoteParentSampled(
- create(parentBasedModel.getRemoteParentSampled(), spiHelper, closeables));
+ Sampler sampler = create(parentBasedModel.getRemoteParentSampled(), spiHelper, closeables);
+ builder.setRemoteParentSampled(sampler);
}
if (parentBasedModel.getRemoteParentNotSampled() != null) {
- builder.setRemoteParentNotSampled(
- create(parentBasedModel.getRemoteParentNotSampled(), spiHelper, closeables));
+ Sampler sampler =
+ create(parentBasedModel.getRemoteParentNotSampled(), spiHelper, closeables);
+ builder.setRemoteParentNotSampled(sampler);
}
if (parentBasedModel.getLocalParentSampled() != null) {
- builder.setLocalParentSampled(
- create(parentBasedModel.getLocalParentSampled(), spiHelper, closeables));
+ Sampler sampler = create(parentBasedModel.getLocalParentSampled(), spiHelper, closeables);
+ builder.setLocalParentSampled(sampler);
}
if (parentBasedModel.getLocalParentNotSampled() != null) {
- builder.setLocalParentNotSampled(
- create(parentBasedModel.getLocalParentNotSampled(), spiHelper, closeables));
+ Sampler sampler =
+ create(parentBasedModel.getLocalParentNotSampled(), spiHelper, closeables);
+ builder.setLocalParentNotSampled(sampler);
}
return builder.build();
}
JaegerRemote jaegerRemoteModel = model.getJaegerRemote();
if (jaegerRemoteModel != null) {
- // Translate from file configuration scheme to environment variable scheme. This is ultimately
- // interpreted by JaegerRemoteSamplerProvider, but we want to avoid the dependency on
- // opentelemetry-sdk-extension-jaeger-remote-sampler
- Map properties = new HashMap<>();
- if (jaegerRemoteModel.getEndpoint() != null) {
- properties.put("endpoint", jaegerRemoteModel.getEndpoint());
- }
- if (jaegerRemoteModel.getInterval() != null) {
- properties.put("pollingInterval", String.valueOf(jaegerRemoteModel.getInterval()));
- }
- // TODO(jack-berg): determine how to support initial sampler. This is first case where a
- // component configured via SPI has property that isn't available in the environment variable
- // scheme.
- String otelTraceSamplerArg =
- properties.entrySet().stream()
- .map(entry -> entry.getKey() + "=" + entry.getValue())
- .collect(joining(","));
-
- ConfigProperties configProperties =
- DefaultConfigProperties.createFromMap(
- Collections.singletonMap("otel.traces.sampler.arg", otelTraceSamplerArg));
- return FileConfigUtil.addAndReturn(
- closeables,
- FileConfigUtil.assertNotNull(
- samplerSpiManager(configProperties, spiHelper).getByName("jaeger_remote"),
- "jaeger remote sampler"));
+ model.getAdditionalProperties().put("jaeger_remote", jaegerRemoteModel);
}
- // TODO(jack-berg): add support for generic SPI samplers
if (!model.getAdditionalProperties().isEmpty()) {
- throw new ConfigurationException(
- "Unrecognized sampler(s): "
- + model.getAdditionalProperties().keySet().stream().collect(joining(",", "[", "]")));
+ Map additionalProperties = model.getAdditionalProperties();
+ if (additionalProperties.size() > 1) {
+ throw new ConfigurationException(
+ "Invalid configuration - multiple samplers exporters set: "
+ + additionalProperties.keySet().stream().collect(joining(",", "[", "]")));
+ }
+ Map.Entry exporterKeyValue =
+ additionalProperties.entrySet().stream()
+ .findFirst()
+ .orElseThrow(
+ () -> new IllegalStateException("Missing sampler. This is a programming error."));
+ Sampler sampler =
+ FileConfigUtil.loadComponent(
+ spiHelper, Sampler.class, exporterKeyValue.getKey(), exporterKeyValue.getValue());
+ return FileConfigUtil.addAndReturn(closeables, sampler);
} else {
throw new ConfigurationException("sampler must be set");
}
}
-
- private static NamedSpiManager samplerSpiManager(
- ConfigProperties config, SpiHelper spiHelper) {
- return spiHelper.loadConfigurable(
- ConfigurableSamplerProvider.class,
- ConfigurableSamplerProvider::getName,
- ConfigurableSamplerProvider::createSampler,
- config);
- }
}
diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/YamlStructuredConfigProperties.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/YamlStructuredConfigProperties.java
index 6475bbe1698..2e9e20d3f0c 100644
--- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/YamlStructuredConfigProperties.java
+++ b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/YamlStructuredConfigProperties.java
@@ -35,13 +35,13 @@ final class YamlStructuredConfigProperties implements StructuredConfigProperties
/** Values are {@link #isPrimitive(Object)}, {@link List} of scalars. */
private final Map simpleEntries;
- private final Map> listEntries;
- private final Map mapEntries;
+ private final Map> listEntries;
+ private final Map mapEntries;
private YamlStructuredConfigProperties(
Map simpleEntries,
- Map> listEntries,
- Map mapEntries) {
+ Map> listEntries,
+ Map mapEntries) {
this.simpleEntries = simpleEntries;
this.listEntries = listEntries;
this.mapEntries = mapEntries;
@@ -59,8 +59,8 @@ private YamlStructuredConfigProperties(
@SuppressWarnings("unchecked")
static YamlStructuredConfigProperties create(Map properties) {
Map simpleEntries = new HashMap<>();
- Map> listEntries = new HashMap<>();
- Map mapEntries = new HashMap<>();
+ Map> listEntries = new HashMap<>();
+ Map mapEntries = new HashMap<>();
for (Map.Entry entry : properties.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
@@ -73,7 +73,7 @@ static YamlStructuredConfigProperties create(Map properties) {
continue;
}
if (isListOfMaps(value)) {
- List list =
+ List list =
((List