From b6b8bb162163fd4c03590952734a1a13458d3999 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 17 May 2024 23:01:24 +0300 Subject: [PATCH 1/9] Collect user provided tracer name and use it for scope name --- internal/pkg/inject/offset_results.json | 92 +++++++++++++++++++ .../otel/traceglobal/bpf/probe.bpf.c | 32 ++++++- .../otel/traceglobal/bpf_arm64_bpfel.go | 8 +- .../otel/traceglobal/bpf_x86_bpfel.go | 8 +- .../otel/traceglobal/probe.go | 6 ++ internal/pkg/instrumentation/probe/event.go | 1 + internal/pkg/opentelemetry/controller.go | 31 +++++-- internal/pkg/opentelemetry/controller_test.go | 31 +++++++ internal/test/e2e/otelglobal/traces.json | 3 +- internal/test/e2e/otelglobal/verify.bats | 2 +- internal/tools/inspect/cmd/offsetgen/main.go | 1 + 11 files changed, 201 insertions(+), 14 deletions(-) diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index eeab94f4d..3a2ea11cb 100644 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -939,6 +939,98 @@ ] } ] + }, + { + "field": "name", + "offsets": [ + { + "offset": null, + "versions": [ + "0.1.0", + "0.1.1", + "0.1.2", + "0.2.0", + "0.2.1", + "0.2.2", + "0.2.3", + "0.3.0", + "0.4.0", + "0.4.1", + "0.4.2", + "0.4.3", + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0" + ] + }, + { + "offset": 0, + "versions": [ + "0.19.0", + "0.20.0", + "1.0.0-RC1", + "1.0.0-RC2", + "1.0.0-RC3", + "1.0.0", + "1.0.1", + "1.1.0", + "1.2.0", + "1.3.0", + "1.4.0", + "1.4.1", + "1.5.0", + "1.6.0", + "1.6.1", + "1.6.2", + "1.6.3", + "1.7.0", + "1.8.0", + "1.9.0", + "1.10.0", + "1.11.0", + "1.11.1", + "1.11.2", + "1.12.0", + "1.13.0", + "1.14.0", + "1.15.0-rc.1", + "1.15.0-rc.2", + "1.15.0", + "1.15.1", + "1.16.0-rc.1", + "1.16.0", + "1.17.0", + "1.18.0", + "1.19.0-rc.1", + "1.19.0" + ] + }, + { + "offset": 16, + "versions": [ + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "1.20.0", + "1.21.0", + "1.22.0", + "1.23.0-rc.1", + "1.23.0", + "1.23.1", + "1.24.0", + "1.25.0", + "1.26.0" + ] + } + ] } ] } diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c index 61aa67beb..cf58f674d 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c @@ -25,6 +25,7 @@ char __license[] SEC("license") = "Dual MIT/GPL"; #define MAX_CONCURRENT 50 #define MAX_SPAN_NAME_LEN 64 #define MAX_STATUS_DESCRIPTION_LEN 64 +#define MAX_TRACER_NAME_LEN 128 struct span_description_t { char buf[MAX_STATUS_DESCRIPTION_LEN]; @@ -39,11 +40,16 @@ struct span_name_t { char buf[MAX_SPAN_NAME_LEN]; }; +typedef struct tracer_name { + char buf[MAX_TRACER_NAME_LEN]; +} tracer_name_t; + struct otel_span_t { BASE_SPAN_PROPERTIES struct span_name_t span_name; otel_status_t status; otel_attributes_t attributes; + tracer_name_t tracer_name; }; struct { @@ -60,6 +66,13 @@ struct { __uint(max_entries, MAX_CONCURRENT); } span_name_by_context SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, void*); + __type(value, tracer_name_t); + __uint(max_entries, MAX_CONCURRENT); +} tracer_name_by_context SEC(".maps"); + struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); @@ -74,6 +87,7 @@ struct { // Injected in init volatile const u64 tracer_delegate_pos; +volatile const u64 tracer_name_pos; // read_span_name reads the span name from the provided span_name_ptr and stores the result in // span_name.buf. @@ -105,6 +119,14 @@ int uprobe_Start(struct pt_regs *ctx) { void *context_ptr_val = get_Go_context(ctx, 3, 0, true); void *key = get_consistent_key(ctx, context_ptr_val); bpf_map_update_elem(&span_name_by_context, &key, &span_name, 0); + + // Get the tracer name + tracer_name_t tracer_name = {0}; + if (!get_go_string_from_user_ptr((void*)(tracer_ptr + tracer_name_pos), tracer_name.buf, MAX_TRACER_NAME_LEN)) { + bpf_printk("Failed to read tracer name"); + } else { + bpf_map_update_elem(&tracer_name_by_context, &key, &tracer_name, 0); + } return 0; } @@ -121,6 +143,11 @@ int uprobe_Start_Returns(struct pt_regs *ctx) { return 0; } + tracer_name_t *tracer_name = bpf_map_lookup_elem(&tracer_name_by_context, &key); + if (tracer_name == NULL) { + goto done_without_tracer_name; + } + u32 zero_span_key = 0; struct otel_span_t *zero_span = bpf_map_lookup_elem(&otel_span_storage_map, &zero_span_key); if (zero_span == NULL) { @@ -137,7 +164,8 @@ int uprobe_Start_Returns(struct pt_regs *ctx) { } otel_span->start_time = bpf_ktime_get_ns(); - copy_byte_arrays((unsigned char*)span_name->buf, (unsigned char*)otel_span->span_name.buf, MAX_SPAN_NAME_LEN); + otel_span->span_name = *span_name; + otel_span->tracer_name = *tracer_name; // Get the ** returned ** context and Span (concrete type of the interfaces) void *ret_context_ptr_val = get_argument(ctx, 2); @@ -157,6 +185,8 @@ int uprobe_Start_Returns(struct pt_regs *ctx) { start_tracking_span(ret_context_ptr_val, &otel_span->sc); done: + bpf_map_delete_elem(&tracer_name_by_context, &key); +done_without_tracer_name: bpf_map_delete_elem(&span_name_by_context, &key); return 0; } diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_arm64_bpfel.go index 673c1c47d..be07d0797 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_arm64_bpfel.go +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_arm64_bpfel.go @@ -32,7 +32,8 @@ type bpfOtelSpanT struct { } ValidAttrs uint8 } - _ [3]byte + TracerName bpfTracerNameT + _ [3]byte } type bpfSliceArrayBuff struct{ Buff [1024]uint8 } @@ -44,6 +45,8 @@ type bpfSpanContext struct { type bpfSpanNameT struct{ Buf [64]int8 } +type bpfTracerNameT struct{ Buf [128]int8 } + // loadBpf returns the embedded CollectionSpec for bpf. func loadBpf() (*ebpf.CollectionSpec, error) { reader := bytes.NewReader(_BpfBytes) @@ -103,6 +106,7 @@ type bpfMapSpecs struct { OtelSpanStorageMap *ebpf.MapSpec `ebpf:"otel_span_storage_map"` SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_map"` SpanNameByContext *ebpf.MapSpec `ebpf:"span_name_by_context"` + TracerNameByContext *ebpf.MapSpec `ebpf:"tracer_name_by_context"` TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` } @@ -132,6 +136,7 @@ type bpfMaps struct { OtelSpanStorageMap *ebpf.Map `ebpf:"otel_span_storage_map"` SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` SpanNameByContext *ebpf.Map `ebpf:"span_name_by_context"` + TracerNameByContext *ebpf.Map `ebpf:"tracer_name_by_context"` TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } @@ -144,6 +149,7 @@ func (m *bpfMaps) Close() error { m.OtelSpanStorageMap, m.SliceArrayBuffMap, m.SpanNameByContext, + m.TracerNameByContext, m.TrackedSpans, m.TrackedSpansBySc, ) diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_x86_bpfel.go b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_x86_bpfel.go index 525428213..de3475c98 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_x86_bpfel.go +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_x86_bpfel.go @@ -32,7 +32,8 @@ type bpfOtelSpanT struct { } ValidAttrs uint8 } - _ [3]byte + TracerName bpfTracerNameT + _ [3]byte } type bpfSliceArrayBuff struct{ Buff [1024]uint8 } @@ -44,6 +45,8 @@ type bpfSpanContext struct { type bpfSpanNameT struct{ Buf [64]int8 } +type bpfTracerNameT struct{ Buf [128]int8 } + // loadBpf returns the embedded CollectionSpec for bpf. func loadBpf() (*ebpf.CollectionSpec, error) { reader := bytes.NewReader(_BpfBytes) @@ -103,6 +106,7 @@ type bpfMapSpecs struct { OtelSpanStorageMap *ebpf.MapSpec `ebpf:"otel_span_storage_map"` SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_map"` SpanNameByContext *ebpf.MapSpec `ebpf:"span_name_by_context"` + TracerNameByContext *ebpf.MapSpec `ebpf:"tracer_name_by_context"` TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` } @@ -132,6 +136,7 @@ type bpfMaps struct { OtelSpanStorageMap *ebpf.Map `ebpf:"otel_span_storage_map"` SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` SpanNameByContext *ebpf.Map `ebpf:"span_name_by_context"` + TracerNameByContext *ebpf.Map `ebpf:"tracer_name_by_context"` TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } @@ -144,6 +149,7 @@ func (m *bpfMaps) Close() error { m.OtelSpanStorageMap, m.SliceArrayBuffMap, m.SpanNameByContext, + m.TracerNameByContext, m.TrackedSpans, m.TrackedSpansBySc, ) diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go index f0b090971..e655a386d 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go @@ -94,6 +94,10 @@ func New(logger logr.Logger) probe.Probe { Key: "tracer_delegate_pos", Val: structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracer", "delegate"), }, + probe.StructFieldConst{ + Key: "tracer_name_pos", + Val: structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracer", "name"), + }, }, Uprobes: []probe.Uprobe[bpfObjects]{ { @@ -252,6 +256,7 @@ type event struct { SpanName [64]byte Status status Attributes attributesBuffer + TracerName [128]byte } func convertEvent(e *event) []*probe.SpanEvent { @@ -288,6 +293,7 @@ func convertEvent(e *event) []*probe.SpanEvent { Code: codes.Code(e.Status.Code), Description: string(unix.ByteSliceToString(e.Status.Description[:])), }, + TracerName: unix.ByteSliceToString(e.TracerName[:]), }, } } diff --git a/internal/pkg/instrumentation/probe/event.go b/internal/pkg/instrumentation/probe/event.go index e3d4b6e99..ea8e5bc96 100644 --- a/internal/pkg/instrumentation/probe/event.go +++ b/internal/pkg/instrumentation/probe/event.go @@ -40,4 +40,5 @@ type SpanEvent struct { SpanContext *trace.SpanContext ParentSpanContext *trace.SpanContext Status Status + TracerName string } diff --git a/internal/pkg/opentelemetry/controller.go b/internal/pkg/opentelemetry/controller.go index da678c955..61f0afd7f 100644 --- a/internal/pkg/opentelemetry/controller.go +++ b/internal/pkg/opentelemetry/controller.go @@ -35,17 +35,32 @@ type Controller struct { bootTime int64 } -func (c *Controller) getTracer(pkg string) trace.Tracer { - t, exists := c.tracersMap[pkg] +func (c *Controller) getTracer(pkg, tracerName string) trace.Tracer { + var ( + newTracer trace.Tracer + tracerKey = pkg + ) + + if tracerName != "" { + tracerKey = tracerName + } + + t, exists := c.tracersMap[tracerKey] if exists { return t } - newTracer := c.tracerProvider.Tracer( - "go.opentelemetry.io/auto/"+pkg, - trace.WithInstrumentationVersion(c.version), - ) - c.tracersMap[pkg] = newTracer + if tracerName != "" { + // If the user has provided a tracer name, use it. + newTracer = c.tracerProvider.Tracer(tracerName) + } else { + newTracer = c.tracerProvider.Tracer( + "go.opentelemetry.io/auto/"+pkg, + trace.WithInstrumentationVersion(c.version), + ) + } + + c.tracersMap[tracerKey] = newTracer return newTracer } @@ -66,7 +81,7 @@ func (c *Controller) Trace(event *probe.Event) { } ctx = ContextWithEBPFEvent(ctx, *se) - _, span := c.getTracer(event.Package). + _, span := c.getTracer(event.Package, se.TracerName). Start(ctx, se.SpanName, trace.WithAttributes(se.Attributes...), trace.WithSpanKind(event.Kind), diff --git a/internal/pkg/opentelemetry/controller_test.go b/internal/pkg/opentelemetry/controller_test.go index 7f1110c1a..53fc72460 100644 --- a/internal/pkg/opentelemetry/controller_test.go +++ b/internal/pkg/opentelemetry/controller_test.go @@ -237,3 +237,34 @@ func TestTrace(t *testing.T) { }) } } + +func TestGetTracer(t *testing.T) { + logger := stdr.New(log.New(os.Stderr, "", log.LstdFlags)) + + exporter := tracetest.NewInMemoryExporter() + tp := sdktrace.NewTracerProvider( + sdktrace.WithSampler(sdktrace.AlwaysSample()), + sdktrace.WithBatcher(exporter), + sdktrace.WithResource(instResource()), + ) + defer func() { + err := tp.Shutdown(context.Background()) + assert.NoError(t, err) + }() + + ctrl, err := NewController(logger, tp, "test") + assert.NoError(t, err) + + t1 := ctrl.getTracer("foo/bar", "test") + assert.Equal(t, t1, ctrl.tracersMap["test"]) + assert.Nil(t, ctrl.tracersMap["foo/bar"]) + + t2 := ctrl.getTracer("net/http", "") + assert.Equal(t, t2, ctrl.tracersMap["net/http"]) + + t3 := ctrl.getTracer("foo/bar", "test") + assert.Equal(t, t1, t3) + + t4 := ctrl.getTracer("net/http", "") + assert.Equal(t, t2, t4) +} diff --git a/internal/test/e2e/otelglobal/traces.json b/internal/test/e2e/otelglobal/traces.json index 5124b2e77..657650a5d 100644 --- a/internal/test/e2e/otelglobal/traces.json +++ b/internal/test/e2e/otelglobal/traces.json @@ -45,8 +45,7 @@ "scopeSpans": [ { "scope": { - "name": "go.opentelemetry.io/auto/go.opentelemetry.io/otel/internal/global", - "version": "v0.12.0-alpha" + "name": "trace-example" }, "spans": [ { diff --git a/internal/test/e2e/otelglobal/verify.bats b/internal/test/e2e/otelglobal/verify.bats index 5a4b37a30..067e8ab3e 100644 --- a/internal/test/e2e/otelglobal/verify.bats +++ b/internal/test/e2e/otelglobal/verify.bats @@ -2,7 +2,7 @@ load ../../test_helpers/utilities -SCOPE="go.opentelemetry.io/auto/go.opentelemetry.io/otel/internal/global" +SCOPE="trace-example" @test "go-auto :: includes service.name in resource attributes" { result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") diff --git a/internal/tools/inspect/cmd/offsetgen/main.go b/internal/tools/inspect/cmd/offsetgen/main.go index 5301a98c7..eeb83a4c2 100644 --- a/internal/tools/inspect/cmd/offsetgen/main.go +++ b/internal/tools/inspect/cmd/offsetgen/main.go @@ -171,6 +171,7 @@ func manifests() ([]inspect.Manifest, error) { }, StructFields: []structfield.ID{ structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracer", "delegate"), + structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracer", "name"), }, }, { From 1b6c3fabd5aaa9e886adfb24bf227c9c66108c59 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sat, 1 Jun 2024 00:14:46 +0300 Subject: [PATCH 2/9] otelglobal: Collect user provided tracer version --- examples/kafka-go/go.mod | 2 +- examples/kafka-go/main.go | 3 +- internal/include/go_types.h | 30 +-- internal/pkg/inject/offset_results.json | 194 +++++++++++++++++- .../otel/traceglobal/bpf/probe.bpf.c | 187 +++++++++++++++-- .../otel/traceglobal/bpf_arm64_bpfel.go | 57 +++-- .../otel/traceglobal/bpf_x86_bpfel.go | 57 +++-- .../otel/traceglobal/probe.go | 24 ++- .../bpf/net/http/client/bpf/probe.bpf.c | 8 - .../bpf/net/http/client/bpf_arm64_bpfel.go | 3 - .../net/http/client/bpf_no_tp_arm64_bpfel.go | 3 - .../net/http/client/bpf_no_tp_x86_bpfel.go | 3 - .../bpf/net/http/client/bpf_x86_bpfel.go | 3 - .../bpf/net/http/client/probe.go | 4 - .../bpf/net/http/server/bpf/probe.bpf.c | 8 +- internal/pkg/instrumentation/probe/event.go | 2 + internal/pkg/opentelemetry/controller.go | 25 ++- internal/pkg/opentelemetry/controller_test.go | 19 +- internal/test/e2e/otelglobal/go.mod | 6 +- internal/test/e2e/otelglobal/main.go | 3 +- internal/test/e2e/otelglobal/traces.json | 3 +- internal/test/e2e/otelglobal/verify.bats | 5 + internal/tools/inspect/cmd/offsetgen/main.go | 2 + 23 files changed, 519 insertions(+), 132 deletions(-) diff --git a/examples/kafka-go/go.mod b/examples/kafka-go/go.mod index 5d4c3dd55..76248e188 100644 --- a/examples/kafka-go/go.mod +++ b/examples/kafka-go/go.mod @@ -5,6 +5,7 @@ go 1.22.0 require ( github.com/segmentio/kafka-go v0.4.47 go.opentelemetry.io/otel v1.27.0 + go.opentelemetry.io/otel/trace v1.27.0 ) require ( @@ -13,5 +14,4 @@ require ( github.com/klauspost/compress v1.15.9 // indirect github.com/pierrec/lz4/v4 v4.1.15 // indirect go.opentelemetry.io/otel/metric v1.27.0 // indirect - go.opentelemetry.io/otel/trace v1.27.0 // indirect ) diff --git a/examples/kafka-go/main.go b/examples/kafka-go/main.go index 05a593261..7c3f42553 100644 --- a/examples/kafka-go/main.go +++ b/examples/kafka-go/main.go @@ -25,9 +25,10 @@ import ( kafka "github.com/segmentio/kafka-go" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" ) -var tracer = otel.Tracer("trace-example") +var tracer = otel.Tracer("trace-example-kafka-go", trace.WithInstrumentationVersion("v1.0.0-test")) type server struct { kafkaWriter *kafka.Writer diff --git a/internal/include/go_types.h b/internal/include/go_types.h index 45861a245..364e19131 100644 --- a/internal/include/go_types.h +++ b/internal/include/go_types.h @@ -23,30 +23,36 @@ Keep a power of 2 to help with masks */ #define MAX_SLICE_ARRAY_SIZE 1024 -struct go_string +typedef struct go_string { char *str; s64 len; -}; +} go_string_t; -struct go_slice +typedef struct go_slice { void *array; s64 len; s64 cap; -}; +} go_slice_t; -struct go_iface +typedef struct go_iface { void *tab; void *data; -}; - -struct map_bucket { - char tophash[8]; - struct go_string keys[8]; - struct go_slice values[8]; - void *overflow; +} go_iface_t; + +// a map bucket type with the given key and value types +#define MAP_BUCKET_TYPE(key_type, value_type) struct map_bucket_##key_type##_##value_type##_t +// a map bucket struct definition with the given key and value types +// for more details about the structure of a map bucket see: +// https://github.com/golang/go/blob/639cc0dcc0948dd02c9d5fc12fbed730a21ebebc/src/runtime/map.go#L143 +#define MAP_BUCKET_DEFINITION(key_type, value_type) \ +MAP_BUCKET_TYPE(key_type, value_type) { \ + char tophash[8]; \ + key_type keys[8]; \ + value_type values[8]; \ + void *overflow; \ }; struct slice_array_buff diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index 04285317b..5a899f066 100644 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -1028,7 +1028,199 @@ "1.23.1", "1.24.0", "1.25.0", - "1.26.0" + "1.26.0", + "1.27.0" + ] + } + ] + }, + { + "field": "provider", + "offsets": [ + { + "offset": null, + "versions": [ + "0.1.0", + "0.1.1", + "0.1.2", + "0.2.0", + "0.2.1", + "0.2.2", + "0.2.3", + "0.3.0", + "0.4.0", + "0.4.1", + "0.4.2", + "0.4.3", + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0", + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0" + ] + }, + { + "offset": 40, + "versions": [ + "1.0.0-RC1", + "1.0.0-RC2", + "1.0.0-RC3", + "1.0.0", + "1.0.1", + "1.1.0", + "1.2.0", + "1.3.0", + "1.4.0", + "1.4.1", + "1.5.0", + "1.6.0", + "1.6.1", + "1.6.2", + "1.6.3", + "1.7.0", + "1.8.0", + "1.9.0", + "1.10.0", + "1.11.0", + "1.11.1", + "1.11.2", + "1.12.0", + "1.13.0", + "1.14.0", + "1.15.0-rc.1", + "1.15.0-rc.2", + "1.15.0", + "1.15.1", + "1.16.0-rc.1", + "1.16.0", + "1.17.0", + "1.18.0", + "1.19.0-rc.1", + "1.19.0" + ] + }, + { + "offset": 56, + "versions": [ + "1.20.0", + "1.21.0", + "1.22.0", + "1.23.0-rc.1", + "1.23.0", + "1.23.1", + "1.24.0", + "1.25.0", + "1.26.0", + "1.27.0" + ] + } + ] + } + ] + }, + { + "struct": "tracerProvider", + "fields": [ + { + "field": "tracers", + "offsets": [ + { + "offset": null, + "versions": [ + "0.1.0", + "0.1.1", + "0.1.2", + "0.2.0", + "0.2.1", + "0.2.2", + "0.2.3", + "0.3.0", + "0.4.0", + "0.4.1", + "0.4.2", + "0.4.3", + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0" + ] + }, + { + "offset": 8, + "versions": [ + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0", + "1.0.0-RC1", + "1.0.0-RC2", + "1.0.0-RC3", + "1.0.0", + "1.0.1", + "1.1.0", + "1.2.0", + "1.3.0", + "1.4.0", + "1.4.1", + "1.5.0", + "1.6.0", + "1.6.1", + "1.6.2", + "1.6.3", + "1.7.0", + "1.8.0", + "1.9.0", + "1.10.0", + "1.11.0", + "1.11.1", + "1.11.2", + "1.12.0", + "1.13.0", + "1.14.0", + "1.15.0-rc.1", + "1.15.0-rc.2", + "1.15.0", + "1.15.1", + "1.16.0-rc.1", + "1.16.0", + "1.17.0", + "1.18.0", + "1.19.0-rc.1", + "1.19.0" + ] + }, + { + "offset": 24, + "versions": [ + "1.20.0", + "1.21.0", + "1.22.0", + "1.23.0-rc.1", + "1.23.0", + "1.23.1", + "1.24.0", + "1.25.0", + "1.26.0", + "1.27.0" ] } ] diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c index cf58f674d..2ce5d5528 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c @@ -26,6 +26,11 @@ char __license[] SEC("license") = "Dual MIT/GPL"; #define MAX_SPAN_NAME_LEN 64 #define MAX_STATUS_DESCRIPTION_LEN 64 #define MAX_TRACER_NAME_LEN 128 +#define MAX_TRACER_VERSION_LEN 32 +#define MAX_TRACER_SCHEMA_URL_LEN 128 + +#define MAX_BUCKETS 8 +#define MAX_TRACERS 64 struct span_description_t { char buf[MAX_STATUS_DESCRIPTION_LEN]; @@ -40,18 +45,31 @@ struct span_name_t { char buf[MAX_SPAN_NAME_LEN]; }; -typedef struct tracer_name { - char buf[MAX_TRACER_NAME_LEN]; -} tracer_name_t; +typedef struct tracer_id { + char name[MAX_TRACER_NAME_LEN]; + char version[MAX_TRACER_VERSION_LEN]; + char schema_url[MAX_TRACER_SCHEMA_URL_LEN]; +} tracer_id_t; struct otel_span_t { BASE_SPAN_PROPERTIES struct span_name_t span_name; otel_status_t status; otel_attributes_t attributes; - tracer_name_t tracer_name; + tracer_id_t tracer_id; }; +typedef struct go_tracer_id { + struct go_string name; + struct go_string version; + // struct go_string schema_url; +} go_tracer_id_t; + +typedef void* go_tracer_ptr; + +// tracerProvider contains a map of tracers +MAP_BUCKET_DEFINITION(go_tracer_id_t, go_tracer_ptr) + struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, void*); @@ -69,9 +87,9 @@ struct { struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, void*); - __type(value, tracer_name_t); + __type(value, tracer_id_t); __uint(max_entries, MAX_CONCURRENT); -} tracer_name_by_context SEC(".maps"); +} tracer_id_by_context SEC(".maps"); struct { @@ -81,6 +99,32 @@ struct __uint(max_entries, 2); } otel_span_storage_map SEC(".maps"); +struct +{ + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(key_size, sizeof(u32)); + __uint(value_size, sizeof(MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr))); + __uint(max_entries, 1); +} golang_mapbucket_storage_map SEC(".maps"); + +struct +{ + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(key_size, sizeof(u32)); + __uint(value_size, sizeof(tracer_id_t)); + __uint(max_entries, 1); +} tracer_id_storage_map SEC(".maps"); + + +struct +{ + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, void*); + __type(value, tracer_id_t); + __uint(max_entries, MAX_TRACERS); +} tracer_ptr_to_id_map SEC(".maps"); + + struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); } events SEC(".maps"); @@ -88,6 +132,9 @@ struct { // Injected in init volatile const u64 tracer_delegate_pos; volatile const u64 tracer_name_pos; +volatile const u64 tracer_provider_pos; +volatile const u64 tracer_provider_tracers_pos; +volatile const u64 buckets_ptr_pos; // read_span_name reads the span name from the provided span_name_ptr and stores the result in // span_name.buf. @@ -96,6 +143,104 @@ static __always_inline void read_span_name(struct span_name_t *span_name, const bpf_probe_read(span_name->buf, span_name_size, span_name_ptr); } +static __always_inline long fill_tracer_id_from_tracers_map(void *tracers_map, go_tracer_ptr tracer, tracer_id_t *tracer_id) { + u64 tracers_count = 0; + long res = 0; + res = bpf_probe_read(&tracers_count, sizeof(tracers_count), tracers_map); + if (res < 0) + { + return -1; + } + if (tracers_count == 0) + { + return -1; + } + unsigned char log_2_bucket_count; + res = bpf_probe_read(&log_2_bucket_count, sizeof(log_2_bucket_count), tracers_map + 9); + if (res < 0) + { + return -1; + } + u64 bucket_count = 1 << log_2_bucket_count; + void *buckets_array; + res = bpf_probe_read(&buckets_array, sizeof(buckets_array), (void*)(tracers_map + buckets_ptr_pos)); + if (res < 0) + { + return -1; + } + u32 map_id = 0; + MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr) *map_bucket = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id); + if (!map_bucket) + { + return -1; + } + + for (u64 j = 0; j < MAX_BUCKETS; j++) + { + if (j >= bucket_count) + { + break; + } + res = bpf_probe_read(map_bucket, sizeof(MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr)), buckets_array + (j * sizeof(MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr)))); + if (res < 0) + { + continue; + } + for (u64 i = 0; i < 8; i++) + { + if (map_bucket->tophash[i] == 0) + { + continue; + } + if (map_bucket->values[i] == NULL) + { + continue; + } + if (map_bucket->values[i] != tracer) + { + continue; + } + get_go_string_from_user_ptr(&map_bucket->keys[i].version, tracer_id->version, MAX_TRACER_VERSION_LEN); + return 0; + } + } + return 0; +} + +static __always_inline long fill_tracer_id(tracer_id_t *tracer_id, go_tracer_ptr tracer) { + // Check if the tracer id is already cached + tracer_id_t *cached_tracer_id = bpf_map_lookup_elem(&tracer_ptr_to_id_map, &tracer); + if (cached_tracer_id != NULL) { + *tracer_id = *cached_tracer_id; + return 0; + } + + if (!get_go_string_from_user_ptr((void*)(tracer + tracer_name_pos), tracer_id->name, MAX_TRACER_NAME_LEN)) { + return -1; + } + + long res = 0; + void *tracer_provider = NULL; + res = bpf_probe_read(&tracer_provider, sizeof(tracer_provider), (void*)(tracer + tracer_provider_pos)); + if (res < 0) { + return res; + } + + void *tracers_map = NULL; + res = bpf_probe_read(&tracers_map, sizeof(tracers_map), (void*)(tracer_provider + tracer_provider_tracers_pos)); + if (res < 0) { + return res; + } + + res = fill_tracer_id_from_tracers_map(tracers_map, tracer, tracer_id); + if (res < 0) { + return res; + } + + bpf_map_update_elem(&tracer_ptr_to_id_map, &tracer, tracer_id, 0); + return 0; +} + // This instrumentation attaches uprobe to the following function: // func (t *tracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) // https://github.com/open-telemetry/opentelemetry-go/blob/98b32a6c3a87fbee5d34c063b9096f416b250897/internal/global/trace.go#L149 @@ -120,13 +265,19 @@ int uprobe_Start(struct pt_regs *ctx) { void *key = get_consistent_key(ctx, context_ptr_val); bpf_map_update_elem(&span_name_by_context, &key, &span_name, 0); - // Get the tracer name - tracer_name_t tracer_name = {0}; - if (!get_go_string_from_user_ptr((void*)(tracer_ptr + tracer_name_pos), tracer_name.buf, MAX_TRACER_NAME_LEN)) { - bpf_printk("Failed to read tracer name"); - } else { - bpf_map_update_elem(&tracer_name_by_context, &key, &tracer_name, 0); + // Get the tracer id + u32 map_id = 0; + tracer_id_t *tracer_id = bpf_map_lookup_elem(&tracer_id_storage_map, &map_id); + if (tracer_id == NULL) { + return 0; + } + __builtin_memset(tracer_id, 0, sizeof(tracer_id_t)); + + long res = fill_tracer_id(tracer_id, tracer_ptr); + if (res < 0) { + return 0; } + bpf_map_update_elem(&tracer_id_by_context, &key, tracer_id, 0); return 0; } @@ -143,9 +294,9 @@ int uprobe_Start_Returns(struct pt_regs *ctx) { return 0; } - tracer_name_t *tracer_name = bpf_map_lookup_elem(&tracer_name_by_context, &key); - if (tracer_name == NULL) { - goto done_without_tracer_name; + tracer_id_t *tracer_id = bpf_map_lookup_elem(&tracer_id_by_context, &key); + if (tracer_id == NULL) { + goto done_without_tracer_id; } u32 zero_span_key = 0; @@ -165,7 +316,7 @@ int uprobe_Start_Returns(struct pt_regs *ctx) { otel_span->start_time = bpf_ktime_get_ns(); otel_span->span_name = *span_name; - otel_span->tracer_name = *tracer_name; + otel_span->tracer_id = *tracer_id; // Get the ** returned ** context and Span (concrete type of the interfaces) void *ret_context_ptr_val = get_argument(ctx, 2); @@ -185,8 +336,8 @@ int uprobe_Start_Returns(struct pt_regs *ctx) { start_tracking_span(ret_context_ptr_val, &otel_span->sc); done: - bpf_map_delete_elem(&tracer_name_by_context, &key); -done_without_tracer_name: + bpf_map_delete_elem(&tracer_id_by_context, &key); +done_without_tracer_id: bpf_map_delete_elem(&span_name_by_context, &key); return 0; } diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_arm64_bpfel.go index be07d0797..6463a348f 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_arm64_bpfel.go +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_arm64_bpfel.go @@ -32,8 +32,8 @@ type bpfOtelSpanT struct { } ValidAttrs uint8 } - TracerName bpfTracerNameT - _ [3]byte + TracerId bpfTracerIdT + _ [3]byte } type bpfSliceArrayBuff struct{ Buff [1024]uint8 } @@ -45,7 +45,11 @@ type bpfSpanContext struct { type bpfSpanNameT struct{ Buf [64]int8 } -type bpfTracerNameT struct{ Buf [128]int8 } +type bpfTracerIdT struct { + Name [128]int8 + Version [32]int8 + SchemaUrl [128]int8 +} // loadBpf returns the embedded CollectionSpec for bpf. func loadBpf() (*ebpf.CollectionSpec, error) { @@ -100,15 +104,18 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - ActiveSpansBySpanPtr *ebpf.MapSpec `ebpf:"active_spans_by_span_ptr"` - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - OtelSpanStorageMap *ebpf.MapSpec `ebpf:"otel_span_storage_map"` - SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_map"` - SpanNameByContext *ebpf.MapSpec `ebpf:"span_name_by_context"` - TracerNameByContext *ebpf.MapSpec `ebpf:"tracer_name_by_context"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` + ActiveSpansBySpanPtr *ebpf.MapSpec `ebpf:"active_spans_by_span_ptr"` + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + Events *ebpf.MapSpec `ebpf:"events"` + GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` + OtelSpanStorageMap *ebpf.MapSpec `ebpf:"otel_span_storage_map"` + SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_map"` + SpanNameByContext *ebpf.MapSpec `ebpf:"span_name_by_context"` + TracerIdByContext *ebpf.MapSpec `ebpf:"tracer_id_by_context"` + TracerIdStorageMap *ebpf.MapSpec `ebpf:"tracer_id_storage_map"` + TracerPtrToIdMap *ebpf.MapSpec `ebpf:"tracer_ptr_to_id_map"` + TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` } // bpfObjects contains all objects after they have been loaded into the kernel. @@ -130,15 +137,18 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - ActiveSpansBySpanPtr *ebpf.Map `ebpf:"active_spans_by_span_ptr"` - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - OtelSpanStorageMap *ebpf.Map `ebpf:"otel_span_storage_map"` - SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` - SpanNameByContext *ebpf.Map `ebpf:"span_name_by_context"` - TracerNameByContext *ebpf.Map `ebpf:"tracer_name_by_context"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` + ActiveSpansBySpanPtr *ebpf.Map `ebpf:"active_spans_by_span_ptr"` + AllocMap *ebpf.Map `ebpf:"alloc_map"` + Events *ebpf.Map `ebpf:"events"` + GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` + OtelSpanStorageMap *ebpf.Map `ebpf:"otel_span_storage_map"` + SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` + SpanNameByContext *ebpf.Map `ebpf:"span_name_by_context"` + TracerIdByContext *ebpf.Map `ebpf:"tracer_id_by_context"` + TracerIdStorageMap *ebpf.Map `ebpf:"tracer_id_storage_map"` + TracerPtrToIdMap *ebpf.Map `ebpf:"tracer_ptr_to_id_map"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { @@ -146,10 +156,13 @@ func (m *bpfMaps) Close() error { m.ActiveSpansBySpanPtr, m.AllocMap, m.Events, + m.GolangMapbucketStorageMap, m.OtelSpanStorageMap, m.SliceArrayBuffMap, m.SpanNameByContext, - m.TracerNameByContext, + m.TracerIdByContext, + m.TracerIdStorageMap, + m.TracerPtrToIdMap, m.TrackedSpans, m.TrackedSpansBySc, ) diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_x86_bpfel.go b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_x86_bpfel.go index de3475c98..f96a5564a 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_x86_bpfel.go +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_x86_bpfel.go @@ -32,8 +32,8 @@ type bpfOtelSpanT struct { } ValidAttrs uint8 } - TracerName bpfTracerNameT - _ [3]byte + TracerId bpfTracerIdT + _ [3]byte } type bpfSliceArrayBuff struct{ Buff [1024]uint8 } @@ -45,7 +45,11 @@ type bpfSpanContext struct { type bpfSpanNameT struct{ Buf [64]int8 } -type bpfTracerNameT struct{ Buf [128]int8 } +type bpfTracerIdT struct { + Name [128]int8 + Version [32]int8 + SchemaUrl [128]int8 +} // loadBpf returns the embedded CollectionSpec for bpf. func loadBpf() (*ebpf.CollectionSpec, error) { @@ -100,15 +104,18 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - ActiveSpansBySpanPtr *ebpf.MapSpec `ebpf:"active_spans_by_span_ptr"` - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - OtelSpanStorageMap *ebpf.MapSpec `ebpf:"otel_span_storage_map"` - SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_map"` - SpanNameByContext *ebpf.MapSpec `ebpf:"span_name_by_context"` - TracerNameByContext *ebpf.MapSpec `ebpf:"tracer_name_by_context"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` + ActiveSpansBySpanPtr *ebpf.MapSpec `ebpf:"active_spans_by_span_ptr"` + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + Events *ebpf.MapSpec `ebpf:"events"` + GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` + OtelSpanStorageMap *ebpf.MapSpec `ebpf:"otel_span_storage_map"` + SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_map"` + SpanNameByContext *ebpf.MapSpec `ebpf:"span_name_by_context"` + TracerIdByContext *ebpf.MapSpec `ebpf:"tracer_id_by_context"` + TracerIdStorageMap *ebpf.MapSpec `ebpf:"tracer_id_storage_map"` + TracerPtrToIdMap *ebpf.MapSpec `ebpf:"tracer_ptr_to_id_map"` + TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` } // bpfObjects contains all objects after they have been loaded into the kernel. @@ -130,15 +137,18 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - ActiveSpansBySpanPtr *ebpf.Map `ebpf:"active_spans_by_span_ptr"` - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - OtelSpanStorageMap *ebpf.Map `ebpf:"otel_span_storage_map"` - SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` - SpanNameByContext *ebpf.Map `ebpf:"span_name_by_context"` - TracerNameByContext *ebpf.Map `ebpf:"tracer_name_by_context"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` + ActiveSpansBySpanPtr *ebpf.Map `ebpf:"active_spans_by_span_ptr"` + AllocMap *ebpf.Map `ebpf:"alloc_map"` + Events *ebpf.Map `ebpf:"events"` + GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` + OtelSpanStorageMap *ebpf.Map `ebpf:"otel_span_storage_map"` + SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` + SpanNameByContext *ebpf.Map `ebpf:"span_name_by_context"` + TracerIdByContext *ebpf.Map `ebpf:"tracer_id_by_context"` + TracerIdStorageMap *ebpf.Map `ebpf:"tracer_id_storage_map"` + TracerPtrToIdMap *ebpf.Map `ebpf:"tracer_ptr_to_id_map"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { @@ -146,10 +156,13 @@ func (m *bpfMaps) Close() error { m.ActiveSpansBySpanPtr, m.AllocMap, m.Events, + m.GolangMapbucketStorageMap, m.OtelSpanStorageMap, m.SliceArrayBuffMap, m.SpanNameByContext, - m.TracerNameByContext, + m.TracerIdByContext, + m.TracerIdStorageMap, + m.TracerPtrToIdMap, m.TrackedSpans, m.TrackedSpansBySc, ) diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go index e655a386d..805bf5953 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go @@ -98,6 +98,18 @@ func New(logger logr.Logger) probe.Probe { Key: "tracer_name_pos", Val: structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracer", "name"), }, + probe.StructFieldConst{ + Key: "tracer_provider_pos", + Val: structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracer", "provider"), + }, + probe.StructFieldConst{ + Key: "tracer_provider_tracers_pos", + Val: structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracerProvider", "tracers"), + }, + probe.StructFieldConst{ + Key: "buckets_ptr_pos", + Val: structfield.NewID("std", "runtime", "hmap", "buckets"), + }, }, Uprobes: []probe.Uprobe[bpfObjects]{ { @@ -250,13 +262,19 @@ type status struct { Description [64]byte } +type tracerID struct { + Name [128]byte + Version [32]byte + SchemaURL [128]byte +} + // event represents a manual span created by the user. type event struct { context.BaseSpanProperties SpanName [64]byte Status status Attributes attributesBuffer - TracerName [128]byte + TracerID tracerID } func convertEvent(e *event) []*probe.SpanEvent { @@ -293,7 +311,9 @@ func convertEvent(e *event) []*probe.SpanEvent { Code: codes.Code(e.Status.Code), Description: string(unix.ByteSliceToString(e.Status.Description[:])), }, - TracerName: unix.ByteSliceToString(e.TracerName[:]), + TracerName: unix.ByteSliceToString(e.TracerID.Name[:]), + TracerVersion: unix.ByteSliceToString(e.TracerID.Version[:]), + TracerSchema: unix.ByteSliceToString(e.TracerID.SchemaURL[:]), }, } } diff --git a/internal/pkg/instrumentation/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentation/bpf/net/http/client/bpf/probe.bpf.c index 20cc560fc..d0dcc08fb 100644 --- a/internal/pkg/instrumentation/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentation/bpf/net/http/client/bpf/probe.bpf.c @@ -44,13 +44,6 @@ struct { __uint(max_entries, MAX_CONCURRENT); } http_events SEC(".maps"); -struct { - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(struct map_bucket)); - __uint(max_entries, 1); -} golang_mapbucket_storage_map SEC(".maps"); - struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); @@ -76,7 +69,6 @@ volatile const u64 url_ptr_pos; volatile const u64 path_ptr_pos; volatile const u64 headers_ptr_pos; volatile const u64 ctx_ptr_pos; -volatile const u64 buckets_ptr_pos; volatile const u64 status_code_pos; volatile const u64 request_host_pos; volatile const u64 request_proto_pos; diff --git a/internal/pkg/instrumentation/bpf/net/http/client/bpf_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/net/http/client/bpf_arm64_bpfel.go index c29a1b56a..1a03f6ec0 100644 --- a/internal/pkg/instrumentation/bpf/net/http/client/bpf_arm64_bpfel.go +++ b/internal/pkg/instrumentation/bpf/net/http/client/bpf_arm64_bpfel.go @@ -93,7 +93,6 @@ type bpfProgramSpecs struct { type bpfMapSpecs struct { AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` HttpClientUprobeStorageMap *ebpf.MapSpec `ebpf:"http_client_uprobe_storage_map"` HttpEvents *ebpf.MapSpec `ebpf:"http_events"` HttpHeaders *ebpf.MapSpec `ebpf:"http_headers"` @@ -123,7 +122,6 @@ func (o *bpfObjects) Close() error { type bpfMaps struct { AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` HttpClientUprobeStorageMap *ebpf.Map `ebpf:"http_client_uprobe_storage_map"` HttpEvents *ebpf.Map `ebpf:"http_events"` HttpHeaders *ebpf.Map `ebpf:"http_headers"` @@ -136,7 +134,6 @@ func (m *bpfMaps) Close() error { return _BpfClose( m.AllocMap, m.Events, - m.GolangMapbucketStorageMap, m.HttpClientUprobeStorageMap, m.HttpEvents, m.HttpHeaders, diff --git a/internal/pkg/instrumentation/bpf/net/http/client/bpf_no_tp_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/net/http/client/bpf_no_tp_arm64_bpfel.go index 18f56342d..348aad0bd 100644 --- a/internal/pkg/instrumentation/bpf/net/http/client/bpf_no_tp_arm64_bpfel.go +++ b/internal/pkg/instrumentation/bpf/net/http/client/bpf_no_tp_arm64_bpfel.go @@ -93,7 +93,6 @@ type bpf_no_tpProgramSpecs struct { type bpf_no_tpMapSpecs struct { AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` HttpClientUprobeStorageMap *ebpf.MapSpec `ebpf:"http_client_uprobe_storage_map"` HttpEvents *ebpf.MapSpec `ebpf:"http_events"` HttpHeaders *ebpf.MapSpec `ebpf:"http_headers"` @@ -123,7 +122,6 @@ func (o *bpf_no_tpObjects) Close() error { type bpf_no_tpMaps struct { AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` HttpClientUprobeStorageMap *ebpf.Map `ebpf:"http_client_uprobe_storage_map"` HttpEvents *ebpf.Map `ebpf:"http_events"` HttpHeaders *ebpf.Map `ebpf:"http_headers"` @@ -136,7 +134,6 @@ func (m *bpf_no_tpMaps) Close() error { return _Bpf_no_tpClose( m.AllocMap, m.Events, - m.GolangMapbucketStorageMap, m.HttpClientUprobeStorageMap, m.HttpEvents, m.HttpHeaders, diff --git a/internal/pkg/instrumentation/bpf/net/http/client/bpf_no_tp_x86_bpfel.go b/internal/pkg/instrumentation/bpf/net/http/client/bpf_no_tp_x86_bpfel.go index 861d7afb8..bbfbaa963 100644 --- a/internal/pkg/instrumentation/bpf/net/http/client/bpf_no_tp_x86_bpfel.go +++ b/internal/pkg/instrumentation/bpf/net/http/client/bpf_no_tp_x86_bpfel.go @@ -93,7 +93,6 @@ type bpf_no_tpProgramSpecs struct { type bpf_no_tpMapSpecs struct { AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` HttpClientUprobeStorageMap *ebpf.MapSpec `ebpf:"http_client_uprobe_storage_map"` HttpEvents *ebpf.MapSpec `ebpf:"http_events"` HttpHeaders *ebpf.MapSpec `ebpf:"http_headers"` @@ -123,7 +122,6 @@ func (o *bpf_no_tpObjects) Close() error { type bpf_no_tpMaps struct { AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` HttpClientUprobeStorageMap *ebpf.Map `ebpf:"http_client_uprobe_storage_map"` HttpEvents *ebpf.Map `ebpf:"http_events"` HttpHeaders *ebpf.Map `ebpf:"http_headers"` @@ -136,7 +134,6 @@ func (m *bpf_no_tpMaps) Close() error { return _Bpf_no_tpClose( m.AllocMap, m.Events, - m.GolangMapbucketStorageMap, m.HttpClientUprobeStorageMap, m.HttpEvents, m.HttpHeaders, diff --git a/internal/pkg/instrumentation/bpf/net/http/client/bpf_x86_bpfel.go b/internal/pkg/instrumentation/bpf/net/http/client/bpf_x86_bpfel.go index bd96c1a5b..50b9b94a2 100644 --- a/internal/pkg/instrumentation/bpf/net/http/client/bpf_x86_bpfel.go +++ b/internal/pkg/instrumentation/bpf/net/http/client/bpf_x86_bpfel.go @@ -93,7 +93,6 @@ type bpfProgramSpecs struct { type bpfMapSpecs struct { AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` HttpClientUprobeStorageMap *ebpf.MapSpec `ebpf:"http_client_uprobe_storage_map"` HttpEvents *ebpf.MapSpec `ebpf:"http_events"` HttpHeaders *ebpf.MapSpec `ebpf:"http_headers"` @@ -123,7 +122,6 @@ func (o *bpfObjects) Close() error { type bpfMaps struct { AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` HttpClientUprobeStorageMap *ebpf.Map `ebpf:"http_client_uprobe_storage_map"` HttpEvents *ebpf.Map `ebpf:"http_events"` HttpHeaders *ebpf.Map `ebpf:"http_headers"` @@ -136,7 +134,6 @@ func (m *bpfMaps) Close() error { return _BpfClose( m.AllocMap, m.Events, - m.GolangMapbucketStorageMap, m.HttpClientUprobeStorageMap, m.HttpEvents, m.HttpHeaders, diff --git a/internal/pkg/instrumentation/bpf/net/http/client/probe.go b/internal/pkg/instrumentation/bpf/net/http/client/probe.go index 205f64fb2..e82ed526b 100644 --- a/internal/pkg/instrumentation/bpf/net/http/client/probe.go +++ b/internal/pkg/instrumentation/bpf/net/http/client/probe.go @@ -105,10 +105,6 @@ func New(logger logr.Logger) probe.Probe { Key: "status_code_pos", Val: structfield.NewID("std", "net/http", "Response", "StatusCode"), }, - probe.StructFieldConst{ - Key: "buckets_ptr_pos", - Val: structfield.NewID("std", "runtime", "hmap", "buckets"), - }, probe.StructFieldConst{ Key: "request_host_pos", Val: structfield.NewID("std", "net/http", "Request", "Host"), 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 15c11579e..48808b574 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 @@ -49,6 +49,8 @@ struct uprobe_data_t u64 resp_ptr; }; +MAP_BUCKET_DEFINITION(go_string_t, go_slice_t) + struct { __uint(type, BPF_MAP_TYPE_HASH); @@ -61,7 +63,7 @@ struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(struct map_bucket)); + __uint(value_size, sizeof(MAP_BUCKET_TYPE(go_string_t, go_slice_t))); __uint(max_entries, 1); } golang_mapbucket_storage_map SEC(".maps"); @@ -138,7 +140,7 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi return NULL; } u32 map_id = 0; - struct map_bucket *map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id); + MAP_BUCKET_TYPE(go_string_t, go_slice_t) *map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id); if (!map_value) { return NULL; @@ -150,7 +152,7 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi { break; } - res = bpf_probe_read(map_value, sizeof(struct map_bucket), header_buckets + (j * sizeof(struct map_bucket))); + res = bpf_probe_read(map_value, sizeof(MAP_BUCKET_TYPE(go_string_t, go_slice_t)), header_buckets + (j * sizeof(MAP_BUCKET_TYPE(go_string_t, go_slice_t)))); if (res < 0) { continue; diff --git a/internal/pkg/instrumentation/probe/event.go b/internal/pkg/instrumentation/probe/event.go index ea8e5bc96..ea2b5d717 100644 --- a/internal/pkg/instrumentation/probe/event.go +++ b/internal/pkg/instrumentation/probe/event.go @@ -41,4 +41,6 @@ type SpanEvent struct { ParentSpanContext *trace.SpanContext Status Status TracerName string + TracerVersion string + TracerSchema string } diff --git a/internal/pkg/opentelemetry/controller.go b/internal/pkg/opentelemetry/controller.go index 61f0afd7f..301514605 100644 --- a/internal/pkg/opentelemetry/controller.go +++ b/internal/pkg/opentelemetry/controller.go @@ -31,28 +31,27 @@ type Controller struct { logger logr.Logger version string tracerProvider trace.TracerProvider - tracersMap map[string]trace.Tracer + tracersMap map[tracerID]trace.Tracer bootTime int64 } -func (c *Controller) getTracer(pkg, tracerName string) trace.Tracer { - var ( - newTracer trace.Tracer - tracerKey = pkg - ) +type tracerID struct{ name, version, schema string } +func (c *Controller) getTracer(pkg, tracerName, version, schema string) trace.Tracer { + tID := tracerID{name: pkg, version: c.version} if tracerName != "" { - tracerKey = tracerName + tID = tracerID{name: tracerName, version: version, schema: schema} } - t, exists := c.tracersMap[tracerKey] + t, exists := c.tracersMap[tID] if exists { return t } + var newTracer trace.Tracer if tracerName != "" { - // If the user has provided a tracer name, use it. - newTracer = c.tracerProvider.Tracer(tracerName) + // If the user has provided a tracer, use it. + newTracer = c.tracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(version), trace.WithSchemaURL(schema)) } else { newTracer = c.tracerProvider.Tracer( "go.opentelemetry.io/auto/"+pkg, @@ -60,7 +59,7 @@ func (c *Controller) getTracer(pkg, tracerName string) trace.Tracer { ) } - c.tracersMap[tracerKey] = newTracer + c.tracersMap[tID] = newTracer return newTracer } @@ -81,7 +80,7 @@ func (c *Controller) Trace(event *probe.Event) { } ctx = ContextWithEBPFEvent(ctx, *se) - _, span := c.getTracer(event.Package, se.TracerName). + _, span := c.getTracer(event.Package, se.TracerName, se.TracerVersion, se.TracerSchema). Start(ctx, se.SpanName, trace.WithAttributes(se.Attributes...), trace.WithSpanKind(event.Kind), @@ -108,7 +107,7 @@ func NewController(logger logr.Logger, tracerProvider trace.TracerProvider, ver logger: logger, version: ver, tracerProvider: tracerProvider, - tracersMap: make(map[string]trace.Tracer), + tracersMap: make(map[tracerID]trace.Tracer), bootTime: bt, }, nil } diff --git a/internal/pkg/opentelemetry/controller_test.go b/internal/pkg/opentelemetry/controller_test.go index 53fc72460..ecb5c1c98 100644 --- a/internal/pkg/opentelemetry/controller_test.go +++ b/internal/pkg/opentelemetry/controller_test.go @@ -255,16 +255,17 @@ func TestGetTracer(t *testing.T) { ctrl, err := NewController(logger, tp, "test") assert.NoError(t, err) - t1 := ctrl.getTracer("foo/bar", "test") - assert.Equal(t, t1, ctrl.tracersMap["test"]) - assert.Nil(t, ctrl.tracersMap["foo/bar"]) + t1 := ctrl.getTracer("foo/bar", "test", "v1", "schema") + assert.Equal(t, t1, ctrl.tracersMap[tracerID{name: "test", version: "v1", schema: "schema"}]) + assert.Nil(t, ctrl.tracersMap[tracerID{name: "foo/bar", version: "v1", schema: "schema"}]) - t2 := ctrl.getTracer("net/http", "") - assert.Equal(t, t2, ctrl.tracersMap["net/http"]) + t2 := ctrl.getTracer("net/http", "", "", "") + assert.Equal(t, t2, ctrl.tracersMap[tracerID{name: "net/http", version: ctrl.version, schema: ""}]) - t3 := ctrl.getTracer("foo/bar", "test") - assert.Equal(t, t1, t3) + t3 := ctrl.getTracer("foo/bar", "test", "v1", "schema") + assert.Same(t, t1, t3) - t4 := ctrl.getTracer("net/http", "") - assert.Equal(t, t2, t4) + t4 := ctrl.getTracer("net/http", "", "", "") + assert.Same(t, t2, t4) + assert.Equal(t, len(ctrl.tracersMap), 2) } diff --git a/internal/test/e2e/otelglobal/go.mod b/internal/test/e2e/otelglobal/go.mod index 72516a313..5b6ba4a52 100644 --- a/internal/test/e2e/otelglobal/go.mod +++ b/internal/test/e2e/otelglobal/go.mod @@ -2,11 +2,13 @@ module go.opentelemetry.io/auto/internal/test/e2e/otelglobal go 1.22.0 -require go.opentelemetry.io/otel v1.27.0 +require ( + go.opentelemetry.io/otel v1.27.0 + go.opentelemetry.io/otel/trace v1.27.0 +) require ( github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect go.opentelemetry.io/otel/metric v1.27.0 // indirect - go.opentelemetry.io/otel/trace v1.27.0 // indirect ) diff --git a/internal/test/e2e/otelglobal/main.go b/internal/test/e2e/otelglobal/main.go index 844233af7..8ecfc2a74 100644 --- a/internal/test/e2e/otelglobal/main.go +++ b/internal/test/e2e/otelglobal/main.go @@ -21,9 +21,10 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" ) -var tracer = otel.Tracer("trace-example") +var tracer = otel.Tracer("trace-example", trace.WithInstrumentationVersion("v1.23.42")) func innerFunction(ctx context.Context) { _, span := tracer.Start(ctx, "child") diff --git a/internal/test/e2e/otelglobal/traces.json b/internal/test/e2e/otelglobal/traces.json index 657650a5d..1f37041e0 100644 --- a/internal/test/e2e/otelglobal/traces.json +++ b/internal/test/e2e/otelglobal/traces.json @@ -45,7 +45,8 @@ "scopeSpans": [ { "scope": { - "name": "trace-example" + "name": "trace-example", + "version": "v1.23.42" }, "spans": [ { diff --git a/internal/test/e2e/otelglobal/verify.bats b/internal/test/e2e/otelglobal/verify.bats index 067e8ab3e..4019245ab 100644 --- a/internal/test/e2e/otelglobal/verify.bats +++ b/internal/test/e2e/otelglobal/verify.bats @@ -9,6 +9,11 @@ SCOPE="trace-example" assert_equal "$result" '"sample-app"' } +@test "go-auto :: include tracer version in scope" { + result=$(spans_received | jq ".scopeSpans[].scope.version") + assert_equal "$result" '"v1.23.42"' +} + @test "server :: valid int attribute" { result=$(span_attributes_for ${SCOPE} | jq "select(.key == \"int_key\").value.intValue") assert_equal "$result" '"42"' diff --git a/internal/tools/inspect/cmd/offsetgen/main.go b/internal/tools/inspect/cmd/offsetgen/main.go index eeb83a4c2..cb5a80499 100644 --- a/internal/tools/inspect/cmd/offsetgen/main.go +++ b/internal/tools/inspect/cmd/offsetgen/main.go @@ -172,6 +172,8 @@ func manifests() ([]inspect.Manifest, error) { StructFields: []structfield.ID{ structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracer", "delegate"), structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracer", "name"), + structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracer", "provider"), + structfield.NewID("go.opentelemetry.io/otel", "go.opentelemetry.io/otel/internal/global", "tracerProvider", "tracers"), }, }, { From 72d445790fb4d7a83a46eab53022a76bf472ed1a Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sat, 6 Jul 2024 00:07:18 +0300 Subject: [PATCH 3/9] Support v1.28 of otel-go, taking into account different tracer key size. Including the schemaURL in newer versions. --- internal/pkg/inject/offset_results.json | 9 +- .../otel/traceglobal/bpf/probe.bpf.c | 95 +++++++++++++++++-- .../otel/traceglobal/probe.go | 22 +++++ internal/test/e2e/otelglobal/go.mod | 8 +- internal/test/e2e/otelglobal/go.sum | 16 ++-- internal/test/e2e/otelglobal/main.go | 6 +- internal/test/e2e/otelglobal/traces.json | 1 + internal/test/e2e/otelglobal/verify.bats | 5 + 8 files changed, 137 insertions(+), 25 deletions(-) diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index 87e5a37a5..12848e16c 100644 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -1030,7 +1030,8 @@ "1.24.0", "1.25.0", "1.26.0", - "1.27.0" + "1.27.0", + "1.28.0" ] } ] @@ -1123,7 +1124,8 @@ "1.24.0", "1.25.0", "1.26.0", - "1.27.0" + "1.27.0", + "1.28.0" ] } ] @@ -1221,7 +1223,8 @@ "1.24.0", "1.25.0", "1.26.0", - "1.27.0" + "1.27.0", + "1.28.0" ] } ] diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c index 2ce5d5528..f87df53dd 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c @@ -59,16 +59,22 @@ struct otel_span_t { tracer_id_t tracer_id; }; -typedef struct go_tracer_id { +typedef struct go_tracer_id_partial { struct go_string name; struct go_string version; - // struct go_string schema_url; -} go_tracer_id_t; +} go_tracer_id_partial_t; + +typedef struct go_tracer_id_full { + struct go_string name; + struct go_string version; + struct go_string schema_url; +} go_tracer_id_full_t; typedef void* go_tracer_ptr; // tracerProvider contains a map of tracers -MAP_BUCKET_DEFINITION(go_tracer_id_t, go_tracer_ptr) +MAP_BUCKET_DEFINITION(go_tracer_id_partial_t, go_tracer_ptr) +MAP_BUCKET_DEFINITION(go_tracer_id_full_t, go_tracer_ptr) struct { __uint(type, BPF_MAP_TYPE_HASH); @@ -103,7 +109,7 @@ struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr))); + __uint(value_size, sizeof(MAP_BUCKET_TYPE(go_tracer_id_full_t, go_tracer_ptr))); __uint(max_entries, 1); } golang_mapbucket_storage_map SEC(".maps"); @@ -136,6 +142,8 @@ volatile const u64 tracer_provider_pos; volatile const u64 tracer_provider_tracers_pos; volatile const u64 buckets_ptr_pos; +volatile const bool tracer_id_contains_schemaURL; + // read_span_name reads the span name from the provided span_name_ptr and stores the result in // span_name.buf. static __always_inline void read_span_name(struct span_name_t *span_name, const u64 span_name_len, void *span_name_ptr) { @@ -143,7 +151,7 @@ static __always_inline void read_span_name(struct span_name_t *span_name, const bpf_probe_read(span_name->buf, span_name_size, span_name_ptr); } -static __always_inline long fill_tracer_id_from_tracers_map(void *tracers_map, go_tracer_ptr tracer, tracer_id_t *tracer_id) { +static __always_inline long fill_partial_tracer_id_from_tracers_map(void *tracers_map, go_tracer_ptr tracer, tracer_id_t *tracer_id) { u64 tracers_count = 0; long res = 0; res = bpf_probe_read(&tracers_count, sizeof(tracers_count), tracers_map); @@ -169,7 +177,7 @@ static __always_inline long fill_tracer_id_from_tracers_map(void *tracers_map, g return -1; } u32 map_id = 0; - MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr) *map_bucket = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id); + MAP_BUCKET_TYPE(go_tracer_id_partial_t, go_tracer_ptr) *map_bucket = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id); if (!map_bucket) { return -1; @@ -181,7 +189,7 @@ static __always_inline long fill_tracer_id_from_tracers_map(void *tracers_map, g { break; } - res = bpf_probe_read(map_bucket, sizeof(MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr)), buckets_array + (j * sizeof(MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr)))); + res = bpf_probe_read(map_bucket, sizeof(MAP_BUCKET_TYPE(go_tracer_id_partial_t, go_tracer_ptr)), buckets_array + (j * sizeof(MAP_BUCKET_TYPE(go_tracer_id_partial_t, go_tracer_ptr)))); if (res < 0) { continue; @@ -207,6 +215,71 @@ static __always_inline long fill_tracer_id_from_tracers_map(void *tracers_map, g return 0; } +static __always_inline long fill_full_tracer_id_from_tracers_map(void *tracers_map, go_tracer_ptr tracer, tracer_id_t *tracer_id) { + u64 tracers_count = 0; + long res = 0; + res = bpf_probe_read(&tracers_count, sizeof(tracers_count), tracers_map); + if (res < 0) + { + return -1; + } + if (tracers_count == 0) + { + return -1; + } + unsigned char log_2_bucket_count; + res = bpf_probe_read(&log_2_bucket_count, sizeof(log_2_bucket_count), tracers_map + 9); + if (res < 0) + { + return -1; + } + u64 bucket_count = 1 << log_2_bucket_count; + void *buckets_array; + res = bpf_probe_read(&buckets_array, sizeof(buckets_array), (void*)(tracers_map + buckets_ptr_pos)); + if (res < 0) + { + return -1; + } + u32 map_id = 0; + MAP_BUCKET_TYPE(go_tracer_id_full_t, go_tracer_ptr) *map_bucket = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id); + if (!map_bucket) + { + return -1; + } + + for (u64 j = 0; j < MAX_BUCKETS; j++) + { + if (j >= bucket_count) + { + break; + } + res = bpf_probe_read(map_bucket, sizeof(MAP_BUCKET_TYPE(go_tracer_id_full_t, go_tracer_ptr)), buckets_array + (j * sizeof(MAP_BUCKET_TYPE(go_tracer_id_full_t, go_tracer_ptr)))); + if (res < 0) + { + continue; + } + for (u64 i = 0; i < 8; i++) + { + if (map_bucket->tophash[i] == 0) + { + continue; + } + if (map_bucket->values[i] == NULL) + { + continue; + } + if (map_bucket->values[i] != tracer) + { + continue; + } + get_go_string_from_user_ptr(&map_bucket->keys[i].version, tracer_id->version, MAX_TRACER_VERSION_LEN); + get_go_string_from_user_ptr(&map_bucket->keys[i].schema_url, tracer_id->schema_url, MAX_TRACER_SCHEMA_URL_LEN); + return 0; + } + } + return 0; +} + static __always_inline long fill_tracer_id(tracer_id_t *tracer_id, go_tracer_ptr tracer) { // Check if the tracer id is already cached tracer_id_t *cached_tracer_id = bpf_map_lookup_elem(&tracer_ptr_to_id_map, &tracer); @@ -232,7 +305,11 @@ static __always_inline long fill_tracer_id(tracer_id_t *tracer_id, go_tracer_ptr return res; } - res = fill_tracer_id_from_tracers_map(tracers_map, tracer, tracer_id); + if (tracer_id_contains_schemaURL) { + res = fill_full_tracer_id_from_tracers_map(tracers_map, tracer, tracer_id); + } else { + res = fill_partial_tracer_id_from_tracers_map(tracers_map, tracer, tracer_id); + } if (res < 0) { return res; } diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go index 2b0258d1a..bcc0d07b7 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go @@ -16,12 +16,16 @@ package global import ( "encoding/binary" + "fmt" "math" + "go.opentelemetry.io/auto/internal/pkg/inject" "go.opentelemetry.io/auto/internal/pkg/instrumentation/probe" + "go.opentelemetry.io/auto/internal/pkg/process" "go.opentelemetry.io/auto/internal/pkg/structfield" "github.com/go-logr/logr" + "github.com/hashicorp/go-version" "golang.org/x/sys/unix" "go.opentelemetry.io/otel/attribute" @@ -106,6 +110,7 @@ func New(logger logr.Logger) probe.Probe { Key: "buckets_ptr_pos", Val: structfield.NewID("std", "runtime", "hmap", "buckets"), }, + tracerIDContainsSchemaURL{}, }, Uprobes: []probe.Uprobe{ { @@ -138,6 +143,23 @@ func New(logger logr.Logger) probe.Probe { } } +// framePosConst is a Probe Const defining whether the tracer key contains schemaURL. +type tracerIDContainsSchemaURL struct{} + +// Prior to v1.28 the tracer key did not contain schemaURL. However, in that version a +// change was made to include it. +// https://github.com/open-telemetry/opentelemetry-go/pull/5426/files +var paramChangeVer = version.Must(version.NewVersion("1.28.0")) + +func (c tracerIDContainsSchemaURL) InjectOption(td *process.TargetDetails) (inject.Option, error) { + ver, ok := td.Libraries["go.opentelemetry.io/otel"] + if !ok { + return nil, fmt.Errorf("unknown module version: %s", pkg) + } + + return inject.WithKeyValue("tracer_id_contains_schemaURL", ver.GreaterThanOrEqual(paramChangeVer)), nil +} + type attributeKeyVal struct { ValLength uint16 Vtype uint8 diff --git a/internal/test/e2e/otelglobal/go.mod b/internal/test/e2e/otelglobal/go.mod index 5b6ba4a52..28f44fd27 100644 --- a/internal/test/e2e/otelglobal/go.mod +++ b/internal/test/e2e/otelglobal/go.mod @@ -3,12 +3,12 @@ module go.opentelemetry.io/auto/internal/test/e2e/otelglobal go 1.22.0 require ( - go.opentelemetry.io/otel v1.27.0 - go.opentelemetry.io/otel/trace v1.27.0 + go.opentelemetry.io/otel v1.28.0 + go.opentelemetry.io/otel/trace v1.28.0 ) require ( - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect ) diff --git a/internal/test/e2e/otelglobal/go.sum b/internal/test/e2e/otelglobal/go.sum index e2c497f85..8a31c6a1b 100644 --- a/internal/test/e2e/otelglobal/go.sum +++ b/internal/test/e2e/otelglobal/go.sum @@ -1,8 +1,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -11,11 +11,11 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= -go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= -go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= -go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/test/e2e/otelglobal/main.go b/internal/test/e2e/otelglobal/main.go index 8ecfc2a74..4a3ca4dc9 100644 --- a/internal/test/e2e/otelglobal/main.go +++ b/internal/test/e2e/otelglobal/main.go @@ -24,7 +24,11 @@ import ( "go.opentelemetry.io/otel/trace" ) -var tracer = otel.Tracer("trace-example", trace.WithInstrumentationVersion("v1.23.42")) +var tracer = otel.Tracer( + "trace-example", + trace.WithInstrumentationVersion("v1.23.42"), + trace.WithSchemaURL("https://some_shcema"), +) func innerFunction(ctx context.Context) { _, span := tracer.Start(ctx, "child") diff --git a/internal/test/e2e/otelglobal/traces.json b/internal/test/e2e/otelglobal/traces.json index 172954450..44a443405 100644 --- a/internal/test/e2e/otelglobal/traces.json +++ b/internal/test/e2e/otelglobal/traces.json @@ -50,6 +50,7 @@ "schemaUrl": "https://opentelemetry.io/schemas/1.22.0", "scopeSpans": [ { + "schemaUrl": "https://some_shcema", "scope": { "name": "trace-example", "version": "v1.23.42" diff --git a/internal/test/e2e/otelglobal/verify.bats b/internal/test/e2e/otelglobal/verify.bats index 4019245ab..88a703360 100644 --- a/internal/test/e2e/otelglobal/verify.bats +++ b/internal/test/e2e/otelglobal/verify.bats @@ -14,6 +14,11 @@ SCOPE="trace-example" assert_equal "$result" '"v1.23.42"' } +@test "go-auto :: include schema url" { + result=$(spans_received | jq ".scopeSpans[].schemaUrl") + assert_equal "$result" '"https://some_shcema"' +} + @test "server :: valid int attribute" { result=$(span_attributes_for ${SCOPE} | jq "select(.key == \"int_key\").value.intValue") assert_equal "$result" '"42"' From 2d04a934b3a1cd1e9067220149738dcfcaa20487 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sat, 6 Jul 2024 00:11:16 +0300 Subject: [PATCH 4/9] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db18f5f82..74d684c41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http - Support `google.golang.org/grpc` `1.63.3`. ([#916](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/916)) - Support `google.golang.org/grpc` `1.64.1`. ([#916](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/916)) - Support `golang.org/x/net` `v0.27.0`. ([#917](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/917)) +- The `otelglobal` probe now collects the user provided tracer name, version and schemaURL. ([#844](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/844)) ### Fixed From 4c0b974929c0c501767bd3ec598dc74dba71d61c Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 10 Jul 2024 10:53:15 +0300 Subject: [PATCH 5/9] precommit and fix buckets offset --- examples/kafka-go/consumer/go.mod | 2 +- examples/kafka-go/consumer/main.go | 3 ++- examples/kafka-go/go.mod | 17 ----------------- examples/kafka-go/producer/go.mod | 9 +-------- examples/kafka-go/producer/go.sum | 11 ----------- examples/kafka-go/producer/main.go | 4 ---- internal/pkg/opentelemetry/controller.go | 1 - 7 files changed, 4 insertions(+), 43 deletions(-) delete mode 100644 examples/kafka-go/go.mod diff --git a/examples/kafka-go/consumer/go.mod b/examples/kafka-go/consumer/go.mod index 923e551a1..2ccfa7feb 100644 --- a/examples/kafka-go/consumer/go.mod +++ b/examples/kafka-go/consumer/go.mod @@ -5,6 +5,7 @@ go 1.22.0 require ( github.com/segmentio/kafka-go v0.4.47 go.opentelemetry.io/otel v1.28.0 + go.opentelemetry.io/otel/trace v1.28.0 ) require ( @@ -13,5 +14,4 @@ require ( github.com/klauspost/compress v1.15.9 // indirect github.com/pierrec/lz4/v4 v4.1.15 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect ) diff --git a/examples/kafka-go/consumer/main.go b/examples/kafka-go/consumer/main.go index b67996b1a..cacab5eb9 100644 --- a/examples/kafka-go/consumer/main.go +++ b/examples/kafka-go/consumer/main.go @@ -25,9 +25,10 @@ import ( kafka "github.com/segmentio/kafka-go" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" ) -var tracer = otel.Tracer("trace-example") +var tracer = otel.Tracer("trace-example-kafka-go", trace.WithInstrumentationVersion("v1.0.0-test")) func getKafkaReader() *kafka.Reader { return kafka.NewReader(kafka.ReaderConfig{ diff --git a/examples/kafka-go/go.mod b/examples/kafka-go/go.mod deleted file mode 100644 index 76248e188..000000000 --- a/examples/kafka-go/go.mod +++ /dev/null @@ -1,17 +0,0 @@ -module go.opentelemetry.io/auto/examples/kafka-go - -go 1.22.0 - -require ( - github.com/segmentio/kafka-go v0.4.47 - go.opentelemetry.io/otel v1.27.0 - go.opentelemetry.io/otel/trace v1.27.0 -) - -require ( - github.com/go-logr/logr v1.4.1 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/klauspost/compress v1.15.9 // indirect - github.com/pierrec/lz4/v4 v4.1.15 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect -) diff --git a/examples/kafka-go/producer/go.mod b/examples/kafka-go/producer/go.mod index f2ec4be1e..e65a5ddad 100644 --- a/examples/kafka-go/producer/go.mod +++ b/examples/kafka-go/producer/go.mod @@ -4,16 +4,9 @@ go 1.22.0 require github.com/segmentio/kafka-go v0.4.47 -require ( - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect -) +require github.com/stretchr/testify v1.9.0 // indirect require ( github.com/klauspost/compress v1.15.9 // indirect github.com/pierrec/lz4/v4 v4.1.15 // indirect - github.com/stretchr/testify v1.9.0 // indirect - go.opentelemetry.io/otel v1.28.0 ) diff --git a/examples/kafka-go/producer/go.sum b/examples/kafka-go/producer/go.sum index 16d7af47f..69d3d500d 100644 --- a/examples/kafka-go/producer/go.sum +++ b/examples/kafka-go/producer/go.sum @@ -1,11 +1,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= @@ -27,12 +22,6 @@ github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3k github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= diff --git a/examples/kafka-go/producer/main.go b/examples/kafka-go/producer/main.go index e8a8a85a1..7bae20aca 100644 --- a/examples/kafka-go/producer/main.go +++ b/examples/kafka-go/producer/main.go @@ -12,12 +12,8 @@ import ( "time" kafka "github.com/segmentio/kafka-go" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/trace" ) -var tracer = otel.Tracer("trace-example-kafka-go", trace.WithInstrumentationVersion("v1.0.0-test")) - type server struct { kafkaWriter *kafka.Writer } diff --git a/internal/pkg/opentelemetry/controller.go b/internal/pkg/opentelemetry/controller.go index 04e391688..0c22df668 100644 --- a/internal/pkg/opentelemetry/controller.go +++ b/internal/pkg/opentelemetry/controller.go @@ -5,7 +5,6 @@ package opentelemetry import ( "context" - "fmt" "time" "github.com/go-logr/logr" From 2d6a50a201c2b4b71d4e4c88a20987e750384a30 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 12 Jul 2024 23:13:49 +0300 Subject: [PATCH 6/9] fill schema URL for each probe --- .../instrumentation/bpf/database/sql/probe.go | 1 + .../segmentio/kafka-go/consumer/probe.go | 1 + .../segmentio/kafka-go/producer/probe.go | 1 + .../google.golang.org/grpc/client/probe.go | 1 + .../google.golang.org/grpc/server/probe.go | 1 + .../bpf/net/http/client/probe.go | 1 + .../bpf/net/http/server/probe.go | 1 + internal/pkg/opentelemetry/controller.go | 1 + internal/pkg/opentelemetry/controller_test.go | 59 +++++++++++++++++-- internal/test/e2e/databasesql/traces.json | 2 + internal/test/e2e/gin/traces.json | 1 + internal/test/e2e/grpc/traces.json | 1 + internal/test/e2e/kafka-go/traces.json | 2 + internal/test/e2e/nethttp/traces.json | 1 + internal/test/e2e/nethttp_custom/traces.json | 1 + 15 files changed, 69 insertions(+), 6 deletions(-) diff --git a/internal/pkg/instrumentation/bpf/database/sql/probe.go b/internal/pkg/instrumentation/bpf/database/sql/probe.go index 7c2c877a7..03a45f9b5 100644 --- a/internal/pkg/instrumentation/bpf/database/sql/probe.go +++ b/internal/pkg/instrumentation/bpf/database/sql/probe.go @@ -103,6 +103,7 @@ func convertEvent(e *event) []*probe.SpanEvent { semconv.DBQueryText(query), }, ParentSpanContext: pscPtr, + TracerSchema: semconv.SchemaURL, }, } } diff --git a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe.go b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe.go index f84caafd5..980e7509b 100644 --- a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe.go +++ b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe.go @@ -127,6 +127,7 @@ func convertEvent(e *event) []*probe.SpanEvent { SpanContext: &sc, ParentSpanContext: pscPtr, Attributes: attributes, + TracerSchema: semconv.SchemaURL, }, } } diff --git a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe.go b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe.go index a85b058be..863eed88a 100644 --- a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe.go +++ b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe.go @@ -143,6 +143,7 @@ func convertEvent(e *event) []*probe.SpanEvent { SpanContext: &sc, Attributes: msgAttrs, ParentSpanContext: pscPtr, + TracerSchema: semconv.SchemaURL, }) } diff --git a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/probe.go b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/probe.go index 6dac503c5..12bfeaba5 100644 --- a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/probe.go +++ b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/probe.go @@ -137,6 +137,7 @@ func convertEvent(e *event) []*probe.SpanEvent { Attributes: attrs, SpanContext: &sc, ParentSpanContext: pscPtr, + TracerSchema: semconv.SchemaURL, }, } } diff --git a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/probe.go b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/probe.go index 3792751ee..9264d125d 100644 --- a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/probe.go +++ b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/probe.go @@ -135,6 +135,7 @@ func convertEvent(e *event) []*probe.SpanEvent { }, ParentSpanContext: pscPtr, SpanContext: &sc, + TracerSchema: semconv.SchemaURL, }, } } diff --git a/internal/pkg/instrumentation/bpf/net/http/client/probe.go b/internal/pkg/instrumentation/bpf/net/http/client/probe.go index 4faff0f1a..f7eb679e7 100644 --- a/internal/pkg/instrumentation/bpf/net/http/client/probe.go +++ b/internal/pkg/instrumentation/bpf/net/http/client/probe.go @@ -279,6 +279,7 @@ func convertEvent(e *event) []*probe.SpanEvent { SpanContext: &sc, Attributes: attrs, ParentSpanContext: pscPtr, + TracerSchema: semconv.SchemaURL, } if int(e.StatusCode) >= 400 && int(e.StatusCode) < 600 { diff --git a/internal/pkg/instrumentation/bpf/net/http/server/probe.go b/internal/pkg/instrumentation/bpf/net/http/server/probe.go index a91063ebc..3996aa770 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/probe.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/probe.go @@ -216,6 +216,7 @@ func convertEvent(e *event) []*probe.SpanEvent { SpanContext: &sc, ParentSpanContext: pscPtr, Attributes: attributes, + TracerSchema: semconv.SchemaURL, } if int(e.StatusCode) >= 500 && int(e.StatusCode) < 600 { diff --git a/internal/pkg/opentelemetry/controller.go b/internal/pkg/opentelemetry/controller.go index 0c22df668..9d0788f38 100644 --- a/internal/pkg/opentelemetry/controller.go +++ b/internal/pkg/opentelemetry/controller.go @@ -44,6 +44,7 @@ func (c *Controller) getTracer(pkg, tracerName, version, schema string) trace.Tr newTracer = c.tracerProvider.Tracer( "go.opentelemetry.io/auto/"+pkg, trace.WithInstrumentationVersion(c.version), + trace.WithSchemaURL(schema), ) } diff --git a/internal/pkg/opentelemetry/controller_test.go b/internal/pkg/opentelemetry/controller_test.go index 517b9f82d..ce8ae2206 100644 --- a/internal/pkg/opentelemetry/controller_test.go +++ b/internal/pkg/opentelemetry/controller_test.go @@ -101,10 +101,11 @@ func TestTrace(t *testing.T) { Kind: trace.SpanKindClient, SpanEvents: []*probe.SpanEvent{ { - SpanName: "testSpan", - StartTime: startTime.Unix(), - EndTime: endTime.Unix(), - SpanContext: &spanContext, + SpanName: "testSpan", + StartTime: startTime.Unix(), + EndTime: endTime.Unix(), + SpanContext: &spanContext, + TracerSchema: semconv.SchemaURL, }, }, }, @@ -116,8 +117,9 @@ func TestTrace(t *testing.T) { EndTime: convertedEndTime, Resource: instResource(), InstrumentationLibrary: instrumentation.Library{ - Name: "go.opentelemetry.io/auto/foo/bar", - Version: "test", + Name: "go.opentelemetry.io/auto/foo/bar", + Version: "test", + SchemaURL: semconv.SchemaURL, }, }, }, @@ -208,6 +210,51 @@ func TestTrace(t *testing.T) { }, }, }, + { + name: "otelglobal", + event: &probe.Event{ + Kind: trace.SpanKindClient, + SpanEvents: []*probe.SpanEvent{ + { + SpanName: "very important span", + StartTime: startTime.Unix(), + EndTime: endTime.Unix(), + SpanContext: &spanContext, + Attributes: []attribute.KeyValue{ + attribute.Int64("int.value", 42), + attribute.String("string.value", "hello"), + attribute.Float64("float.value", 3.14), + attribute.Bool("bool.value", true), + }, + Status: probe.Status{Code: codes.Error, Description: "error description"}, + TracerName: "user-tracer", + TracerVersion: "v1", + TracerSchema: "user-schema", + }, + }, + }, + expected: tracetest.SpanStubs{ + { + Name: "very important span", + SpanKind: trace.SpanKindClient, + StartTime: convertedStartTime, + EndTime: convertedEndTime, + Resource: instResource(), + InstrumentationLibrary: instrumentation.Library{ + Name: "user-tracer", + Version: "v1", + SchemaURL: "user-schema", + }, + Attributes: []attribute.KeyValue{ + attribute.Int64("int.value", 42), + attribute.String("string.value", "hello"), + attribute.Float64("float.value", 3.14), + attribute.Bool("bool.value", true), + }, + Status: sdktrace.Status{Code: codes.Error, Description: "error description"}, + }, + }, + }, } for _, tt := range testCases { diff --git a/internal/test/e2e/databasesql/traces.json b/internal/test/e2e/databasesql/traces.json index 36168b9d2..2c81f0304 100644 --- a/internal/test/e2e/databasesql/traces.json +++ b/internal/test/e2e/databasesql/traces.json @@ -50,6 +50,7 @@ "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scopeSpans": [ { + "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scope": { "name": "go.opentelemetry.io/auto/database/sql", "version": "v0.13.0-alpha" @@ -75,6 +76,7 @@ ] }, { + "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scope": { "name": "go.opentelemetry.io/auto/net/http", "version": "v0.13.0-alpha" diff --git a/internal/test/e2e/gin/traces.json b/internal/test/e2e/gin/traces.json index 78a7834c8..b83a347b0 100644 --- a/internal/test/e2e/gin/traces.json +++ b/internal/test/e2e/gin/traces.json @@ -50,6 +50,7 @@ "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scopeSpans": [ { + "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scope": { "name": "go.opentelemetry.io/auto/net/http", "version": "v0.13.0-alpha" diff --git a/internal/test/e2e/grpc/traces.json b/internal/test/e2e/grpc/traces.json index 3c50fd4d1..f5d5a595a 100644 --- a/internal/test/e2e/grpc/traces.json +++ b/internal/test/e2e/grpc/traces.json @@ -50,6 +50,7 @@ "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scopeSpans": [ { + "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scope": { "name": "go.opentelemetry.io/auto/google.golang.org/grpc", "version": "v0.13.0-alpha" diff --git a/internal/test/e2e/kafka-go/traces.json b/internal/test/e2e/kafka-go/traces.json index 5b7253f9a..ce52aff20 100644 --- a/internal/test/e2e/kafka-go/traces.json +++ b/internal/test/e2e/kafka-go/traces.json @@ -50,6 +50,7 @@ "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scopeSpans": [ { + "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scope": { "name": "go.opentelemetry.io/auto/github.com/segmentio/kafka-go", "version": "v0.13.0-alpha" @@ -191,6 +192,7 @@ "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scopeSpans": [ { + "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scope": { "name": "go.opentelemetry.io/auto/github.com/segmentio/kafka-go", "version": "v0.13.0-alpha" diff --git a/internal/test/e2e/nethttp/traces.json b/internal/test/e2e/nethttp/traces.json index 4ecb71016..1f1908939 100644 --- a/internal/test/e2e/nethttp/traces.json +++ b/internal/test/e2e/nethttp/traces.json @@ -50,6 +50,7 @@ "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scopeSpans": [ { + "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scope": { "name": "go.opentelemetry.io/auto/net/http", "version": "v0.13.0-alpha" diff --git a/internal/test/e2e/nethttp_custom/traces.json b/internal/test/e2e/nethttp_custom/traces.json index 2d20834c4..58c2b2ac6 100644 --- a/internal/test/e2e/nethttp_custom/traces.json +++ b/internal/test/e2e/nethttp_custom/traces.json @@ -50,6 +50,7 @@ "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scopeSpans": [ { + "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scope": { "name": "go.opentelemetry.io/auto/net/http", "version": "v0.13.0-alpha" From 7594c209741b633ac73b68618fe4011916c23b23 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 12 Jul 2024 23:30:27 +0300 Subject: [PATCH 7/9] update tests to contains schemaURL --- .../instrumentation/bpf/database/sql/probe_test.go | 1 + .../segmentio/kafka-go/consumer/probe_test.go | 1 + .../segmentio/kafka-go/producer/probe_test.go | 2 ++ .../otel/traceglobal/probe_test.go | 11 +++++++++++ .../instrumentation/bpf/net/http/client/probe_test.go | 10 ++++++++-- .../instrumentation/bpf/net/http/server/probe_test.go | 6 +++++- 6 files changed, 28 insertions(+), 3 deletions(-) diff --git a/internal/pkg/instrumentation/bpf/database/sql/probe_test.go b/internal/pkg/instrumentation/bpf/database/sql/probe_test.go index 5ed9d8e18..57a2cdb98 100644 --- a/internal/pkg/instrumentation/bpf/database/sql/probe_test.go +++ b/internal/pkg/instrumentation/bpf/database/sql/probe_test.go @@ -47,6 +47,7 @@ func TestProbeConvertEvent(t *testing.T) { Attributes: []attribute.KeyValue{ semconv.DBQueryText("SELECT * FROM foo"), }, + TracerSchema: semconv.SchemaURL, } assert.Equal(t, want, got[0]) } diff --git a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe_test.go b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe_test.go index 38e3cb84d..30f5d4cfc 100644 --- a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe_test.go +++ b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe_test.go @@ -59,6 +59,7 @@ func TestProbeConvertEvent(t *testing.T) { semconv.MessagingKafkaMessageKey("key1"), semconv.MessagingKafkaConsumerGroup("test consumer group"), }, + TracerSchema: semconv.SchemaURL, } assert.Equal(t, want, got[0]) } diff --git a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe_test.go b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe_test.go index 957baa40f..45d1623cc 100644 --- a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe_test.go +++ b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe_test.go @@ -73,6 +73,7 @@ func TestProbeConvertEvent(t *testing.T) { semconv.MessagingOperationTypePublish, semconv.MessagingBatchMessageCount(2), }, + TracerSchema: semconv.SchemaURL, } want2 := &probe.SpanEvent{ @@ -87,6 +88,7 @@ func TestProbeConvertEvent(t *testing.T) { semconv.MessagingOperationTypePublish, semconv.MessagingBatchMessageCount(2), }, + TracerSchema: semconv.SchemaURL, } assert.Equal(t, want1, got[0]) assert.Equal(t, want2, got[1]) diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe_test.go b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe_test.go index 01e03619c..a6be025c2 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe_test.go +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe_test.go @@ -87,6 +87,14 @@ func TestProbeConvertEvent(t *testing.T) { }, ValidAttrs: 5, }, + TracerID: tracerID{ + // "user-tracer" + Name: [128]byte{0x75, 0x73, 0x65, 0x72, 0x2d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72}, + // "v1" + Version: [32]byte{0x76, 0x31}, + // "user-schema" + SchemaURL: [128]byte{0x75, 0x73, 0x65, 0x72, 0x2d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61}, + }, }) sc := trace.NewSpanContext(trace.SpanContextConfig{ @@ -106,6 +114,9 @@ func TestProbeConvertEvent(t *testing.T) { attribute.Int64("int_key", 42), attribute.String("string_key2", "string value 2"), }, + TracerName: "user-tracer", + TracerVersion: "v1", + TracerSchema: "user-schema", } assert.Equal(t, want, got[0]) } diff --git a/internal/pkg/instrumentation/bpf/net/http/client/probe_test.go b/internal/pkg/instrumentation/bpf/net/http/client/probe_test.go index 0a7dc3630..9369b62c6 100644 --- a/internal/pkg/instrumentation/bpf/net/http/client/probe_test.go +++ b/internal/pkg/instrumentation/bpf/net/http/client/probe_test.go @@ -106,6 +106,7 @@ func TestConvertEvent(t *testing.T) { semconv.ServerAddress(hostString), semconv.NetworkProtocolVersion("1.1"), }, + TracerSchema: semconv.SchemaURL, }, }, }, @@ -138,7 +139,8 @@ func TestConvertEvent(t *testing.T) { semconv.ServerAddress(hostString), semconv.NetworkProtocolVersion("1.1"), }, - Status: probe.Status{Code: codes.Error}, + Status: probe.Status{Code: codes.Error}, + TracerSchema: semconv.SchemaURL, }, }, }, @@ -171,7 +173,8 @@ func TestConvertEvent(t *testing.T) { semconv.ServerAddress(hostString), semconv.NetworkProtocolVersion("1.1"), }, - Status: probe.Status{Code: codes.Error}, + Status: probe.Status{Code: codes.Error}, + TracerSchema: semconv.SchemaURL, }, }, }, @@ -205,6 +208,7 @@ func TestConvertEvent(t *testing.T) { semconv.NetworkProtocolName("foo"), semconv.NetworkProtocolVersion("2.2"), }, + TracerSchema: semconv.SchemaURL, }, }, }, @@ -240,6 +244,7 @@ func TestConvertEvent(t *testing.T) { semconv.ServerAddress(hostString), semconv.NetworkProtocolVersion("1.1"), }, + TracerSchema: semconv.SchemaURL, }, }, }, @@ -275,6 +280,7 @@ func TestConvertEvent(t *testing.T) { semconv.URLFull("http:/home?"), semconv.NetworkProtocolVersion("1.1"), }, + TracerSchema: semconv.SchemaURL, }, }, }, diff --git a/internal/pkg/instrumentation/bpf/net/http/server/probe_test.go b/internal/pkg/instrumentation/bpf/net/http/server/probe_test.go index 18a3c0ab1..bcf50e338 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/probe_test.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/probe_test.go @@ -71,6 +71,7 @@ func TestProbeConvertEvent(t *testing.T) { semconv.ServerPort(8080), semconv.NetworkProtocolVersion("1.1"), }, + TracerSchema: semconv.SchemaURL, }, }, }, @@ -111,6 +112,7 @@ func TestProbeConvertEvent(t *testing.T) { semconv.NetworkProtocolName("FOO"), semconv.NetworkProtocolVersion("2.2"), }, + TracerSchema: semconv.SchemaURL, }, }, }, @@ -150,6 +152,7 @@ func TestProbeConvertEvent(t *testing.T) { semconv.ServerPort(8080), semconv.NetworkProtocolVersion("1.1"), }, + TracerSchema: semconv.SchemaURL, }, }, }, @@ -189,7 +192,8 @@ func TestProbeConvertEvent(t *testing.T) { semconv.ServerPort(8080), semconv.NetworkProtocolVersion("1.1"), }, - Status: probe.Status{Code: codes.Error}, + Status: probe.Status{Code: codes.Error}, + TracerSchema: semconv.SchemaURL, }, }, }, From 707f84aaacb6b3bf1119c351ab605742927291c4 Mon Sep 17 00:00:00 2001 From: Ron Federman <73110295+RonFed@users.noreply.github.com> Date: Fri, 12 Jul 2024 23:38:38 +0300 Subject: [PATCH 8/9] Apply suggestions from code review Co-authored-by: Tyler Yahn --- internal/pkg/opentelemetry/controller.go | 1 + internal/test/e2e/otelglobal/main.go | 2 +- internal/test/e2e/otelglobal/traces.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/pkg/opentelemetry/controller.go b/internal/pkg/opentelemetry/controller.go index 9d0788f38..66bf53b90 100644 --- a/internal/pkg/opentelemetry/controller.go +++ b/internal/pkg/opentelemetry/controller.go @@ -26,6 +26,7 @@ type Controller struct { type tracerID struct{ name, version, schema string } func (c *Controller) getTracer(pkg, tracerName, version, schema string) trace.Tracer { + // Default Tracer ID, if the user does not provide one. tID := tracerID{name: pkg, version: c.version} if tracerName != "" { tID = tracerID{name: tracerName, version: version, schema: schema} diff --git a/internal/test/e2e/otelglobal/main.go b/internal/test/e2e/otelglobal/main.go index af9a59a6d..58e79af7f 100644 --- a/internal/test/e2e/otelglobal/main.go +++ b/internal/test/e2e/otelglobal/main.go @@ -16,7 +16,7 @@ import ( var tracer = otel.Tracer( "trace-example", trace.WithInstrumentationVersion("v1.23.42"), - trace.WithSchemaURL("https://some_shcema"), + trace.WithSchemaURL("https://some_schema"), ) func innerFunction(ctx context.Context) { diff --git a/internal/test/e2e/otelglobal/traces.json b/internal/test/e2e/otelglobal/traces.json index 4c7bd28d7..89f272c08 100644 --- a/internal/test/e2e/otelglobal/traces.json +++ b/internal/test/e2e/otelglobal/traces.json @@ -50,7 +50,7 @@ "schemaUrl": "https://opentelemetry.io/schemas/1.26.0", "scopeSpans": [ { - "schemaUrl": "https://some_shcema", + "schemaUrl": "https://some_schema", "scope": { "name": "trace-example", "version": "v1.23.42" From a92df1d09de16d6eed626ae546598a557222f647 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 12 Jul 2024 23:41:51 +0300 Subject: [PATCH 9/9] update verify.bats --- internal/test/e2e/otelglobal/verify.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/test/e2e/otelglobal/verify.bats b/internal/test/e2e/otelglobal/verify.bats index 88a703360..54332ed8f 100644 --- a/internal/test/e2e/otelglobal/verify.bats +++ b/internal/test/e2e/otelglobal/verify.bats @@ -16,7 +16,7 @@ SCOPE="trace-example" @test "go-auto :: include schema url" { result=$(spans_received | jq ".scopeSpans[].schemaUrl") - assert_equal "$result" '"https://some_shcema"' + assert_equal "$result" '"https://some_schema"' } @test "server :: valid int attribute" {