Skip to content

Commit 70bc80f

Browse files
author
elsa
committed
feat: enable support for code hotspots
* go.mod, * go.sum, * reporter/datadog_reporter.go: Here.
1 parent 96715d5 commit 70bc80f

3 files changed

Lines changed: 64 additions & 20 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,4 @@ require (
127127
// To update the Datadog/opentelemetry-ebpf-profiler dependency on latest commit on datadog branch, change the following line to:
128128
// replace go.opentelemetry.io/ebpf-profiler => github.com/DataDog/opentelemetry-ebpf-profiler datadog
129129
// and run `GOPRIVATE=github.com/Datadog/* go mod tidy`
130-
replace go.opentelemetry.io/ebpf-profiler => github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20250312101446-72b55407d98e
130+
replace go.opentelemetry.io/ebpf-profiler => github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20250407112148-5e4e6cf9388c

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/
3434
github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM=
3535
github.com/DataDog/jsonapi v0.10.0 h1:qDNSVEdnNteT6lXg9xN/JaGNgvVphwmN8frtJVzUVEU=
3636
github.com/DataDog/jsonapi v0.10.0/go.mod h1:FUSGF3bwMARlVfXEoFo9R/CVlYYy9BGL4C/Prf6Ke3M=
37-
github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20250312101446-72b55407d98e h1:S3oAhWo5+njoAQajfLPMzCR0rxWdtW7/vwOsQNhe6Dw=
38-
github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20250312101446-72b55407d98e/go.mod h1:LZs0Ai6k5IPICeMqXRDpr1uyW7NJnoXgyrlaQh36XSM=
37+
github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20250407112148-5e4e6cf9388c h1:8XPB8YBUADmuCNPgV/fLAniBbdo3vSbKtzHoUkFDJms=
38+
github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20250407112148-5e4e6cf9388c/go.mod h1:LZs0Ai6k5IPICeMqXRDpr1uyW7NJnoXgyrlaQh36XSM=
3939
github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes v0.20.0 h1:fKv05WFWHCXQmUTehW1eEZvXJP65Qv00W4V01B1EqSA=
4040
github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes v0.20.0/go.mod h1:dvIWN9pA2zWNTw5rhDWZgzZnhcfpH++d+8d1SWW6xkY=
4141
github.com/DataDog/sketches-go v1.4.5 h1:ki7VfeNz7IcNafq7yI/j5U/YCkO3LJiMDtXz9OMQbyE=

reporter/datadog_reporter.go

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ package reporter
88
import (
99
"bytes"
1010
"context"
11+
"encoding/binary"
1112
"fmt"
1213
"maps"
1314
"os"
1415
"path"
1516
"runtime"
1617
"strconv"
18+
"strings"
1719
"time"
1820

1921
"github.com/DataDog/zstd"
@@ -62,11 +64,15 @@ type funcInfo struct {
6264
// that we don't accidentally merge traces with different fields.
6365
type traceAndMetaKey struct {
6466
hash libpf.TraceHash
65-
// comm and apmServiceName are provided by the eBPF programs
66-
comm string
67-
apmServiceName string
68-
pid libpf.PID
69-
tid libpf.PID
67+
// comm and apm information are provided by the eBPF programs
68+
comm string
69+
apmServiceName string
70+
apmRuntimeID string
71+
apmTraceID libpf.APMTraceID
72+
apmTransactionID libpf.APMTransactionID
73+
apmSpanID libpf.APMSpanID
74+
pid libpf.PID
75+
tid libpf.PID
7076
}
7177

7278
// traceEvents holds known information about a trace.
@@ -211,11 +217,15 @@ func (r *DatadogReporter) ReportTraceEvent(trace *libpf.Trace, meta *reporter.Tr
211217
}
212218

213219
key := traceAndMetaKey{
214-
hash: trace.Hash,
215-
comm: meta.Comm,
216-
apmServiceName: meta.APMServiceName,
217-
pid: meta.PID,
218-
tid: meta.TID,
220+
hash: trace.Hash,
221+
comm: meta.Comm,
222+
apmServiceName: meta.APMServiceName,
223+
apmRuntimeID: meta.APMRuntimeID,
224+
apmTraceID: meta.APMTraceID,
225+
apmTransactionID: meta.APMTransactionID,
226+
apmSpanID: meta.APMSpanID,
227+
pid: meta.PID,
228+
tid: meta.TID,
219229
}
220230

221231
if tr, exists := (*traceEventsMap)[key]; exists {
@@ -386,7 +396,7 @@ func (r *DatadogReporter) Start(mainCtx context.Context) error {
386396

387397
// reportProfile creates and sends out a profile.
388398
func (r *DatadogReporter) reportProfile(ctx context.Context) error {
389-
profile, startTS, endTS := r.getPprofProfile()
399+
profile, startTS, endTS, runtimeID := r.getPprofProfile()
390400

391401
if len(profile.Sample) == 0 {
392402
log.Debugf("Skip sending of pprof profile with no samples")
@@ -429,7 +439,8 @@ func (r *DatadogReporter) reportProfile(ctx context.Context) error {
429439
MakeTag("profiler_name", profilerName),
430440
MakeTag("profiler_version", r.version),
431441
MakeTag("cpu_arch", runtime.GOARCH),
432-
MakeTag("profile_seq", strconv.FormatUint(r.profileSeq, 10)))
442+
MakeTag("profile_seq", strconv.FormatUint(r.profileSeq, 10)),
443+
MakeTag("runtime-id", runtimeID))
433444

434445
r.profileSeq++
435446

@@ -441,7 +452,7 @@ func (r *DatadogReporter) reportProfile(ctx context.Context) error {
441452

442453
// getPprofProfile returns a pprof profile containing all collected samples up to this moment.
443454
func (r *DatadogReporter) getPprofProfile() (profile *pprofile.Profile,
444-
startTS uint64, endTS uint64) {
455+
startTS uint64, endTS uint64, runtimeID string) {
445456
traceEvents := r.traceEvents.WLock()
446457
samples := maps.Clone(*traceEvents)
447458
for key := range *traceEvents {
@@ -572,10 +583,14 @@ func (r *DatadogReporter) getPprofProfile() (profile *pprofile.Profile,
572583
sample.Location = append(sample.Location, loc)
573584
}
574585

586+
if traceKey.apmRuntimeID != "" {
587+
runtimeID = traceKey.apmRuntimeID
588+
}
589+
575590
if !r.timeline {
576591
count := int64(len(traceInfo.timestamps))
577592
labels := make(map[string][]string)
578-
addTraceLabels(labels, traceKey, processMeta.containerMetadata, baseExec, 0)
593+
addTraceLabels(labels, &traceKey, processMeta.containerMetadata, baseExec, 0)
579594
sample.Value = append(sample.Value, count, count*samplingPeriod)
580595
sample.Label = labels
581596
profile.Sample = append(profile.Sample, sample)
@@ -585,7 +600,7 @@ func (r *DatadogReporter) getPprofProfile() (profile *pprofile.Profile,
585600
sampleWithTimestamp := &pprofile.Sample{}
586601
*sampleWithTimestamp = *sample
587602
labels := make(map[string][]string)
588-
addTraceLabels(labels, traceKey, processMeta.containerMetadata, baseExec, ts)
603+
addTraceLabels(labels, &traceKey, processMeta.containerMetadata, baseExec, ts)
589604
sampleWithTimestamp.Label = labels
590605
profile.Sample = append(profile.Sample, sampleWithTimestamp)
591606
}
@@ -600,7 +615,7 @@ func (r *DatadogReporter) getPprofProfile() (profile *pprofile.Profile,
600615

601616
profile = profile.Compact()
602617

603-
return profile, startTS, endTS
618+
return profile, startTS, endTS, runtimeID
604619
}
605620

606621
// createFunctionEntry adds a new function and returns its reference index.
@@ -627,7 +642,18 @@ func createPprofFunctionEntry(funcMap map[funcInfo]*pprofile.Function,
627642
return function
628643
}
629644

630-
func addTraceLabels(labels map[string][]string, i traceAndMetaKey, containerMetadata containermetadata.ContainerMetadata,
645+
func hexPadded(value uint64) string {
646+
const hexDigits = 16
647+
hexStr := strconv.FormatUint(value, 16) // convert to lower-case hex string
648+
// Pad with leading zeros if necessary.
649+
if len(hexStr) < hexDigits {
650+
padding := strings.Repeat("0", hexDigits-len(hexStr))
651+
hexStr = padding + hexStr
652+
}
653+
return hexStr
654+
}
655+
656+
func addTraceLabels(labels map[string][]string, i *traceAndMetaKey, containerMetadata containermetadata.ContainerMetadata,
631657
baseExec string, timestamp uint64) {
632658
if i.comm != "" {
633659
labels["thread_name"] = append(labels["thread_name"], i.comm)
@@ -649,6 +675,24 @@ func addTraceLabels(labels map[string][]string, i traceAndMetaKey, containerMeta
649675
labels["apmServiceName"] = append(labels["apmServiceName"], i.apmServiceName)
650676
}
651677

678+
if i.apmTraceID != [16]byte{} {
679+
low := binary.LittleEndian.Uint64(i.apmTraceID[:8])
680+
high := binary.LittleEndian.Uint64(i.apmTraceID[8:])
681+
lowStr := hexPadded(low)
682+
highStr := hexPadded(high)
683+
labels["trace id"] = append(labels["trace id"], highStr+lowStr)
684+
}
685+
686+
if i.apmTransactionID != libpf.InvalidAPMSpanID {
687+
transactionID := binary.LittleEndian.Uint64(i.apmTransactionID[:])
688+
labels["local root span id"] = append(labels["local root span id"], strconv.FormatUint(transactionID, 10))
689+
}
690+
691+
if i.apmSpanID != libpf.InvalidAPMSpanID {
692+
spanID := binary.LittleEndian.Uint64(i.apmSpanID[:])
693+
labels["span id"] = append(labels["span id"], strconv.FormatUint(spanID, 10))
694+
}
695+
652696
if i.pid != 0 {
653697
labels["process_id"] = append(labels["process_id"], fmt.Sprintf("%d", i.pid))
654698
}

0 commit comments

Comments
 (0)