Skip to content

Commit 72d4457

Browse files
committed
Support v1.28 of otel-go, taking into account different tracer key size. Including the schemaURL in newer versions.
1 parent 78f9640 commit 72d4457

File tree

8 files changed

+137
-25
lines changed

8 files changed

+137
-25
lines changed

internal/pkg/inject/offset_results.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,8 @@
10301030
"1.24.0",
10311031
"1.25.0",
10321032
"1.26.0",
1033-
"1.27.0"
1033+
"1.27.0",
1034+
"1.28.0"
10341035
]
10351036
}
10361037
]
@@ -1123,7 +1124,8 @@
11231124
"1.24.0",
11241125
"1.25.0",
11251126
"1.26.0",
1126-
"1.27.0"
1127+
"1.27.0",
1128+
"1.28.0"
11271129
]
11281130
}
11291131
]
@@ -1221,7 +1223,8 @@
12211223
"1.24.0",
12221224
"1.25.0",
12231225
"1.26.0",
1224-
"1.27.0"
1226+
"1.27.0",
1227+
"1.28.0"
12251228
]
12261229
}
12271230
]

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

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,22 @@ struct otel_span_t {
5959
tracer_id_t tracer_id;
6060
};
6161

62-
typedef struct go_tracer_id {
62+
typedef struct go_tracer_id_partial {
6363
struct go_string name;
6464
struct go_string version;
65-
// struct go_string schema_url;
66-
} go_tracer_id_t;
65+
} go_tracer_id_partial_t;
66+
67+
typedef struct go_tracer_id_full {
68+
struct go_string name;
69+
struct go_string version;
70+
struct go_string schema_url;
71+
} go_tracer_id_full_t;
6772

6873
typedef void* go_tracer_ptr;
6974

7075
// tracerProvider contains a map of tracers
71-
MAP_BUCKET_DEFINITION(go_tracer_id_t, go_tracer_ptr)
76+
MAP_BUCKET_DEFINITION(go_tracer_id_partial_t, go_tracer_ptr)
77+
MAP_BUCKET_DEFINITION(go_tracer_id_full_t, go_tracer_ptr)
7278

7379
struct {
7480
__uint(type, BPF_MAP_TYPE_HASH);
@@ -103,7 +109,7 @@ struct
103109
{
104110
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
105111
__uint(key_size, sizeof(u32));
106-
__uint(value_size, sizeof(MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr)));
112+
__uint(value_size, sizeof(MAP_BUCKET_TYPE(go_tracer_id_full_t, go_tracer_ptr)));
107113
__uint(max_entries, 1);
108114
} golang_mapbucket_storage_map SEC(".maps");
109115

@@ -136,14 +142,16 @@ volatile const u64 tracer_provider_pos;
136142
volatile const u64 tracer_provider_tracers_pos;
137143
volatile const u64 buckets_ptr_pos;
138144

145+
volatile const bool tracer_id_contains_schemaURL;
146+
139147
// read_span_name reads the span name from the provided span_name_ptr and stores the result in
140148
// span_name.buf.
141149
static __always_inline void read_span_name(struct span_name_t *span_name, const u64 span_name_len, void *span_name_ptr) {
142150
const u64 span_name_size = MAX_SPAN_NAME_LEN < span_name_len ? MAX_SPAN_NAME_LEN : span_name_len;
143151
bpf_probe_read(span_name->buf, span_name_size, span_name_ptr);
144152
}
145153

146-
static __always_inline long fill_tracer_id_from_tracers_map(void *tracers_map, go_tracer_ptr tracer, tracer_id_t *tracer_id) {
154+
static __always_inline long fill_partial_tracer_id_from_tracers_map(void *tracers_map, go_tracer_ptr tracer, tracer_id_t *tracer_id) {
147155
u64 tracers_count = 0;
148156
long res = 0;
149157
res = bpf_probe_read(&tracers_count, sizeof(tracers_count), tracers_map);
@@ -169,7 +177,7 @@ static __always_inline long fill_tracer_id_from_tracers_map(void *tracers_map, g
169177
return -1;
170178
}
171179
u32 map_id = 0;
172-
MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr) *map_bucket = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
180+
MAP_BUCKET_TYPE(go_tracer_id_partial_t, go_tracer_ptr) *map_bucket = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
173181
if (!map_bucket)
174182
{
175183
return -1;
@@ -181,7 +189,7 @@ static __always_inline long fill_tracer_id_from_tracers_map(void *tracers_map, g
181189
{
182190
break;
183191
}
184-
res = bpf_probe_read(map_bucket, sizeof(MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr)), buckets_array + (j * sizeof(MAP_BUCKET_TYPE(go_tracer_id_t, go_tracer_ptr))));
192+
res = bpf_probe_read(map_bucket, sizeof(MAP_BUCKET_TYPE(go_tracer_id_partial_t, go_tracer_ptr)), buckets_array + (j * sizeof(MAP_BUCKET_TYPE(go_tracer_id_partial_t, go_tracer_ptr))));
185193
if (res < 0)
186194
{
187195
continue;
@@ -207,6 +215,71 @@ static __always_inline long fill_tracer_id_from_tracers_map(void *tracers_map, g
207215
return 0;
208216
}
209217

218+
static __always_inline long fill_full_tracer_id_from_tracers_map(void *tracers_map, go_tracer_ptr tracer, tracer_id_t *tracer_id) {
219+
u64 tracers_count = 0;
220+
long res = 0;
221+
res = bpf_probe_read(&tracers_count, sizeof(tracers_count), tracers_map);
222+
if (res < 0)
223+
{
224+
return -1;
225+
}
226+
if (tracers_count == 0)
227+
{
228+
return -1;
229+
}
230+
unsigned char log_2_bucket_count;
231+
res = bpf_probe_read(&log_2_bucket_count, sizeof(log_2_bucket_count), tracers_map + 9);
232+
if (res < 0)
233+
{
234+
return -1;
235+
}
236+
u64 bucket_count = 1 << log_2_bucket_count;
237+
void *buckets_array;
238+
res = bpf_probe_read(&buckets_array, sizeof(buckets_array), (void*)(tracers_map + buckets_ptr_pos));
239+
if (res < 0)
240+
{
241+
return -1;
242+
}
243+
u32 map_id = 0;
244+
MAP_BUCKET_TYPE(go_tracer_id_full_t, go_tracer_ptr) *map_bucket = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
245+
if (!map_bucket)
246+
{
247+
return -1;
248+
}
249+
250+
for (u64 j = 0; j < MAX_BUCKETS; j++)
251+
{
252+
if (j >= bucket_count)
253+
{
254+
break;
255+
}
256+
res = bpf_probe_read(map_bucket, sizeof(MAP_BUCKET_TYPE(go_tracer_id_full_t, go_tracer_ptr)), buckets_array + (j * sizeof(MAP_BUCKET_TYPE(go_tracer_id_full_t, go_tracer_ptr))));
257+
if (res < 0)
258+
{
259+
continue;
260+
}
261+
for (u64 i = 0; i < 8; i++)
262+
{
263+
if (map_bucket->tophash[i] == 0)
264+
{
265+
continue;
266+
}
267+
if (map_bucket->values[i] == NULL)
268+
{
269+
continue;
270+
}
271+
if (map_bucket->values[i] != tracer)
272+
{
273+
continue;
274+
}
275+
get_go_string_from_user_ptr(&map_bucket->keys[i].version, tracer_id->version, MAX_TRACER_VERSION_LEN);
276+
get_go_string_from_user_ptr(&map_bucket->keys[i].schema_url, tracer_id->schema_url, MAX_TRACER_SCHEMA_URL_LEN);
277+
return 0;
278+
}
279+
}
280+
return 0;
281+
}
282+
210283
static __always_inline long fill_tracer_id(tracer_id_t *tracer_id, go_tracer_ptr tracer) {
211284
// Check if the tracer id is already cached
212285
tracer_id_t *cached_tracer_id = bpf_map_lookup_elem(&tracer_ptr_to_id_map, &tracer);
@@ -232,7 +305,11 @@ static __always_inline long fill_tracer_id(tracer_id_t *tracer_id, go_tracer_ptr
232305
return res;
233306
}
234307

235-
res = fill_tracer_id_from_tracers_map(tracers_map, tracer, tracer_id);
308+
if (tracer_id_contains_schemaURL) {
309+
res = fill_full_tracer_id_from_tracers_map(tracers_map, tracer, tracer_id);
310+
} else {
311+
res = fill_partial_tracer_id_from_tracers_map(tracers_map, tracer, tracer_id);
312+
}
236313
if (res < 0) {
237314
return res;
238315
}

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@ package global
1616

1717
import (
1818
"encoding/binary"
19+
"fmt"
1920
"math"
2021

22+
"go.opentelemetry.io/auto/internal/pkg/inject"
2123
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
24+
"go.opentelemetry.io/auto/internal/pkg/process"
2225
"go.opentelemetry.io/auto/internal/pkg/structfield"
2326

2427
"github.com/go-logr/logr"
28+
"github.com/hashicorp/go-version"
2529
"golang.org/x/sys/unix"
2630

2731
"go.opentelemetry.io/otel/attribute"
@@ -106,6 +110,7 @@ func New(logger logr.Logger) probe.Probe {
106110
Key: "buckets_ptr_pos",
107111
Val: structfield.NewID("std", "runtime", "hmap", "buckets"),
108112
},
113+
tracerIDContainsSchemaURL{},
109114
},
110115
Uprobes: []probe.Uprobe{
111116
{
@@ -138,6 +143,23 @@ func New(logger logr.Logger) probe.Probe {
138143
}
139144
}
140145

146+
// framePosConst is a Probe Const defining whether the tracer key contains schemaURL.
147+
type tracerIDContainsSchemaURL struct{}
148+
149+
// Prior to v1.28 the tracer key did not contain schemaURL. However, in that version a
150+
// change was made to include it.
151+
// https://github.com/open-telemetry/opentelemetry-go/pull/5426/files
152+
var paramChangeVer = version.Must(version.NewVersion("1.28.0"))
153+
154+
func (c tracerIDContainsSchemaURL) InjectOption(td *process.TargetDetails) (inject.Option, error) {
155+
ver, ok := td.Libraries["go.opentelemetry.io/otel"]
156+
if !ok {
157+
return nil, fmt.Errorf("unknown module version: %s", pkg)
158+
}
159+
160+
return inject.WithKeyValue("tracer_id_contains_schemaURL", ver.GreaterThanOrEqual(paramChangeVer)), nil
161+
}
162+
141163
type attributeKeyVal struct {
142164
ValLength uint16
143165
Vtype uint8

internal/test/e2e/otelglobal/go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ module go.opentelemetry.io/auto/internal/test/e2e/otelglobal
33
go 1.22.0
44

55
require (
6-
go.opentelemetry.io/otel v1.27.0
7-
go.opentelemetry.io/otel/trace v1.27.0
6+
go.opentelemetry.io/otel v1.28.0
7+
go.opentelemetry.io/otel/trace v1.28.0
88
)
99

1010
require (
11-
github.com/go-logr/logr v1.4.1 // indirect
11+
github.com/go-logr/logr v1.4.2 // indirect
1212
github.com/go-logr/stdr v1.2.2 // indirect
13-
go.opentelemetry.io/otel/metric v1.27.0 // indirect
13+
go.opentelemetry.io/otel/metric v1.28.0 // indirect
1414
)
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
33
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
4-
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
5-
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
4+
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
5+
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
66
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
77
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
88
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
@@ -11,11 +11,11 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
1111
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
1212
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
1313
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
14-
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
15-
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
16-
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
17-
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
18-
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
19-
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
14+
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
15+
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
16+
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
17+
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
18+
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
19+
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
2020
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
2121
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/test/e2e/otelglobal/main.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ import (
2424
"go.opentelemetry.io/otel/trace"
2525
)
2626

27-
var tracer = otel.Tracer("trace-example", trace.WithInstrumentationVersion("v1.23.42"))
27+
var tracer = otel.Tracer(
28+
"trace-example",
29+
trace.WithInstrumentationVersion("v1.23.42"),
30+
trace.WithSchemaURL("https://some_shcema"),
31+
)
2832

2933
func innerFunction(ctx context.Context) {
3034
_, span := tracer.Start(ctx, "child")

internal/test/e2e/otelglobal/traces.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"schemaUrl": "https://opentelemetry.io/schemas/1.22.0",
5151
"scopeSpans": [
5252
{
53+
"schemaUrl": "https://some_shcema",
5354
"scope": {
5455
"name": "trace-example",
5556
"version": "v1.23.42"

internal/test/e2e/otelglobal/verify.bats

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ SCOPE="trace-example"
1414
assert_equal "$result" '"v1.23.42"'
1515
}
1616

17+
@test "go-auto :: include schema url" {
18+
result=$(spans_received | jq ".scopeSpans[].schemaUrl")
19+
assert_equal "$result" '"https://some_shcema"'
20+
}
21+
1722
@test "server :: valid int attribute" {
1823
result=$(span_attributes_for ${SCOPE} | jq "select(.key == \"int_key\").value.intValue")
1924
assert_equal "$result" '"42"'

0 commit comments

Comments
 (0)