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

otelhttp: client metrics #4707

Merged
merged 16 commits into from Feb 2, 2024

Conversation

Sovietaced
Copy link
Contributor

@Sovietaced Sovietaced commented Dec 17, 2023

This pull request attempts to follow up on the work that @RangelReale did in #3769 and close out the work. This pull request adds support for http client metrics that mostly adhere to the v1.20 semantic conventions. In many ways this code attempts to mirror the http server metric code in implementation.

As such, it reuses the HTTP request body wrapper logic and introduces HTTP response body wrapper logic with callbacks to record metrics once the response body has been read.

Open Questions:

  • As written these client metrics follow the convention of the server metrics, but don't actually follow the convention of the OTEL spec as noted in Metrics are non conformant to semantic conventions #4501. I guess this migration can be done later?
  • I don't believe the code will report HTTP response metrics unless the response body is read, which is the responsibility of the client. Are we ok with this behavior? I tried to follow the the pattern where reading bodies is done with wrapping to minimize allocations.
  • It is not clear to me how the body wrappers work with long lived connections?

Fixes #3134
Fixes #1336

Copy link

codecov bot commented Dec 17, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (5047be2) 79.7% compared to head (cac99f8) 80.3%.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##            main   #4707     +/-   ##
=======================================
+ Coverage   79.7%   80.3%   +0.5%     
=======================================
  Files        151     151             
  Lines       9959   10209    +250     
=======================================
+ Hits        7946    8201    +255     
+ Misses      1859    1854      -5     
  Partials     154     154             
Files Coverage Δ
...stful/otelrestful/internal/semconvutil/httpconv.go 95.6% <100.0%> (+0.3%) ⬆️
...gonic/gin/otelgin/internal/semconvutil/httpconv.go 95.6% <100.0%> (+0.3%) ⬆️
...rilla/mux/otelmux/internal/semconvutil/httpconv.go 95.6% <100.0%> (+0.3%) ⬆️
...ack/echo/otelecho/internal/semconvutil/httpconv.go 95.6% <100.0%> (+0.3%) ⬆️
...on.v1/otelmacaron/internal/semconvutil/httpconv.go 95.6% <100.0%> (+0.3%) ⬆️
...ace/otelhttptrace/internal/semconvutil/httpconv.go 95.6% <100.0%> (+0.3%) ⬆️
instrumentation/net/http/otelhttp/common.go 100.0% <ø> (ø)
instrumentation/net/http/otelhttp/handler.go 87.3% <100.0%> (ø)
...net/http/otelhttp/internal/semconvutil/httpconv.go 95.6% <100.0%> (+0.3%) ⬆️
instrumentation/net/http/otelhttp/transport.go 96.9% <100.0%> (+2.1%) ⬆️

... and 2 files with indirect coverage changes

@Sovietaced Sovietaced changed the title Initial stab at http client metrics otelhttp: client metrics Dec 17, 2023
@Sovietaced Sovietaced marked this pull request as ready for review December 17, 2023 21:22
instrumentation/net/http/otelhttp/common.go Outdated Show resolved Hide resolved
instrumentation/net/http/otelhttp/transport.go Outdated Show resolved Hide resolved
instrumentation/net/http/otelhttp/transport_test.go Outdated Show resolved Hide resolved
@pellared
Copy link
Member

I don't believe the code will report HTTP response metrics unless the response body is read, which is the responsibility of the client. Are we ok with this behavior? I tried to follow the the pattern where reading bodies is done with wrapping to minimize allocations.

We are fine. From https://pkg.go.dev/net/http:

The caller must close the response body when finished with it:
...
Caller should close resp.Body when done reading from it.

Also we already have this requirement for trace instrumentation.

Side note: probably we should call it out in package documentation.

@pellared
Copy link
Member

As written these client metrics follow the convention of the server metrics, but don't actually follow the convention of the OTEL spec as noted in #4501. I guess this migration can be done later?

We want to first be be compliant with the v1.20 semantic conventions. Next semantic convention versions have many breaking changes and we want to help a little with the migration.

instrumentation/net/http/otelhttp/test/transport_test.go Outdated Show resolved Hide resolved
instrumentation/net/http/otelhttp/common.go Outdated Show resolved Hide resolved
instrumentation/net/http/otelhttp/transport.go Outdated Show resolved Hide resolved
instrumentation/net/http/otelhttp/common.go Outdated Show resolved Hide resolved
@pellared
Copy link
Member

Please add a changelog entry.

@Sovietaced
Copy link
Contributor Author

Please add a changelog entry.

Will do, I didn't add one since you seemed a bit picky about the changelog entries on my last PR :)

pellared
pellared previously approved these changes Dec 29, 2023
@Sovietaced
Copy link
Contributor Author

@dmathieu @Aneurysm9 @dashpole @hanyuancheung Please take a look when you have a chance. TY

@Sovietaced
Copy link
Contributor Author

@pellared should be good to go

Copy link
Member

@pellared pellared left a comment

Choose a reason for hiding this comment

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

Little comments that I would like to have addressed. Besides looks good 👍

instrumentation/net/http/otelhttp/transport_test.go Outdated Show resolved Hide resolved
instrumentation/net/http/otelhttp/transport_test.go Outdated Show resolved Hide resolved
@gaiaz-iusipov
Copy link

It would be nice to have something similar to otelhttp.WithRouteTag for the transport, thus allowing the separation of different requests in metrics. For example: otelhttp.WithRequestTag.

@pellared pellared merged commit b76d81c into open-telemetry:main Feb 2, 2024
22 checks passed
@pellared
Copy link
Member

pellared commented Feb 2, 2024

@Sovietaced Thank you for your contribution

@Sovietaced Sovietaced deleted the otelhttp-transport-metrics branch February 3, 2024 19:39
@Sovietaced
Copy link
Contributor Author

It would be nice to have something similar to otelhttp.WithRouteTag for the transport, thus allowing the separation of different requests in metrics. For example: otelhttp.WithRequestTag.

Maybe create a separate issue for this?

@MrAlias MrAlias added this to the v0.48.0 milestone Feb 6, 2024
@MrAlias MrAlias mentioned this pull request Feb 7, 2024
@StarpTech
Copy link

Hi, it would be great if new features like metrics are built behind a feature flag. For example, we use the middleware for everything expect metrics. As a workaround, we pass a Noop meter.

@@ -50,8 +50,8 @@ func assertScopeMetrics(t *testing.T, sm metricdata.ScopeMetrics, attrs attribut
require.Len(t, sm.Metrics, 3)

want := metricdata.Metrics{
Name: "http.server.request_content_length",
Description: "Measures the size of HTTP request content length (uncompressed)",
Name: "http.server.request.size",
Copy link

@StarpTech StarpTech Feb 9, 2024

Choose a reason for hiding this comment

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

@pellared This looks to me like a breaking change. Why wasn't it communicated as such?

Copy link
Contributor

Choose a reason for hiding this comment

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

@sharptech sorry about that. I've opened #4898 to add it to the changelog.

Copy link

@StarpTech StarpTech Feb 9, 2024

Choose a reason for hiding this comment

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

Hi @dashpole wouldn't it be better to rollback so the deprecation statements remains true? I saw that the old name isn't used at all in the code. I also think breaking stuff with a feature release isn't the right approach.

Copy link
Contributor

Choose a reason for hiding this comment

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

The deprecation statements refer to these constants: https://github.com/open-telemetry/opentelemetry-go-contrib/pull/4707/files#diff-be9e2412d1919396470e196d2be4bddf6997059892167fd8381a9cfa478933faR34

I also think breaking stuff with a feature release isn't the right approach.

The otelhttp module is not stable, and is still released under a v0.* version, so breaking changes are expected. You can see the versioning policy here: https://github.com/open-telemetry/opentelemetry-go/blob/main/VERSIONING.md. The telemetry in otelhttp follows the semantic conventions for http metrics: https://opentelemetry.io/docs/specs/semconv/http/http-metrics/, so breaking changes to conventions require us to make breaking changes here.

Choose a reason for hiding this comment

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

I understand, but users like me running this in production. We need to deprecate fields before we can upgrade. If I would want to use the new metrics I couldn't. I'm saying the feature and the breaking change could have been shipped in two PR (releases).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add metrics for transport layer in instrumentation net/http Add Instrumentation (metric) for net/http