From 33463396bb6898f0a68dd06df0f1dc298f24ce4c Mon Sep 17 00:00:00 2001 From: Ron Federman <73110295+RonFed@users.noreply.github.com> Date: Fri, 7 Jun 2024 20:35:43 +0300 Subject: [PATCH] Initial support for Trace-flags (#868) * Initial support for Trace-flags in ebpf * remove dependabot changes * Add padding in go struct * Use get_root_span in http client when required * add changelog entry --------- Co-authored-by: Tyler Yahn --- CHANGELOG.md | 1 + internal/include/span_context.h | 47 ++++++++-- internal/include/utils.h | 4 - .../bpf/database/sql/bpf_arm64_bpfel.go | 6 +- .../bpf/database/sql/bpf_x86_bpfel.go | 6 +- .../kafka-go/consumer/bpf_arm64_bpfel.go | 6 +- .../kafka-go/consumer/bpf_x86_bpfel.go | 6 +- .../kafka-go/producer/bpf_arm64_bpfel.go | 6 +- .../kafka-go/producer/bpf_x86_bpfel.go | 6 +- .../otel/traceglobal/bpf_arm64_bpfel.go | 6 +- .../otel/traceglobal/bpf_x86_bpfel.go | 6 +- .../grpc/client/bpf_arm64_bpfel.go | 6 +- .../grpc/client/bpf_x86_bpfel.go | 6 +- .../grpc/server/bpf_arm64_bpfel.go | 6 +- .../grpc/server/bpf_x86_bpfel.go | 6 +- .../bpf/net/http/client/bpf/probe.bpf.c | 2 +- .../bpf/net/http/client/bpf_arm64_bpfel.go | 6 +- .../net/http/client/bpf_no_tp_arm64_bpfel.go | 6 +- .../net/http/client/bpf_no_tp_x86_bpfel.go | 6 +- .../bpf/net/http/client/bpf_x86_bpfel.go | 6 +- .../bpf/net/http/server/bpf/probe.bpf.c | 85 ++++++++----------- .../bpf/net/http/server/bpf_arm64_bpfel.go | 53 ++++++------ .../bpf/net/http/server/bpf_x86_bpfel.go | 53 ++++++------ .../bpf/net/http/server/probe.go | 4 +- .../instrumentation/context/span_context.go | 6 +- 25 files changed, 201 insertions(+), 150 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a95cdd21..02022c8aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http ### Added +- Initial support for `trace-flags`. ([#868](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/868)) - Support `google.golang.org/grpc` `1.66.0-dev`. ([#872](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/872)) ## [v0.13.0-alpha] - 2024-06-04 diff --git a/internal/include/span_context.h b/internal/include/span_context.h index c43bd0bcd..f4087b193 100644 --- a/internal/include/span_context.h +++ b/internal/include/span_context.h @@ -20,13 +20,40 @@ #define SPAN_CONTEXT_STRING_SIZE 55 #define W3C_KEY_LENGTH 11 // length of the "traceparent" key #define W3C_VAL_LENGTH 55 +#define TRACE_ID_SIZE 16 +#define TRACE_ID_STRING_SIZE 32 +#define SPAN_ID_SIZE 8 +#define SPAN_ID_STRING_SIZE 16 +#define TRACE_FLAGS_SIZE 1 +#define TRACE_FLAGS_STRING_SIZE 2 + +static const u8 FLAG_SAMPLED = 1; struct span_context { - unsigned char TraceID[TRACE_ID_SIZE]; - unsigned char SpanID[SPAN_ID_SIZE]; + u8 TraceID[TRACE_ID_SIZE]; + u8 SpanID[SPAN_ID_SIZE]; + u8 TraceFlags; + u8 padding[7]; }; +// Fill the child span context based on the parent span context, +// generating a new span id and copying the trace id and trace flags +static __always_inline void get_span_context_from_parent(struct span_context *parent, struct span_context *child) { + copy_byte_arrays(parent->TraceID, child->TraceID, TRACE_ID_SIZE); + generate_random_bytes(child->SpanID, SPAN_ID_SIZE); + child->TraceFlags = parent->TraceFlags; +} + +// Fill the passed span context as root span context +static __always_inline void get_root_span_context(struct span_context *sc) { + generate_random_bytes(sc->TraceID, TRACE_ID_SIZE); + generate_random_bytes(sc->SpanID, SPAN_ID_SIZE); + // currently we always sample + sc->TraceFlags = FLAG_SAMPLED; +} + +// TODO: remove this function once all the probes move to the above functions static __always_inline struct span_context generate_span_context() { struct span_context context = {}; @@ -55,17 +82,23 @@ static __always_inline void span_context_to_w3c_string(struct span_context *ctx, out += SPAN_ID_STRING_SIZE; *out++ = '-'; - // Write sampled - *out++ = '0'; - *out = '1'; + // Write trace flags + bytes_to_hex_string(&ctx->TraceFlags, TRACE_FLAGS_SIZE, out); } static __always_inline void w3c_string_to_span_context(char *str, struct span_context *ctx) { u32 trace_id_start_pos = 3; - u32 span_id_start_pod = 36; + u32 span_id_start_pos = 36; + u32 trace_flags_start_pos = 53; hex_string_to_bytes(str + trace_id_start_pos, TRACE_ID_STRING_SIZE, ctx->TraceID); - hex_string_to_bytes(str + span_id_start_pod, SPAN_ID_STRING_SIZE, ctx->SpanID); + hex_string_to_bytes(str + span_id_start_pos, SPAN_ID_STRING_SIZE, ctx->SpanID); + hex_string_to_bytes(str + trace_flags_start_pos, TRACE_FLAGS_STRING_SIZE, &ctx->TraceFlags); +} + +static __always_inline bool is_sampled(struct span_context *ctx) +{ + return ((ctx->TraceFlags & FLAG_SAMPLED) == FLAG_SAMPLED); } #endif diff --git a/internal/include/utils.h b/internal/include/utils.h index 3a1a7d3aa..6cf372b77 100644 --- a/internal/include/utils.h +++ b/internal/include/utils.h @@ -17,10 +17,6 @@ #include "bpf_helpers.h" -#define TRACE_ID_SIZE 16 -#define TRACE_ID_STRING_SIZE 32 -#define SPAN_ID_SIZE 8 -#define SPAN_ID_STRING_SIZE 16 static __always_inline bool bpf_memcmp(char *s1, char *s2, s32 size) { diff --git a/internal/pkg/instrumentation/bpf/database/sql/bpf_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/database/sql/bpf_arm64_bpfel.go index f41b85538..c658f5c9b 100644 --- a/internal/pkg/instrumentation/bpf/database/sql/bpf_arm64_bpfel.go +++ b/internal/pkg/instrumentation/bpf/database/sql/bpf_arm64_bpfel.go @@ -15,8 +15,10 @@ import ( type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } type bpfSqlRequestT struct { diff --git a/internal/pkg/instrumentation/bpf/database/sql/bpf_x86_bpfel.go b/internal/pkg/instrumentation/bpf/database/sql/bpf_x86_bpfel.go index ccef220f6..f6367d501 100644 --- a/internal/pkg/instrumentation/bpf/database/sql/bpf_x86_bpfel.go +++ b/internal/pkg/instrumentation/bpf/database/sql/bpf_x86_bpfel.go @@ -15,8 +15,10 @@ import ( type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } type bpfSqlRequestT struct { diff --git a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/bpf_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/bpf_arm64_bpfel.go index e8a7d26b1..74ed30cc5 100644 --- a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/bpf_arm64_bpfel.go +++ b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/bpf_arm64_bpfel.go @@ -27,8 +27,10 @@ type bpfKafkaRequestT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf returns the embedded CollectionSpec for bpf. diff --git a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/bpf_x86_bpfel.go b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/bpf_x86_bpfel.go index 4437531d8..401c19594 100644 --- a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/bpf_x86_bpfel.go +++ b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/bpf_x86_bpfel.go @@ -27,8 +27,10 @@ type bpfKafkaRequestT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf returns the embedded CollectionSpec for bpf. diff --git a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/bpf_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/bpf_arm64_bpfel.go index 5cb73fdf5..f2b3eef5b 100644 --- a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/bpf_arm64_bpfel.go +++ b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/bpf_arm64_bpfel.go @@ -29,8 +29,10 @@ type bpfKafkaRequestT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf returns the embedded CollectionSpec for bpf. diff --git a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/bpf_x86_bpfel.go b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/bpf_x86_bpfel.go index 159d1c09a..71f83ba96 100644 --- a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/bpf_x86_bpfel.go +++ b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/bpf_x86_bpfel.go @@ -29,8 +29,10 @@ type bpfKafkaRequestT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf returns the embedded CollectionSpec for bpf. 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..f36e9c00a 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 @@ -38,8 +38,10 @@ type bpfOtelSpanT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } type bpfSpanNameT struct{ Buf [64]int8 } 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..34026c226 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 @@ -38,8 +38,10 @@ type bpfOtelSpanT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } type bpfSpanNameT struct{ Buf [64]int8 } diff --git a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/bpf_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/bpf_arm64_bpfel.go index caf70e9c4..fc7189230 100644 --- a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/bpf_arm64_bpfel.go +++ b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/bpf_arm64_bpfel.go @@ -25,8 +25,10 @@ type bpfGrpcRequestT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf returns the embedded CollectionSpec for bpf. diff --git a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/bpf_x86_bpfel.go b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/bpf_x86_bpfel.go index 6d57daf33..38f8d74ba 100644 --- a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/bpf_x86_bpfel.go +++ b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/bpf_x86_bpfel.go @@ -25,8 +25,10 @@ type bpfGrpcRequestT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf returns the embedded CollectionSpec for bpf. diff --git a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/bpf_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/bpf_arm64_bpfel.go index eee00da9b..71c75fa73 100644 --- a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/bpf_arm64_bpfel.go +++ b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/bpf_arm64_bpfel.go @@ -24,8 +24,10 @@ type bpfGrpcRequestT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf returns the embedded CollectionSpec for bpf. diff --git a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/bpf_x86_bpfel.go b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/bpf_x86_bpfel.go index 3f7905abd..8d4332805 100644 --- a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/bpf_x86_bpfel.go +++ b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/bpf_x86_bpfel.go @@ -24,8 +24,10 @@ type bpfGrpcRequestT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf returns the embedded CollectionSpec for bpf. 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..92789e1b8 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 @@ -131,7 +131,7 @@ int uprobe_Transport_roundTrip(struct pt_regs *ctx) { copy_byte_arrays(httpReq->psc.TraceID, httpReq->sc.TraceID, TRACE_ID_SIZE); generate_random_bytes(httpReq->sc.SpanID, SPAN_ID_SIZE); } else { - httpReq->sc = generate_span_context(); + get_root_span_context(&httpReq->sc); } if (!get_go_string_from_user_ptr((void *)(req_ptr+method_ptr_pos), httpReq->method, sizeof(httpReq->method))) { 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..62d6e7c2b 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 @@ -37,8 +37,10 @@ type bpfHttpRequestT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf returns the embedded CollectionSpec for bpf. 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..06294fada 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 @@ -37,8 +37,10 @@ type bpf_no_tpHttpRequestT struct { type bpf_no_tpSliceArrayBuff struct{ Buff [1024]uint8 } type bpf_no_tpSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf_no_tp returns the embedded CollectionSpec for bpf_no_tp. 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..9157b67fd 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 @@ -37,8 +37,10 @@ type bpf_no_tpHttpRequestT struct { type bpf_no_tpSliceArrayBuff struct{ Buff [1024]uint8 } type bpf_no_tpSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf_no_tp returns the embedded CollectionSpec for bpf_no_tp. 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..206215330 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 @@ -37,8 +37,10 @@ type bpfHttpRequestT struct { type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } // loadBpf returns the embedded CollectionSpec for bpf. 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..35390da10 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 @@ -65,14 +65,6 @@ struct __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(struct span_context)); - __uint(max_entries, 1); -} parent_span_context_storage_map SEC(".maps"); - struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); @@ -105,43 +97,46 @@ volatile const bool pattern_path_supported; volatile const u64 req_pat_pos; volatile const u64 pat_str_pos; -static __always_inline struct span_context *extract_context_from_req_headers(void *headers_ptr_ptr) +// Extracts the span context from the request headers by looking for the 'traceparent' header. +// Fills the parent_span_context with the extracted span context. +// Returns 0 on success, negative value on error. +static __always_inline long extract_context_from_req_headers(void *headers_ptr_ptr, struct span_context *parent_span_context) { void *headers_ptr; long res; res = bpf_probe_read(&headers_ptr, sizeof(headers_ptr), headers_ptr_ptr); if (res < 0) { - return NULL; + return res; } u64 headers_count = 0; res = bpf_probe_read(&headers_count, sizeof(headers_count), headers_ptr); if (res < 0) { - return NULL; + return res; } if (headers_count == 0) { - return NULL; + return -1; } unsigned char log_2_bucket_count; res = bpf_probe_read(&log_2_bucket_count, sizeof(log_2_bucket_count), headers_ptr + 9); if (res < 0) { - return NULL; + return -1; } u64 bucket_count = 1 << log_2_bucket_count; void *header_buckets; res = bpf_probe_read(&header_buckets, sizeof(header_buckets), (void*)(headers_ptr + buckets_ptr_pos)); if (res < 0) { - return NULL; + return -1; } u32 map_id = 0; struct map_bucket *map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id); if (!map_value) { - return NULL; + return -1; } for (u64 j = 0; j < MAX_BUCKETS; j++) @@ -176,7 +171,7 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi res = bpf_probe_read(&traceparent_header_value_go_str, sizeof(traceparent_header_value_go_str), traceparent_header_value_ptr); if (res < 0) { - return NULL; + return -1; } if (traceparent_header_value_go_str.len != W3C_VAL_LENGTH) { @@ -186,24 +181,26 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi res = bpf_probe_read(&traceparent_header_value, sizeof(traceparent_header_value), traceparent_header_value_go_str.str); if (res < 0) { - return NULL; - } - struct span_context *parent_span_context = bpf_map_lookup_elem(&parent_span_context_storage_map, &map_id); - if (!parent_span_context) - { - return NULL; + return res; } w3c_string_to_span_context(traceparent_header_value, parent_span_context); - return parent_span_context; + return 0; } } - return NULL; + return -1; +} + +static __always_inline void read_go_string(void *base, int offset, char *output, int maxLen, const char *errorMsg) { + void *ptr = (void *)(base + offset); + if (!get_go_string_from_user_ptr(ptr, output, maxLen)) { + bpf_printk("Failed to get %s", errorMsg); + } } // This instrumentation attaches uprobe to the following function: // func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) -SEC("uprobe/HandlerFunc_ServeHTTP") -int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) +SEC("uprobe/serverHandler_ServeHTTP") +int uprobe_serverHandler_ServeHTTP(struct pt_regs *ctx) { void *req_ctx_ptr = get_Go_context(ctx, 4, ctx_ptr_pos, false); void *key = get_consistent_key(ctx, req_ctx_ptr); @@ -233,17 +230,11 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) // Propagate context void *req_ptr = get_argument(ctx, 4); - struct span_context *parent_ctx = extract_context_from_req_headers((void*)(req_ptr + headers_ptr_pos)); - if (parent_ctx != NULL) - { - // found parent context in http headers - http_server_span->psc = *parent_ctx; - copy_byte_arrays(http_server_span->psc.TraceID, http_server_span->sc.TraceID, TRACE_ID_SIZE); - generate_random_bytes(http_server_span->sc.SpanID, SPAN_ID_SIZE); - } - else - { - http_server_span->sc = generate_span_context(); + long res = extract_context_from_req_headers((void*)(req_ptr + headers_ptr_pos), &http_server_span->psc); + if (res < 0) { + get_root_span_context(&http_server_span->sc); + } else { + get_span_context_from_parent(&http_server_span->psc, &http_server_span->sc); } if (req_ctx_ptr == NULL) @@ -257,18 +248,10 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) return 0; } -void read_go_string(void *base, int offset, char *output, int maxLen, const char *errorMsg) { - void *ptr = (void *)(base + offset); - if (!get_go_string_from_user_ptr(ptr, output, maxLen)) { - bpf_printk("Failed to get %s", errorMsg); - } - -} - // This instrumentation attaches uprobe to the following function: // func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) -SEC("uprobe/HandlerFunc_ServeHTTP") -int uprobe_HandlerFunc_ServeHTTP_Returns(struct pt_regs *ctx) { +SEC("uprobe/serverHandler_ServeHTTP") +int uprobe_serverHandler_ServeHTTP_Returns(struct pt_regs *ctx) { u64 end_time = bpf_ktime_get_ns(); void *req_ctx_ptr = get_Go_context(ctx, 4, ctx_ptr_pos, false); void *key = get_consistent_key(ctx, req_ctx_ptr); @@ -278,9 +261,12 @@ int uprobe_HandlerFunc_ServeHTTP_Returns(struct pt_regs *ctx) { bpf_printk("uprobe/HandlerFunc_ServeHTTP_Returns: entry_state is NULL"); return 0; } - bpf_map_delete_elem(&http_server_uprobes, &key); struct http_server_span_t *http_server_span = &uprobe_data->span; + if (!is_sampled(&http_server_span->sc)) { + goto done; + } + void *resp_ptr = (void *)uprobe_data->resp_ptr; void *req_ptr = NULL; bpf_probe_read(&req_ptr, sizeof(req_ptr), (void *)(resp_ptr + req_ptr_pos)); @@ -307,6 +293,9 @@ int uprobe_HandlerFunc_ServeHTTP_Returns(struct pt_regs *ctx) { bpf_probe_read(&http_server_span->status_code, sizeof(http_server_span->status_code), (void *)(resp_ptr + status_code_pos)); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, http_server_span, sizeof(*http_server_span)); + +done: stop_tracking_span(&http_server_span->sc, &http_server_span->psc); + bpf_map_delete_elem(&http_server_uprobes, &key); return 0; } \ No newline at end of file diff --git a/internal/pkg/instrumentation/bpf/net/http/server/bpf_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/net/http/server/bpf_arm64_bpfel.go index 52859e5ff..1a9d0b7c4 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/bpf_arm64_bpfel.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/bpf_arm64_bpfel.go @@ -15,8 +15,10 @@ import ( type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } type bpfUprobeDataT struct { @@ -77,23 +79,22 @@ type bpfSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfProgramSpecs struct { - UprobeHandlerFuncServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_HandlerFunc_ServeHTTP"` - UprobeHandlerFuncServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_HandlerFunc_ServeHTTP_Returns"` + UprobeServerHandlerServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_serverHandler_ServeHTTP"` + UprobeServerHandlerServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_serverHandler_ServeHTTP_Returns"` } // bpfMapSpecs contains maps before they are loaded into the kernel. // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` - HttpServerUprobeStorageMap *ebpf.MapSpec `ebpf:"http_server_uprobe_storage_map"` - HttpServerUprobes *ebpf.MapSpec `ebpf:"http_server_uprobes"` - ParentSpanContextStorageMap *ebpf.MapSpec `ebpf:"parent_span_context_storage_map"` - SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_map"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + Events *ebpf.MapSpec `ebpf:"events"` + GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` + HttpServerUprobeStorageMap *ebpf.MapSpec `ebpf:"http_server_uprobe_storage_map"` + HttpServerUprobes *ebpf.MapSpec `ebpf:"http_server_uprobes"` + SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_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. @@ -115,15 +116,14 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` - HttpServerUprobeStorageMap *ebpf.Map `ebpf:"http_server_uprobe_storage_map"` - HttpServerUprobes *ebpf.Map `ebpf:"http_server_uprobes"` - ParentSpanContextStorageMap *ebpf.Map `ebpf:"parent_span_context_storage_map"` - SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` + AllocMap *ebpf.Map `ebpf:"alloc_map"` + Events *ebpf.Map `ebpf:"events"` + GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` + HttpServerUprobeStorageMap *ebpf.Map `ebpf:"http_server_uprobe_storage_map"` + HttpServerUprobes *ebpf.Map `ebpf:"http_server_uprobes"` + SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { @@ -133,7 +133,6 @@ func (m *bpfMaps) Close() error { m.GolangMapbucketStorageMap, m.HttpServerUprobeStorageMap, m.HttpServerUprobes, - m.ParentSpanContextStorageMap, m.SliceArrayBuffMap, m.TrackedSpans, m.TrackedSpansBySc, @@ -144,14 +143,14 @@ func (m *bpfMaps) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfPrograms struct { - UprobeHandlerFuncServeHTTP *ebpf.Program `ebpf:"uprobe_HandlerFunc_ServeHTTP"` - UprobeHandlerFuncServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_HandlerFunc_ServeHTTP_Returns"` + UprobeServerHandlerServeHTTP *ebpf.Program `ebpf:"uprobe_serverHandler_ServeHTTP"` + UprobeServerHandlerServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_serverHandler_ServeHTTP_Returns"` } func (p *bpfPrograms) Close() error { return _BpfClose( - p.UprobeHandlerFuncServeHTTP, - p.UprobeHandlerFuncServeHTTP_Returns, + p.UprobeServerHandlerServeHTTP, + p.UprobeServerHandlerServeHTTP_Returns, ) } diff --git a/internal/pkg/instrumentation/bpf/net/http/server/bpf_x86_bpfel.go b/internal/pkg/instrumentation/bpf/net/http/server/bpf_x86_bpfel.go index 2aa3aa2cd..0b5937d2c 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/bpf_x86_bpfel.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/bpf_x86_bpfel.go @@ -15,8 +15,10 @@ import ( type bpfSliceArrayBuff struct{ Buff [1024]uint8 } type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 } type bpfUprobeDataT struct { @@ -77,23 +79,22 @@ type bpfSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfProgramSpecs struct { - UprobeHandlerFuncServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_HandlerFunc_ServeHTTP"` - UprobeHandlerFuncServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_HandlerFunc_ServeHTTP_Returns"` + UprobeServerHandlerServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_serverHandler_ServeHTTP"` + UprobeServerHandlerServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_serverHandler_ServeHTTP_Returns"` } // bpfMapSpecs contains maps before they are loaded into the kernel. // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` - HttpServerUprobeStorageMap *ebpf.MapSpec `ebpf:"http_server_uprobe_storage_map"` - HttpServerUprobes *ebpf.MapSpec `ebpf:"http_server_uprobes"` - ParentSpanContextStorageMap *ebpf.MapSpec `ebpf:"parent_span_context_storage_map"` - SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_map"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + Events *ebpf.MapSpec `ebpf:"events"` + GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` + HttpServerUprobeStorageMap *ebpf.MapSpec `ebpf:"http_server_uprobe_storage_map"` + HttpServerUprobes *ebpf.MapSpec `ebpf:"http_server_uprobes"` + SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_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. @@ -115,15 +116,14 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` - HttpServerUprobeStorageMap *ebpf.Map `ebpf:"http_server_uprobe_storage_map"` - HttpServerUprobes *ebpf.Map `ebpf:"http_server_uprobes"` - ParentSpanContextStorageMap *ebpf.Map `ebpf:"parent_span_context_storage_map"` - SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` + AllocMap *ebpf.Map `ebpf:"alloc_map"` + Events *ebpf.Map `ebpf:"events"` + GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` + HttpServerUprobeStorageMap *ebpf.Map `ebpf:"http_server_uprobe_storage_map"` + HttpServerUprobes *ebpf.Map `ebpf:"http_server_uprobes"` + SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { @@ -133,7 +133,6 @@ func (m *bpfMaps) Close() error { m.GolangMapbucketStorageMap, m.HttpServerUprobeStorageMap, m.HttpServerUprobes, - m.ParentSpanContextStorageMap, m.SliceArrayBuffMap, m.TrackedSpans, m.TrackedSpansBySc, @@ -144,14 +143,14 @@ func (m *bpfMaps) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfPrograms struct { - UprobeHandlerFuncServeHTTP *ebpf.Program `ebpf:"uprobe_HandlerFunc_ServeHTTP"` - UprobeHandlerFuncServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_HandlerFunc_ServeHTTP_Returns"` + UprobeServerHandlerServeHTTP *ebpf.Program `ebpf:"uprobe_serverHandler_ServeHTTP"` + UprobeServerHandlerServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_serverHandler_ServeHTTP_Returns"` } func (p *bpfPrograms) Close() error { return _BpfClose( - p.UprobeHandlerFuncServeHTTP, - p.UprobeHandlerFuncServeHTTP_Returns, + p.UprobeServerHandlerServeHTTP, + p.UprobeServerHandlerServeHTTP_Returns, ) } diff --git a/internal/pkg/instrumentation/bpf/net/http/server/probe.go b/internal/pkg/instrumentation/bpf/net/http/server/probe.go index 8ad5dd5b9..dba1a0208 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/probe.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/probe.go @@ -148,7 +148,7 @@ func uprobeServeHTTP(name string, exec *link.Executable, target *process.TargetD } opts := &link.UprobeOptions{Address: offset, PID: target.PID} - l, err := exec.Uprobe("", obj.UprobeHandlerFuncServeHTTP, opts) + l, err := exec.Uprobe("", obj.UprobeServerHandlerServeHTTP, opts) if err != nil { return nil, err } @@ -161,7 +161,7 @@ func uprobeServeHTTP(name string, exec *link.Executable, target *process.TargetD for _, ret := range retOffsets { opts := &link.UprobeOptions{Address: ret} - l, err := exec.Uprobe("", obj.UprobeHandlerFuncServeHTTP_Returns, opts) + l, err := exec.Uprobe("", obj.UprobeServerHandlerServeHTTP_Returns, opts) if err != nil { return nil, err } diff --git a/internal/pkg/instrumentation/context/span_context.go b/internal/pkg/instrumentation/context/span_context.go index ab432f368..07a9a3880 100644 --- a/internal/pkg/instrumentation/context/span_context.go +++ b/internal/pkg/instrumentation/context/span_context.go @@ -27,6 +27,8 @@ type BaseSpanProperties struct { // EBPFSpanContext is the the span context representation within the eBPF // instrumentation system. type EBPFSpanContext struct { - TraceID trace.TraceID - SpanID trace.SpanID + TraceID trace.TraceID + SpanID trace.SpanID + TraceFlags trace.TraceFlags + _ [7]byte // padding }