Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
8282947
feat: support parse oceanbase、lindorm、polardb、opentracing connection url
pepeshore Sep 18, 2025
d0acc07
Merge branch 'open-telemetry:main' into feature/additonal-jdbc-url-pa…
pepeshore Sep 25, 2025
4251ef4
delete test main method
pepeshore Sep 25, 2025
8d79717
./gradlew spotlessApply
otelbot[bot] Sep 25, 2025
a4a325f
fix:fix some code comments
pepeshore Sep 28, 2025
28c2324
Merge remote-tracking branch 'origin/feature/additonal-jdbc-url-parse…
pepeshore Sep 28, 2025
e5d0f3c
Optimized the comments for OceanBase url parser
pepeshore Oct 9, 2025
ae6a467
./gradlew spotlessApply
otelbot[bot] Oct 9, 2025
660f26b
delete url parameter
pepeshore Oct 9, 2025
548e0df
Merge remote-tracking branch 'origin/feature/additonal-jdbc-url-parse…
pepeshore Oct 9, 2025
73286f8
./gradlew spotlessApply
otelbot[bot] Oct 9, 2025
87105b6
Merge branch 'main' into feature/additonal-jdbc-url-parser
laurit Oct 9, 2025
92a0e4c
review
laurit Oct 9, 2025
3bd593a
feat:support JFinal framework
pepeshore Nov 4, 2025
7ab2d87
./gradlew spotlessApply
otelbot[bot] Nov 4, 2025
eebb74c
Merge branch 'main' into feat/support-jfinal
pepeshore Nov 5, 2025
de238a4
fix:fix failing check
pepeshore Nov 5, 2025
fed5680
Merge remote-tracking branch 'origin/feat/support-jfinal' into feat/s…
pepeshore Nov 5, 2025
63b2d8f
refactor:update package name & remove useless dependency and code
pepeshore Nov 5, 2025
85cc395
./gradlew spotlessApply
otelbot[bot] Nov 5, 2025
5f55199
refactor:delete useless code
pepeshore Nov 5, 2025
f61ac70
Merge remote-tracking branch 'origin/feat/support-jfinal' into feat/s…
pepeshore Nov 5, 2025
3602e5b
refactor: improve JFinal instrumentation implementation
pepeshore Nov 12, 2025
2e9cf76
./gradlew spotlessApply
otelbot[bot] Nov 12, 2025
85ce47f
refactor: optimize ActionHandlerInstrumentation implementation
pepeshore Nov 12, 2025
8516299
refactor: rename jfinal-3.6 to jfinal-3.2 and update package references
pepeshore Nov 12, 2025
98e6131
./gradlew spotlessApply
otelbot[bot] Nov 12, 2025
59d8140
refactor: update JFinal instrumentation configuration
pepeshore Nov 12, 2025
9e6f362
./gradlew spotlessApply
otelbot[bot] Nov 12, 2025
c233117
chore: update FOSSA configuration for JFinal instrumentation
pepeshore Nov 12, 2025
be1073e
Merge branch 'main' into feat/support-jfinal
steverao Nov 13, 2025
47a29a7
docs: add comment explaining TypeConverter version check in JFinal in…
pepeshore Nov 13, 2025
95f7b99
enable redirect test
laurit Nov 13, 2025
64fb545
remove try catch
laurit Nov 13, 2025
94def77
test with 3.2
laurit Nov 13, 2025
f4d8fc8
mark indy ready
laurit Nov 13, 2025
d381462
Record code attributes for the controller span
laurit Nov 13, 2025
3338786
Merge branch 'main' into feat/support-jfinal
laurit Nov 13, 2025
d60533b
Apply suggestions from code review
laurit Nov 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .fossa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ targets:
- type: gradle
path: ./
target: ':instrumentation:jdbc:library'
- type: gradle
path: ./
target: ':instrumentation:jfinal-3.2:javaagent'
- type: gradle
path: ./
target: ':instrumentation:jmx-metrics:javaagent'
Expand Down
1 change: 1 addition & 0 deletions docs/supported-libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ These are the supported libraries and frameworks:
| [JBoss Log Manager](https://github.com/jboss-logging/jboss-logmanager) | 1.1+ | N/A | none |
| [JDBC](https://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html) | Java 8+ | [opentelemetry-jdbc](../instrumentation/jdbc/library) | [Database Client Spans], [Database Client Metrics] [6] |
| [Jedis](https://github.com/xetorthio/jedis) | 1.4+ | N/A | [Database Client Spans], [Database Client Metrics] [6] |
| [JFinal](https://github.com/jfinal/jfinal) | 3.2+ | N/A | Provides `http.route` [2], Controller Spans [3] |
| [JMS](https://javaee.github.io/javaee-spec/javadocs/javax/jms/package-summary.html) | 1.1+ | N/A | [Messaging Spans] |
| [Jodd Http](https://http.jodd.org/) | 4.2+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] |
| [JSP](https://javaee.github.io/javaee-spec/javadocs/javax/servlet/jsp/package-summary.html) | 2.3.x only | N/A | Controller Spans [3] |
Expand Down
31 changes: 31 additions & 0 deletions instrumentation/jfinal-3.2/javaagent/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
plugins {
id("otel.javaagent-instrumentation")
}

muzzle {
pass {
group.set("com.jfinal")
module.set("jfinal")
versions.set("[3.2,)")
assertInverse.set(true)
}
}

if (!(findProperty("testLatestDeps") as Boolean)) {
otelJava {
// jfinal 3.2 doesn't work with Java 9+
maxJavaVersionForTests.set(JavaVersion.VERSION_1_8)
}
}

dependencies {
library("com.jfinal:jfinal:3.2")
testLibrary("com.jfinal:jetty-server:2019.3")
testInstrumentation(project(":instrumentation:jetty:jetty-8.0:javaagent"))
testInstrumentation(project(":instrumentation:jetty:jetty-11.0:javaagent"))
testInstrumentation(project(":instrumentation:jetty:jetty-common:javaagent"))
}

tasks.withType<Test>().configureEach {
jvmArgs("-Dotel.instrumentation.common.experimental.controller-telemetry.enabled=true")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jfinal.v3_2;

import static net.bytebuddy.matcher.ElementMatchers.named;

import com.jfinal.core.Action;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

public class ActionMappingInstrumentation implements TypeInstrumentation {

@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("com.jfinal.core.ActionMapping");
}

@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
named("getAction"), this.getClass().getName() + "$GetActionAdvice");
}

@SuppressWarnings("unused")
public static class GetActionAdvice {

@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void exitGetAction(@Advice.Return Action action) {
JFinalSingletons.updateRoute(action);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jfinal.v3_2;

import static io.opentelemetry.javaagent.instrumentation.jfinal.v3_2.JFinalSingletons.instrumenter;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments;

import com.jfinal.aop.Invocation;
import com.jfinal.core.Action;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.incubator.semconv.util.ClassAndMethod;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import javax.annotation.Nullable;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

public class InvocationInstrumentation implements TypeInstrumentation {

@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("com.jfinal.aop.Invocation");
}

@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
named("invoke").and(takesNoArguments()), this.getClass().getName() + "$InvokeAdvice");
}

@SuppressWarnings("unused")
public static class InvokeAdvice {

public static class AdviceScope {
private final CallDepth callDepth;
private final ClassAndMethod request;
private final Context context;
private final Scope scope;

public AdviceScope(
CallDepth callDepth, ClassAndMethod request, Context context, Scope scope) {
this.callDepth = callDepth;
this.request = request;
this.context = context;
this.scope = scope;
}

public static AdviceScope start(CallDepth callDepth, Action action) {
if (callDepth.getAndIncrement() > 0 || action == null) {
return new AdviceScope(callDepth, null, null, null);
}

Context parentContext = Context.current();
ClassAndMethod request =
ClassAndMethod.create(action.getControllerClass(), action.getMethodName());
if (!instrumenter().shouldStart(parentContext, request)) {
return new AdviceScope(callDepth, null, null, null);
}

Context context = instrumenter().start(parentContext, request);
return new AdviceScope(callDepth, request, context, context.makeCurrent());
}

public void end(@Nullable Throwable throwable) {
if (callDepth.decrementAndGet() > 0 || scope == null) {
return;
}
scope.close();
instrumenter().end(context, request, null, throwable);
}
}

@Advice.OnMethodEnter(suppress = Throwable.class)
public static AdviceScope onEnter(@Advice.FieldValue("action") Action action) {
CallDepth callDepth = CallDepth.forClass(Invocation.class);
return AdviceScope.start(callDepth, action);
}

@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void stopTraceOnResponse(
@Advice.Thrown @Nullable Throwable throwable, @Advice.Enter AdviceScope actionScope) {
actionScope.end(throwable);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jfinal.v3_2;

import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
import static java.util.Arrays.asList;
import static net.bytebuddy.matcher.ElementMatchers.not;

import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
import java.util.List;
import net.bytebuddy.matcher.ElementMatcher;

@AutoService(InstrumentationModule.class)
public class JFinalInstrumentationModule extends InstrumentationModule
implements ExperimentalInstrumentationModule {

public JFinalInstrumentationModule() {
super("jfinal", "jfinal-3.2");
}

@Override
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
// In version 3.2, TypeConverter is moved from com.jfinal.core
// to com.jfinal.core.converter
return not(hasClassesNamed("com.jfinal.core.TypeConverter"));
}

@Override
public boolean isIndyReady() {
return true;
}

@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(new ActionMappingInstrumentation(), new InvocationInstrumentation());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jfinal.v3_2;

import com.jfinal.core.Action;
import com.jfinal.render.JsonRender;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor;
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesGetter;
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeSpanNameExtractor;
import io.opentelemetry.instrumentation.api.incubator.semconv.util.ClassAndMethod;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource;
import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig;

public final class JFinalSingletons {

private static final Instrumenter<ClassAndMethod, Void> INSTRUMENTER;

static {
// see
// https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/11465#issuecomment-2137294837
excludeOtAttrs();

CodeAttributesGetter<ClassAndMethod> codedAttributesGetter =
ClassAndMethod.codeAttributesGetter();
INSTRUMENTER =
Instrumenter.<ClassAndMethod, Void>builder(
GlobalOpenTelemetry.get(),
"io.opentelemetry.jfinal-3.2",
CodeSpanNameExtractor.create(codedAttributesGetter))
.setEnabled(ExperimentalConfig.get().controllerTelemetryEnabled())
.addAttributesExtractor(CodeAttributesExtractor.create(codedAttributesGetter))
.buildInstrumenter();
}

public static Instrumenter<ClassAndMethod, Void> instrumenter() {
return INSTRUMENTER;
}

public static void updateRoute(Action action) {
if (action == null) {
return;
}
String route = action.getActionKey();
Context context = Context.current();
if (route != null) {
HttpServerRoute.update(context, HttpServerRouteSource.CONTROLLER, route);
}
}

private static void excludeOtAttrs() {
JsonRender.addExcludedAttrs(
"io.opentelemetry.javaagent.instrumentation.servlet.ServletHelper.Context",
"trace_id",
"span_id");
}

private JFinalSingletons() {}
}
Loading
Loading