Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add OpenTelemetry instrumentation for ActiveJ HTTP server #13335

Open
wants to merge 35 commits into
base: main
Choose a base branch
from

Conversation

kcsurapaneni
Copy link

Overview

This PR introduces OpenTelemetry instrumentation for the ActiveJ framework, enabling distributed tracing and context propagation for ActiveJ-based HTTP servers. The changes allow developers to monitor and debug ActiveJ applications in distributed systems by capturing trace context from incoming requests and propagating it through responses.

Key Features

  • Distributed Tracing: Automatically propagates trace context using the traceparent header.
  • HTTP Attribute Extraction: Captures detailed HTTP attributes (e.g., method, path, headers, status code) for enriched telemetry data.
  • Error Handling: Maps exceptions to appropriate HTTP status codes and associates them with spans for better error visibility.

Changes Included

  1. Instrumentation:

    • ActiveJHttpServerConnectionInstrumentation: Instruments the serve method of ActiveJ servlets to capture and propagate trace context.
  2. Testing:

    • Added test cases to validate tracing behavior and ensure compliance with W3C Trace Context.
  3. Documentation:

    • Added README with details about the instrumentation, usage, and configuration.

Testing

  • All existing tests pass successfully.
  • New test cases have been added to validate:
    • Trace context propagation via the traceparent header.
    • Correctness of HTTP attribute extraction.
    • Error handling and span enrichment.

Benefits

  • Observability for ActiveJ applications, making it easier to monitor and debug distributed systems.
  • Seamless integration with OpenTelemetry exporters (e.g., Jaeger, Zipkin, HyperDX) for visualizing traces.

Related Issues

Closes #13202

Acknowledgments

This implementation was inspired by and adapted from the ActiveJ framework codebase. Special thanks to the ActiveJ community for their excellent work and contributions.

@kcsurapaneni kcsurapaneni requested a review from a team as a code owner February 18, 2025 06:46
Copy link

linux-foundation-easycla bot commented Feb 18, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

…nabling distributed tracing and context propagation for ActiveJ-based HTTP servers
Copy link
Member

@jaydeluca jaydeluca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will want integration tests for any new instrumentation

@kcsurapaneni
Copy link
Author

we will want integration tests for any new instrumentation

@jaydeluca I have added test cases and resolved most of the workflow job failures. But, still there are couple of them are failing and not able to understand the cause after checking the raw logs as well. Could you please help me to understand what causing them to failure so that I can fix them. Thank you!

CC: @trask @laurit

@laurit
Copy link
Contributor

laurit commented Feb 19, 2025

See https://scans.gradle.com/s/dy73bc67fptxo/tests/task/:instrumentation:activej-http-6.0:javaagent:test/details/(N%2FA)/Gradle%20Test%20Executor%2045?top-execution=1
Framework seems to require java 17

@kcsurapaneni
Copy link
Author

See https://scans.gradle.com/s/dy73bc67fptxo/tests/task/:instrumentation:activej-http-6.0:javaagent:test/details/(N%2FA)/Gradle%20Test%20Executor%2045?top-execution=1 Framework seems to require java 17

@laurit Thanks for the link. So, all the agents should support minimum java 8?

@laurit
Copy link
Contributor

laurit commented Feb 19, 2025

@laurit Thanks for the link. So, all the agents should support minimum java 8?

If the framework does not support java 8 then you shouldn't run the tests for it with java 8. Add

otelJava {
minJavaVersionSupported.set(JavaVersion.VERSION_17)
}

@kcsurapaneni
Copy link
Author

@laurit Thanks for the link. So, all the agents should support minimum java 8?

If the framework does not support java 8 then you shouldn't run the tests for it with java 8. Add

otelJava {
minJavaVersionSupported.set(JavaVersion.VERSION_17)
}

Thanks for the help! @laurit . Build looks good now. Please review

@laurit
Copy link
Contributor

laurit commented Feb 20, 2025

implementation dependencies are bundled into the agent. Replace this with library("io.activej:activej-http:6.0-rc2") library is a custom scope that means compileOnly + testImplementation

@laurit after making the suggested change build job is failed. You can check here https://github.com/open-telemetry/opentelemetry-java-instrumentation/actions/runs/13439272495/job/37549353284?pr=13335

Not sure why import is failing here, any idea? in my local it is working just fine

Latest dep tests try to automatically bump the library dependencies to latest version. You can run them locally by adding -PtestLatestDeps=true. Probably the issue is that the latest version detection ignores milestones and release candidates. Since for 6.x there are only release candidates it probably ends up choosing the latest 5.x version. You can work around it by explicitly setting the version for latest deps with latestDepTestLibrary("io.activej:activej-http:6.0-rc2").

@kcsurapaneni
Copy link
Author

kcsurapaneni commented Feb 20, 2025

implementation dependencies are bundled into the agent. Replace this with library("io.activej:activej-http:6.0-rc2") library is a custom scope that means compileOnly + testImplementation

@laurit after making the suggested change build job is failed. You can check here https://github.com/open-telemetry/opentelemetry-java-instrumentation/actions/runs/13439272495/job/37549353284?pr=13335
Not sure why import is failing here, any idea? in my local it is working just fine

Latest dep tests try to automatically bump the library dependencies to latest version. You can run them locally by adding -PtestLatestDeps=true. Probably the issue is that the latest version detection ignores milestones and release candidates. Since for 6.x there are only release candidates it probably ends up choosing the latest 5.x version. You can work around it by explicitly setting the version for latest deps with latestDepTestLibrary("io.activej:activej-http:6.0-rc2").

@laurit now test-latest-deps / testLatestDeps2 is failing. Like you said in my local when I ran ./gradlew :instrumentation:activej-http-6.0:javaagent:test -PtestLatestDeps=true, build was successful.

I don't find the error in the logs as well, so not sure what is happening here. In Raw logs as well, don't see much info and it is really difficult to navigate. Last time you shared an URL like this - https://scans.gradle.com/s/dy73bc67fptxo/tests/task/:instrumentation:activej-http-6.0:javaagent:test/details/(N%2FA)/Gradle%20Test%20Executor%2045?top-execution=1. Can you tell me how to access that in case of failure, so that it will be easy for me in future. Thanks!

@trask
Copy link
Member

trask commented Feb 20, 2025

The :instrumentation:spring:spring-webmvc:spring-webmvc-6.0:javaagent:test task failed

this failure looks unrelated to your PR

@trask
Copy link
Member

trask commented Feb 20, 2025

this failure looks unrelated to your PR

it's been fixed in main now, should go away whenever you merge latest main into your branch and push

zeitlinger and others added 13 commits February 20, 2025 20:42
…-telemetry#13349)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…emconv to v1.30.0 (open-telemetry#13351)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Lauri Tulmin <[email protected]>
…en-telemetry#13354)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…ts to v4-rev20250211-2.0.0 (open-telemetry#13357)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@github-actions github-actions bot added the test native This label can be applied to PRs to trigger them to run native tests label Feb 21, 2025
@kcsurapaneni
Copy link
Author

this failure looks unrelated to your PR

it's been fixed in main now, should go away whenever you merge latest main into your branch and push

Thanks @trask . Looks good now

kcsurapaneni and others added 3 commits February 21, 2025 04:14
…rter-web to v3.4.3 (open-telemetry#13362)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…20.5 (open-telemetry#13365)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@kcsurapaneni
Copy link
Author

@laurit all the comments are addressed. Please check again. Thanks!

Comment on lines +83 to +88
instrumenter()
.end(
context,
httpRequest,
responsePromise == null ? null : responsePromise.getResult(),
throwable);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt this is the right way. We want to end the span when the request processing ends. For async methods request processing ends when the promise completes not when the called method exits.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@laurit I don't see a better way to do this. I even looked into some of the existing async handling and this is how it is done, here is an example from google-http-client

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the linked code in google http client only ends the span on method exit when there was an exception. Did you try what I proposed in #13335 (comment)


public class ActivejHttpServerTest extends AbstractHttpServerTest<HttpServer> {

@ClassRule public static final EventloopRule eventloopRule = new EventloopRule();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

classrule is for junit4 we use junit5

Comment on lines 87 to 90
@Override
protected void assertHighConcurrency(int count) {
//
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not implemented

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
test native This label can be applied to PRs to trigger them to run native tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Context Propagation for ActiveJ Applications Using OpenTelemetry Java Agent Instrumentation
6 participants