Skip to content

Commit

Permalink
Timeline (#55)
Browse files Browse the repository at this point in the history
* Timeline
- Allow timestamps to be added to the samples as labels.
- Ensure process name is added as a label to help with thread grouping logics.
  • Loading branch information
r1viollet authored Sep 10, 2024
1 parent 3c6fb18 commit 054e5e3
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 6 deletions.
2 changes: 2 additions & 0 deletions cli_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ var (
argProbabilisticInterval time.Duration
argPprofAddr string
argSaveCPUProfile bool
argTimeline bool

// "internal" flag variables.
// Flag variables that are configured in "internal" builds will have to be assigned
Expand Down Expand Up @@ -161,6 +162,7 @@ func parseArgs() error {
saveCPUProfileHelp)
fs.IntVar(&argSamplesPerSecond, "samples-per-second", defaultArgSamplesPerSecond,
samplesPerSecondHelp)
fs.BoolVar(&argTimeline, "timeline", false, "Enable timeline feature.")

fs.Usage = func() {
fs.PrintDefaults()
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ func mainWithExitCode() exitCode {
FallbackSymbolsMaxQueue: 1024,
DisableTLS: argDisableTLS,
MaxGRPCRetries: 5,
Timeline: argTimeline,
SamplesPerSecond: conf.SamplesPerSecond,
SaveCPUProfile: argSaveCPUProfile,
Times: times,
Expand Down
3 changes: 3 additions & 0 deletions reporter/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type Config struct {

SaveCPUProfile bool

// Whether to include timestamps on samples for the timeline feature
Timeline bool

Times Times

// gRPCInterceptor is the client gRPC interceptor, e.g., for sending gRPC metadata.
Expand Down
32 changes: 26 additions & 6 deletions reporter/datadog_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"os"
"path"
"runtime"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -49,6 +50,8 @@ type DatadogReporter struct {

agentAddr string

timeline bool

samplingPeriod uint64

saveCPUProfile bool
Expand Down Expand Up @@ -255,6 +258,7 @@ func StartDatadog(mainCtx context.Context, cfg *Config) (Reporter, error) {
agentAddr: cfg.CollAgentAddr,
samplingPeriod: 1000000000 / uint64(cfg.SamplesPerSecond),
saveCPUProfile: cfg.SaveCPUProfile,
timeline: cfg.Timeline,
fallbackSymbols: fallbackSymbols,
executables: executables,
frames: frames,
Expand Down Expand Up @@ -512,17 +516,21 @@ func (r *DatadogReporter) getPprofProfile() (profile *pprofile.Profile,
// location with the kernel as the function name.
execPath = "kernel"
}
baseExec := path.Base(execPath)

if execPath != "" {
base := path.Base(execPath)
loc := createPProfLocation(profile, 0)
m := createPprofFunctionEntry(funcMap, profile, base, execPath)
m := createPprofFunctionEntry(funcMap, profile, baseExec, execPath)
loc.Line = append(loc.Line, pprofile.Line{Function: m})
sample.Location = append(sample.Location, loc)
}

sample.Label = make(map[string][]string)
addTraceLabels(sample.Label, traceKey)
var timestamps []uint64
if r.timeline {
timestamps = traceInfo.timestamps
}
addTraceLabels(sample.Label, &traceKey, baseExec, timestamps) //nolint:gomemory

count := int64(len(traceInfo.timestamps))
sample.Value = append(sample.Value, count, count*int64(r.samplingPeriod))
Expand Down Expand Up @@ -564,12 +572,11 @@ func createPprofFunctionEntry(funcMap map[funcInfo]*pprofile.Function,
return function
}

//nolint:gocritic
func addTraceLabels(labels map[string][]string, k traceAndMetaKey) {
func addTraceLabels(labels map[string][]string, k *traceAndMetaKey,
baseExec string, timestamps []uint64) {
if k.comm != "" {
labels["thread_name"] = append(labels["thread_name"], k.comm)
}

if k.podName != "" {
labels["pod_name"] = append(labels["pod_name"], k.podName)
}
Expand All @@ -596,6 +603,19 @@ func addTraceLabels(labels map[string][]string, k traceAndMetaKey) {
// This is also consistent with ddprof.
labels["thread id"] = append(labels["thread id"], fmt.Sprintf("%d", k.tid))
}

if baseExec != "" {
labels["process_name"] = append(labels["process_name"], baseExec)
}

if len(timestamps) > 0 {
timestampStrs := make([]string, 0, len(timestamps))
for _, ts := range timestamps {
timestampStrs = append(timestampStrs, strconv.FormatUint(ts, 10))
}
// Assign all timestamps as a single label entry
labels["end_timestamp_ns"] = timestampStrs
}
}

// getDummyMappingIndex inserts or looks up a dummy entry for interpreted FileIDs.
Expand Down

0 comments on commit 054e5e3

Please sign in to comment.