Skip to content

Commit 31b8a88

Browse files
SentryManotelbot[bot]laurit
authored
Add Helidon Instrumentation (#13776)
Co-authored-by: otelbot <[email protected]> Co-authored-by: Lauri Tulmin <[email protected]>
1 parent 2071fb2 commit 31b8a88

File tree

24 files changed

+898
-0
lines changed

24 files changed

+898
-0
lines changed

.fossa.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ targets:
136136
- type: gradle
137137
path: ./
138138
target: ':instrumentation:gwt-2.0:javaagent'
139+
- type: gradle
140+
path: ./
141+
target: ':instrumentation:helidon-4.3:javaagent'
142+
- type: gradle
143+
path: ./
144+
target: ':instrumentation:helidon-4.3:library'
139145
- type: gradle
140146
path: ./
141147
target: ':instrumentation:hikaricp-3.0:javaagent'

.github/config/lychee.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ exclude = [
2121
'^http://code.google.com/p/concurrentlinkedhashmap$',
2222
'^https://softwareengineering.stackexchange.com/questions/29727.*',
2323
'^https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/io/opentelemetry/$',
24+
# new artifact, remove after 2.21.0 release
25+
'^https://central.sonatype.com/artifact/io.opentelemetry.instrumentation/opentelemetry-helidon-4.3$',
2426
]

docs/supported-libraries.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ These are the supported libraries and frameworks:
7676
| [gRPC](https://github.com/grpc/grpc-java) | 1.6+ | [opentelemetry-grpc-1.6](../instrumentation/grpc-1.6/library) | [RPC Client Spans], [RPC Client Metrics], [RPC Server Spans], [RPC Server Metrics] |
7777
| [Guava ListenableFuture](https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/ListenableFuture.html) | 10.0+ | [opentelemetry-guava-10.0](../instrumentation/guava-10.0/library) | Context propagation |
7878
| [GWT](https://www.gwtproject.org/) | 2.0+ | N/A | [RPC Server Spans] |
79+
| [Helidon](https://helidon.io/) | 4.3+ | [opentelemetry-helidon-4.3](../instrumentation/helidon-4.3/library) | [HTTP Server Spans], [HTTP Server Metrics], Provides `http.route` [2] |
7980
| [Hibernate](https://github.com/hibernate/hibernate-orm) | 3.3+ | N/A | none |
8081
| [Hibernate Reactive](https://hibernate.org/reactive) | 1.0+ | N/A | none |
8182
| [HikariCP](https://github.com/brettwooldridge/HikariCP) | 3.0+ | [opentelemetry-hikaricp-3.0](../instrumentation/hikaricp-3.0/library) | [Database Pool Metrics] |
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
plugins {
2+
id("otel.javaagent-instrumentation")
3+
}
4+
5+
muzzle {
6+
pass {
7+
group.set("io.helidon.webserver")
8+
module.set("helidon-webserver")
9+
versions.set("[4.3.0,)")
10+
assertInverse.set(true)
11+
}
12+
}
13+
14+
otelJava {
15+
minJavaVersionSupported.set(JavaVersion.VERSION_21)
16+
}
17+
18+
dependencies {
19+
library("io.helidon.webserver:helidon-webserver:4.3.0")
20+
implementation(project(":instrumentation:helidon-4.3:library"))
21+
testImplementation(project(":instrumentation:helidon-4.3:testing"))
22+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.helidon.v4_3;
7+
8+
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
9+
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
10+
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
11+
import static net.bytebuddy.matcher.ElementMatchers.named;
12+
13+
import io.helidon.webserver.http.HttpRouting;
14+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
15+
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
16+
import net.bytebuddy.asm.Advice;
17+
import net.bytebuddy.description.type.TypeDescription;
18+
import net.bytebuddy.matcher.ElementMatcher;
19+
20+
public class HelidonInstrumentation implements TypeInstrumentation {
21+
22+
@Override
23+
public ElementMatcher<TypeDescription> typeMatcher() {
24+
return named("io.helidon.webserver.http.HttpRouting");
25+
}
26+
27+
@Override
28+
public void transform(TypeTransformer transformer) {
29+
transformer.applyAdviceToMethod(
30+
isMethod().and(isPublic()).and(isStatic()).and(named("builder")),
31+
HelidonInstrumentation.class.getName() + "$BuildAdvice");
32+
}
33+
34+
@SuppressWarnings("unused")
35+
public static class BuildAdvice {
36+
37+
@Advice.OnMethodExit(suppress = Throwable.class)
38+
public static void onExit(@Advice.Return HttpRouting.Builder httpContext) {
39+
HelidonSingletons.FILTERS.forEach(httpContext::addFilter);
40+
}
41+
}
42+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.helidon.v4_3;
7+
8+
import static java.util.Collections.singletonList;
9+
10+
import com.google.auto.service.AutoService;
11+
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
12+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
13+
import java.util.List;
14+
15+
@AutoService(InstrumentationModule.class)
16+
public class HelidonInstrumentationModule extends InstrumentationModule {
17+
public HelidonInstrumentationModule() {
18+
super("helidon", "helidon-4.3");
19+
}
20+
21+
@Override
22+
public List<TypeInstrumentation> typeInstrumentations() {
23+
return singletonList(new HelidonInstrumentation());
24+
}
25+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.helidon.v4_3;
7+
8+
import io.helidon.webserver.http.ServerResponse;
9+
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseMutator;
10+
11+
enum HelidonServerResponseMutator implements HttpServerResponseMutator<ServerResponse> {
12+
INSTANCE;
13+
14+
@Override
15+
public void appendHeader(ServerResponse res, String name, String value) {
16+
res.header(name, value);
17+
}
18+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.helidon.v4_3;
7+
8+
import io.helidon.webserver.http.Filter;
9+
import io.opentelemetry.api.GlobalOpenTelemetry;
10+
import io.opentelemetry.instrumentation.helidon.v4_3.HelidonTelemetry;
11+
import io.opentelemetry.instrumentation.helidon.v4_3.internal.HelidonInstrumenterBuilderUtil;
12+
import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig;
13+
import java.util.List;
14+
15+
public final class HelidonSingletons {
16+
17+
public static final List<Filter> FILTERS;
18+
19+
static {
20+
var serverBuilder = HelidonTelemetry.builder(GlobalOpenTelemetry.get());
21+
HelidonInstrumenterBuilderUtil.getServerBuilderExtractor()
22+
.apply(serverBuilder)
23+
.configure(AgentCommonConfig.get());
24+
var serverTelemetry = serverBuilder.build();
25+
26+
FILTERS = List.of(serverTelemetry.createFilter(), new ResponseCustomizingFilter());
27+
}
28+
29+
private HelidonSingletons() {}
30+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.helidon.v4_3;
7+
8+
import io.helidon.webserver.http.Filter;
9+
import io.helidon.webserver.http.FilterChain;
10+
import io.helidon.webserver.http.RoutingRequest;
11+
import io.helidon.webserver.http.RoutingResponse;
12+
import io.opentelemetry.context.Context;
13+
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizerHolder;
14+
15+
final class ResponseCustomizingFilter implements Filter {
16+
17+
ResponseCustomizingFilter() {}
18+
19+
@Override
20+
public void filter(FilterChain chain, RoutingRequest req, RoutingResponse res) {
21+
22+
var context = Context.current();
23+
HttpServerResponseCustomizerHolder.getCustomizer()
24+
.customize(context, res, HelidonServerResponseMutator.INSTANCE);
25+
chain.proceed();
26+
}
27+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.helidon.v4_3;
7+
8+
import io.opentelemetry.instrumentation.helidon.v4_3.AbstractHelidonTest;
9+
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
10+
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension;
11+
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions;
12+
import org.junit.jupiter.api.extension.RegisterExtension;
13+
14+
class HelidonServerTest extends AbstractHelidonTest {
15+
16+
@RegisterExtension
17+
static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent();
18+
19+
@Override
20+
protected void configure(HttpServerTestOptions options) {
21+
super.configure(options);
22+
options.setHasResponseCustomizer(serverEndpoint -> true);
23+
24+
options.setTestNotFound(false);
25+
}
26+
}

0 commit comments

Comments
 (0)