Skip to content

Commit

Permalink
feat(otelglobal): add support for Span SetName
Browse files Browse the repository at this point in the history
  • Loading branch information
asecondo authored and Tony Secondo committed Jan 10, 2024
1 parent c21b568 commit ec328e2
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http

## [Unreleased]

### Added
- Add support for manual instrumentation with Span `SetName`. ([#590](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/590))

## [v0.10.0-alpha] - 2024-01-03

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ struct {
// Injected in init
volatile const u64 tracer_delegate_pos;


// span_name_read reads the span name from the provided span_name_ptr and stores the result in
// span_name.buf.
static __always_inline void span_name_read(void *span_name_ptr, struct span_name_t span_name, const u64 span_name_len) {
const u64 span_name_size = MAX_SPAN_NAME_LEN < span_name_len ? MAX_SPAN_NAME_LEN : span_name_len;
bpf_probe_read(span_name.buf, span_name_size, span_name_ptr);
}

// This instrumentation attaches uprobe to the following function:
// func (t *tracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span)
// https://github.com/open-telemetry/opentelemetry-go/blob/98b32a6c3a87fbee5d34c063b9096f416b250897/internal/global/trace.go#L149
Expand All @@ -81,8 +89,7 @@ int uprobe_Start(struct pt_regs *ctx) {
// Getting span name
void *span_name_ptr = get_argument(ctx, 4);
u64 span_name_len = (u64)get_argument(ctx, 5);
u64 span_name_size = MAX_SPAN_NAME_LEN < span_name_len ? MAX_SPAN_NAME_LEN : span_name_len;
bpf_probe_read(span_name.buf, span_name_size, span_name_ptr);
span_name_read(span_name_ptr, span_name, span_name_len);

// Save the span name in map to be read once the Start function returns
void *context_ptr_val = get_Go_context(ctx, 3, 0, true);
Expand Down Expand Up @@ -162,6 +169,32 @@ int uprobe_SetAttributes(struct pt_regs *ctx) {
return 0;
}

// This instrumentation attaches uprobe to the following function:
// func (nonRecordingSpan) SetName(string)
SEC("uprobe/SetName")
int uprobe_SetName(struct pt_regs *ctx) {
void *non_recording_span_ptr = get_argument(ctx, 1);
struct otel_span_t *span = bpf_map_lookup_elem(&active_spans_by_span_ptr, &non_recording_span_ptr);
if (span == NULL) {
return 0;
}

struct span_name_t span_name = {0};

// Getting span name
void *span_name_ptr = get_argument(ctx, 4);
if (span_name_ptr == NULL) {
return 0;
}

u64 span_name_len = (u64)get_argument(ctx, 5);

span_name_read(span_name_ptr, span_name, span_name_len);
span->span_name = span_name;

bpf_map_update_elem(&active_spans_by_span_ptr, &non_recording_span_ptr, span, 0);
return 0;
}

// This instrumentation attaches uprobe to the following function:
// func (*nonRecordingSpan) End(...trace.SpanEndOption)
Expand All @@ -178,4 +211,4 @@ int uprobe_End(struct pt_regs *ctx) {

bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, span, sizeof(*span));
return 0;
}
}

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.

Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,19 @@ func New(logger logr.Logger) probe.Probe {
Sym: "go.opentelemetry.io/otel/internal/global.(*tracer).Start",
Fn: uprobeTracerStart,
},
{
Sym: "go.opentelemetry.io/otel/internal/global.(*nonRecordingSpan).End",
Fn: uprobeSpanEnd,
},
{
Sym: "go.opentelemetry.io/otel/internal/global.(*nonRecordingSpan).SetAttributes",
Fn: uprobeSetAttributes,
Optional: true,
},
{
Sym: "go.opentelemetry.io/otel/internal/global.(*nonRecordingSpan).End",
Fn: uprobeSpanEnd,
Sym: "go.opentelemetry.io/otel/internal/global.(*nonRecordingSpan).SetName",
Fn: uprobeSpanSetName,
Optional: true,
},
},

Expand Down Expand Up @@ -166,6 +171,23 @@ func uprobeSetAttributes(name string, exec *link.Executable, target *process.Tar
return links, nil
}

func uprobeSpanSetName(name string, exec *link.Executable, target *process.TargetDetails, obj *bpfObjects) ([]link.Link, error) {
offset, err := target.GetFunctionOffset(name)
if err != nil {
return nil, err
}

opts := &link.UprobeOptions{Address: offset}
l, err := exec.Uprobe("", obj.UprobeSetName, opts)
if err != nil {
return nil, err
}

links := []link.Link{l}

return links, nil
}

func uprobeSpanEnd(name string, exec *link.Executable, target *process.TargetDetails, obj *bpfObjects) ([]link.Link, error) {
offset, err := target.GetFunctionOffset(name)
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions internal/test/e2e/otelglobal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,19 @@ func innerFunction(ctx context.Context) {
span.SetAttributes(attribute.String("inner.key", "inner.value"))
}

func setNameOverride(ctx context.Context) {
_, span := tracer.Start(ctx, "SetNameOriginal")
defer span.End()

span.SetName("SetNameOverride")
}

func createMainSpan(ctx context.Context) {
ctx, span := tracer.Start(ctx, "parent")
defer span.End()

innerFunction(ctx)
setNameOverride(ctx)

intAttr := attribute.Int("int_key", 42)
strAttr := attribute.String("string_key", "forty-two")
Expand Down
9 changes: 9 additions & 0 deletions internal/test/e2e/otelglobal/traces.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@
"status": {},
"traceId": "xxxxx"
},
{
"attributes": [],
"kind": 3,
"name": "SetNameOverride",
"parentSpanId": "xxxxx",
"spanId": "xxxxx",
"status": {},
"traceId": "xxxxx"
},
{
"attributes": [
{
Expand Down
5 changes: 5 additions & 0 deletions internal/test/e2e/otelglobal/verify.bats
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ SCOPE="go.opentelemetry.io/auto/go.opentelemetry.io/otel/internal/global"
assert_regex "$parent_span_id" ${MATCH_A_SPAN_ID}
}

@test "server :: span set name overrides original span name" {
span_set_name_override=$(spans_from_scope_named ${SCOPE} | jq "select(.name == \"SetNameOverride\")" | jq ".traceId")
assert_regex "$trace_id" ${MATCH_A_TRACE_ID}
}

@test "server :: expected (redacted) trace output" {
redact_json
assert_equal "$(git --no-pager diff ${BATS_TEST_DIRNAME}/traces.json)" ""
Expand Down

0 comments on commit ec328e2

Please sign in to comment.