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

Don't read Go maps anymore #1413

Merged
merged 15 commits into from
Nov 27, 2024
Merged

Don't read Go maps anymore #1413

merged 15 commits into from
Nov 27, 2024

Conversation

grcevski
Copy link
Contributor

@grcevski grcevski commented Nov 26, 2024

Since swiss maps are introduced in Go 1.24, our Go map key extraction will stop working. Please see issue #1369.

I took a look at implementing the swiss map lookup and I'm not sure it's possible to implement the double nested loop without hitting verifier issues, assuming we can reimplement all the bit masking required by the group logic.

So I took a different approach:

  1. For gRPC and HTTP2 I found a place where the data is exposed as an array, so this was easy to traverse.
  2. For HTTP I found a place where the headers are parsed before we add them to the map. This will be slower than our existing approach, but it's a stop gap solution which will work until (if) we decide to reimplement the swiss map logic.

TODO:

  • Offsets for the hardcoded grpc offset tracking.

Closes #1369

@grcevski grcevski marked this pull request as ready for review November 26, 2024 20:30
}, test.Interval(100*time.Millisecond))

spans := trace.FindByOperationName(method)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removed test was a long shot anyway. Essentially, since we had the ability to parse Go maps we used them to parse the outgoing headers on client calls. This didn't quite fit Beyla's usecase, we auto instrument, we don't expect users to put 'Traceparent' in their outgoing headers. But since it was free (in terms of functionality) we did it anyway, even though if you were tracking incoming call and user manually added traceparent, we'd actually provide a wrong trace. Now however, it's no longer possible. The map is pre-constructed and we can't read it in Go 1.24.

Copy link
Contributor

@rafaelroquetto rafaelroquetto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff! Mostly nits from my end, but I think there may be a potential bug involving the "Traceparent:" literal.

bpf/go_common.h Outdated
@@ -401,4 +401,37 @@ static __always_inline void *unwrap_tls_conn_info(void *conn_ptr, void *tls_stat
return conn_ptr;
}

static __always_inline void process_meta_frame_headers(void *frame, tp_info_t *tp) {
if (frame) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: an early return may improve readability by reducing the indentation depth

bpf/go_common.h Outdated
u64 fields_len = 0;
bpf_probe_read(&fields_len, sizeof(fields_len), (void *)(frame + 8 + 8));
bpf_dbg_printk("fields ptr %llx, len %d", fields, fields_len);
if (fields && fields_len > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idem

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe my preference is otherwise :), indenting is a problem, but returns in middle of text are easy to miss.

bpf/go_common.h Outdated
if (!bpf_memicmp((const char *)temp, "traceparent", W3C_KEY_LENGTH)) {
bpf_dbg_printk("found grpc traceparent header");
bpf_probe_read(&temp, W3C_VAL_LENGTH, field.val_ptr);
decode_go_traceparent(temp, tp->trace_id, tp->parent_id, &tp->flags);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we break after this line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch.

bpf/go_nethttp.h Outdated
u64 len = (u64)GO_PARAM2(ctx);
u8 *buf = (u8 *)GO_PARAM1(ctx);

if (len >= 68) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any chance we could slap a name here instead of a magic number? It's not clear what 68 means without any further context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100%, I forgot to update that.

bpf/go_nethttp.h Outdated

connection_info_t *existing = bpf_map_lookup_elem(&ongoing_server_connections, &g_key);
if (existing) {
if (!bpf_memicmp((const char *)temp, "Traceparent: ", W3C_KEY_LENGTH + 2)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a potential bug here - the comment of bpf_memicmp states that s2 needs to be lowercase, which is not the case here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch too, I forgot about those semantics.

bpf/go_nethttp.h Outdated
goroutine_addr,
&invocation.tp,
(void *)(req + go_offset_of(ot, (go_offset){.v = _req_header_ptr_pos})));
__attribute__((__unused__)) u8 existing_tp =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we still need this attribute xor existing_tp?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope we can clean up.

@@ -186,7 +186,7 @@ static __always_inline u8 valid_span(const unsigned char *span_id) {
}

static __always_inline u8 valid_trace(const unsigned char *trace_id) {
return *((u64 *)trace_id) != 0 && *((u64 *)(trace_id + 8)) != 0;
return *((u64 *)trace_id) != 0 || *((u64 *)(trace_id + 8)) != 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch!

grcevski and others added 2 commits November 26, 2024 15:47
Co-authored-by: Rafael Roquetto <rafaelroquetto@users.noreply.github.com>
Co-authored-by: Rafael Roquetto <rafaelroquetto@users.noreply.github.com>
Copy link

codecov bot commented Nov 26, 2024

Codecov Report

Attention: Patch coverage is 81.81818% with 8 lines in your changes missing coverage. Please review.

Project coverage is 80.99%. Comparing base (d2a8a83) to head (a3990be).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
pkg/internal/goexec/structmembers.go 75.00% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1413      +/-   ##
==========================================
+ Coverage   80.95%   80.99%   +0.03%     
==========================================
  Files         146      146              
  Lines       14822    14877      +55     
==========================================
+ Hits        11999    12049      +50     
- Misses       2234     2240       +6     
+ Partials      589      588       -1     
Flag Coverage Δ
integration-test 59.09% <81.81%> (-0.09%) ⬇️
k8s-integration-test 60.05% <75.00%> (+0.09%) ⬆️
oats-test 33.96% <59.09%> (+0.01%) ⬆️
unittests 51.48% <47.72%> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@mariomac mariomac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing! that's life saving

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support Go 1.24 swiss maps
3 participants