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

Put http.route attribute onto http.server.duration on Play framework request processing #7801

Merged
merged 8 commits into from
Feb 14, 2023

Conversation

moznion
Copy link
Contributor

@moznion moznion commented Feb 11, 2023

Basically, akka-http instrumenter has the responsibility to instrument the http.server.duration for the Play framework application, but the current implementation has not marked the http.route attribute.
ref:

Actually, it's hard to record that attribute by only the akka-http layer because that library's request object doesn't hold the route information, e.g. placeholder.

So this patch delegates that job to the play-mvc instrumenter and when that has been able to get the route info, the instrumenter puts http.route attribute onto http.server.duration.

For example, when the routes configuration of the Play is like the following:

GET  /foo/:bar  controllers.HomeController.doSomething(bar: String)

and when it tries to access that API, then OTEL instruments like so:

http_server_duration_count{otel_scope_name="io.opentelemetry.akka-http-10.0",otel_scope_version="1.23.0-alpha-SNAPSHOT",http_flavor="1.1",http_method="GET",http_route="/foo/$bar<[^/]+>",http_scheme="http",http_status_code="200",net_host_name="localhost",net_host_port="9000"} 1.0 1676078079798
http_server_duration_sum{otel_scope_name="io.opentelemetry.akka-http-10.0",otel_scope_version="1.23.0-alpha-SNAPSHOT",http_flavor="1.1",http_method="GET",http_route="/foo/$bar<[^/]+>",http_scheme="http",http_status_code="200",net_host_name="localhost",net_host_port="9000"} 12183.558843 1676078079798
http_server_duration_bucket{otel_scope_name="io.opentelemetry.akka-http-10.0",otel_scope_version="1.23.0-alpha-SNAPSHOT",http_flavor="1.1",http_method="GET",http_route="/foo/$bar<[^/]+>",http_scheme="http",http_status_code="200",net_host_name="localhost",net_host_port="9000",le="0.0"} 0.0 1676078079798
...
http_server_duration_bucket{otel_scope_name="io.opentelemetry.akka-http-10.0",otel_scope_version="1.23.0-alpha-SNAPSHOT",http_flavor="1.1",http_method="GET",http_route="/foo/$bar<[^/]+>",http_scheme="http",http_status_code="200",net_host_name="localhost",net_host_port="9000",le="+Inf"} 1.0 1676078079798

Rel: #1415

…ork request processing

Basically, `akka-http` instrumenter has the responsibility to
instrument the `http_server_duration`, but the current implementation
has not marked the `http_route` attribute.
ref: https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/8e8161cb2e5b27d78b8afb7872df17cfa25a2f74/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/AkkaHttpServerAttributesGetter.java#L59

Actually, it's hard to record that attribute by only the akka-http layer
because that library's request object doesn't hold the route
information, e.g. placeholder.

So this patch delegates that job to the `play` instrumenter and when
that has been able to get the route info, the instrumenter puts
`http_route` attribute onto `http_server_duration`.

For example, when the routes configuration of the Play is like the
following:

```
GET  /foo/:bar  controllers.HomeController.doSomething(bar: String)
```

and when it tries to access that API, then OTEL instruments like so:

```prometheus
http_server_duration_count{otel_scope_name="io.opentelemetry.akka-http-10.0",otel_scope_version="1.23.0-alpha-SNAPSHOT",http_flavor="1.1",http_method="GET",http_route="/foo/$bar<[^/]+>",http_scheme="http",http_status_code="200",net_host_name="localhost",net_host_port="9000"} 1.0 1676078079798
http_server_duration_sum{otel_scope_name="io.opentelemetry.akka-http-10.0",otel_scope_version="1.23.0-alpha-SNAPSHOT",http_flavor="1.1",http_method="GET",http_route="/foo/$bar<[^/]+>",http_scheme="http",http_status_code="200",net_host_name="localhost",net_host_port="9000"} 12183.558843 1676078079798
http_server_duration_bucket{otel_scope_name="io.opentelemetry.akka-http-10.0",otel_scope_version="1.23.0-alpha-SNAPSHOT",http_flavor="1.1",http_method="GET",http_route="/foo/$bar<[^/]+>",http_scheme="http",http_status_code="200",net_host_name="localhost",net_host_port="9000",le="0.0"} 0.0 1676078079798
...
http_server_duration_bucket{otel_scope_name="io.opentelemetry.akka-http-10.0",otel_scope_version="1.23.0-alpha-SNAPSHOT",http_flavor="1.1",http_method="GET",http_route="/foo/$bar<[^/]+>",http_scheme="http",http_status_code="200",net_host_name="localhost",net_host_port="9000",le="+Inf"} 1.0 1676078079798
```

Rel: open-telemetry#1415

Signed-off-by: moznion <moznion@mail.moznion.net>
@moznion moznion requested a review from a team as a code owner February 11, 2023 01:42
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Feb 11, 2023

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: moznion / name: moznion (451c07b)

…bute

Signed-off-by: moznion <moznion@mail.moznion.net>
Copy link
Member

@trask trask left a comment

Choose a reason for hiding this comment

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

thx @moznion!

can you see if you can add a test that shows http.route now getting collected on the spans?

@moznion
Copy link
Contributor Author

moznion commented Feb 12, 2023

@trask sure, I'll add some test cases for this.
I actually wanted to confirm whether this patch's way is acceptable to solve the issue by contributors's review at first. I appreciate your review and comment.

…in a server span with Play framework

Signed-off-by: moznion <moznion@mail.moznion.net>
@moznion
Copy link
Contributor Author

moznion commented Feb 13, 2023

@trask I added the test case for this patch to the smoke test @ 5151da5.

Essentially, this test case should be in the individual instrumentation subproject (i.e. instrumentation/play/play-mvc/play-mvc-2.6/javaagent/src/test) but it doesn't because the current test code in the subproject uses "custom routing" instead of the actual Play application, so it doesn't inject the HANDLER_DEF value for the request object (see also: playframework/playframework#7829).
Due to this problem, it's hard to do test in the subproject (actually, I'm not sure how to make an application for testing purposes without polution for that subproject. Probably it needs to locate that under the test/ directory but I have no idea how can I do that), thus this diverts the smoke test which uses the actual Play app to check the attribute injection.

@moznion moznion requested review from trask and removed request for theletterf February 13, 2023 08:25
Signed-off-by: moznion <moznion@mail.moznion.net>
@moznion moznion changed the title Put http_route attribute onto http_server_duration on Play framework request processing Put http.route attribute onto http.server.duration on Play framework request processing Feb 13, 2023
Copy link
Member

@mateuszrzeszutek mateuszrzeszutek left a comment

Choose a reason for hiding this comment

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

Thanks @moznion !

Comment on lines 69 to 70
// set the span name on the upstream akka/netty span
Span serverSpan = LocalRootSpan.fromContextOrNull(context);
Copy link
Member

Choose a reason for hiding this comment

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

Can you remove the code that handles the serverSpan below? The HttpRouteHolder does that already

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for pointing out it. I removed them at ff97ca1.

@@ -66,6 +73,10 @@ public static void updateSpanNames(Context context, Request<?> request) {
}
}

private static void updateHttpRoute(Context context, String route) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: this method is so simple that it could be inlined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, actually this was an intentional thing to try making the aim of the procedure obvious by the method name, but as you mentioned this has already been enough self-descriptive and ff97ca1 removed extra lines, so I changed them to be inlined.

Comment on lines 43 to 45
def httpRouteAttributes = extractRouteAttributesFrom(traces)
httpRouteAttributes.size() == 1
httpRouteAttributes.get(0).value.stringValue == "/welcome"
Copy link
Member

Choose a reason for hiding this comment

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

Nit: you could use TraceInspector and countFilteredAttributes instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's good to know! I simplified that at 5be95b8.

@@ -52,12 +54,17 @@ public static Instrumenter<Void, Void> instrumenter() {
return INSTRUMENTER;
}

public static void updateSpanNames(Context context, Request<?> request) {
public static void updateContext(Context context, Request<?> request) {
Copy link
Contributor

Choose a reason for hiding this comment

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

would it be possible to do the same changes in play 2.4 instrumentation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I applied the same change for Play 2.4 MVC at 6109ae3.

@moznion moznion requested review from mateuszrzeszutek and laurit and removed request for trask, theletterf, mateuszrzeszutek and laurit February 13, 2023 21:23
@@ -37,6 +38,8 @@ class PlaySmokeTest extends SmokeTest {
//One internal, one SERVER
countSpansByName(traces, '/welcome') == 2

new TraceInspector(traces).countFilteredAttributes(SemanticAttributes.HTTP_ROUTE.key, "/welcome") == 1
Copy link
Member

Choose a reason for hiding this comment

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

❤️ this is good enough for me, thx!

@trask trask added this to the v1.23.0 milestone Feb 13, 2023
Copy link
Member

@mateuszrzeszutek mateuszrzeszutek left a comment

Choose a reason for hiding this comment

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

Thanks @moznion !

@laurit laurit merged commit 7e8d76a into open-telemetry:main Feb 14, 2023
@moznion moznion deleted the add_http_route_attribute_on_play branch February 14, 2023 18:01
@trask trask mentioned this pull request Feb 14, 2023
trask added a commit that referenced this pull request Feb 14, 2023
resolves #7813

caused by conflict between #7730 and #7801
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants