Skip to content

Commit b25ff44

Browse files
committed
Unload the newSpan probe after first call
1 parent 957d831 commit b25ff44

File tree

13 files changed

+138
-41
lines changed

13 files changed

+138
-41
lines changed

internal/pkg/instrumentation/bpf/database/sql/probe.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func New(logger *slog.Logger, version string) probe.Probe {
5353
Val: shouldIncludeDBStatement(),
5454
},
5555
},
56-
Uprobes: []probe.Uprobe{
56+
Uprobes: []*probe.Uprobe{
5757
{
5858
Sym: "database/sql.(*DB).queryDC",
5959
EntryProbe: "uprobe_queryDC",

internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func New(logger *slog.Logger, version string) probe.Probe {
6969
Val: structfield.NewID("github.com/segmentio/kafka-go", "github.com/segmentio/kafka-go", "ReaderConfig", "GroupID"),
7070
},
7171
},
72-
Uprobes: []probe.Uprobe{
72+
Uprobes: []*probe.Uprobe{
7373
{
7474
Sym: "github.com/segmentio/kafka-go.(*Reader).FetchMessage",
7575
EntryProbe: "uprobe_FetchMessage",

internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func New(logger *slog.Logger, version string) probe.Probe {
5757
Val: structfield.NewID("github.com/segmentio/kafka-go", "github.com/segmentio/kafka-go", "Message", "Time"),
5858
},
5959
},
60-
Uprobes: []probe.Uprobe{
60+
Uprobes: []*probe.Uprobe{
6161
{
6262
Sym: "github.com/segmentio/kafka-go.(*Writer).WriteMessages",
6363
EntryProbe: "uprobe_WriteMessages",

internal/pkg/instrumentation/bpf/go.opentelemetry.io/auto/sdk/probe.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func New(logger *slog.Logger) probe.Probe {
6060
),
6161
},
6262
},
63-
Uprobes: []probe.Uprobe{
63+
Uprobes: []*probe.Uprobe{
6464
{
6565
Sym: "go.opentelemetry.io/auto/sdk.(*tracer).start",
6666
EntryProbe: "uprobe_Tracer_start",
@@ -86,25 +86,25 @@ type converter struct {
8686
logger *slog.Logger
8787
}
8888

89-
func (c *converter) decodeEvent(record perf.Record) (event, error) {
89+
func (c *converter) decodeEvent(record perf.Record) (*event, error) {
9090
reader := bytes.NewReader(record.RawSample)
9191

9292
var e event
9393
err := binary.Read(reader, binary.LittleEndian, &e.Size)
9494
if err != nil {
9595
c.logger.Error("failed to decode size", "error", err)
96-
return event{}, err
96+
return nil, err
9797
}
9898
c.logger.Debug("decoded size", "size", e.Size)
9999

100100
e.SpanData = make([]byte, e.Size)
101101
_, err = reader.Read(e.SpanData)
102102
if err != nil {
103103
c.logger.Error("failed to read span data", "error", err)
104-
return event{}, err
104+
return nil, err
105105
}
106106
c.logger.Debug("decoded span data", "size", e.Size)
107-
return e, nil
107+
return &e, nil
108108
}
109109

110110
func (c *converter) processFn(e *event) ptrace.ScopeSpans {

internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf/probe.bpf.c

+9-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ typedef struct tracer_id {
4545
char schema_url[MAX_TRACER_SCHEMA_URL_LEN];
4646
} tracer_id_t;
4747

48+
struct control_t {
49+
u32 kind; // Required to be 1.
50+
};
51+
4852
struct otel_span_t {
53+
u32 kind; // Required to be 0.
4954
BASE_SPAN_PROPERTIES
5055
struct span_name_t span_name;
5156
otel_status_t status;
@@ -415,7 +420,10 @@ int uprobe_newStart(struct pt_regs *ctx) {
415420
}
416421

417422
wrote_flag = true;
418-
return 0;
423+
424+
// Signal this uprobe should be unloaded.
425+
struct control_t ctrl = {1};
426+
return bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, (void *)(&ctrl), sizeof(struct control_t));
419427
}
420428

421429
// This instrumentation attaches uprobe to the following function:

internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_arm64_bpfel.go

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/bpf_x86_bpfel.go

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go

+60-7
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
package global
55

66
import (
7+
"bytes"
78
"encoding/binary"
89
"fmt"
910
"log/slog"
1011
"math"
12+
"sync"
1113

1214
"go.opentelemetry.io/collector/pdata/pcommon"
1315
"go.opentelemetry.io/collector/pdata/ptrace"
@@ -18,6 +20,7 @@ import (
1820
"go.opentelemetry.io/auto/internal/pkg/process"
1921
"go.opentelemetry.io/auto/internal/pkg/structfield"
2022

23+
"github.com/cilium/ebpf/perf"
2124
"github.com/hashicorp/go-version"
2225
"golang.org/x/sys/unix"
2326

@@ -41,6 +44,17 @@ func New(logger *slog.Logger) probe.Probe {
4144
SpanKind: trace.SpanKindClient,
4245
InstrumentedPkg: pkg,
4346
}
47+
48+
uprobeNewStart := &probe.Uprobe{
49+
Sym: "go.opentelemetry.io/otel/internal/global.(*tracer).newSpan",
50+
EntryProbe: "uprobe_newStart",
51+
FailureMode: probe.FailureModeWarn,
52+
}
53+
54+
c := &converter{
55+
logger: logger,
56+
uprobeNewStart: uprobeNewStart,
57+
}
4458
return &probe.TraceProducer[bpfObjects, event]{
4559
Base: probe.Base[bpfObjects, event]{
4660
ID: id,
@@ -107,12 +121,8 @@ func New(logger *slog.Logger) probe.Probe {
107121
tracerIDContainsSchemaURL{},
108122
tracerIDContainsScopeAttributes{},
109123
},
110-
Uprobes: []probe.Uprobe{
111-
{
112-
Sym: "go.opentelemetry.io/otel/internal/global.(*tracer).newSpan",
113-
EntryProbe: "uprobe_newStart",
114-
FailureMode: probe.FailureModeWarn,
115-
},
124+
Uprobes: []*probe.Uprobe{
125+
uprobeNewStart,
116126
{
117127
Sym: "go.opentelemetry.io/otel/internal/global.(*tracer).Start",
118128
EntryProbe: "uprobe_Start",
@@ -138,12 +148,55 @@ func New(logger *slog.Logger) probe.Probe {
138148
FailureMode: probe.FailureModeIgnore,
139149
},
140150
},
141-
SpecFn: loadBpf,
151+
SpecFn: loadBpf,
152+
ProcessRecord: c.decodeEvent,
142153
},
143154
ProcessFn: processFn,
144155
}
145156
}
146157

158+
type recordKind uint32
159+
160+
const (
161+
recordKindTelemetry recordKind = iota
162+
recordKindConrol
163+
)
164+
165+
type converter struct {
166+
logger *slog.Logger
167+
168+
uprobeNewStart *probe.Uprobe
169+
uprobeNewStartMu sync.Mutex
170+
}
171+
172+
func (c *converter) decodeEvent(record perf.Record) (*event, error) {
173+
reader := bytes.NewReader(record.RawSample)
174+
175+
var kind recordKind
176+
err := binary.Read(reader, binary.LittleEndian, &kind)
177+
if err != nil {
178+
return nil, err
179+
}
180+
181+
var e *event
182+
switch kind {
183+
case recordKindTelemetry:
184+
e := new(event)
185+
reader.Reset(record.RawSample)
186+
err = binary.Read(reader, binary.LittleEndian, e)
187+
case recordKindConrol:
188+
c.uprobeNewStartMu.Lock()
189+
if c.uprobeNewStart != nil {
190+
err = c.uprobeNewStart.Close()
191+
c.uprobeNewStart = nil
192+
}
193+
c.uprobeNewStartMu.Unlock()
194+
default:
195+
err = fmt.Errorf("unknown record kind: %d", kind)
196+
}
197+
return e, err
198+
}
199+
147200
// tracerIDContainsSchemaURL is a Probe Const defining whether the tracer key contains schemaURL.
148201
type tracerIDContainsSchemaURL struct{}
149202

internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/probe.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func New(logger *slog.Logger, version string) probe.Probe {
103103
MinVersion: writeStatusMinVersion,
104104
},
105105
},
106-
Uprobes: []probe.Uprobe{
106+
Uprobes: []*probe.Uprobe{
107107
{
108108
Sym: "google.golang.org/grpc.(*ClientConn).Invoke",
109109
EntryProbe: "uprobe_ClientConn_Invoke",

internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/probe.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func New(logger *slog.Logger, ver string) probe.Probe {
126126
},
127127
framePosConst{},
128128
},
129-
Uprobes: []probe.Uprobe{
129+
Uprobes: []*probe.Uprobe{
130130
{
131131
Sym: "google.golang.org/grpc.(*Server).handleStream",
132132
EntryProbe: "uprobe_server_handleStream",

internal/pkg/instrumentation/bpf/net/http/client/probe.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func New(logger *slog.Logger, version string) probe.Probe {
4040
InstrumentedPkg: pkg,
4141
}
4242

43-
uprobes := []probe.Uprobe{
43+
uprobes := []*probe.Uprobe{
4444
{
4545
Sym: "net/http.(*Transport).roundTrip",
4646
EntryProbe: "uprobe_Transport_roundTrip",
@@ -52,7 +52,7 @@ func New(logger *slog.Logger, version string) probe.Probe {
5252
// probe which writes the data in the outgoing buffer.
5353
if utils.SupportsContextPropagation() {
5454
uprobes = append(uprobes,
55-
probe.Uprobe{
55+
&probe.Uprobe{
5656
Sym: "net/http.Header.writeSubset",
5757
EntryProbe: "uprobe_writeSubset",
5858
// We mark this probe as dependent on roundTrip, so we don't accidentally

internal/pkg/instrumentation/bpf/net/http/server/probe.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func New(logger *slog.Logger, version string) probe.Probe {
103103
},
104104
patternPathSupportedConst{},
105105
},
106-
Uprobes: []probe.Uprobe{
106+
Uprobes: []*probe.Uprobe{
107107
{
108108
Sym: "net/http.serverHandler.ServeHTTP",
109109
EntryProbe: "uprobe_serverHandler_ServeHTTP",

0 commit comments

Comments
 (0)