@@ -8,12 +8,14 @@ package reporter
88import (
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.
6365type 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.
388398func (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.
443454func (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