From f62983d36b3d672d17fdeb498824d3259c858f34 Mon Sep 17 00:00:00 2001 From: Flc Date: Mon, 9 Dec 2024 19:51:50 +0800 Subject: [PATCH] backup --- .../net/http/otelhttp/internal/semconv/env.go | 14 ++++-- .../otelhttp/internal/semconv/env_test.go | 36 ++++++++----- .../otelhttp/internal/semconv/httpconv.go | 19 ++++--- .../internal/semconv/httpconv_test.go | 50 +++++++++++++++++-- .../otelhttp/internal/semconv/v1.20.0_test.go | 26 +++++----- 5 files changed, 101 insertions(+), 44 deletions(-) diff --git a/instrumentation/net/http/otelhttp/internal/semconv/env.go b/instrumentation/net/http/otelhttp/internal/semconv/env.go index 3229edbfa48..469821e2620 100644 --- a/instrumentation/net/http/otelhttp/internal/semconv/env.go +++ b/instrumentation/net/http/otelhttp/internal/semconv/env.go @@ -15,6 +15,10 @@ import ( "go.opentelemetry.io/otel/metric" ) +// OTelSemConvStabilityOptIn is an environment variable. +// That can be set to "old" or "http/dup" to opt into the new HTTP semantic conventions. +const OTelSemConvStabilityOptIn = "OTEL_SEMCONV_STABILITY_OPT_IN" + type ResponseTelemetry struct { StatusCode int ReadBytes int64 @@ -32,9 +36,9 @@ type HTTPServer struct { serverLatencyMeasure metric.Float64Histogram // New metrics - requestDurationHistogram metric.Float64Histogram requestBodySizeHistogram metric.Int64Histogram responseBodySizeHistogram metric.Int64Histogram + requestDurationHistogram metric.Float64Histogram } // RequestTraceAttrs returns trace attributes for an HTTP request received by a @@ -120,21 +124,21 @@ func (s HTTPServer) RecordMetrics(ctx context.Context, md ServerMetricData) { if s.duplicate && s.requestDurationHistogram != nil && s.requestBodySizeHistogram != nil && s.responseBodySizeHistogram != nil { attributes := newHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes) o := metric.WithAttributeSet(attribute.NewSet(attributes...)) - s.requestDurationHistogram.Record(ctx, md.ElapsedTime, o) s.requestBodySizeHistogram.Record(ctx, md.RequestSize, o) s.responseBodySizeHistogram.Record(ctx, md.ResponseSize, o) + s.requestDurationHistogram.Record(ctx, md.ElapsedTime, o) } } func NewHTTPServer(meter metric.Meter) HTTPServer { - env := strings.ToLower(os.Getenv("OTEL_SEMCONV_STABILITY_OPT_IN")) + env := strings.ToLower(os.Getenv(OTelSemConvStabilityOptIn)) duplicate := env == "http/dup" server := HTTPServer{ duplicate: duplicate, } server.requestBytesCounter, server.responseBytesCounter, server.serverLatencyMeasure = oldHTTPServer{}.createMeasures(meter) if duplicate { - server.requestDurationHistogram, server.requestBodySizeHistogram, server.responseBodySizeHistogram = newHTTPServer{}.createMeasures(meter) + server.requestBodySizeHistogram, server.responseBodySizeHistogram, server.requestDurationHistogram = newHTTPServer{}.createMeasures(meter) } return server } @@ -149,7 +153,7 @@ type HTTPClient struct { } func NewHTTPClient(meter metric.Meter) HTTPClient { - env := strings.ToLower(os.Getenv("OTEL_SEMCONV_STABILITY_OPT_IN")) + env := strings.ToLower(os.Getenv(OTelSemConvStabilityOptIn)) client := HTTPClient{ duplicate: env == "http/dup", } diff --git a/instrumentation/net/http/otelhttp/internal/semconv/env_test.go b/instrumentation/net/http/otelhttp/internal/semconv/env_test.go index 3a02a777373..9fda8fe80e4 100644 --- a/instrumentation/net/http/otelhttp/internal/semconv/env_test.go +++ b/instrumentation/net/http/otelhttp/internal/semconv/env_test.go @@ -94,24 +94,31 @@ func TestHTTPClientDoesNotPanic(t *testing.T) { } } -type testInst struct { +type testRecorder[T any] struct { embedded.Int64Counter + embedded.Int64Histogram embedded.Float64Histogram - intValue int64 - floatValue float64 + value T attributes []attribute.KeyValue } -func (t *testInst) Add(ctx context.Context, incr int64, options ...metric.AddOption) { - t.intValue = incr +var ( + _ metric.Int64Counter = (*testRecorder[int64])(nil) + _ metric.Float64Histogram = (*testRecorder[float64])(nil) + _ metric.Int64Histogram = (*testRecorder[int64])(nil) + _ metric.Float64Histogram = (*testRecorder[float64])(nil) +) + +func (t *testRecorder[T]) Add(_ context.Context, incr T, options ...metric.AddOption) { + t.value = incr cfg := metric.NewAddConfig(options) attr := cfg.Attributes() t.attributes = attr.ToSlice() } -func (t *testInst) Record(ctx context.Context, value float64, options ...metric.RecordOption) { - t.floatValue = value +func (t *testRecorder[T]) Record(_ context.Context, value T, options ...metric.RecordOption) { + t.value = value cfg := metric.NewRecordConfig(options) attr := cfg.Attributes() t.attributes = attr.ToSlice() @@ -119,16 +126,19 @@ func (t *testInst) Record(ctx context.Context, value float64, options ...metric. func NewTestHTTPServer() HTTPServer { return HTTPServer{ - requestBytesCounter: &testInst{}, - responseBytesCounter: &testInst{}, - serverLatencyMeasure: &testInst{}, + requestBytesCounter: &testRecorder[int64]{}, + responseBytesCounter: &testRecorder[int64]{}, + serverLatencyMeasure: &testRecorder[float64]{}, + requestBodySizeHistogram: &testRecorder[int64]{}, + responseBodySizeHistogram: &testRecorder[int64]{}, + requestDurationHistogram: &testRecorder[float64]{}, } } func NewTestHTTPClient() HTTPClient { return HTTPClient{ - requestBytesCounter: &testInst{}, - responseBytesCounter: &testInst{}, - latencyMeasure: &testInst{}, + requestBytesCounter: &testRecorder[int64]{}, + responseBytesCounter: &testRecorder[int64]{}, + latencyMeasure: &testRecorder[float64]{}, } } diff --git a/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go b/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go index cb729b96c0a..3f2417b52b1 100644 --- a/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go +++ b/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go @@ -202,19 +202,12 @@ func (n newHTTPServer) Route(route string) attribute.KeyValue { return semconvNew.HTTPRoute(route) } -func (n newHTTPServer) createMeasures(meter metric.Meter) (metric.Float64Histogram, metric.Int64Histogram, metric.Int64Histogram) { +func (n newHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Histogram, metric.Int64Histogram, metric.Float64Histogram) { if meter == nil { - return noop.Float64Histogram{}, noop.Int64Histogram{}, noop.Int64Histogram{} + return noop.Int64Histogram{}, noop.Int64Histogram{}, noop.Float64Histogram{} } var err error - requestDurationHistogram, err := meter.Float64Histogram( - semconvNew.HTTPServerRequestDurationName, - metric.WithUnit(semconvNew.HTTPServerRequestDurationUnit), - metric.WithDescription(semconvNew.HTTPServerRequestDurationDescription), - ) - handleErr(err) - requestBodySizeHistogram, err := meter.Int64Histogram( semconvNew.HTTPServerRequestBodySizeName, metric.WithUnit(semconvNew.HTTPServerRequestBodySizeUnit), @@ -228,8 +221,14 @@ func (n newHTTPServer) createMeasures(meter metric.Meter) (metric.Float64Histogr metric.WithDescription(semconvNew.HTTPServerResponseBodySizeDescription), ) handleErr(err) + requestDurationHistogram, err := meter.Float64Histogram( + semconvNew.HTTPServerRequestDurationName, + metric.WithUnit(semconvNew.HTTPServerRequestDurationUnit), + metric.WithDescription(semconvNew.HTTPServerRequestDurationDescription), + ) + handleErr(err) - return requestDurationHistogram, requestBodySizeHistogram, responseBodySizeHistogram + return requestBodySizeHistogram, responseBodySizeHistogram, requestDurationHistogram } func (n newHTTPServer) MetricAttributes(server string, req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue { diff --git a/instrumentation/net/http/otelhttp/internal/semconv/httpconv_test.go b/instrumentation/net/http/otelhttp/internal/semconv/httpconv_test.go index 6a3f6c09a4f..5394251cbc4 100644 --- a/instrumentation/net/http/otelhttp/internal/semconv/httpconv_test.go +++ b/instrumentation/net/http/otelhttp/internal/semconv/httpconv_test.go @@ -4,6 +4,7 @@ package semconv import ( + "context" "errors" "fmt" "net/http" @@ -17,7 +18,7 @@ import ( ) func TestNewTraceRequest(t *testing.T) { - t.Setenv("OTEL_SEMCONV_STABILITY_OPT_IN", "http/dup") + t.Setenv(OTelSemConvStabilityOptIn, "http/dup") serv := NewHTTPServer(nil) want := func(req testServerReq) []attribute.KeyValue { return []attribute.KeyValue{ @@ -95,6 +96,49 @@ func TestNewTraceResponse(t *testing.T) { } } +func TestNewRecordMetrics(t *testing.T) { + t.Setenv(OTelSemConvStabilityOptIn, "http/dup") + server := NewTestHTTPServer() + server.duplicate = true + req, err := http.NewRequest("POST", "http://example.com", nil) + assert.NoError(t, err) + + server.RecordMetrics(context.Background(), ServerMetricData{ + ServerName: "stuff", + ResponseSize: 200, + MetricAttributes: MetricAttributes{ + Req: req, + StatusCode: 301, + AdditionalAttributes: []attribute.KeyValue{ + attribute.String("key", "value"), + }, + }, + MetricData: MetricData{ + RequestSize: 100, + ElapsedTime: 300, + }, + }) + + assert.Equal(t, int64(100), server.requestBodySizeHistogram.(*testRecorder[int64]).value) + assert.Equal(t, int64(200), server.responseBodySizeHistogram.(*testRecorder[int64]).value) + assert.Equal(t, float64(300), server.requestDurationHistogram.(*testRecorder[float64]).value) + + want := []attribute.KeyValue{ + attribute.String("http.scheme", "http"), + attribute.String("http.method", "POST"), + attribute.Int64("http.status_code", 301), + attribute.String("key", "value"), + attribute.String("net.host.name", "stuff"), + attribute.String("net.protocol.name", "http"), + attribute.String("net.protocol.version", "1.1"), + } + _ = want + + // assert.ElementsMatch(t, want, server.requestBodySizeHistogram.(*testRecorder[int64]).attributes) + // assert.ElementsMatch(t, want, server.responseBodySizeHistogram.(*testRecorder[int64]).attributes) + // assert.ElementsMatch(t, want, server.requestDurationHistogram.(*testRecorder[float64]).attributes) +} + func TestNewMethod(t *testing.T) { testCases := []struct { method string @@ -131,7 +175,7 @@ func TestNewMethod(t *testing.T) { } func TestNewTraceRequest_Client(t *testing.T) { - t.Setenv("OTEL_SEMCONV_STABILITY_OPT_IN", "http/dup") + t.Setenv(OTelSemConvStabilityOptIn, "http/dup") body := strings.NewReader("Hello, world!") url := "https://example.com:8888/foo/bar?stuff=morestuff" req := httptest.NewRequest("pOST", url, body) @@ -156,7 +200,7 @@ func TestNewTraceRequest_Client(t *testing.T) { } func TestNewTraceResponse_Client(t *testing.T) { - t.Setenv("OTEL_SEMCONV_STABILITY_OPT_IN", "http/dup") + t.Setenv(OTelSemConvStabilityOptIn, "http/dup") testcases := []struct { resp http.Response want []attribute.KeyValue diff --git a/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0_test.go b/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0_test.go index eef382a5047..ef5a4568965 100644 --- a/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0_test.go +++ b/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0_test.go @@ -17,7 +17,7 @@ import ( func TestV120TraceRequest(t *testing.T) { // Anything but "http" or "http/dup" works. - t.Setenv("OTEL_SEMCONV_STABILITY_OPT_IN", "old") + t.Setenv(OTelSemConvStabilityOptIn, "old") serv := NewHTTPServer(nil) want := func(req testServerReq) []attribute.KeyValue { return []attribute.KeyValue{ @@ -108,9 +108,9 @@ func TestV120RecordMetrics(t *testing.T) { }, }) - assert.Equal(t, int64(100), server.requestBytesCounter.(*testInst).intValue) - assert.Equal(t, int64(200), server.responseBytesCounter.(*testInst).intValue) - assert.Equal(t, float64(300), server.serverLatencyMeasure.(*testInst).floatValue) + assert.Equal(t, int64(100), server.requestBytesCounter.(*testRecorder[int64]).value) + assert.Equal(t, int64(200), server.responseBytesCounter.(*testRecorder[int64]).value) + assert.Equal(t, float64(300), server.serverLatencyMeasure.(*testRecorder[float64]).value) want := []attribute.KeyValue{ attribute.String("http.scheme", "http"), @@ -122,9 +122,9 @@ func TestV120RecordMetrics(t *testing.T) { attribute.String("net.protocol.version", "1.1"), } - assert.ElementsMatch(t, want, server.requestBytesCounter.(*testInst).attributes) - assert.ElementsMatch(t, want, server.responseBytesCounter.(*testInst).attributes) - assert.ElementsMatch(t, want, server.serverLatencyMeasure.(*testInst).attributes) + assert.ElementsMatch(t, want, server.requestBytesCounter.(*testRecorder[int64]).attributes) + assert.ElementsMatch(t, want, server.responseBytesCounter.(*testRecorder[int64]).attributes) + assert.ElementsMatch(t, want, server.serverLatencyMeasure.(*testRecorder[float64]).attributes) } func TestV120ClientRequest(t *testing.T) { @@ -183,9 +183,9 @@ func TestV120ClientMetrics(t *testing.T) { ElapsedTime: 300, }, opts) - assert.Equal(t, int64(100), client.requestBytesCounter.(*testInst).intValue) - assert.Equal(t, int64(200), client.responseBytesCounter.(*testInst).intValue) - assert.Equal(t, float64(300), client.latencyMeasure.(*testInst).floatValue) + assert.Equal(t, int64(100), client.requestBytesCounter.(*testRecorder[int64]).value) + assert.Equal(t, int64(200), client.responseBytesCounter.(*testRecorder[int64]).value) + assert.Equal(t, float64(300), client.latencyMeasure.(*testRecorder[float64]).value) want := []attribute.KeyValue{ attribute.String("http.method", "POST"), @@ -194,9 +194,9 @@ func TestV120ClientMetrics(t *testing.T) { attribute.String("net.peer.name", "example.com"), } - assert.ElementsMatch(t, want, client.requestBytesCounter.(*testInst).attributes) - assert.ElementsMatch(t, want, client.responseBytesCounter.(*testInst).attributes) - assert.ElementsMatch(t, want, client.latencyMeasure.(*testInst).attributes) + assert.ElementsMatch(t, want, client.requestBytesCounter.(*testRecorder[int64]).attributes) + assert.ElementsMatch(t, want, client.responseBytesCounter.(*testRecorder[int64]).attributes) + assert.ElementsMatch(t, want, client.latencyMeasure.(*testRecorder[float64]).attributes) } func TestStandardizeHTTPMethodMetric(t *testing.T) {