(t *testing.T)
| 14 | ) |
| 15 | |
| 16 | func TestTracer_pprof_labels_propagation(t *testing.T) { |
| 17 | tt := initTestTracer(t, 1) |
| 18 | defer func() { require.NoError(t, tt.Close()) }() |
| 19 | |
| 20 | t.Run("root span name and ID are propagated as pprof labels", func(t *testing.T) { |
| 21 | rootSpan, _ := opentracing.StartSpanFromContext(context.Background(), "RootSpan") |
| 22 | defer rootSpan.Finish() |
| 23 | pprofLabels := spanPprofLabels(rootSpan) |
| 24 | // Label / tag names should be specified explicitly. |
| 25 | require.Equal(t, pprofLabels["span_name"], "RootSpan") |
| 26 | _, err := jaeger.SpanIDFromString(pprofLabels["span_id"]) |
| 27 | require.NoError(t, err) |
| 28 | // trace_id is the 32-character W3C form of the span's trace ID. |
| 29 | traceID := pprofLabels["trace_id"] |
| 30 | require.Len(t, traceID, 32) |
| 31 | parsed, err := jaeger.TraceIDFromString(traceID) |
| 32 | require.NoError(t, err) |
| 33 | require.Equal(t, rootSpan.Context().(jaeger.SpanContext).TraceID(), parsed) |
| 34 | // Make sure the root span has "pyroscope.profile.id" attribute, |
| 35 | // and it matches the corresponding pprof label. |
| 36 | require.Equal(t, pprofLabels["span_id"], spanTags(rootSpan)["pyroscope.profile.id"]) |
| 37 | }) |
| 38 | |
| 39 | t.Run("pprof labels are propagated to child spans", func(t *testing.T) { |
| 40 | rootSpan, ctx := opentracing.StartSpanFromContext(context.Background(), "RootSpan") |
| 41 | defer rootSpan.Finish() |
| 42 | childSpan, _ := opentracing.StartSpanFromContext(ctx, "ChildSpan") |
| 43 | defer childSpan.Finish() |
| 44 | // Goroutine labels are inherited from the parent, |
| 45 | // we do not set them repeatedly for the child spans. |
| 46 | require.Empty(t, spanPprofLabels(childSpan)) |
| 47 | // Only the root span is annotated with the profile ID tag. |
| 48 | require.Nil(t, spanTags(childSpan)["pyroscope.profile.id"]) |
| 49 | }) |
| 50 | |
| 51 | t.Run("pprof labels are not propagated to child spans after parent is finished", func(t *testing.T) { |
| 52 | rootSpan, ctx := opentracing.StartSpanFromContext(context.Background(), "RootSpan") |
| 53 | rootLabels := spanPprofLabels(rootSpan) |
| 54 | require.NotEmpty(t, rootLabels) |
| 55 | // This removes the labels from the goroutine's storage. |
| 56 | // Note that we can't access them (Go runtime does not provide public |
| 57 | // methods) but we rely on SetGoroutineLabels implementation: |
| 58 | // tracer alters currentPprofCtx, so that it actually points to the |
| 59 | // parentPprofCtx – the state prior StartSpanFromContext call. |
| 60 | rootSpan.Finish() |
| 61 | childSpan, _ := opentracing.StartSpanFromContext(ctx, "ChildSpan") |
| 62 | defer childSpan.Finish() |
| 63 | childLabels := spanPprofLabels(childSpan) |
| 64 | require.Empty(t, childLabels) |
| 65 | }) |
| 66 | |
| 67 | t.Run("pprof labels are not propagated to child spans if they are created in a separate goroutine hierarchy", func(t *testing.T) { |
| 68 | c := make(chan opentracing.SpanContext) |
| 69 | done := make(chan struct{}) |
| 70 | go func() { |
| 71 | defer close(done) |
| 72 | // Normally, we assume that pprof labels are propagated to child |
| 73 | // goroutines, and we do not have to set pprof labels for each nested |
nothing calls this directly
no test coverage detected