Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use common macro for Uprobe return flow #257

Merged
merged 4 commits into from
Aug 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http
It now has an additional flag indicating whether it'll build a dummy app for Go stdlib packages or not. ([#256]https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/256)
- The function signature of `"go.opentelemetry.io/auto/offsets-tracker/target".New` has changed.
It now accepts a flag to determine if the returned `Data` is from the Go stdlib or not. ([#256]https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/256)
- Use UPROBE_RETURN to declare the common uprobe return logic (finding the corresponding context, setting up end time, and sending the event via perf buffer) ([#257]https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/257)
- BASE_SPAN_PROPERTIES as common fields (start time, end time, SpanContext and ParentSpanContext) for all instrumentations events (consistent between C and Go structs). ([#257]https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/257)
- Header guards in eBPF code. ([#257]https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/257)

### Fixed

Expand Down
5 changes: 5 additions & 0 deletions include/alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef _ALLOC_H_
#define _ALLOC_H_

#include "bpf_helpers.h"

#define MAX_ENTRIES 50
Expand Down Expand Up @@ -119,3 +122,5 @@ static __always_inline void *write_target_data(void *data, s32 size)
return NULL;
}
}

#endif
7 changes: 6 additions & 1 deletion include/arguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef _ARGUMENTS_H_
#define _ARGUMENTS_H_

#include "common.h"
#include "bpf_tracing.h"
#include "bpf_helpers.h"
Expand Down Expand Up @@ -80,4 +83,6 @@ static __always_inline void *get_consistent_key(struct pt_regs *ctx, void *conte
void *ctx_ptr = 0;
bpf_probe_read(&ctx_ptr, sizeof(ctx_ptr), contextContext);
return ctx_ptr;
}
}

#endif
7 changes: 6 additions & 1 deletion include/go_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef _GO_CONTEXT_H_
#define _GO_CONTEXT_H_

#include "bpf_helpers.h"

#define MAX_DISTANCE 10
Expand Down Expand Up @@ -83,4 +86,6 @@ static __always_inline void stop_tracking_span(struct span_context *sc) {

bpf_map_delete_elem(&tracked_spans, &ctx);
bpf_map_delete_elem(&tracked_spans_by_sc, sc);
}
}

#endif
7 changes: 6 additions & 1 deletion include/go_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef _GO_TYPES_H
#define _GO_TYPES_H

#include "alloc.h"
#include "bpf_helpers.h"

Expand Down Expand Up @@ -121,4 +124,6 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n
// Update len
slice->len++;
long success = bpf_probe_write_user(slice_user_ptr->len, &slice->len, sizeof(slice->len));
}
}

#endif
5 changes: 5 additions & 0 deletions include/span_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef _SPAN_CONTEXT_H_
#define _SPAN_CONTEXT_H_

#include "utils.h"

#define SPAN_CONTEXT_STRING_SIZE 55
Expand Down Expand Up @@ -63,3 +66,5 @@ static __always_inline void w3c_string_to_span_context(char *str, struct span_co
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);
}

#endif
50 changes: 50 additions & 0 deletions include/uprobe.h
RonFed marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef _UPROBE_H_
#define _UPROBE_H_

#include "common.h"
#include "span_context.h"
#include "go_context.h"

#define BASE_SPAN_PROPERTIES \
u64 start_time; \
u64 end_time; \
struct span_context sc; \
struct span_context psc;

// Common flow for uprobe return:
// 1. Find consistend key for the current uprobe context
// 2. Use the key to lookup for the uprobe context in the uprobe_context_map
// 3. Update the end time of the found span
// 4. Submit the constructed event to the agent code using perf buffer events_map
// 5. Delete the span from the uprobe_context_map
// 6. Delete the span from the global active spans map
#define UPROBE_RETURN(name, event_type, ctx_struct_pos, ctx_struct_offset, uprobe_context_map, events_map) \
SEC("uprobe/##name##") \
int uprobe_##name##_Returns(struct pt_regs *ctx) { \
void *req_ptr = get_argument(ctx, ctx_struct_pos); \
void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_struct_offset)); \
void *req_ptr_map = bpf_map_lookup_elem(&uprobe_context_map, &key); \
event_type tmpReq = {}; \
bpf_probe_read(&tmpReq, sizeof(tmpReq), req_ptr_map); \
tmpReq.end_time = bpf_ktime_get_ns(); \
bpf_perf_event_output(ctx, &events_map, BPF_F_CURRENT_CPU, &tmpReq, sizeof(tmpReq)); \
bpf_map_delete_elem(&uprobe_context_map, &key); \
stop_tracking_span(&tmpReq.sc); \
return 0; \
}

#endif
23 changes: 3 additions & 20 deletions pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "arguments.h"
#include "span_context.h"
#include "go_context.h"
#include "uprobe.h"

char __license[] SEC("license") = "Dual MIT/GPL";

Expand All @@ -23,11 +24,9 @@ char __license[] SEC("license") = "Dual MIT/GPL";
#define MAX_CONCURRENT 50

struct http_request_t {
u64 start_time;
u64 end_time;
BASE_SPAN_PROPERTIES
char method[METHOD_MAX_LEN];
char path[PATH_MAX_LEN];
struct span_context sc;
};

struct {
Expand Down Expand Up @@ -90,20 +89,4 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) {
return 0;
}

SEC("uprobe/GinEngine_ServeHTTP")
int uprobe_GinEngine_ServeHTTP_Returns(struct pt_regs *ctx) {
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(&http_events, &key);
stop_tracking_span(&httpReq.sc);
return 0;
}
UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events)

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,9 @@ const instrumentedPkg = "github.com/gin-gonic/gin"
// Event represents an event in the gin-gonic/gin server during an HTTP
// request-response.
type Event struct {
StartTime uint64
EndTime uint64
Method [7]byte
Path [100]byte
SpanContext context.EBPFSpanContext
context.BaseSpanProperties
Method [7]byte
Path [100]byte
}

// Instrumentor is the gin-gonic/gin instrumentor.
Expand Down
10 changes: 6 additions & 4 deletions pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ func TestInstrumentorConvertEvent(t *testing.T) {

i := New()
got := i.convertEvent(&Event{
StartTime: uint64(start.UnixNano()),
EndTime: uint64(end.UnixNano()),
BaseSpanProperties: context.BaseSpanProperties{
StartTime: uint64(start.UnixNano()),
EndTime: uint64(end.UnixNano()),
SpanContext: context.EBPFSpanContext{TraceID: traceID, SpanID: spanID},
},
// "GET"
Method: [7]byte{0x47, 0x45, 0x54},
// "/foo/bar"
Path: [100]byte{0x2f, 0x66, 0x6f, 0x6f, 0x2f, 0x62, 0x61, 0x72},
SpanContext: context.EBPFSpanContext{TraceID: traceID, SpanID: spanID},
Path: [100]byte{0x2f, 0x66, 0x6f, 0x6f, 0x2f, 0x62, 0x61, 0x72},
})

sc := trace.NewSpanContext(trace.SpanContextConfig{
Expand Down
23 changes: 3 additions & 20 deletions pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "arguments.h"
#include "span_context.h"
#include "go_context.h"
#include "uprobe.h"

char __license[] SEC("license") = "Dual MIT/GPL";

Expand All @@ -23,11 +24,9 @@ char __license[] SEC("license") = "Dual MIT/GPL";
#define MAX_CONCURRENT 50

struct http_request_t {
u64 start_time;
u64 end_time;
BASE_SPAN_PROPERTIES
char method[METHOD_MAX_LEN];
char path[PATH_MAX_LEN];
struct span_context sc;
};

struct {
Expand Down Expand Up @@ -90,20 +89,4 @@ int uprobe_GorillaMux_ServeHTTP(struct pt_regs *ctx) {
return 0;
}

SEC("uprobe/GorillaMux_ServeHTTP")
int uprobe_GorillaMux_ServeHTTP_Returns(struct pt_regs *ctx) {
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(&http_events, &key);
stop_tracking_span(&httpReq.sc);
return 0;
}
UPROBE_RETURN(GorillaMux_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events)

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,9 @@ const instrumentedPkg = "github.com/gorilla/mux"
// Event represents an event in the gorilla/mux server during an HTTP
// request-response.
type Event struct {
StartTime uint64
EndTime uint64
Method [7]byte
Path [100]byte
SpanContext context.EBPFSpanContext
context.BaseSpanProperties
Method [7]byte
Path [100]byte
}

// Instrumentor is the gorilla/mux instrumentor.
Expand Down
10 changes: 6 additions & 4 deletions pkg/instrumentors/bpf/github.com/gorilla/mux/probe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ func TestInstrumentorConvertEvent(t *testing.T) {

i := New()
got := i.convertEvent(&Event{
StartTime: uint64(start.UnixNano()),
EndTime: uint64(end.UnixNano()),
BaseSpanProperties: context.BaseSpanProperties{
StartTime: uint64(start.UnixNano()),
EndTime: uint64(end.UnixNano()),
SpanContext: context.EBPFSpanContext{TraceID: traceID, SpanID: spanID},
},
// "GET"
Method: [7]byte{0x47, 0x45, 0x54},
// "/foo/bar"
Path: [100]byte{0x2f, 0x66, 0x6f, 0x6f, 0x2f, 0x62, 0x61, 0x72},
SpanContext: context.EBPFSpanContext{TraceID: traceID, SpanID: spanID},
Path: [100]byte{0x2f, 0x66, 0x6f, 0x6f, 0x2f, 0x62, 0x61, 0x72},
})

sc := trace.NewSpanContext(trace.SpanContextConfig{
Expand Down
Loading
Loading