From 3d8e4c2fe5061662e00c2a5458e68611b9bb59d4 Mon Sep 17 00:00:00 2001 From: dacheng Date: Mon, 30 Jun 2025 16:46:38 +0800 Subject: [PATCH] offcpu: Fix incorrect OffTimes values in offcpu profiling. --- reporter/internal/pdata/generate.go | 15 +++++----- reporter/internal/pdata/generate_test.go | 36 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/reporter/internal/pdata/generate.go b/reporter/internal/pdata/generate.go index 6b9d77da5..fe066349b 100644 --- a/reporter/internal/pdata/generate.go +++ b/reporter/internal/pdata/generate.go @@ -5,8 +5,8 @@ package pdata // import "go.opentelemetry.io/ebpf-profiler/reporter/internal/pda import ( "fmt" + "math" "path/filepath" - "slices" "time" log "github.com/sirupsen/logrus" @@ -129,14 +129,15 @@ func (p *Pdata) setProfile( attrMgr := samples.NewAttrTableManager(dic.AttributeTable()) locationIndex := int32(profile.LocationIndices().Len()) - var startTS, endTS pcommon.Timestamp + startTS, endTS := uint64(math.MaxUint64), uint64(0) for traceKey, traceInfo := range events { sample := profile.Sample().AppendEmpty() sample.SetLocationsStartIndex(locationIndex) - slices.Sort(traceInfo.Timestamps) - startTS = pcommon.Timestamp(traceInfo.Timestamps[0]) - endTS = pcommon.Timestamp(traceInfo.Timestamps[len(traceInfo.Timestamps)-1]) + for _, ts := range traceInfo.Timestamps { + startTS = min(startTS, ts) + endTS = max(endTS, ts) + } sample.TimestampsUnixNano().FromRaw(traceInfo.Timestamps) switch origin { @@ -283,8 +284,8 @@ func (p *Pdata) setProfile( log.Debugf("Reporting OTLP profile with %d samples", profile.Sample().Len()) - profile.SetDuration(endTS - startTS) - profile.SetStartTime(startTS) + profile.SetDuration(pcommon.Timestamp(endTS - startTS)) + profile.SetStartTime(pcommon.Timestamp(startTS)) return nil } diff --git a/reporter/internal/pdata/generate_test.go b/reporter/internal/pdata/generate_test.go index 575c5880e..a990f2a7f 100644 --- a/reporter/internal/pdata/generate_test.go +++ b/reporter/internal/pdata/generate_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/pprofile" semconv "go.opentelemetry.io/otel/semconv/v1.34.0" @@ -217,3 +218,38 @@ func TestFunctionTableOrder(t *testing.T) { }) } } + +func TestProfileDuration(t *testing.T) { + for _, tt := range []struct { + name string + events map[libpf.Origin]samples.KeyToEventMapping + }{ + { + name: "profile duration", + events: map[libpf.Origin]samples.KeyToEventMapping{ + support.TraceOriginSampling: map[samples.TraceAndMetaKey]*samples.TraceEvents{ + {Pid: 1}: { + Timestamps: []uint64{2, 1, 3, 4, 7}, + }, + {Pid: 2}: { + Timestamps: []uint64{8}, + }, + }, + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + d, err := New(100, 100, 100, nil) + require.NoError(t, err) + + tree := make(samples.TraceEventsTree) + tree[""] = tt.events + res, err := d.Generate(tree, tt.name, "version") + require.NoError(t, err) + + profile := res.ResourceProfiles().At(0).ScopeProfiles().At(0).Profiles().At(0) + require.Equal(t, pcommon.Timestamp(7), profile.Duration()) + require.Equal(t, pcommon.Timestamp(1), profile.StartTime()) + }) + } +}