Skip to content

Commit 2f31d3f

Browse files
committed
Merge branch 'main' of https://github.com/open-telemetry/opentelemetry-java into promote-component-loader
2 parents a7ce48f + a7315c6 commit 2f31d3f

File tree

24 files changed

+599
-130
lines changed

24 files changed

+599
-130
lines changed

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -256,33 +256,35 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for:
256256

257257
### Code owners
258258

259-
Triagers:
259+
#### Maintainers
260260

261-
- [Gregor Zeitlinger](https://github.com/zeitlinger), Grafana Labs
261+
- [Jack Berg](https://github.com/jack-berg), New Relic
262+
- [John Watson](https://github.com/jkwatson), Verta.ai
262263

263-
*Find more about the triager role in [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#triager).*
264+
For more information about the maintainer role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer).
264265

265-
Approvers ([@open-telemetry/java-approvers](https://github.com/orgs/open-telemetry/teams/java-approvers)):
266+
#### Approvers
266267

267268
- [Jason Plumb](https://github.com/breedx-splk), Splunk
268269
- [Josh Suereth](https://github.com/jsuereth), Google
269270
- [Lauri Tulmin](https://github.com/laurit), Splunk
270271
- [Trask Stalnaker](https://github.com/trask), Microsoft
271272

272-
*Find more about the approver role in [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).*
273+
For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).
273274

274-
Maintainers ([@open-telemetry/java-maintainers](https://github.com/orgs/open-telemetry/teams/java-maintainers)):
275+
#### Triagers
275276

276-
- [Jack Berg](https://github.com/jack-berg), New Relic
277-
- [John Watson](https://github.com/jkwatson), Verta.ai
277+
- [Gregor Zeitlinger](https://github.com/zeitlinger), Grafana Labs
278278

279-
Emeritus:
279+
For more information about the triager role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#triager).
280+
281+
#### Emeritus
280282

281283
- Maintainer [Bogdan Drutu](https://github.com/BogdanDrutu)
282284
- Maintainer [Carlos Alberto](https://github.com/carlosalberto)
283285
- Approver [Mateusz Rzeszutek](https://github.com/mateuszrzeszutek)
284286

285-
*Find more about the maintainer role in [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer).*
287+
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
286288

287289
### Help wanted
288290

@@ -293,14 +295,12 @@ We are currently resource constrained and are actively seeking new contributors
293295
- Issues labeled [help wanted](https://github.com/open-telemetry/opentelemetry-java/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) are project priorities. Code contributions (or pull request reviews when a PR is linked) for these issues are particularly important.
294296
- Triaging / responding to new issues and discussions is a great way to engage with the project.
295297

296-
### Thanks to all the people who have contributed
298+
### Thanks to all of our contributors!
297299

298300
<a href="https://github.com/open-telemetry/opentelemetry-java/graphs/contributors">
299-
<img src="https://contrib.rocks/image?repo=open-telemetry/opentelemetry-java" />
301+
<img alt="Repo contributors" src="https://contrib.rocks/image?repo=open-telemetry/opentelemetry-java" />
300302
</a>
301303

302-
Made with [contrib.rocks](https://contrib.rocks).
303-
304304
[codecov-image]: https://codecov.io/gh/open-telemetry/opentelemetry-java/branch/main/graph/badge.svg
305305
[codecov-url]: https://app.codecov.io/gh/open-telemetry/opentelemetry-java/branch/main/
306306
[dependencies-and-boms]: https://opentelemetry.io/docs/languages/java/intro/#dependencies-and-boms

buildSrc/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ dependencies {
6262
implementation("gradle.plugin.io.morethan.jmhreport:gradle-jmh-report:0.9.6")
6363
implementation("me.champeau.gradle:japicmp-gradle-plugin:0.4.6")
6464
implementation("me.champeau.jmh:jmh-gradle-plugin:0.7.3")
65-
implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.2.0")
65+
implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.3.0")
6666
implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.2.0")
6767
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.21")
6868
implementation("org.owasp:dependency-check-gradle:12.1.3")

exporters/common/src/main/java/io/opentelemetry/exporter/internal/compression/CompressorUtil.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
*/
2525
public final class CompressorUtil {
2626

27-
private static final Map<String, Compressor> compressorRegistry = buildCompressorRegistry();
27+
private static final Map<String, Compressor> compressorRegistry =
28+
buildCompressorRegistry(
29+
ComponentLoader.forClassLoader(CompressorUtil.class.getClassLoader()));
2830

2931
private CompressorUtil() {}
3032

@@ -36,20 +38,36 @@ private CompressorUtil() {}
3638
*/
3739
@Nullable
3840
public static Compressor validateAndResolveCompressor(String compressionMethod) {
39-
Set<String> supportedEncodings = compressorRegistry.keySet();
40-
Compressor compressor = compressorRegistry.get(compressionMethod);
41+
return validateAndResolveCompressor(compressionMethod, null);
42+
}
43+
44+
/**
45+
* Validate that the {@code compressionMethod} is "none" or matches a registered compressor.
46+
*
47+
* @param compressionMethod the compression method to validate and resolve
48+
* @param componentLoader the component loader to use for loading SPI implementations, or null to
49+
* use the default
50+
* @return {@code null} if {@code compressionMethod} is "none" or the registered compressor
51+
* @throws IllegalArgumentException if no match is found
52+
*/
53+
@Nullable
54+
public static Compressor validateAndResolveCompressor(
55+
String compressionMethod, @Nullable ComponentLoader componentLoader) {
56+
Map<String, Compressor> registry =
57+
componentLoader == null ? compressorRegistry : buildCompressorRegistry(componentLoader);
58+
59+
Set<String> supportedEncodings = registry.keySet();
60+
Compressor compressor = registry.get(compressionMethod);
4161
checkArgument(
4262
"none".equals(compressionMethod) || compressor != null,
4363
"Unsupported compressionMethod. Compression method must be \"none\" or one of: "
4464
+ supportedEncodings.stream().collect(joining(",", "[", "]")));
4565
return compressor;
4666
}
4767

48-
private static Map<String, Compressor> buildCompressorRegistry() {
68+
private static Map<String, Compressor> buildCompressorRegistry(ComponentLoader componentLoader) {
4969
Map<String, Compressor> compressors = new HashMap<>();
50-
for (CompressorProvider spi :
51-
ComponentLoader.forClassLoader(CompressorUtil.class.getClassLoader())
52-
.load(CompressorProvider.class)) {
70+
for (CompressorProvider spi : componentLoader.load(CompressorProvider.class)) {
5371
Compressor compressor = spi.getInstance();
5472
compressors.put(compressor.getEncoding(), compressor);
5573
}

exporters/common/src/main/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilder.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
1515
import io.opentelemetry.exporter.internal.TlsConfigHelper;
1616
import io.opentelemetry.exporter.internal.compression.Compressor;
17+
import io.opentelemetry.exporter.internal.compression.CompressorProvider;
18+
import io.opentelemetry.exporter.internal.compression.CompressorUtil;
1719
import io.opentelemetry.exporter.internal.marshal.Marshaler;
1820
import io.opentelemetry.sdk.common.InternalTelemetryVersion;
1921
import io.opentelemetry.sdk.common.export.RetryPolicy;
@@ -116,6 +118,17 @@ public GrpcExporterBuilder<T> setCompression(@Nullable Compressor compressor) {
116118
return this;
117119
}
118120

121+
/**
122+
* Sets the method used to compress payloads. If unset, compression is disabled. Compression
123+
* method "gzip" and "none" are supported out of the box. Support for additional compression
124+
* methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
125+
*/
126+
public GrpcExporterBuilder<T> setCompression(String compressionMethod) {
127+
Compressor compressor =
128+
CompressorUtil.validateAndResolveCompressor(compressionMethod, componentLoader);
129+
return setCompression(compressor);
130+
}
131+
119132
public GrpcExporterBuilder<T> setTrustManagerFromCerts(byte[] trustedCertificatesPem) {
120133
tlsConfigHelper.setTrustManagerFromCerts(trustedCertificatesPem);
121134
return this;

exporters/common/src/main/java/io/opentelemetry/exporter/internal/http/HttpExporterBuilder.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
1313
import io.opentelemetry.exporter.internal.TlsConfigHelper;
1414
import io.opentelemetry.exporter.internal.compression.Compressor;
15+
import io.opentelemetry.exporter.internal.compression.CompressorProvider;
16+
import io.opentelemetry.exporter.internal.compression.CompressorUtil;
1517
import io.opentelemetry.exporter.internal.marshal.Marshaler;
1618
import io.opentelemetry.sdk.common.InternalTelemetryVersion;
1719
import io.opentelemetry.sdk.common.export.ProxyOptions;
@@ -96,6 +98,17 @@ public HttpExporterBuilder<T> setCompression(@Nullable Compressor compressor) {
9698
return this;
9799
}
98100

101+
/**
102+
* Sets the method used to compress payloads. If unset, compression is disabled. Compression
103+
* method "gzip" and "none" are supported out of the box. Support for additional compression
104+
* methods is available by implementing {@link Compressor} and {@link CompressorProvider}.
105+
*/
106+
public HttpExporterBuilder<T> setCompression(String compressionMethod) {
107+
Compressor compressor =
108+
CompressorUtil.validateAndResolveCompressor(compressionMethod, componentLoader);
109+
return setCompression(compressor);
110+
}
111+
99112
public HttpExporterBuilder<T> addConstantHeaders(String key, String value) {
100113
constantHeaders.put(key, value);
101114
return this;
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.internal.compression;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
10+
11+
import io.opentelemetry.context.ComponentLoader;
12+
import java.net.URL;
13+
import java.net.URLClassLoader;
14+
import org.junit.jupiter.api.Test;
15+
16+
class CompressorUtilTest {
17+
18+
private final ComponentLoader componentLoader =
19+
ComponentLoader.forClassLoader(CompressorUtilTest.class.getClassLoader());
20+
21+
@Test
22+
void validateAndResolveCompressor_none() {
23+
assertThat(CompressorUtil.validateAndResolveCompressor("none")).isNull();
24+
}
25+
26+
@Test
27+
void validateAndResolveCompressor_gzip() {
28+
assertThat(CompressorUtil.validateAndResolveCompressor("gzip"))
29+
.isEqualTo(GzipCompressor.getInstance());
30+
}
31+
32+
@Test
33+
void validateAndResolveCompressor_invalid() {
34+
assertThatThrownBy(() -> CompressorUtil.validateAndResolveCompressor("invalid"))
35+
.isInstanceOf(IllegalArgumentException.class)
36+
.hasMessageContaining("Unsupported compressionMethod");
37+
}
38+
39+
@Test
40+
void validateAndResolveCompressor_withClassLoader_none() {
41+
assertThat(CompressorUtil.validateAndResolveCompressor("none", componentLoader)).isNull();
42+
}
43+
44+
@Test
45+
void validateAndResolveCompressor_withClassLoader_gzip() {
46+
assertThat(CompressorUtil.validateAndResolveCompressor("gzip", componentLoader))
47+
.isEqualTo(GzipCompressor.getInstance());
48+
}
49+
50+
@Test
51+
void validateAndResolveCompressor_withClassLoader_invalid() {
52+
assertThatThrownBy(
53+
() -> CompressorUtil.validateAndResolveCompressor("invalid", componentLoader))
54+
.isInstanceOf(IllegalArgumentException.class)
55+
.hasMessageContaining("Unsupported compressionMethod");
56+
}
57+
58+
@Test
59+
void validateAndResolveCompressor_emptyClassLoader() {
60+
// Create a class loader that cannot load CompressorProvider services
61+
ComponentLoader emptyComponentLoader =
62+
ComponentLoader.forClassLoader(new URLClassLoader(new URL[0], null));
63+
64+
// Gzip should still work because it's hardcoded
65+
assertThat(CompressorUtil.validateAndResolveCompressor("gzip", emptyComponentLoader))
66+
.isEqualTo(GzipCompressor.getInstance());
67+
68+
// None should still work because it doesn't require loading services
69+
assertThat(CompressorUtil.validateAndResolveCompressor("none", emptyComponentLoader)).isNull();
70+
71+
// Any SPI-based compressor should not be available
72+
assertThatThrownBy(
73+
() -> CompressorUtil.validateAndResolveCompressor("base64", emptyComponentLoader))
74+
.isInstanceOf(IllegalArgumentException.class)
75+
.hasMessageContaining("Unsupported compressionMethod");
76+
}
77+
78+
@Test
79+
void validateAndResolveCompressor_delegatesCorrectly() {
80+
// Test that single-parameter method delegates to two-parameter method
81+
assertThat(CompressorUtil.validateAndResolveCompressor("gzip"))
82+
.isEqualTo(CompressorUtil.validateAndResolveCompressor("gzip", componentLoader));
83+
84+
assertThat(CompressorUtil.validateAndResolveCompressor("none"))
85+
.isEqualTo(CompressorUtil.validateAndResolveCompressor("none", componentLoader));
86+
}
87+
}

exporters/common/src/test/java/io/opentelemetry/exporter/internal/grpc/GrpcExporterBuilderTest.java

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,16 @@
66
package io.opentelemetry.exporter.internal.grpc;
77

88
import static org.assertj.core.api.Assertions.assertThat;
9+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
910

11+
import io.opentelemetry.context.ComponentLoader;
12+
import io.opentelemetry.exporter.internal.compression.Compressor;
1013
import io.opentelemetry.exporter.internal.compression.GzipCompressor;
1114
import io.opentelemetry.exporter.internal.marshal.Marshaler;
1215
import io.opentelemetry.sdk.internal.StandardComponentId;
1316
import java.net.URI;
17+
import java.net.URL;
18+
import java.net.URLClassLoader;
1419
import org.junit.jupiter.api.BeforeEach;
1520
import org.junit.jupiter.api.Test;
1621

@@ -36,7 +41,7 @@ void compressionDefault() {
3641

3742
@Test
3843
void compressionNone() {
39-
builder.setCompression(null);
44+
builder.setCompression((Compressor) null);
4045

4146
assertThat(builder).extracting("compressor").isNull();
4247
}
@@ -50,8 +55,45 @@ void compressionGzip() {
5055

5156
@Test
5257
void compressionEnabledAndDisabled() {
53-
builder.setCompression(GzipCompressor.getInstance()).setCompression(null);
58+
builder.setCompression(GzipCompressor.getInstance()).setCompression((Compressor) null);
5459

5560
assertThat(builder).extracting("compressor").isNull();
5661
}
62+
63+
@Test
64+
void compressionString_none() {
65+
builder.setCompression("none");
66+
67+
assertThat(builder).extracting("compressor").isNull();
68+
}
69+
70+
@Test
71+
void compressionString_gzip() {
72+
builder.setCompression("gzip");
73+
74+
assertThat(builder).extracting("compressor").isEqualTo(GzipCompressor.getInstance());
75+
}
76+
77+
@Test
78+
void compressionString_invalid() {
79+
assertThatThrownBy(() -> builder.setCompression("invalid-compression"))
80+
.isInstanceOf(IllegalArgumentException.class)
81+
.hasMessageContaining("Unsupported compressionMethod");
82+
}
83+
84+
@Test
85+
void compressionString_usesServiceClassLoader() {
86+
// Create a class loader that cannot load CompressorProvider services
87+
ComponentLoader emptyComponentLoader =
88+
ComponentLoader.forClassLoader(new URLClassLoader(new URL[0], null));
89+
builder.setComponentLoader(emptyComponentLoader);
90+
91+
// This should still work because gzip compressor is hardcoded
92+
builder.setCompression("gzip");
93+
assertThat(builder).extracting("compressor").isEqualTo(GzipCompressor.getInstance());
94+
95+
// This should still work because "none" doesn't require loading services
96+
builder.setCompression("none");
97+
assertThat(builder).extracting("compressor").isNull();
98+
}
5799
}

0 commit comments

Comments
 (0)