francoposa / tower-otel-http-metrics

OpenTelemetry HTTP Metrics Middleware Layer for Tower-Compatible Servers (Axum, Hyper)
https://docs.rs/tower-otel-http-metrics/latest/tower_otel_http_metrics
MIT License
8 stars 5 forks source link

Switch duration seconds metric from u64 to f64 #5

Closed sartak closed 6 months ago

sartak commented 6 months ago

Thanks for tower-otel-http-metrics! I noticed that http.server.request.duration is (correctly) logged as a number of seconds. However, because it's an integer rather than a float, it's not as useful as it could be.

This PR switches duration from u64 to f64.

francoposa commented 6 months ago

awesome, thanks for submitting this! will run some tests locally with the collector locally to see how it the difference shows up, just want to check if makes sense to make this a patch version bump or a minor version bump.

sartak commented 6 months ago

I tested with VictoriaMetrics and Grafana, and they both handled the type change gracefully. I haven't looked at the otel specs to see if they say anything about this though.

Either way, minor version bump is probably prudent.

francoposa commented 6 months ago

yep, definitely a version bump here. otel-collector logs for a single request on main branch:

otel-collector  | 2024-05-14T17:16:09.193Z  info    ResourceMetrics #0
otel-collector  | Resource SchemaURL: 
otel-collector  | Resource attributes:
otel-collector  |      -> service.name: Str(example-axum-http-service)
otel-collector  |      -> telemetry.sdk.language: Str(rust)
otel-collector  |      -> telemetry.sdk.name: Str(opentelemetry)
otel-collector  |      -> telemetry.sdk.version: Str(0.22.1)
otel-collector  | ScopeMetrics #0
otel-collector  | ScopeMetrics SchemaURL: 
otel-collector  | InstrumentationScope example-axum-http-service 
otel-collector  | Metric #0
otel-collector  | Descriptor:
otel-collector  |      -> Name: http.server.request.duration
otel-collector  |      -> Description: 
otel-collector  |      -> Unit: 
otel-collector  |      -> DataType: Histogram
otel-collector  |      -> AggregationTemporality: Cumulative
otel-collector  | HistogramDataPoints #0
otel-collector  | Data point attributes:
otel-collector  |      -> http.request.method: Str(GET)
otel-collector  |      -> http.response.status_code: Str(200 OK)
otel-collector  |      -> http.route: Str(/)
otel-collector  |      -> network.protocol.name: Str(http)
otel-collector  |      -> network.protocol.version: Str(1.1)
otel-collector  | StartTimestamp: 2024-05-14 17:15:39.189696127 +0000 UTC
otel-collector  | Timestamp: 2024-05-14 17:16:09.191614482 +0000 UTC
otel-collector  | Count: 1
otel-collector  | Sum: 0.000000
otel-collector  | Min: 0.000000
otel-collector  | Max: 0.000000
otel-collector  | ExplicitBounds #0: 0.000000
otel-collector  | ExplicitBounds #1: 5.000000
otel-collector  | ExplicitBounds #2: 10.000000
otel-collector  | ExplicitBounds #3: 25.000000
otel-collector  | ExplicitBounds #4: 50.000000
otel-collector  | ExplicitBounds #5: 75.000000
otel-collector  | ExplicitBounds #6: 100.000000
otel-collector  | ExplicitBounds #7: 250.000000
otel-collector  | ExplicitBounds #8: 500.000000
otel-collector  | ExplicitBounds #9: 750.000000
otel-collector  | ExplicitBounds #10: 1000.000000
otel-collector  | ExplicitBounds #11: 2500.000000
otel-collector  | ExplicitBounds #12: 5000.000000
otel-collector  | ExplicitBounds #13: 7500.000000
otel-collector  | ExplicitBounds #14: 10000.000000
otel-collector  | Buckets #0, Count: 1
otel-collector  | Buckets #1, Count: 0
otel-collector  | Buckets #2, Count: 0
otel-collector  | Buckets #3, Count: 0
otel-collector  | Buckets #4, Count: 0
otel-collector  | Buckets #5, Count: 0
otel-collector  | Buckets #6, Count: 0
otel-collector  | Buckets #7, Count: 0
otel-collector  | Buckets #8, Count: 0
otel-collector  | Buckets #9, Count: 0
otel-collector  | Buckets #10, Count: 0
otel-collector  | Buckets #11, Count: 0
otel-collector  | Buckets #12, Count: 0
otel-collector  | Buckets #13, Count: 0
otel-collector  | Buckets #14, Count: 0
otel-collector  | Buckets #15, Count: 0

otel-collector logs for a single request on duration-f64 branch:

otel-collector  | 2024-05-14T17:18:49.820Z  info    ResourceMetrics #0
otel-collector  | Resource SchemaURL: 
otel-collector  | Resource attributes:
otel-collector  |      -> telemetry.sdk.version: Str(0.22.1)
otel-collector  |      -> telemetry.sdk.name: Str(opentelemetry)
otel-collector  |      -> telemetry.sdk.language: Str(rust)
otel-collector  |      -> service.name: Str(example-axum-http-service)
otel-collector  | ScopeMetrics #0
otel-collector  | ScopeMetrics SchemaURL: 
otel-collector  | InstrumentationScope example-axum-http-service 
otel-collector  | Metric #0
otel-collector  | Descriptor:
otel-collector  |      -> Name: http.server.request.duration
otel-collector  |      -> Description: 
otel-collector  |      -> Unit: 
otel-collector  |      -> DataType: Histogram
otel-collector  |      -> AggregationTemporality: Cumulative
otel-collector  | HistogramDataPoints #0
otel-collector  | Data point attributes:
otel-collector  |      -> http.request.method: Str(GET)
otel-collector  |      -> http.response.status_code: Str(200 OK)
otel-collector  |      -> http.route: Str(/)
otel-collector  |      -> network.protocol.name: Str(http)
otel-collector  |      -> network.protocol.version: Str(1.1)
otel-collector  | StartTimestamp: 2024-05-14 17:18:39.817396731 +0000 UTC
otel-collector  | Timestamp: 2024-05-14 17:18:49.818441264 +0000 UTC
otel-collector  | Count: 1
otel-collector  | Sum: 0.000061
otel-collector  | Min: 0.000061
otel-collector  | Max: 0.000061
otel-collector  | ExplicitBounds #0: 0.000000
otel-collector  | ExplicitBounds #1: 5.000000
otel-collector  | ExplicitBounds #2: 10.000000
otel-collector  | ExplicitBounds #3: 25.000000
otel-collector  | ExplicitBounds #4: 50.000000
otel-collector  | ExplicitBounds #5: 75.000000
otel-collector  | ExplicitBounds #6: 100.000000
otel-collector  | ExplicitBounds #7: 250.000000
otel-collector  | ExplicitBounds #8: 500.000000
otel-collector  | ExplicitBounds #9: 750.000000
otel-collector  | ExplicitBounds #10: 1000.000000
otel-collector  | ExplicitBounds #11: 2500.000000
otel-collector  | ExplicitBounds #12: 5000.000000
otel-collector  | ExplicitBounds #13: 7500.000000
otel-collector  | ExplicitBounds #14: 10000.000000
otel-collector  | Buckets #0, Count: 0
otel-collector  | Buckets #1, Count: 1
otel-collector  | Buckets #2, Count: 0
otel-collector  | Buckets #3, Count: 0
otel-collector  | Buckets #4, Count: 0
otel-collector  | Buckets #5, Count: 0
otel-collector  | Buckets #6, Count: 0
otel-collector  | Buckets #7, Count: 0
otel-collector  | Buckets #8, Count: 0
otel-collector  | Buckets #9, Count: 0
otel-collector  | Buckets #10, Count: 0
otel-collector  | Buckets #11, Count: 0
otel-collector  | Buckets #12, Count: 0
otel-collector  | Buckets #13, Count: 0
otel-collector  | Buckets #14, Count: 0
otel-collector  | Buckets #15, Count: 0

I used the Mimir + Grafana setup to visualize and this is a lot better - I missed it because I always look at the _count metric when testing and not the actual durations.