diff --git a/CHANGELOG.md b/CHANGELOG.md index 39a90b553..553949090 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http ## [Unreleased] +### Fixed + +- Fix context propagation across different goroutines. ([#118](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/118)) + ## [v0.2.2-alpha] - 2023-07-12 ### Added diff --git a/include/arguments.h b/include/arguments.h index 8d5307b04..e05e689ee 100644 --- a/include/arguments.h +++ b/include/arguments.h @@ -64,12 +64,20 @@ void *get_argument(struct pt_regs *ctx, int index) return get_argument_by_stack(ctx, index); } -inline void *get_goroutine_address(struct pt_regs *ctx, int go_ctx_index) +// Every span created by the auto instrumentation should contain end timestamp. +// This end timestamp is recorded at the end of probed function by editing the struct that was created at the beginning. +// Usually instrumentors create an eBPF map to store the span struct and retrieve it at the end of the function. +// Consistent key is used as a key for that map. +// For Go < 1.17: consistent key is the address of context.Context. +// For Go >= 1.17: consistent key is the goroutine address. +static __always_inline void *get_consistent_key(struct pt_regs *ctx, void *contextContext) { if (is_registers_abi) { return (void *)GOROUTINE(ctx); } - return get_argument_by_stack(ctx, go_ctx_index); -} + void *ctx_ptr = 0; + bpf_probe_read(&ctx_ptr, sizeof(ctx_ptr), contextContext); + return ctx_ptr; +} \ No newline at end of file diff --git a/include/go_context.h b/include/go_context.h index 027498722..9c335efc1 100644 --- a/include/go_context.h +++ b/include/go_context.h @@ -16,18 +16,35 @@ #define MAX_DISTANCE 10 -static __always_inline void *find_context_in_map(void *ctx, void *context_map) +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, void *); + __type(value, struct span_context); + __uint(max_entries, MAX_CONCURRENT_SPANS); + __uint(pinning, LIBBPF_PIN_BY_NAME); +} tracked_spans SEC(".maps"); + +struct +{ + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, struct span_context); + __type(value, void *); + __uint(max_entries, MAX_CONCURRENT_SPANS); + __uint(pinning, LIBBPF_PIN_BY_NAME); +} tracked_spans_by_sc SEC(".maps"); + +static __always_inline void *get_parent_go_context(void *ctx, void *map) { void *data = ctx; for (int i = 0; i < MAX_DISTANCE; i++) { - void *found_in_map = bpf_map_lookup_elem(context_map, &data); + void *found_in_map = bpf_map_lookup_elem(map, &data); if (found_in_map != NULL) { return data; } - // We assume context.Context implementation containens Parent context.Context member + // We assume context.Context implementation contains Parent context.Context member // Since the parent is also an interface, we need to read the data part of it bpf_probe_read(&data, sizeof(data), data + 8); } @@ -35,3 +52,35 @@ static __always_inline void *find_context_in_map(void *ctx, void *context_map) bpf_printk("context %lx not found in context map", ctx); return NULL; } + +static __always_inline struct span_context *get_parent_span_context(void *ctx) { + void *parent_ctx = get_parent_go_context(ctx, &tracked_spans); + if (parent_ctx == NULL) + { + return NULL; + } + + struct span_context *parent_sc = bpf_map_lookup_elem(&tracked_spans, &parent_ctx); + if (parent_sc == NULL) + { + return NULL; + } + + return parent_sc; +} + +static __always_inline void start_tracking_span(void *ctx, struct span_context *sc) { + bpf_map_update_elem(&tracked_spans, &ctx, sc, BPF_ANY); + bpf_map_update_elem(&tracked_spans_by_sc, sc, &ctx, BPF_ANY); +} + +static __always_inline void stop_tracking_span(struct span_context *sc) { + void *ctx = bpf_map_lookup_elem(&tracked_spans_by_sc, sc); + if (ctx == NULL) + { + return; + } + + bpf_map_delete_elem(&tracked_spans, &ctx); + bpf_map_delete_elem(&tracked_spans_by_sc, sc); +} \ No newline at end of file diff --git a/include/span_context.h b/include/span_context.h index 571d29278..76ab69c88 100644 --- a/include/span_context.h +++ b/include/span_context.h @@ -23,15 +23,6 @@ struct span_context unsigned char SpanID[SPAN_ID_SIZE]; }; -struct -{ - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, void *); - __type(value, struct span_context); - __uint(max_entries, MAX_CONCURRENT_SPANS); - __uint(pinning, LIBBPF_PIN_BY_NAME); -} spans_in_progress SEC(".maps"); - static __always_inline struct span_context generate_span_context() { struct span_context context = {}; diff --git a/offsets-tracker/main.go b/offsets-tracker/main.go index 6240f5081..7c850a6cc 100644 --- a/offsets-tracker/main.go +++ b/offsets-tracker/main.go @@ -109,6 +109,18 @@ func main() { StructName: "golang.org/x/net/http2.FrameHeader", Field: "StreamID", }, + { + StructName: "google.golang.org/grpc/internal/transport.http2Client", + Field: "nextID", + }, + { + StructName: "google.golang.org/grpc/internal/transport.headerFrame", + Field: "streamID", + }, + { + StructName: "google.golang.org/grpc/internal/transport.headerFrame", + Field: "hf", + }, }) if err != nil { diff --git a/pkg/inject/offset_results.json b/pkg/inject/offset_results.json index 443a8e3c8..0ef0b42b0 100755 --- a/pkg/inject/offset_results.json +++ b/pkg/inject/offset_results.json @@ -100,6 +100,70 @@ ] } }, + "google.golang.org/grpc/internal/transport.headerFrame": { + "hf": { + "versions": { + "oldest": "1.3.0", + "newest": "1.58.0-dev" + }, + "offsets": [ + { + "offset": 8, + "since": "v1.3.0" + } + ] + }, + "streamID": { + "versions": { + "oldest": "1.3.0", + "newest": "1.58.0-dev" + }, + "offsets": [ + { + "offset": 0, + "since": "v1.3.0" + } + ] + } + }, + "google.golang.org/grpc/internal/transport.http2Client": { + "nextID": { + "versions": { + "oldest": "1.3.0", + "newest": "1.58.0-dev" + }, + "offsets": [ + { + "offset": 412, + "since": "v1.3.0" + }, + { + "offset": 356, + "since": "v1.15.0" + }, + { + "offset": 348, + "since": "v1.24.0" + }, + { + "offset": 340, + "since": "v1.35.0" + }, + { + "offset": 348, + "since": "v1.48.0" + }, + { + "offset": 340, + "since": "v1.51.0" + }, + { + "offset": 412, + "since": "v1.52.0" + } + ] + } + }, "net/http.Request": { "Header": { "versions": { diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c index a068fe450..7621cb5a1 100644 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c @@ -30,13 +30,12 @@ struct http_request_t { struct span_context sc; }; -// map key: pointer to the goroutine that handles the request struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, void *); __type(value, struct http_request_t); __uint(max_entries, MAX_CONCURRENT); -} context_to_http_events SEC(".maps"); +} http_events SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); @@ -79,25 +78,32 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { path_size = path_size < path_len ? path_size : path_len; bpf_probe_read(&httpReq.path, path_size, path_ptr); - // Get goroutine pointer - void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); + // Get key + void *req_ctx_ptr = 0; + bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), (void *)(req_ptr + ctx_ptr_pos)); + void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); // Write event httpReq.sc = generate_span_context(); - bpf_map_update_elem(&context_to_http_events, &goroutine, &httpReq, 0); - bpf_map_update_elem(&spans_in_progress, &goroutine, &httpReq.sc, 0); + bpf_map_update_elem(&http_events, &key, &httpReq, 0); + start_tracking_span(req_ctx_ptr, &httpReq.sc); return 0; } SEC("uprobe/GinEngine_ServeHTTP") int uprobe_GinEngine_ServeHTTP_Returns(struct pt_regs *ctx) { - void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); - void *httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &goroutine); + u64 request_pos = 4; + void *req_ptr = get_argument(ctx, request_pos); + + // Get key + void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); + + void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); struct http_request_t httpReq = {}; bpf_probe_read(&httpReq, sizeof(httpReq), httpReq_ptr); httpReq.end_time = bpf_ktime_get_ns(); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &httpReq, sizeof(httpReq)); - bpf_map_delete_elem(&context_to_http_events, &goroutine); - bpf_map_delete_elem(&spans_in_progress, &goroutine); + bpf_map_delete_elem(&http_events, &key); + stop_tracking_span(&httpReq.sc); return 0; } \ No newline at end of file diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go index de8a6a3a6..e1cf3a2c1 100644 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go +++ b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go @@ -75,9 +75,10 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` - Events *ebpf.MapSpec `ebpf:"events"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + Events *ebpf.MapSpec `ebpf:"events"` + HttpEvents *ebpf.MapSpec `ebpf:"http_events"` + 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. @@ -99,16 +100,18 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` - Events *ebpf.Map `ebpf:"events"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + Events *ebpf.Map `ebpf:"events"` + HttpEvents *ebpf.Map `ebpf:"http_events"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( - m.ContextToHttpEvents, m.Events, - m.SpansInProgress, + m.HttpEvents, + m.TrackedSpans, + m.TrackedSpansBySc, ) } diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go index 7628caae8..c8c80a0d4 100644 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go +++ b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go @@ -75,9 +75,10 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` - Events *ebpf.MapSpec `ebpf:"events"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + Events *ebpf.MapSpec `ebpf:"events"` + HttpEvents *ebpf.MapSpec `ebpf:"http_events"` + 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. @@ -99,16 +100,18 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` - Events *ebpf.Map `ebpf:"events"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + Events *ebpf.Map `ebpf:"events"` + HttpEvents *ebpf.Map `ebpf:"http_events"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( - m.ContextToHttpEvents, m.Events, - m.SpansInProgress, + m.HttpEvents, + m.TrackedSpans, + m.TrackedSpansBySc, ) } diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go index ffae3949a..85bcdeb2c 100644 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go +++ b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go @@ -99,6 +99,11 @@ func (h *Instrumentor) Load(ctx *context.InstrumentorContext) error { StructName: "net/url.URL", Field: "Path", }, + { + VarName: "ctx_ptr_pos", + StructName: "net/http.Request", + Field: "ctx", + }, }, false) if err != nil { diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c index e20865fe9..c05603a69 100644 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c @@ -30,13 +30,12 @@ struct http_request_t { struct span_context sc; }; -// map key: pointer to the goroutine that handles the request struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, void *); __type(value, struct http_request_t); __uint(max_entries, MAX_CONCURRENT); -} context_to_http_events SEC(".maps"); +} http_events SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); @@ -79,28 +78,32 @@ int uprobe_GorillaMux_ServeHTTP(struct pt_regs *ctx) { path_size = path_size < path_len ? path_size : path_len; bpf_probe_read(&httpReq.path, path_size, path_ptr); - // Get goroutine pointer - void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); + // Get key + void *req_ctx_ptr = 0; + bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), (void *)(req_ptr + ctx_ptr_pos)); + void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); // Write event httpReq.sc = generate_span_context(); - bpf_map_update_elem(&context_to_http_events, &goroutine, &httpReq, 0); - bpf_map_update_elem(&spans_in_progress, &goroutine, &httpReq.sc, 0); + bpf_map_update_elem(&http_events, &key, &httpReq, 0); + start_tracking_span(req_ctx_ptr, &httpReq.sc); return 0; } SEC("uprobe/GorillaMux_ServeHTTP") int uprobe_GorillaMux_ServeHTTP_Returns(struct pt_regs *ctx) { u64 request_pos = 4; - void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); void* req_ptr = get_argument(ctx, request_pos); - void* httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &goroutine); + // Get key + void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); + + void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); struct http_request_t httpReq = {}; bpf_probe_read(&httpReq, sizeof(httpReq), httpReq_ptr); httpReq.end_time = bpf_ktime_get_ns(); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &httpReq, sizeof(httpReq)); - bpf_map_delete_elem(&context_to_http_events, &goroutine); - bpf_map_delete_elem(&spans_in_progress, &goroutine); + bpf_map_delete_elem(&http_events, &key); + stop_tracking_span(&httpReq.sc); return 0; } \ No newline at end of file diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go index a7d8d8310..fc088a71d 100644 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go @@ -75,9 +75,10 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` - Events *ebpf.MapSpec `ebpf:"events"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + Events *ebpf.MapSpec `ebpf:"events"` + HttpEvents *ebpf.MapSpec `ebpf:"http_events"` + 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. @@ -99,16 +100,18 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` - Events *ebpf.Map `ebpf:"events"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + Events *ebpf.Map `ebpf:"events"` + HttpEvents *ebpf.Map `ebpf:"http_events"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( - m.ContextToHttpEvents, m.Events, - m.SpansInProgress, + m.HttpEvents, + m.TrackedSpans, + m.TrackedSpansBySc, ) } diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go index 81713dbff..7cb65a057 100644 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go @@ -75,9 +75,10 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` - Events *ebpf.MapSpec `ebpf:"events"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + Events *ebpf.MapSpec `ebpf:"events"` + HttpEvents *ebpf.MapSpec `ebpf:"http_events"` + 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. @@ -99,16 +100,18 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` - Events *ebpf.Map `ebpf:"events"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + Events *ebpf.Map `ebpf:"events"` + HttpEvents *ebpf.Map `ebpf:"http_events"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( - m.ContextToHttpEvents, m.Events, - m.SpansInProgress, + m.HttpEvents, + m.TrackedSpans, + m.TrackedSpansBySc, ) } diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c index e56880266..7fd38c103 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c @@ -46,7 +46,15 @@ struct __type(key, void *); __type(value, struct grpc_request_t); __uint(max_entries, MAX_CONCURRENT); -} context_to_grpc_events SEC(".maps"); +} grpc_events SEC(".maps"); + +struct +{ + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, u32); + __type(value, struct span_context); + __uint(max_entries, MAX_CONCURRENT); +} streamid_to_span_contexts SEC(".maps"); struct headers_buff { @@ -68,6 +76,9 @@ struct // Injected in init volatile const u64 clientconn_target_ptr_pos; +volatile const u64 httpclient_nextid_pos; +volatile const u64 headerFrame_streamid_pos; +volatile const u64 headerFrame_hf_pos; // This instrumentation attaches uprobe to the following function: // func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error @@ -100,9 +111,28 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) target_size = target_size < target_len ? target_size : target_len; bpf_probe_read(&grpcReq.target, target_size, target_ptr); - // Write event + // Get parent if exists void *context_ptr = get_argument(ctx, context_pos); - bpf_map_update_elem(&context_to_grpc_events, &context_ptr, &grpcReq, 0); + void *context_ptr_val = 0; + bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); + struct span_context *parent_span_ctx = get_parent_span_context(context_ptr_val); + if (parent_span_ctx != NULL) + { + bpf_probe_read(&grpcReq.psc, sizeof(grpcReq.psc), parent_span_ctx); + copy_byte_arrays(grpcReq.psc.TraceID, grpcReq.sc.TraceID, TRACE_ID_SIZE); + generate_random_bytes(grpcReq.sc.SpanID, SPAN_ID_SIZE); + } + else + { + grpcReq.sc = generate_span_context(); + } + + // Get key + void *key = get_consistent_key(ctx, context_ptr); + + // Write event + bpf_map_update_elem(&grpc_events, &key, &grpcReq, 0); + start_tracking_span(context_ptr_val, &grpcReq.sc); return 0; } @@ -111,84 +141,78 @@ int uprobe_ClientConn_Invoke_Returns(struct pt_regs *ctx) { u64 context_pos = 3; void *context_ptr = get_argument(ctx, context_pos); - void *grpcReq_ptr = bpf_map_lookup_elem(&context_to_grpc_events, &context_ptr); + void *key = get_consistent_key(ctx, context_ptr); + void *grpcReq_ptr = bpf_map_lookup_elem(&grpc_events, &key); struct grpc_request_t grpcReq = {}; bpf_probe_read(&grpcReq, sizeof(grpcReq), grpcReq_ptr); grpcReq.end_time = bpf_ktime_get_ns(); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &grpcReq, sizeof(grpcReq)); - bpf_map_delete_elem(&context_to_grpc_events, &context_ptr); - + bpf_map_delete_elem(&grpc_events, &key); + stop_tracking_span(&grpcReq.sc); return 0; } -// func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr) ([]hpack.HeaderField, error) -SEC("uprobe/Http2Client_createHeaderFields") -int uprobe_Http2Client_CreateHeaderFields(struct pt_regs *ctx) +// func (l *loopyWriter) headerHandler(h *headerFrame) error +SEC("uprobe/loopyWriter_headerHandler") +int uprobe_LoopyWriter_HeaderHandler(struct pt_regs *ctx) { - // Read slice - s32 context_pointer_pos = 3; - struct go_slice slice = {}; - struct go_slice_user_ptr slice_user_ptr = {}; - if (is_registers_abi) - { - slice.array = (void *)GO_PARAM1(ctx); - slice.len = (s32)GO_PARAM2(ctx); - slice.cap = (s32)GO_PARAM3(ctx); - slice_user_ptr.array = (void *)&GO_PARAM1(ctx); - slice_user_ptr.len = (void *)&GO_PARAM2(ctx); - slice_user_ptr.cap = (void *)&GO_PARAM3(ctx); - } - else + void *headerFrame_ptr = get_argument(ctx, 2); + u32 stream_id = 0; + bpf_probe_read(&stream_id, sizeof(stream_id), (void *)(headerFrame_ptr + (headerFrame_streamid_pos))); + void *sc_ptr = bpf_map_lookup_elem(&streamid_to_span_contexts, &stream_id); + if (sc_ptr == NULL) { - u64 slice_pointer_pos = 5; - s32 slice_len_pos = 6; - s32 slice_cap_pos = 7; - slice.array = get_argument(ctx, slice_pointer_pos); - slice.len = (long)get_argument(ctx, slice_len_pos); - slice.cap = (long)get_argument(ctx, slice_cap_pos); - slice_user_ptr.array = (void *)(PT_REGS_SP(ctx) + (slice_pointer_pos * 8)); - slice_user_ptr.len = (void *)(PT_REGS_SP(ctx) + (slice_len_pos * 8)); - slice_user_ptr.cap = (void *)(PT_REGS_SP(ctx) + (slice_cap_pos * 8)); + return 0; } - char key[11] = "traceparent"; - struct go_string key_str = write_user_go_string(key, sizeof(key)); + + bpf_map_delete_elem(&streamid_to_span_contexts, &stream_id); + struct go_slice slice = {}; + struct go_slice_user_ptr slice_user_ptr = {}; + slice_user_ptr.array = (void *)(headerFrame_ptr + (headerFrame_hf_pos)); + slice_user_ptr.len = (void *)(headerFrame_ptr + (headerFrame_hf_pos + 8)); + slice_user_ptr.cap = (void *)(headerFrame_ptr + (headerFrame_hf_pos + 16)); + bpf_probe_read(&slice.array, sizeof(slice.array), slice_user_ptr.array); + bpf_probe_read(&slice.len, sizeof(slice.len), slice_user_ptr.len); + bpf_probe_read(&slice.cap, sizeof(slice.cap), slice_user_ptr.cap); + + struct span_context current_span_context = {}; + bpf_probe_read(¤t_span_context, sizeof(current_span_context), sc_ptr); + + char tp_key[11] = "traceparent"; + struct go_string key_str = write_user_go_string(tp_key, sizeof(tp_key)); if (key_str.len == 0) { bpf_printk("write failed, aborting ebpf probe"); return 0; } - // Get grpc request struct - void *context_ptr = 0; - bpf_probe_read(&context_ptr, sizeof(context_ptr), (void *)(PT_REGS_SP(ctx) + (context_pointer_pos * 8))); - void *parent_ctx = find_context_in_map(context_ptr, &context_to_grpc_events); - void *grpcReq_ptr = bpf_map_lookup_elem(&context_to_grpc_events, &parent_ctx); - struct grpc_request_t grpcReq = {}; - bpf_probe_read(&grpcReq, sizeof(grpcReq), grpcReq_ptr); - - // Get parent if exists - void *parent_span_ctx = find_context_in_map(context_ptr, &spans_in_progress); - if (parent_span_ctx != NULL) - { - void *psc_ptr = bpf_map_lookup_elem(&spans_in_progress, &parent_span_ctx); - bpf_probe_read(&grpcReq.psc, sizeof(grpcReq.psc), psc_ptr); - copy_byte_arrays(grpcReq.psc.TraceID, grpcReq.sc.TraceID, TRACE_ID_SIZE); - generate_random_bytes(grpcReq.sc.SpanID, SPAN_ID_SIZE); - } - else - { - grpcReq.sc = generate_span_context(); - } - // Write headers char val[SPAN_CONTEXT_STRING_SIZE]; - span_context_to_w3c_string(&grpcReq.sc, val); + span_context_to_w3c_string(¤t_span_context, val); struct go_string val_str = write_user_go_string(val, sizeof(val)); struct hpack_header_field hf = {}; hf.name = key_str; hf.value = val_str; append_item_to_slice(&slice, &hf, sizeof(hf), &slice_user_ptr, &headers_buff_map); - bpf_map_update_elem(&context_to_grpc_events, &parent_ctx, &grpcReq, 0); + return 0; +} + +SEC("uprobe/http2Client_NewStream") +// func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error) +int uprobe_http2Client_NewStream(struct pt_regs *ctx) +{ + void *context_ptr = get_argument(ctx, 3); + void *context_ptr_val = 0; + bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); + + void *httpclient_ptr = get_argument(ctx, 1); + u32 nextid = 0; + bpf_probe_read(&nextid, sizeof(nextid), (void *)(httpclient_ptr + (httpclient_nextid_pos))); + + struct span_context *current_span_context = get_parent_span_context(context_ptr_val); + if (current_span_context != NULL) { + bpf_map_update_elem(&streamid_to_span_contexts, &nextid, current_span_context, 0); + } return 0; } \ No newline at end of file diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go index c69cba22f..4ad69dd42 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go @@ -70,20 +70,23 @@ type bpfSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfProgramSpecs struct { - UprobeClientConnInvoke *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke"` - UprobeClientConnInvokeReturns *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke_Returns"` - UprobeHttp2ClientCreateHeaderFields *ebpf.ProgramSpec `ebpf:"uprobe_Http2Client_CreateHeaderFields"` + UprobeClientConnInvoke *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke"` + UprobeClientConnInvokeReturns *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke_Returns"` + UprobeLoopyWriterHeaderHandler *ebpf.ProgramSpec `ebpf:"uprobe_LoopyWriter_HeaderHandler"` + UprobeHttp2ClientNewStream *ebpf.ProgramSpec `ebpf:"uprobe_http2Client_NewStream"` } // 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"` - ContextToGrpcEvents *ebpf.MapSpec `ebpf:"context_to_grpc_events"` - Events *ebpf.MapSpec `ebpf:"events"` - HeadersBuffMap *ebpf.MapSpec `ebpf:"headers_buff_map"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + Events *ebpf.MapSpec `ebpf:"events"` + GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` + HeadersBuffMap *ebpf.MapSpec `ebpf:"headers_buff_map"` + StreamidToSpanContexts *ebpf.MapSpec `ebpf:"streamid_to_span_contexts"` + 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. @@ -105,20 +108,24 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - ContextToGrpcEvents *ebpf.Map `ebpf:"context_to_grpc_events"` - Events *ebpf.Map `ebpf:"events"` - HeadersBuffMap *ebpf.Map `ebpf:"headers_buff_map"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + AllocMap *ebpf.Map `ebpf:"alloc_map"` + Events *ebpf.Map `ebpf:"events"` + GrpcEvents *ebpf.Map `ebpf:"grpc_events"` + HeadersBuffMap *ebpf.Map `ebpf:"headers_buff_map"` + StreamidToSpanContexts *ebpf.Map `ebpf:"streamid_to_span_contexts"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( m.AllocMap, - m.ContextToGrpcEvents, m.Events, + m.GrpcEvents, m.HeadersBuffMap, - m.SpansInProgress, + m.StreamidToSpanContexts, + m.TrackedSpans, + m.TrackedSpansBySc, ) } @@ -126,16 +133,18 @@ func (m *bpfMaps) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfPrograms struct { - UprobeClientConnInvoke *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke"` - UprobeClientConnInvokeReturns *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke_Returns"` - UprobeHttp2ClientCreateHeaderFields *ebpf.Program `ebpf:"uprobe_Http2Client_CreateHeaderFields"` + UprobeClientConnInvoke *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke"` + UprobeClientConnInvokeReturns *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke_Returns"` + UprobeLoopyWriterHeaderHandler *ebpf.Program `ebpf:"uprobe_LoopyWriter_HeaderHandler"` + UprobeHttp2ClientNewStream *ebpf.Program `ebpf:"uprobe_http2Client_NewStream"` } func (p *bpfPrograms) Close() error { return _BpfClose( p.UprobeClientConnInvoke, p.UprobeClientConnInvokeReturns, - p.UprobeHttp2ClientCreateHeaderFields, + p.UprobeLoopyWriterHeaderHandler, + p.UprobeHttp2ClientNewStream, ) } diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go index 7e72f0a43..9dc1ed357 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go @@ -70,20 +70,23 @@ type bpfSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfProgramSpecs struct { - UprobeClientConnInvoke *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke"` - UprobeClientConnInvokeReturns *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke_Returns"` - UprobeHttp2ClientCreateHeaderFields *ebpf.ProgramSpec `ebpf:"uprobe_Http2Client_CreateHeaderFields"` + UprobeClientConnInvoke *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke"` + UprobeClientConnInvokeReturns *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke_Returns"` + UprobeLoopyWriterHeaderHandler *ebpf.ProgramSpec `ebpf:"uprobe_LoopyWriter_HeaderHandler"` + UprobeHttp2ClientNewStream *ebpf.ProgramSpec `ebpf:"uprobe_http2Client_NewStream"` } // 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"` - ContextToGrpcEvents *ebpf.MapSpec `ebpf:"context_to_grpc_events"` - Events *ebpf.MapSpec `ebpf:"events"` - HeadersBuffMap *ebpf.MapSpec `ebpf:"headers_buff_map"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + Events *ebpf.MapSpec `ebpf:"events"` + GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` + HeadersBuffMap *ebpf.MapSpec `ebpf:"headers_buff_map"` + StreamidToSpanContexts *ebpf.MapSpec `ebpf:"streamid_to_span_contexts"` + 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. @@ -105,20 +108,24 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - ContextToGrpcEvents *ebpf.Map `ebpf:"context_to_grpc_events"` - Events *ebpf.Map `ebpf:"events"` - HeadersBuffMap *ebpf.Map `ebpf:"headers_buff_map"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + AllocMap *ebpf.Map `ebpf:"alloc_map"` + Events *ebpf.Map `ebpf:"events"` + GrpcEvents *ebpf.Map `ebpf:"grpc_events"` + HeadersBuffMap *ebpf.Map `ebpf:"headers_buff_map"` + StreamidToSpanContexts *ebpf.Map `ebpf:"streamid_to_span_contexts"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( m.AllocMap, - m.ContextToGrpcEvents, m.Events, + m.GrpcEvents, m.HeadersBuffMap, - m.SpansInProgress, + m.StreamidToSpanContexts, + m.TrackedSpans, + m.TrackedSpansBySc, ) } @@ -126,16 +133,18 @@ func (m *bpfMaps) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfPrograms struct { - UprobeClientConnInvoke *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke"` - UprobeClientConnInvokeReturns *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke_Returns"` - UprobeHttp2ClientCreateHeaderFields *ebpf.Program `ebpf:"uprobe_Http2Client_CreateHeaderFields"` + UprobeClientConnInvoke *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke"` + UprobeClientConnInvokeReturns *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke_Returns"` + UprobeLoopyWriterHeaderHandler *ebpf.Program `ebpf:"uprobe_LoopyWriter_HeaderHandler"` + UprobeHttp2ClientNewStream *ebpf.Program `ebpf:"uprobe_http2Client_NewStream"` } func (p *bpfPrograms) Close() error { return _BpfClose( p.UprobeClientConnInvoke, p.UprobeClientConnInvokeReturns, - p.UprobeHttp2ClientCreateHeaderFields, + p.UprobeLoopyWriterHeaderHandler, + p.UprobeHttp2ClientNewStream, ) } diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go index 3fbfeeb74..b0827e004 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go @@ -53,11 +53,9 @@ type Event struct { // Instrumentor is the gRPC client instrumentor. type Instrumentor struct { - bpfObjects *bpfObjects - uprobe link.Link - returnProbs []link.Link - writeHeadersProbe []link.Link - eventsReader *perf.Reader + bpfObjects *bpfObjects + uprobes []link.Link + eventsReader *perf.Reader } // New returns a new [Instrumentor]. @@ -74,7 +72,8 @@ func (g *Instrumentor) LibraryName() string { // instrumented. func (g *Instrumentor) FuncNames() []string { return []string{"google.golang.org/grpc.(*ClientConn).Invoke", - "google.golang.org/grpc/internal/transport.(*http2Client).createHeaderFields"} + "google.golang.org/grpc/internal/transport.(*http2Client).NewStream", + "google.golang.org/grpc/internal/transport.(*loopyWriter).headerHandler"} } // Load loads all instrumentation offsets. @@ -89,6 +88,21 @@ func (g *Instrumentor) Load(ctx *context.InstrumentorContext) error { StructName: "google.golang.org/grpc.ClientConn", Field: "target", }, + { + VarName: "httpclient_nextid_pos", + StructName: "google.golang.org/grpc/internal/transport.http2Client", + Field: "nextID", + }, + { + VarName: "headerFrame_hf_pos", + StructName: "google.golang.org/grpc/internal/transport.headerFrame", + Field: "hf", + }, + { + VarName: "headerFrame_streamid_pos", + StructName: "google.golang.org/grpc/internal/transport.headerFrame", + Field: "streamID", + }, }, true) if err != nil { @@ -118,7 +132,8 @@ func (g *Instrumentor) Load(ctx *context.InstrumentorContext) error { return err } - g.uprobe = up + g.uprobes = append(g.uprobes, up) + retOffsets, err := ctx.TargetDetails.GetFunctionReturns(g.FuncNames()[0]) if err != nil { return err @@ -131,31 +146,42 @@ func (g *Instrumentor) Load(ctx *context.InstrumentorContext) error { if err != nil { return err } - g.returnProbs = append(g.returnProbs, retProbe) + g.uprobes = append(g.uprobes, retProbe) } - rd, err := perf.NewReader(g.bpfObjects.Events, os.Getpagesize()) + // SendMsg probe + sendMsgOffset, err := ctx.TargetDetails.GetFunctionOffset(g.FuncNames()[1]) if err != nil { return err } - g.eventsReader = rd + sendMsgProbe, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeHttp2ClientNewStream, &link.UprobeOptions{ + Address: sendMsgOffset, + }) + if err != nil { + return err + } + g.uprobes = append(g.uprobes, sendMsgProbe) // Write headers probe - whOffsets, err := ctx.TargetDetails.GetFunctionReturns(g.FuncNames()[1]) + whOffset, err := ctx.TargetDetails.GetFunctionOffset(g.FuncNames()[2]) if err != nil { return err } - for _, whOffset := range whOffsets { - whProbe, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeHttp2ClientCreateHeaderFields, &link.UprobeOptions{ - Address: whOffset, - }) - if err != nil { - return err - } - g.writeHeadersProbe = append(g.writeHeadersProbe, whProbe) + whProbe, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeLoopyWriterHeaderHandler, &link.UprobeOptions{ + Address: whOffset, + }) + if err != nil { + return err } + g.uprobes = append(g.uprobes, whProbe) + + rd, err := perf.NewReader(g.bpfObjects.Events, os.Getpagesize()) + if err != nil { + return err + } + g.eventsReader = rd return nil } @@ -242,15 +268,7 @@ func (g *Instrumentor) Close() { g.eventsReader.Close() } - if g.uprobe != nil { - g.uprobe.Close() - } - - for _, r := range g.returnProbs { - r.Close() - } - - for _, r := range g.writeHeadersProbe { + for _, r := range g.uprobes { r.Close() } diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c index 424b7b53f..79e9d4c7c 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c @@ -15,6 +15,7 @@ #include "arguments.h" #include "go_types.h" #include "span_context.h" +#include "go_context.h" char __license[] SEC("license") = "Dual MIT/GPL"; @@ -40,7 +41,7 @@ struct __type(key, void *); __type(value, struct grpc_request_t); __uint(max_entries, MAX_CONCURRENT); -} context_to_grpc_events SEC(".maps"); +} grpc_events SEC(".maps"); struct { @@ -104,33 +105,32 @@ int uprobe_server_handleStream(struct pt_regs *ctx) method_size = method_size < method_len ? method_size : method_len; bpf_probe_read(&grpcReq.method, method_size, method_ptr); - // Write event + // Get key void *ctx_iface = 0; bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(stream_ptr + stream_ctx_pos)); - void *ctx_instance = 0; - bpf_probe_read(&ctx_instance, sizeof(ctx_instance), (void *)(ctx_iface + 8)); - bpf_map_update_elem(&context_to_grpc_events, &ctx_instance, &grpcReq, 0); - bpf_map_update_elem(&spans_in_progress, &ctx_instance, &grpcReq.sc, 0); + void *key = get_consistent_key(ctx, (void *)(stream_ptr + stream_ctx_pos)); + + // Write event + bpf_map_update_elem(&grpc_events, &key, &grpcReq, 0); + start_tracking_span(ctx_iface, &grpcReq.sc); return 0; } SEC("uprobe/server_handleStream") -int uprobe_server_handleStream_Returns(struct pt_regs *ctx) { +int uprobe_server_handleStream_Returns(struct pt_regs *ctx) +{ u64 stream_pos = 4; void *stream_ptr = get_argument(ctx, stream_pos); - void *ctx_iface = 0; - bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(stream_ptr + stream_ctx_pos)); - void *ctx_instance = 0; - bpf_probe_read(&ctx_instance, sizeof(ctx_instance), (void *)(ctx_iface + 8)); + void *key = get_consistent_key(ctx, (void *)(stream_ptr + stream_ctx_pos)); - void *grpcReq_ptr = bpf_map_lookup_elem(&context_to_grpc_events, &ctx_instance); + void *grpcReq_ptr = bpf_map_lookup_elem(&grpc_events, &key); struct grpc_request_t grpcReq = {}; bpf_probe_read(&grpcReq, sizeof(grpcReq), grpcReq_ptr); grpcReq.end_time = bpf_ktime_get_ns(); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &grpcReq, sizeof(grpcReq)); - bpf_map_delete_elem(&context_to_grpc_events, &ctx_instance); - bpf_map_delete_elem(&spans_in_progress, &ctx_instance); + bpf_map_delete_elem(&grpc_events, &key); + stop_tracking_span(&grpcReq.sc); return 0; } diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go index c8b6aca8a..5f076d284 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go @@ -77,10 +77,11 @@ type bpfProgramSpecs struct { // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - ContextToGrpcEvents *ebpf.MapSpec `ebpf:"context_to_grpc_events"` Events *ebpf.MapSpec `ebpf:"events"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` StreamidToGrpcEvents *ebpf.MapSpec `ebpf:"streamid_to_grpc_events"` + 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. @@ -103,19 +104,21 @@ func (o *bpfObjects) Close() error { // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { AllocMap *ebpf.Map `ebpf:"alloc_map"` - ContextToGrpcEvents *ebpf.Map `ebpf:"context_to_grpc_events"` Events *ebpf.Map `ebpf:"events"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + GrpcEvents *ebpf.Map `ebpf:"grpc_events"` StreamidToGrpcEvents *ebpf.Map `ebpf:"streamid_to_grpc_events"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( m.AllocMap, - m.ContextToGrpcEvents, m.Events, - m.SpansInProgress, + m.GrpcEvents, m.StreamidToGrpcEvents, + m.TrackedSpans, + m.TrackedSpansBySc, ) } diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go index 04e1f85f8..c92fefa63 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go @@ -77,10 +77,11 @@ type bpfProgramSpecs struct { // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - ContextToGrpcEvents *ebpf.MapSpec `ebpf:"context_to_grpc_events"` Events *ebpf.MapSpec `ebpf:"events"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` StreamidToGrpcEvents *ebpf.MapSpec `ebpf:"streamid_to_grpc_events"` + 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. @@ -103,19 +104,21 @@ func (o *bpfObjects) Close() error { // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { AllocMap *ebpf.Map `ebpf:"alloc_map"` - ContextToGrpcEvents *ebpf.Map `ebpf:"context_to_grpc_events"` Events *ebpf.Map `ebpf:"events"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + GrpcEvents *ebpf.Map `ebpf:"grpc_events"` StreamidToGrpcEvents *ebpf.Map `ebpf:"streamid_to_grpc_events"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( m.AllocMap, - m.ContextToGrpcEvents, m.Events, - m.SpansInProgress, + m.GrpcEvents, m.StreamidToGrpcEvents, + m.TrackedSpans, + m.TrackedSpansBySc, ) } diff --git a/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index 6cd09a2d5..3a5258d08 100644 --- a/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -25,7 +25,7 @@ struct { __type(key, void*); __type(value, struct http_request_t); __uint(max_entries, MAX_CONCURRENT); -} context_to_http_events SEC(".maps"); +} http_events SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); @@ -34,7 +34,6 @@ struct { __uint(max_entries, 1); } golang_mapbucket_storage_map SEC(".maps"); - struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); } events SEC(".maps"); @@ -54,8 +53,10 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context // Currently only maps with less than 8 keys are supported for injection if (map_keyvalue_count >= 8) { + bpf_printk("Map size is bigger than 8, skipping context propagation"); return 0; } + long res; if (map_keyvalue_count == 0) { u32 map_id = 0; @@ -67,22 +68,21 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context res = bpf_probe_write_user(headers_ptr + 16, &bucket_ptr, sizeof(bucket_ptr)); if(res < 0) { + bpf_printk("Failed to write bucket ptr, return code: %d", res); return -1; } } void *map_keyvalues_ptr = NULL; - bpf_probe_read(&map_keyvalues_ptr, sizeof(map_keyvalues_ptr), headers_ptr + 16); - void *injected_key_ptr = map_keyvalues_ptr + 8 + (16 * map_keyvalue_count); - char traceparent_tophash = 0xee; void *tophashes_ptr = map_keyvalues_ptr + map_keyvalue_count; res = bpf_probe_write_user(tophashes_ptr, &traceparent_tophash, 1); if(res < 0) { + bpf_printk("Failed to write tophash, return code: %d", res); return -1; } @@ -90,7 +90,6 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context void *ptr = write_target_data(key, W3C_KEY_LENGTH); res = bpf_probe_write_user(injected_key_ptr, &ptr, sizeof(ptr)); - if(res < 0) { return -1; } @@ -103,11 +102,7 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context } void *injected_value_ptr = injected_key_ptr + (16 * (8 - map_keyvalue_count)) + 24 * map_keyvalue_count; - - - char val[W3C_VAL_LENGTH]; - span_context_to_w3c_string(propagated_ctx, val); ptr = write_target_data(val, sizeof(val)); @@ -146,20 +141,19 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context // func net/http/client.Do(req *Request) SEC("uprobe/HttpClient") int uprobe_HttpClient_Do(struct pt_regs *ctx) { - struct http_request_t httpReq = {}; httpReq.start_time = bpf_ktime_get_ns(); - u64 request_pos = 2; void *req_ptr = get_argument(ctx, request_pos); - // Get Request.ctx - void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); // Get parent if exists - struct span_context *span_ctx = bpf_map_lookup_elem(&spans_in_progress, &goroutine); - if (span_ctx != NULL) { - bpf_probe_read(&httpReq.psc, sizeof(httpReq.psc), span_ctx); + void *context_ptr = (void *)(req_ptr+ctx_ptr_pos); + void *context_ptr_val = 0; + bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); + struct span_context *parent_span_ctx = get_parent_span_context(context_ptr_val); + if (parent_span_ctx != NULL) { + bpf_probe_read(&httpReq.psc, sizeof(httpReq.psc), parent_span_ctx); copy_byte_arrays(httpReq.psc.TraceID, httpReq.sc.TraceID, TRACE_ID_SIZE); generate_random_bytes(httpReq.sc.SpanID, SPAN_ID_SIZE); } else { @@ -196,9 +190,12 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { bpf_printk("uprobe_HttpClient_Do: Failed to inject header"); } - bpf_map_update_elem(&context_to_http_events, &goroutine, &httpReq, 0); - bpf_map_update_elem(&spans_in_progress, &goroutine, &httpReq.sc, 0); + // Get key + void *key = get_consistent_key(ctx, context_ptr); + // Write event + bpf_map_update_elem(&http_events, &key, &httpReq, 0); + start_tracking_span(context_ptr_val, &httpReq.sc); return 0; } @@ -207,16 +204,17 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { SEC("uprobe/HttpClient") int uprobe_HttpClient_Do_Returns(struct pt_regs *ctx) { u64 request_pos = 2; - void *req_ptr = get_argument_by_stack(ctx, request_pos); - void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); - void *httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &goroutine); + void *req_ptr = get_argument(ctx, request_pos); + void *context_ptr = (void *)(req_ptr+ctx_ptr_pos); + void *key = get_consistent_key(ctx, context_ptr); + void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); struct http_request_t httpReq = {}; bpf_probe_read(&httpReq, sizeof(httpReq), httpReq_ptr); + httpReq.end_time = bpf_ktime_get_ns(); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &httpReq, sizeof(httpReq)); - - bpf_map_delete_elem(&context_to_http_events, &goroutine); - bpf_map_delete_elem(&spans_in_progress, &goroutine); + bpf_map_delete_elem(&http_events, &key); + stop_tracking_span(&httpReq.sc); return 0; } \ No newline at end of file diff --git a/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go index d1c2e1873..48e5c07ee 100644 --- a/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go +++ b/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go @@ -77,10 +77,11 @@ type bpfProgramSpecs struct { // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + HttpEvents *ebpf.MapSpec `ebpf:"http_events"` + 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. @@ -103,19 +104,21 @@ func (o *bpfObjects) Close() error { // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { AllocMap *ebpf.Map `ebpf:"alloc_map"` - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + HttpEvents *ebpf.Map `ebpf:"http_events"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( m.AllocMap, - m.ContextToHttpEvents, m.Events, m.GolangMapbucketStorageMap, - m.SpansInProgress, + m.HttpEvents, + m.TrackedSpans, + m.TrackedSpansBySc, ) } diff --git a/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go index d00be723c..11053132c 100644 --- a/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go +++ b/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go @@ -77,10 +77,11 @@ type bpfProgramSpecs struct { // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + HttpEvents *ebpf.MapSpec `ebpf:"http_events"` + 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. @@ -103,19 +104,21 @@ func (o *bpfObjects) Close() error { // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { AllocMap *ebpf.Map `ebpf:"alloc_map"` - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + HttpEvents *ebpf.Map `ebpf:"http_events"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( m.AllocMap, - m.ContextToHttpEvents, m.Events, m.GolangMapbucketStorageMap, - m.SpansInProgress, + m.HttpEvents, + m.TrackedSpans, + m.TrackedSpansBySc, ) } diff --git a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index cdff5b9ab..f36099924 100644 --- a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -36,14 +36,13 @@ struct http_request_t struct span_context psc; }; -// map key: pointer to the goroutine that handles the request struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, void *); __type(value, struct http_request_t); __uint(max_entries, MAX_CONCURRENT); -} context_to_http_events SEC(".maps"); +} http_events SEC(".maps"); struct { @@ -200,8 +199,7 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) path_size = path_size < path_len ? path_size : path_len; bpf_probe_read(&httpReq.path, path_size, path_ptr); - // Get goroutine pointer - void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); + // Propagate context struct span_context *parent_ctx = extract_context_from_req_headers(req_ptr + headers_ptr_pos); if (parent_ctx != NULL) { @@ -214,22 +212,31 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) httpReq.sc = generate_span_context(); } + // Get key + void *req_ctx_ptr = 0; + bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), (void *)(req_ptr + ctx_ptr_pos)); + void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); + // Write event - bpf_map_update_elem(&context_to_http_events, &goroutine, &httpReq, 0); - bpf_map_update_elem(&spans_in_progress, &goroutine, &httpReq.sc, 0); + httpReq.sc = generate_span_context(); + bpf_map_update_elem(&http_events, &key, &httpReq, 0); + start_tracking_span(req_ctx_ptr, &httpReq.sc); return 0; } SEC("uprobe/ServerMux_ServeHTTP") int uprobe_ServerMux_ServeHTTP_Returns(struct pt_regs *ctx) { - void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); - void *httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &goroutine); + u64 request_pos = 4; + void *req_ptr = get_argument(ctx, request_pos); + void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); + + void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); struct http_request_t httpReq = {}; bpf_probe_read(&httpReq, sizeof(httpReq), httpReq_ptr); httpReq.end_time = bpf_ktime_get_ns(); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &httpReq, sizeof(httpReq)); - bpf_map_delete_elem(&context_to_http_events, &goroutine); - bpf_map_delete_elem(&spans_in_progress, &goroutine); + bpf_map_delete_elem(&http_events, &key); + stop_tracking_span(&httpReq.sc); return 0; } \ No newline at end of file diff --git a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go index 1b7302e76..dc2c056ef 100644 --- a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go +++ b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go @@ -77,11 +77,12 @@ type bpfProgramSpecs struct { // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` + HttpEvents *ebpf.MapSpec `ebpf:"http_events"` ParentSpanContextStorageMap *ebpf.MapSpec `ebpf:"parent_span_context_storage_map"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + 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. @@ -104,21 +105,23 @@ func (o *bpfObjects) Close() error { // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { AllocMap *ebpf.Map `ebpf:"alloc_map"` - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` + HttpEvents *ebpf.Map `ebpf:"http_events"` ParentSpanContextStorageMap *ebpf.Map `ebpf:"parent_span_context_storage_map"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( m.AllocMap, - m.ContextToHttpEvents, m.Events, m.GolangMapbucketStorageMap, + m.HttpEvents, m.ParentSpanContextStorageMap, - m.SpansInProgress, + m.TrackedSpans, + m.TrackedSpansBySc, ) } diff --git a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go index 0678abe86..c3edd9e6c 100644 --- a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go +++ b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go @@ -77,11 +77,12 @@ type bpfProgramSpecs struct { // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` + HttpEvents *ebpf.MapSpec `ebpf:"http_events"` ParentSpanContextStorageMap *ebpf.MapSpec `ebpf:"parent_span_context_storage_map"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + 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. @@ -104,21 +105,23 @@ func (o *bpfObjects) Close() error { // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { AllocMap *ebpf.Map `ebpf:"alloc_map"` - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` + HttpEvents *ebpf.Map `ebpf:"http_events"` ParentSpanContextStorageMap *ebpf.Map `ebpf:"parent_span_context_storage_map"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` } func (m *bpfMaps) Close() error { return _BpfClose( m.AllocMap, - m.ContextToHttpEvents, m.Events, m.GolangMapbucketStorageMap, + m.HttpEvents, m.ParentSpanContextStorageMap, - m.SpansInProgress, + m.TrackedSpans, + m.TrackedSpansBySc, ) } diff --git a/pkg/instrumentors/bpf/net/http/server/probe.go b/pkg/instrumentors/bpf/net/http/server/probe.go index eba369e40..b2b3cb095 100644 --- a/pkg/instrumentors/bpf/net/http/server/probe.go +++ b/pkg/instrumentors/bpf/net/http/server/probe.go @@ -98,6 +98,11 @@ func (h *Instrumentor) Load(ctx *context.InstrumentorContext) error { StructName: "net/url.URL", Field: "Path", }, + { + VarName: "ctx_ptr_pos", + StructName: "net/http.Request", + Field: "ctx", + }, { VarName: "headers_ptr_pos", StructName: "net/http.Request",