From b894f530bf5c753364bb2811adfb8fac51eb52a7 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 27 Mar 2024 17:31:28 +0200 Subject: [PATCH 01/13] Support template paths as part of span names for go versions >= 1.22 --- internal/pkg/inject/offset_results.json | 179 ++++++++++++++++++ .../bpf/net/http/http_event.go | 37 ++++ .../bpf/net/http/http_event_test.go | 92 +++++++++ .../bpf/net/http/server/bpf/probe.bpf.c | 16 +- .../bpf/net/http/server/probe.go | 47 ++++- internal/pkg/instrumentation/probe/probe.go | 30 ++- internal/test/e2e/nethttp/traces.json | 2 +- internal/test/e2e/nethttp/verify.bats | 4 +- internal/tools/inspect/cmd/offsetgen/main.go | 2 + 9 files changed, 400 insertions(+), 9 deletions(-) create mode 100644 internal/pkg/instrumentation/bpf/net/http/http_event_test.go diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index 96a9d29df..572d57c16 100644 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -2750,6 +2750,168 @@ ] } ] + }, + { + "field": "pat", + "offsets": [ + { + "offset": 24, + "versions": [ + "1.12.0", + "1.12.1", + "1.12.2", + "1.12.3", + "1.12.4", + "1.12.5", + "1.12.6", + "1.12.7", + "1.12.8", + "1.12.9", + "1.12.10", + "1.12.11", + "1.12.12", + "1.12.13", + "1.12.14", + "1.12.15", + "1.12.16", + "1.12.17", + "1.13.0", + "1.13.1", + "1.13.2", + "1.13.3", + "1.13.4", + "1.13.5", + "1.13.6", + "1.13.7", + "1.13.8", + "1.13.9", + "1.13.10", + "1.13.11", + "1.13.12", + "1.13.13", + "1.13.14", + "1.13.15", + "1.14.0", + "1.14.1", + "1.14.2", + "1.14.3", + "1.14.4", + "1.14.5", + "1.14.6", + "1.14.7", + "1.14.8", + "1.14.9", + "1.14.10", + "1.14.11", + "1.14.12", + "1.14.13", + "1.14.14", + "1.14.15", + "1.15.0", + "1.15.1", + "1.15.2", + "1.15.3", + "1.15.4", + "1.15.5", + "1.15.6", + "1.15.7", + "1.15.8", + "1.15.9", + "1.15.10", + "1.15.11", + "1.15.12", + "1.15.13", + "1.15.14", + "1.15.15", + "1.16.0", + "1.16.1", + "1.16.2", + "1.16.3", + "1.16.4", + "1.16.5", + "1.16.6", + "1.16.7", + "1.16.8", + "1.16.9", + "1.16.10", + "1.16.11", + "1.16.12", + "1.16.13", + "1.16.14", + "1.16.15", + "1.17.0", + "1.17.1", + "1.17.2", + "1.17.3", + "1.17.4", + "1.17.5", + "1.17.6", + "1.17.7", + "1.17.8", + "1.17.9", + "1.17.10", + "1.17.11", + "1.17.12", + "1.17.13", + "1.18.0", + "1.18.1", + "1.18.2", + "1.18.3", + "1.18.4", + "1.18.5", + "1.18.6", + "1.18.7", + "1.18.8", + "1.18.9", + "1.18.10", + "1.19.0", + "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", + "1.20.0", + "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8" + ] + }, + { + "offset": 248, + "versions": [ + "1.22.0", + "1.22.1" + ] + } + ] } ] }, @@ -2915,6 +3077,23 @@ } ] }, + { + "struct": "pattern", + "fields": [ + { + "field": "str", + "offsets": [ + { + "offset": 0, + "versions": [ + "1.22.0", + "1.22.1" + ] + } + ] + } + ] + }, { "struct": "response", "fields": [ diff --git a/internal/pkg/instrumentation/bpf/net/http/http_event.go b/internal/pkg/instrumentation/bpf/net/http/http_event.go index 864d251cb..f3790dc3d 100644 --- a/internal/pkg/instrumentation/bpf/net/http/http_event.go +++ b/internal/pkg/instrumentation/bpf/net/http/http_event.go @@ -15,6 +15,7 @@ package http import ( + "errors" "net" "strconv" "strings" @@ -61,3 +62,39 @@ func NetPeerAddressPortAttributes(host []byte) (addr attribute.KeyValue, port at } return } + +var ( + // ErrEmptyPattern is returned when the input pattern is empty. + ErrEmptyPattern = errors.New("empty pattern") + // ErrMissingPathOrHost is returned when the input pattern is missing path or host. + ErrMissingPathOrHost = errors.New("missing path or host") +) + +// The string's syntax is +// +// [METHOD] [HOST]/[PATH] +// +// https://cs.opensource.google/go/go/+/master:src/net/http/pattern.go;l=84;drc=b47f2febea5c570fef4a5c27a46473f511fbdaa3?q=PATTERN%20STRUCT&ss=go%2Fgo +func ParsePattern(s string) (method, host, path string, err error) { + if len(s) == 0 { + return "", "", "", ErrEmptyPattern + } + + method, rest, found := s, "", false + if i := strings.IndexAny(s, " \t"); i >= 0 { + method, rest, found = s[:i], strings.TrimLeft(s[i+1:], " \t"), true + } + if !found { + rest = method + method = "" + } + + i := strings.IndexByte(rest, '/') + if i < 0 { + return "", "", "", ErrMissingPathOrHost + } + host = rest[:i] + path = rest[i:] + err = nil + return +} diff --git a/internal/pkg/instrumentation/bpf/net/http/http_event_test.go b/internal/pkg/instrumentation/bpf/net/http/http_event_test.go new file mode 100644 index 000000000..b88b6cde8 --- /dev/null +++ b/internal/pkg/instrumentation/bpf/net/http/http_event_test.go @@ -0,0 +1,92 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package http + +import ( + "errors" + "testing" +) +// TestParsePattern tests the ParsePattern function with various inputs. +func TestParsePattern(t *testing.T) { + // Define test cases + tests := []struct { + name string + input string + method string + host string + path string + wantErr error + }{ + { + name: "Normal case", + input: "GET example.com/test/{id}", + method: "GET", + host: "example.com", + path: "/test/{id}", + wantErr: nil, + }, + { + name: "No method", + input: "example.com/test", + method: "", + host: "example.com", + path: "/test", + wantErr: nil, + }, + { + name: "Empty input", + input: "", + method: "", + host: "", + path: "", + wantErr: ErrEmptyPattern, + }, + { + name: "Missing path or host", + input: "GET example.com", + method: "", + host: "", + path: "", + wantErr: ErrMissingPathOrHost, + }, + { + name: "Simple / path with host", + input: "GET example.com/", + method: "GET", + host: "example.com", + path: "/", + wantErr: nil, + }, + { + name: "Simple / path without host", + input: "GET /", + method: "GET", + host: "", + path: "/", + wantErr: nil, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + method, host, path, err := ParsePattern(tc.input) + + if method != tc.method || host != tc.host || path != tc.path || !errors.Is(err, tc.wantErr) { + t.Errorf("TestParsePattern(%q) = %q, %q, %q, %v; want %q, %q, %q, %v", + tc.input, method, host, path, err, tc.method, tc.host, tc.path, tc.wantErr) + } + }) + } +} diff --git a/internal/pkg/instrumentation/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentation/bpf/net/http/server/bpf/probe.bpf.c index 549798c63..9a30e9928 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentation/bpf/net/http/server/bpf/probe.bpf.c @@ -100,6 +100,12 @@ volatile const u64 remote_addr_pos; volatile const u64 host_pos; volatile const u64 proto_pos; +// A flag indicating whether pattern handlers are supported +volatile const bool pattern_path_supported; +// In case pattern handlers are supported the following offsets will be used: +volatile const u64 req_pat_pos; +volatile const u64 pat_str_pos; + static __always_inline struct span_context *extract_context_from_req_headers(void *headers_ptr_ptr) { void *headers_ptr; @@ -286,7 +292,15 @@ int uprobe_HandlerFunc_ServeHTTP_Returns(struct pt_regs *ctx) { bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr + url_ptr_pos)); // Collect fields from response read_go_string(req_ptr, method_ptr_pos, http_server_span->method, sizeof(http_server_span->method), "method from request"); - read_go_string(url_ptr, path_ptr_pos, http_server_span->path, sizeof(http_server_span->path), "path from Request.URL"); + if (pattern_path_supported) { + void *pat_ptr = NULL; + bpf_probe_read(&pat_ptr, sizeof(pat_ptr), (void *)(req_ptr + req_pat_pos)); + if (pat_ptr != NULL) { + read_go_string(pat_ptr, pat_str_pos, http_server_span->path, sizeof(http_server_span->path), "patterned path from Request"); + } + } else { + read_go_string(url_ptr, path_ptr_pos, http_server_span->path, sizeof(http_server_span->path), "path from Request.URL"); + } read_go_string(req_ptr, remote_addr_pos, http_server_span->remote_addr, sizeof(http_server_span->remote_addr), "remote addr from Request.RemoteAddr"); read_go_string(req_ptr, host_pos, http_server_span->host, sizeof(http_server_span->host), "host from Request.Host"); read_go_string(req_ptr, proto_pos, http_server_span->proto, sizeof(http_server_span->proto), "proto from Request.Proto"); diff --git a/internal/pkg/instrumentation/bpf/net/http/server/probe.go b/internal/pkg/instrumentation/bpf/net/http/server/probe.go index 471b7d111..04efbb01a 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/probe.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/probe.go @@ -21,11 +21,13 @@ import ( "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/perf" "github.com/go-logr/logr" + "github.com/hashicorp/go-version" "go.opentelemetry.io/otel/attribute" semconv "go.opentelemetry.io/otel/semconv/v1.24.0" "go.opentelemetry.io/otel/trace" "golang.org/x/sys/unix" + "go.opentelemetry.io/auto/internal/pkg/inject" "go.opentelemetry.io/auto/internal/pkg/instrumentation/bpf/net/http" "go.opentelemetry.io/auto/internal/pkg/instrumentation/context" "go.opentelemetry.io/auto/internal/pkg/instrumentation/probe" @@ -95,6 +97,21 @@ func New(logger logr.Logger) probe.Probe { Key: "proto_pos", Val: structfield.NewID("std", "net/http", "Request", "Proto"), }, + probe.StructFieldConstMinVersion{ + StructField: probe.StructFieldConst{ + Key: "req_pat_pos", + Val: structfield.NewID("std", "net/http", "Request", "pat"), + }, + MinVersion: patternPathMinVersion, + }, + probe.StructFieldConstMinVersion{ + StructField: probe.StructFieldConst{ + Key: "pat_str_pos", + Val: structfield.NewID("std", "net/http", "pattern", "str"), + }, + MinVersion: patternPathMinVersion, + }, + patternPathSupportedConst{}, }, Uprobes: []probe.Uprobe[bpfObjects]{ { @@ -111,6 +128,18 @@ func New(logger logr.Logger) probe.Probe { } } +type patternPathSupportedConst struct{} + +var ( + patternPathMinVersion = version.Must(version.NewVersion("1.22.0")) + isPatternPathSupported = false +) + +func (c patternPathSupportedConst) InjectOption(td *process.TargetDetails) (inject.Option, error) { + isPatternPathSupported = td.GoVersion.GreaterThanOrEqual(patternPathMinVersion) + return inject.WithKeyValue("pattern_path_supported", isPatternPathSupported), nil +} + func uprobeServeHTTP(name string, exec *link.Executable, target *process.TargetDetails, obj *bpfObjects) ([]link.Link, error) { offset, err := target.GetFunctionOffset(name) if err != nil { @@ -154,8 +183,15 @@ type event struct { } func convertEvent(e *event) *probe.SpanEvent { - method := unix.ByteSliceToString(e.Method[:]) path := unix.ByteSliceToString(e.Path[:]) + method := unix.ByteSliceToString(e.Method[:]) + + isValidPatternPath := true + _, _, patternPath, err := http.ParsePattern(path) + if err != nil || patternPath == "" { + isValidPatternPath = false + } + proto := unix.ByteSliceToString(e.Proto[:]) sc := trace.NewSpanContext(trace.SpanContextConfig{ @@ -208,10 +244,13 @@ func convertEvent(e *event) *probe.SpanEvent { } } + spanName := method + if isPatternPathSupported && isValidPatternPath { + spanName = spanName + " " + patternPath + } + return &probe.SpanEvent{ - // Do not include the high-cardinality path here (there is no - // templatized path manifest to reference). - SpanName: method, + SpanName: spanName, StartTime: int64(e.StartTime), EndTime: int64(e.EndTime), SpanContext: &sc, diff --git a/internal/pkg/instrumentation/probe/probe.go b/internal/pkg/instrumentation/probe/probe.go index 5e77599ed..33e9b2db5 100644 --- a/internal/pkg/instrumentation/probe/probe.go +++ b/internal/pkg/instrumentation/probe/probe.go @@ -26,6 +26,7 @@ import ( "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/perf" "github.com/go-logr/logr" + "github.com/hashicorp/go-version" "go.opentelemetry.io/auto/internal/pkg/inject" "go.opentelemetry.io/auto/internal/pkg/instrumentation/bpffs" @@ -265,7 +266,7 @@ func (c consts) injectOpts(td *process.TargetDetails) ([]inject.Option, error) { for _, cnst := range c { o, e := cnst.InjectOption(td) err = errors.Join(err, e) - if e == nil { + if e == nil && o != nil { out = append(out, o) } } @@ -290,6 +291,33 @@ func (c StructFieldConst) InjectOption(td *process.TargetDetails) (inject.Option return inject.WithOffset(c.Key, c.Val, ver), nil } +// StructFieldConstMinVersion is a [Const] for a struct field offset. These struct field +// ID needs to be known offsets in the [inject] package. The offset is only +// injected if the module version is greater than or equal to the MinVersion. +type StructFieldConstMinVersion struct { + StructField StructFieldConst + MinVersion *version.Version +} + +// InjectOption returns the appropriately configured [inject.WithOffset] if the +// version of the struct field module is known and is greater than or equal to +// the MinVersion. If the module version is not known, an error is returned. +// If the module version is known but is less than the MinVersion, no offset is +// injected. +func (c StructFieldConstMinVersion) InjectOption(td *process.TargetDetails) (inject.Option, error) { + sf := c.StructField + ver, ok := td.Libraries[sf.Val.ModPath] + if !ok { + return nil, fmt.Errorf("unknown module version: %s", sf.Val.ModPath) + } + + if !ver.GreaterThanOrEqual(c.MinVersion) { + return nil, nil + } + + return inject.WithOffset(sf.Key, sf.Val, ver), nil +} + // AllocationConst is a [Const] for all the allocation details that need to be // injected into an eBPF program. type AllocationConst struct{} diff --git a/internal/test/e2e/nethttp/traces.json b/internal/test/e2e/nethttp/traces.json index ef200b78e..d3b68e528 100644 --- a/internal/test/e2e/nethttp/traces.json +++ b/internal/test/e2e/nethttp/traces.json @@ -101,7 +101,7 @@ } ], "kind": 2, - "name": "GET", + "name": "GET /hello", "parentSpanId": "xxxxx", "spanId": "xxxxx", "status": {}, diff --git a/internal/test/e2e/nethttp/verify.bats b/internal/test/e2e/nethttp/verify.bats index aa5edd41f..2b4c28943 100644 --- a/internal/test/e2e/nethttp/verify.bats +++ b/internal/test/e2e/nethttp/verify.bats @@ -9,9 +9,9 @@ SCOPE="go.opentelemetry.io/auto/net/http" assert_equal "$result" '"sample-app"' } -@test "server :: emits a span name '{http.request.method}' (per semconv)" { +@test "server :: emits a span name '{http.request.method} {url.path}' (per semconv)" { result=$(server_span_names_for ${SCOPE}) - assert_equal "$result" '"GET"' + assert_equal "$result" '"GET /hello"' } @test "server :: includes http.request.method attribute" { diff --git a/internal/tools/inspect/cmd/offsetgen/main.go b/internal/tools/inspect/cmd/offsetgen/main.go index c79daf481..6f394c520 100644 --- a/internal/tools/inspect/cmd/offsetgen/main.go +++ b/internal/tools/inspect/cmd/offsetgen/main.go @@ -117,6 +117,8 @@ func manifests() ([]inspect.Manifest, error) { structfield.NewID("std", "net/http", "Request", "Proto"), structfield.NewID("std", "net/http", "Request", "RequestURI"), structfield.NewID("std", "net/http", "Request", "Host"), + structfield.NewID("std", "net/http", "Request", "pat"), + structfield.NewID("std", "net/http", "pattern", "str"), structfield.NewID("std", "net/url", "URL", "Path"), }, }, From faa7740c2957d75442ce6457f27cb03f32f06709 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 28 Mar 2024 09:49:25 +0200 Subject: [PATCH 02/13] Add http.route if a path template is available. Update nethttp e2e test --- .../bpf/net/http/http_event_test.go | 1 + .../bpf/net/http/server/bpf/probe.bpf.c | 6 +++--- .../bpf/net/http/server/bpf_bpfel_arm64.go | 21 ++++++++++--------- .../bpf/net/http/server/bpf_bpfel_x86.go | 21 ++++++++++--------- .../bpf/net/http/server/probe.go | 17 ++++++++------- internal/test/e2e/nethttp/main.go | 4 ++-- internal/test/e2e/nethttp/traces.json | 14 +++++++++---- internal/test/e2e/nethttp/verify.bats | 4 ++-- 8 files changed, 50 insertions(+), 38 deletions(-) diff --git a/internal/pkg/instrumentation/bpf/net/http/http_event_test.go b/internal/pkg/instrumentation/bpf/net/http/http_event_test.go index b88b6cde8..688bba44c 100644 --- a/internal/pkg/instrumentation/bpf/net/http/http_event_test.go +++ b/internal/pkg/instrumentation/bpf/net/http/http_event_test.go @@ -18,6 +18,7 @@ import ( "errors" "testing" ) + // TestParsePattern tests the ParsePattern function with various inputs. func TestParsePattern(t *testing.T) { // Define test cases diff --git a/internal/pkg/instrumentation/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentation/bpf/net/http/server/bpf/probe.bpf.c index 9a30e9928..43117889b 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentation/bpf/net/http/server/bpf/probe.bpf.c @@ -36,6 +36,7 @@ struct http_server_span_t u64 status_code; char method[METHOD_MAX_LEN]; char path[PATH_MAX_LEN]; + char path_pattern[PATH_MAX_LEN]; char remote_addr[REMOTE_ADDR_MAX_LEN]; char host[HOST_MAX_LEN]; char proto[PROTO_MAX_LEN]; @@ -296,11 +297,10 @@ int uprobe_HandlerFunc_ServeHTTP_Returns(struct pt_regs *ctx) { void *pat_ptr = NULL; bpf_probe_read(&pat_ptr, sizeof(pat_ptr), (void *)(req_ptr + req_pat_pos)); if (pat_ptr != NULL) { - read_go_string(pat_ptr, pat_str_pos, http_server_span->path, sizeof(http_server_span->path), "patterned path from Request"); + read_go_string(pat_ptr, pat_str_pos, http_server_span->path_pattern, sizeof(http_server_span->path), "patterned path from Request"); } - } else { - read_go_string(url_ptr, path_ptr_pos, http_server_span->path, sizeof(http_server_span->path), "path from Request.URL"); } + read_go_string(url_ptr, path_ptr_pos, http_server_span->path, sizeof(http_server_span->path), "path from Request.URL"); read_go_string(req_ptr, remote_addr_pos, http_server_span->remote_addr, sizeof(http_server_span->remote_addr), "remote addr from Request.RemoteAddr"); read_go_string(req_ptr, host_pos, http_server_span->host, sizeof(http_server_span->host), "host from Request.Host"); read_go_string(req_ptr, proto_pos, http_server_span->proto, sizeof(http_server_span->proto), "proto from Request.Proto"); diff --git a/internal/pkg/instrumentation/bpf/net/http/server/bpf_bpfel_arm64.go b/internal/pkg/instrumentation/bpf/net/http/server/bpf_bpfel_arm64.go index 2848ba5df..d3a30a7b4 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/bpf_bpfel_arm64.go @@ -21,16 +21,17 @@ type bpfSpanContext struct { type bpfUprobeDataT struct { Span struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - StatusCode uint64 - Method [8]int8 - Path [128]int8 - RemoteAddr [256]int8 - Host [256]int8 - Proto [8]int8 + StartTime uint64 + EndTime uint64 + Sc bpfSpanContext + Psc bpfSpanContext + StatusCode uint64 + Method [8]int8 + Path [128]int8 + PathPattern [128]int8 + RemoteAddr [256]int8 + Host [256]int8 + Proto [8]int8 } RespPtr uint64 } diff --git a/internal/pkg/instrumentation/bpf/net/http/server/bpf_bpfel_x86.go b/internal/pkg/instrumentation/bpf/net/http/server/bpf_bpfel_x86.go index c15dd8468..1d71141d8 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/bpf_bpfel_x86.go @@ -21,16 +21,17 @@ type bpfSpanContext struct { type bpfUprobeDataT struct { Span struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - StatusCode uint64 - Method [8]int8 - Path [128]int8 - RemoteAddr [256]int8 - Host [256]int8 - Proto [8]int8 + StartTime uint64 + EndTime uint64 + Sc bpfSpanContext + Psc bpfSpanContext + StatusCode uint64 + Method [8]int8 + Path [128]int8 + PathPattern [128]int8 + RemoteAddr [256]int8 + Host [256]int8 + Proto [8]int8 } RespPtr uint64 } diff --git a/internal/pkg/instrumentation/bpf/net/http/server/probe.go b/internal/pkg/instrumentation/bpf/net/http/server/probe.go index 04efbb01a..edc8e47d9 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/probe.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/probe.go @@ -174,20 +174,22 @@ func uprobeServeHTTP(name string, exec *link.Executable, target *process.TargetD // request-response. type event struct { context.BaseSpanProperties - StatusCode uint64 - Method [8]byte - Path [128]byte - RemoteAddr [256]byte - Host [256]byte - Proto [8]byte + StatusCode uint64 + Method [8]byte + Path [128]byte + PathPattern [128]byte + RemoteAddr [256]byte + Host [256]byte + Proto [8]byte } func convertEvent(e *event) *probe.SpanEvent { path := unix.ByteSliceToString(e.Path[:]) method := unix.ByteSliceToString(e.Method[:]) + patternPath := unix.ByteSliceToString(e.PathPattern[:]) isValidPatternPath := true - _, _, patternPath, err := http.ParsePattern(path) + _, _, patternPath, err := http.ParsePattern(patternPath) if err != nil || patternPath == "" { isValidPatternPath = false } @@ -247,6 +249,7 @@ func convertEvent(e *event) *probe.SpanEvent { spanName := method if isPatternPathSupported && isValidPatternPath { spanName = spanName + " " + patternPath + attributes = append(attributes, semconv.HTTPRouteKey.String(patternPath)) } return &probe.SpanEvent{ diff --git a/internal/test/e2e/nethttp/main.go b/internal/test/e2e/nethttp/main.go index 38488ee40..3ecc2bb9b 100644 --- a/internal/test/e2e/nethttp/main.go +++ b/internal/test/e2e/nethttp/main.go @@ -27,7 +27,7 @@ func hello(w http.ResponseWriter, _ *http.Request) { } func main() { - http.HandleFunc("/hello", hello) + http.HandleFunc("/hello/{id}", hello) go func() { _ = http.ListenAndServe(":8080", nil) }() @@ -35,7 +35,7 @@ func main() { // give time for auto-instrumentation to start up time.Sleep(5 * time.Second) - resp, err := http.Get("http://localhost:8080/hello") + resp, err := http.Get("http://localhost:8080/hello/42") if err != nil { log.Fatal(err) } diff --git a/internal/test/e2e/nethttp/traces.json b/internal/test/e2e/nethttp/traces.json index d3b68e528..0c8189a47 100644 --- a/internal/test/e2e/nethttp/traces.json +++ b/internal/test/e2e/nethttp/traces.json @@ -60,7 +60,7 @@ { "key": "url.path", "value": { - "stringValue": "/hello" + "stringValue": "/hello/42" } }, { @@ -98,10 +98,16 @@ "value": { "stringValue": "1.1" } + }, + { + "key": "http.route", + "value": { + "stringValue": "/hello/{id}" + } } ], "kind": 2, - "name": "GET /hello", + "name": "GET /hello/{id}", "parentSpanId": "xxxxx", "spanId": "xxxxx", "status": {}, @@ -118,7 +124,7 @@ { "key": "url.path", "value": { - "stringValue": "/hello" + "stringValue": "/hello/42" } }, { @@ -147,7 +153,7 @@ } ], "kind": 3, - "name": "/hello", + "name": "/hello/42", "parentSpanId": "", "spanId": "xxxxx", "status": {}, diff --git a/internal/test/e2e/nethttp/verify.bats b/internal/test/e2e/nethttp/verify.bats index 2b4c28943..a4a8b09a6 100644 --- a/internal/test/e2e/nethttp/verify.bats +++ b/internal/test/e2e/nethttp/verify.bats @@ -11,7 +11,7 @@ SCOPE="go.opentelemetry.io/auto/net/http" @test "server :: emits a span name '{http.request.method} {url.path}' (per semconv)" { result=$(server_span_names_for ${SCOPE}) - assert_equal "$result" '"GET /hello"' + assert_equal "$result" '"GET /hello/{id}"' } @test "server :: includes http.request.method attribute" { @@ -21,7 +21,7 @@ SCOPE="go.opentelemetry.io/auto/net/http" @test "server :: includes url.path attribute" { result=$(server_span_attributes_for ${SCOPE} | jq "select(.key == \"url.path\").value.stringValue") - assert_equal "$result" '"/hello"' + assert_equal "$result" '"/hello/42"' } @test "server :: includes hhttp.response.status_code attribute" { From a911e1dfe51ac5ce11b33eb9399585dce4933d57 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 28 Mar 2024 10:03:31 +0200 Subject: [PATCH 03/13] Update databasesql test results --- internal/test/e2e/databasesql/traces.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/test/e2e/databasesql/traces.json b/internal/test/e2e/databasesql/traces.json index fa1c67d36..8736eade2 100644 --- a/internal/test/e2e/databasesql/traces.json +++ b/internal/test/e2e/databasesql/traces.json @@ -122,10 +122,16 @@ "value": { "stringValue": "1.1" } + }, + { + "key": "http.route", + "value": { + "stringValue": "/query_db" + } } ], "kind": 2, - "name": "GET", + "name": "GET /query_db", "parentSpanId": "xxxxx", "spanId": "xxxxx", "status": {}, From fd46105faa6bc4b54ea0cff7eae01bf51d4d4c23 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 28 Mar 2024 15:08:29 +0200 Subject: [PATCH 04/13] update offsets --- internal/pkg/inject/offset_results.json | 145 ++++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index 572d57c16..35a26445e 100644 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -3086,6 +3086,151 @@ { "offset": 0, "versions": [ + "1.12.0", + "1.12.1", + "1.12.2", + "1.12.3", + "1.12.4", + "1.12.5", + "1.12.6", + "1.12.7", + "1.12.8", + "1.12.9", + "1.12.10", + "1.12.11", + "1.12.12", + "1.12.13", + "1.12.14", + "1.12.15", + "1.12.16", + "1.12.17", + "1.13.0", + "1.13.1", + "1.13.2", + "1.13.3", + "1.13.4", + "1.13.5", + "1.13.6", + "1.13.7", + "1.13.8", + "1.13.9", + "1.13.10", + "1.13.11", + "1.13.12", + "1.13.13", + "1.13.14", + "1.13.15", + "1.14.0", + "1.14.1", + "1.14.2", + "1.14.3", + "1.14.4", + "1.14.5", + "1.14.6", + "1.14.7", + "1.14.8", + "1.14.9", + "1.14.10", + "1.14.11", + "1.14.12", + "1.14.13", + "1.14.14", + "1.14.15", + "1.15.0", + "1.15.1", + "1.15.2", + "1.15.3", + "1.15.4", + "1.15.5", + "1.15.6", + "1.15.7", + "1.15.8", + "1.15.9", + "1.15.10", + "1.15.11", + "1.15.12", + "1.15.13", + "1.15.14", + "1.15.15", + "1.16.0", + "1.16.1", + "1.16.2", + "1.16.3", + "1.16.4", + "1.16.5", + "1.16.6", + "1.16.7", + "1.16.8", + "1.16.9", + "1.16.10", + "1.16.11", + "1.16.12", + "1.16.13", + "1.16.14", + "1.16.15", + "1.17.0", + "1.17.1", + "1.17.2", + "1.17.3", + "1.17.4", + "1.17.5", + "1.17.6", + "1.17.7", + "1.17.8", + "1.17.9", + "1.17.10", + "1.17.11", + "1.17.12", + "1.17.13", + "1.18.0", + "1.18.1", + "1.18.2", + "1.18.3", + "1.18.4", + "1.18.5", + "1.18.6", + "1.18.7", + "1.18.8", + "1.18.9", + "1.18.10", + "1.19.0", + "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", + "1.20.0", + "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", "1.22.0", "1.22.1" ] From 3b5362eb9421f6b0d32d47d34c72fa158589cc1a Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 29 Mar 2024 18:39:52 +0300 Subject: [PATCH 05/13] Changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 796a5c504..65493dea9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http ## [Unreleased] +### Added + +- Support http server path templated from go version 1.22 (`http.route` attribute and modified span name) ([#740](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/740)) + ## [v0.11.0-alpha] - 2024-03-26 From 7b5f9a639173e4ca21db79ff9d6ecc5f4fa9ac5b Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sat, 6 Apr 2024 19:38:01 +0300 Subject: [PATCH 06/13] code review fix --- .../bpf/net/http/http_event.go | 9 ++++---- .../bpf/net/http/http_event_test.go | 22 ++++--------------- .../bpf/net/http/server/probe.go | 2 +- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/internal/pkg/instrumentation/bpf/net/http/http_event.go b/internal/pkg/instrumentation/bpf/net/http/http_event.go index f3790dc3d..dfede96d7 100644 --- a/internal/pkg/instrumentation/bpf/net/http/http_event.go +++ b/internal/pkg/instrumentation/bpf/net/http/http_event.go @@ -75,9 +75,10 @@ var ( // [METHOD] [HOST]/[PATH] // // https://cs.opensource.google/go/go/+/master:src/net/http/pattern.go;l=84;drc=b47f2febea5c570fef4a5c27a46473f511fbdaa3?q=PATTERN%20STRUCT&ss=go%2Fgo -func ParsePattern(s string) (method, host, path string, err error) { +// Copyright 2023 The Go Authors. All rights reserved. +func ParsePattern(s string) (path string, err error) { if len(s) == 0 { - return "", "", "", ErrEmptyPattern + return "", ErrEmptyPattern } method, rest, found := s, "", false @@ -86,14 +87,12 @@ func ParsePattern(s string) (method, host, path string, err error) { } if !found { rest = method - method = "" } i := strings.IndexByte(rest, '/') if i < 0 { - return "", "", "", ErrMissingPathOrHost + return "", ErrMissingPathOrHost } - host = rest[:i] path = rest[i:] err = nil return diff --git a/internal/pkg/instrumentation/bpf/net/http/http_event_test.go b/internal/pkg/instrumentation/bpf/net/http/http_event_test.go index 688bba44c..40a3c71fb 100644 --- a/internal/pkg/instrumentation/bpf/net/http/http_event_test.go +++ b/internal/pkg/instrumentation/bpf/net/http/http_event_test.go @@ -25,56 +25,42 @@ func TestParsePattern(t *testing.T) { tests := []struct { name string input string - method string - host string path string wantErr error }{ { name: "Normal case", input: "GET example.com/test/{id}", - method: "GET", - host: "example.com", path: "/test/{id}", wantErr: nil, }, { name: "No method", input: "example.com/test", - method: "", - host: "example.com", path: "/test", wantErr: nil, }, { name: "Empty input", input: "", - method: "", - host: "", path: "", wantErr: ErrEmptyPattern, }, { name: "Missing path or host", input: "GET example.com", - method: "", - host: "", path: "", wantErr: ErrMissingPathOrHost, }, { name: "Simple / path with host", input: "GET example.com/", - method: "GET", - host: "example.com", path: "/", wantErr: nil, }, { name: "Simple / path without host", input: "GET /", - method: "GET", - host: "", path: "/", wantErr: nil, }, @@ -82,11 +68,11 @@ func TestParsePattern(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - method, host, path, err := ParsePattern(tc.input) + path, err := ParsePattern(tc.input) - if method != tc.method || host != tc.host || path != tc.path || !errors.Is(err, tc.wantErr) { - t.Errorf("TestParsePattern(%q) = %q, %q, %q, %v; want %q, %q, %q, %v", - tc.input, method, host, path, err, tc.method, tc.host, tc.path, tc.wantErr) + if path != tc.path || !errors.Is(err, tc.wantErr) { + t.Errorf("TestParsePattern(%q) = %q, %v; want %q, %v", + tc.input, path, err, tc.path, tc.wantErr) } }) } diff --git a/internal/pkg/instrumentation/bpf/net/http/server/probe.go b/internal/pkg/instrumentation/bpf/net/http/server/probe.go index edc8e47d9..7efcaaeb9 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/probe.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/probe.go @@ -189,7 +189,7 @@ func convertEvent(e *event) *probe.SpanEvent { patternPath := unix.ByteSliceToString(e.PathPattern[:]) isValidPatternPath := true - _, _, patternPath, err := http.ParsePattern(patternPath) + patternPath, err := http.ParsePattern(patternPath) if err != nil || patternPath == "" { isValidPatternPath = false } From e689298338aa1b46d0b1ae2f35ee06d4fa1210ef Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sat, 6 Apr 2024 19:44:07 +0300 Subject: [PATCH 07/13] update offsets --- internal/pkg/inject/offset_results.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index 679066373..b6d140476 100644 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -2943,14 +2943,16 @@ "1.21.5", "1.21.6", "1.21.7", - "1.21.8" + "1.21.8", + "1.21.9" ] }, { "offset": 248, "versions": [ "1.22.0", - "1.22.1" + "1.22.1", + "1.22.2" ] } ] @@ -3275,8 +3277,10 @@ "1.21.6", "1.21.7", "1.21.8", + "1.21.9", "1.22.0", - "1.22.1" + "1.22.1", + "1.22.2" ] } ] From 276d2fa33161802b9e4fee1f5997bfa7dc5c309a Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 25 Apr 2024 18:30:44 +0300 Subject: [PATCH 08/13] Update offsets --- internal/pkg/inject/offset_results.json | 297 ------------------------ 1 file changed, 297 deletions(-) diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index ec3ea06e1..eba018351 100644 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -3694,157 +3694,6 @@ { "field": "pat", "offsets": [ - { - "offset": 24, - "versions": [ - "1.12.0", - "1.12.1", - "1.12.2", - "1.12.3", - "1.12.4", - "1.12.5", - "1.12.6", - "1.12.7", - "1.12.8", - "1.12.9", - "1.12.10", - "1.12.11", - "1.12.12", - "1.12.13", - "1.12.14", - "1.12.15", - "1.12.16", - "1.12.17", - "1.13.0", - "1.13.1", - "1.13.2", - "1.13.3", - "1.13.4", - "1.13.5", - "1.13.6", - "1.13.7", - "1.13.8", - "1.13.9", - "1.13.10", - "1.13.11", - "1.13.12", - "1.13.13", - "1.13.14", - "1.13.15", - "1.14.0", - "1.14.1", - "1.14.2", - "1.14.3", - "1.14.4", - "1.14.5", - "1.14.6", - "1.14.7", - "1.14.8", - "1.14.9", - "1.14.10", - "1.14.11", - "1.14.12", - "1.14.13", - "1.14.14", - "1.14.15", - "1.15.0", - "1.15.1", - "1.15.2", - "1.15.3", - "1.15.4", - "1.15.5", - "1.15.6", - "1.15.7", - "1.15.8", - "1.15.9", - "1.15.10", - "1.15.11", - "1.15.12", - "1.15.13", - "1.15.14", - "1.15.15", - "1.16.0", - "1.16.1", - "1.16.2", - "1.16.3", - "1.16.4", - "1.16.5", - "1.16.6", - "1.16.7", - "1.16.8", - "1.16.9", - "1.16.10", - "1.16.11", - "1.16.12", - "1.16.13", - "1.16.14", - "1.16.15", - "1.17.0", - "1.17.1", - "1.17.2", - "1.17.3", - "1.17.4", - "1.17.5", - "1.17.6", - "1.17.7", - "1.17.8", - "1.17.9", - "1.17.10", - "1.17.11", - "1.17.12", - "1.17.13", - "1.18.0", - "1.18.1", - "1.18.2", - "1.18.3", - "1.18.4", - "1.18.5", - "1.18.6", - "1.18.7", - "1.18.8", - "1.18.9", - "1.18.10", - "1.19.0", - "1.19.1", - "1.19.2", - "1.19.3", - "1.19.4", - "1.19.5", - "1.19.6", - "1.19.7", - "1.19.8", - "1.19.9", - "1.19.10", - "1.19.11", - "1.19.12", - "1.19.13", - "1.20.0", - "1.20.1", - "1.20.2", - "1.20.3", - "1.20.4", - "1.20.5", - "1.20.6", - "1.20.7", - "1.20.8", - "1.20.9", - "1.20.10", - "1.20.11", - "1.20.12", - "1.20.13", - "1.20.14", - "1.21.0", - "1.21.1", - "1.21.2", - "1.21.3", - "1.21.4", - "1.21.5", - "1.21.6", - "1.21.7", - "1.21.8", - "1.21.9" - ] - }, { "offset": 248, "versions": [ @@ -4030,152 +3879,6 @@ { "offset": 0, "versions": [ - "1.12.0", - "1.12.1", - "1.12.2", - "1.12.3", - "1.12.4", - "1.12.5", - "1.12.6", - "1.12.7", - "1.12.8", - "1.12.9", - "1.12.10", - "1.12.11", - "1.12.12", - "1.12.13", - "1.12.14", - "1.12.15", - "1.12.16", - "1.12.17", - "1.13.0", - "1.13.1", - "1.13.2", - "1.13.3", - "1.13.4", - "1.13.5", - "1.13.6", - "1.13.7", - "1.13.8", - "1.13.9", - "1.13.10", - "1.13.11", - "1.13.12", - "1.13.13", - "1.13.14", - "1.13.15", - "1.14.0", - "1.14.1", - "1.14.2", - "1.14.3", - "1.14.4", - "1.14.5", - "1.14.6", - "1.14.7", - "1.14.8", - "1.14.9", - "1.14.10", - "1.14.11", - "1.14.12", - "1.14.13", - "1.14.14", - "1.14.15", - "1.15.0", - "1.15.1", - "1.15.2", - "1.15.3", - "1.15.4", - "1.15.5", - "1.15.6", - "1.15.7", - "1.15.8", - "1.15.9", - "1.15.10", - "1.15.11", - "1.15.12", - "1.15.13", - "1.15.14", - "1.15.15", - "1.16.0", - "1.16.1", - "1.16.2", - "1.16.3", - "1.16.4", - "1.16.5", - "1.16.6", - "1.16.7", - "1.16.8", - "1.16.9", - "1.16.10", - "1.16.11", - "1.16.12", - "1.16.13", - "1.16.14", - "1.16.15", - "1.17.0", - "1.17.1", - "1.17.2", - "1.17.3", - "1.17.4", - "1.17.5", - "1.17.6", - "1.17.7", - "1.17.8", - "1.17.9", - "1.17.10", - "1.17.11", - "1.17.12", - "1.17.13", - "1.18.0", - "1.18.1", - "1.18.2", - "1.18.3", - "1.18.4", - "1.18.5", - "1.18.6", - "1.18.7", - "1.18.8", - "1.18.9", - "1.18.10", - "1.19.0", - "1.19.1", - "1.19.2", - "1.19.3", - "1.19.4", - "1.19.5", - "1.19.6", - "1.19.7", - "1.19.8", - "1.19.9", - "1.19.10", - "1.19.11", - "1.19.12", - "1.19.13", - "1.20.0", - "1.20.1", - "1.20.2", - "1.20.3", - "1.20.4", - "1.20.5", - "1.20.6", - "1.20.7", - "1.20.8", - "1.20.9", - "1.20.10", - "1.20.11", - "1.20.12", - "1.20.13", - "1.20.14", - "1.21.0", - "1.21.1", - "1.21.2", - "1.21.3", - "1.21.4", - "1.21.5", - "1.21.6", - "1.21.7", - "1.21.8", - "1.21.9", "1.22.0", "1.22.1", "1.22.2" From 55cbd29e0dbc306fdedfabb1033909d56ba2bda4 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 25 Apr 2024 18:36:53 +0300 Subject: [PATCH 09/13] update verify.bats --- internal/test/e2e/nethttp/verify.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/test/e2e/nethttp/verify.bats b/internal/test/e2e/nethttp/verify.bats index c0cfd1c8f..9f5431efc 100644 --- a/internal/test/e2e/nethttp/verify.bats +++ b/internal/test/e2e/nethttp/verify.bats @@ -31,7 +31,7 @@ SCOPE="go.opentelemetry.io/auto/net/http" @test "client :: includes url.path attribute" { result=$(client_span_attributes_for ${SCOPE} | jq "select(.key == \"url.path\").value.stringValue") - assert_equal "$result" '"/hello"' + assert_equal "$result" '"/hello/42"' } @test "server :: includes hhttp.response.status_code attribute" { From 78de785cda5b33b533d496b0088c21802b738246 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 26 Apr 2024 18:27:09 +0300 Subject: [PATCH 10/13] Fix copyright comment --- internal/pkg/instrumentation/bpf/net/http/http_event.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/pkg/instrumentation/bpf/net/http/http_event.go b/internal/pkg/instrumentation/bpf/net/http/http_event.go index dfede96d7..af577b65f 100644 --- a/internal/pkg/instrumentation/bpf/net/http/http_event.go +++ b/internal/pkg/instrumentation/bpf/net/http/http_event.go @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package http import ( @@ -75,7 +79,6 @@ var ( // [METHOD] [HOST]/[PATH] // // https://cs.opensource.google/go/go/+/master:src/net/http/pattern.go;l=84;drc=b47f2febea5c570fef4a5c27a46473f511fbdaa3?q=PATTERN%20STRUCT&ss=go%2Fgo -// Copyright 2023 The Go Authors. All rights reserved. func ParsePattern(s string) (path string, err error) { if len(s) == 0 { return "", ErrEmptyPattern From 36593e3d699d94cc006ac43f7f01e36b1813a416 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 1 May 2024 09:17:13 +0300 Subject: [PATCH 11/13] update offsets --- internal/pkg/inject/offset_results.json | 302 ++++++++++++++++++++++++ 1 file changed, 302 insertions(+) diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index 49868f6cb..69a9d6602 100644 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -4032,6 +4032,157 @@ { "field": "pat", "offsets": [ + { + "offset": null, + "versions": [ + "1.12.0", + "1.12.1", + "1.12.2", + "1.12.3", + "1.12.4", + "1.12.5", + "1.12.6", + "1.12.7", + "1.12.8", + "1.12.9", + "1.12.10", + "1.12.11", + "1.12.12", + "1.12.13", + "1.12.14", + "1.12.15", + "1.12.16", + "1.12.17", + "1.13.0", + "1.13.1", + "1.13.2", + "1.13.3", + "1.13.4", + "1.13.5", + "1.13.6", + "1.13.7", + "1.13.8", + "1.13.9", + "1.13.10", + "1.13.11", + "1.13.12", + "1.13.13", + "1.13.14", + "1.13.15", + "1.14.0", + "1.14.1", + "1.14.2", + "1.14.3", + "1.14.4", + "1.14.5", + "1.14.6", + "1.14.7", + "1.14.8", + "1.14.9", + "1.14.10", + "1.14.11", + "1.14.12", + "1.14.13", + "1.14.14", + "1.14.15", + "1.15.0", + "1.15.1", + "1.15.2", + "1.15.3", + "1.15.4", + "1.15.5", + "1.15.6", + "1.15.7", + "1.15.8", + "1.15.9", + "1.15.10", + "1.15.11", + "1.15.12", + "1.15.13", + "1.15.14", + "1.15.15", + "1.16.0", + "1.16.1", + "1.16.2", + "1.16.3", + "1.16.4", + "1.16.5", + "1.16.6", + "1.16.7", + "1.16.8", + "1.16.9", + "1.16.10", + "1.16.11", + "1.16.12", + "1.16.13", + "1.16.14", + "1.16.15", + "1.17.0", + "1.17.1", + "1.17.2", + "1.17.3", + "1.17.4", + "1.17.5", + "1.17.6", + "1.17.7", + "1.17.8", + "1.17.9", + "1.17.10", + "1.17.11", + "1.17.12", + "1.17.13", + "1.18.0", + "1.18.1", + "1.18.2", + "1.18.3", + "1.18.4", + "1.18.5", + "1.18.6", + "1.18.7", + "1.18.8", + "1.18.9", + "1.18.10", + "1.19.0", + "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", + "1.20.0", + "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", + "1.21.9" + ] + }, { "offset": 248, "versions": [ @@ -4214,6 +4365,157 @@ { "field": "str", "offsets": [ + { + "offset": null, + "versions": [ + "1.12.0", + "1.12.1", + "1.12.2", + "1.12.3", + "1.12.4", + "1.12.5", + "1.12.6", + "1.12.7", + "1.12.8", + "1.12.9", + "1.12.10", + "1.12.11", + "1.12.12", + "1.12.13", + "1.12.14", + "1.12.15", + "1.12.16", + "1.12.17", + "1.13.0", + "1.13.1", + "1.13.2", + "1.13.3", + "1.13.4", + "1.13.5", + "1.13.6", + "1.13.7", + "1.13.8", + "1.13.9", + "1.13.10", + "1.13.11", + "1.13.12", + "1.13.13", + "1.13.14", + "1.13.15", + "1.14.0", + "1.14.1", + "1.14.2", + "1.14.3", + "1.14.4", + "1.14.5", + "1.14.6", + "1.14.7", + "1.14.8", + "1.14.9", + "1.14.10", + "1.14.11", + "1.14.12", + "1.14.13", + "1.14.14", + "1.14.15", + "1.15.0", + "1.15.1", + "1.15.2", + "1.15.3", + "1.15.4", + "1.15.5", + "1.15.6", + "1.15.7", + "1.15.8", + "1.15.9", + "1.15.10", + "1.15.11", + "1.15.12", + "1.15.13", + "1.15.14", + "1.15.15", + "1.16.0", + "1.16.1", + "1.16.2", + "1.16.3", + "1.16.4", + "1.16.5", + "1.16.6", + "1.16.7", + "1.16.8", + "1.16.9", + "1.16.10", + "1.16.11", + "1.16.12", + "1.16.13", + "1.16.14", + "1.16.15", + "1.17.0", + "1.17.1", + "1.17.2", + "1.17.3", + "1.17.4", + "1.17.5", + "1.17.6", + "1.17.7", + "1.17.8", + "1.17.9", + "1.17.10", + "1.17.11", + "1.17.12", + "1.17.13", + "1.18.0", + "1.18.1", + "1.18.2", + "1.18.3", + "1.18.4", + "1.18.5", + "1.18.6", + "1.18.7", + "1.18.8", + "1.18.9", + "1.18.10", + "1.19.0", + "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", + "1.20.0", + "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", + "1.21.9" + ] + }, { "offset": 0, "versions": [ From 48d883b73045cdf42e95b9625a95fe7fc0618968 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 1 May 2024 09:25:01 +0300 Subject: [PATCH 12/13] update test files for nethttp --- internal/test/e2e/nethttp/traces.json | 8 +------- internal/test/e2e/nethttp/verify.bats | 7 ++++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/internal/test/e2e/nethttp/traces.json b/internal/test/e2e/nethttp/traces.json index 56fee59da..67ee9ed38 100644 --- a/internal/test/e2e/nethttp/traces.json +++ b/internal/test/e2e/nethttp/traces.json @@ -122,12 +122,6 @@ "stringValue": "GET" } }, - { - "key": "url.path", - "value": { - "stringValue": "/hello/42" - } - }, { "key": "http.response.status_code", "value": { @@ -137,7 +131,7 @@ { "key": "url.path", "value": { - "stringValue": "/hello" + "stringValue": "/hello/42" } }, { diff --git a/internal/test/e2e/nethttp/verify.bats b/internal/test/e2e/nethttp/verify.bats index 9f5431efc..f354b0098 100644 --- a/internal/test/e2e/nethttp/verify.bats +++ b/internal/test/e2e/nethttp/verify.bats @@ -9,7 +9,7 @@ SCOPE="go.opentelemetry.io/auto/net/http" assert_equal "$result" '"sample-app"' } -@test "server :: emits a span name '{http.request.method} {url.path}' (per semconv)" { +@test "server :: emits a span name '{http.request.method} {http.route}' (per semconv)" { result=$(server_span_names_for ${SCOPE}) assert_equal "$result" '"GET /hello/{id}"' } @@ -91,6 +91,11 @@ SCOPE="go.opentelemetry.io/auto/net/http" assert_equal "$result" '"::1"' } +@test "server :: includes http.route attribute" { + result=$(server_span_attributes_for ${SCOPE} | jq "select(.key == \"http.route\").value.stringValue") + assert_equal "$result" '"/hello/{id}"' +} + @test "client :: includes server.address attribute" { result=$(client_span_attributes_for ${SCOPE} | jq "select(.key == \"server.address\").value.stringValue") assert_equal "$result" '"localhost"' From 1b7d0f8813ace220e3f451d6874f12fcfbc01f81 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 1 May 2024 09:29:24 +0300 Subject: [PATCH 13/13] fix changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84442c24b..b90a7dd45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http - kafka-go instrumentation ([#709](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/709)) - Support `go.opentelemetry.io/otel@v1.26.0`. ([#796](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/796)) +- Support HTTP server path template added in Go version 1.22. +The `http.route` attribute is included and the span name updated to use this information. ([#740](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/740)) ### Fixed @@ -19,8 +21,6 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http - Don't set empty URL path in HTTP client probe. ([#810](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/810)) - Don't fail HTTP client probe attribute resolution on empty URL path. ([#810](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/810)) - Extract `process.runtime.version` and `process.runtime.name` from instrumented process. ([#811](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/811)) -- Support HTTP server path template added in Go version 1.22. -The `http.route` attribute is included and the span name updated to use this information. ([#740](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/740)) ## [v0.12.0-alpha] - 2024-04-10