feat(profiler): inject PID/TGID/cgroup/pgroup dimensions as pprof labels (#329 PR 1/4)#396
Open
123123213weqw wants to merge 1 commit into
Open
Conversation
First PR toward issue ccfos#329 (multi-dimension profiling capture). Pure-Go dimension capture and label injection; the three lock-contention profilers (mutex/spinlock/rwlock) ship as separate PRs once the label format is signed off by maintainers. Adds: - ParseOption.Dimensions: opt-in flags selecting which dimensions to emit (PID/TGID/Cgroup/ProcessGroup). Zero value = no injection, so existing profiler output is byte-for-byte unchanged. - SampleOutput.TGID/CgroupPath/ProcessGroup (multi-PID path) and ParseInput.SampleDimensions (single-PID path): carriers for the values used when injection is requested. JSON omitempty so legacy data round-trips. - buildDimensionLabels: renders the requested dimensions in canonical pprof form (e.g. "pid=123;tgid=456;cgroup=/kubepods/...;pgroup=web"), appended to the existing first-frame header ("threadName#pid;...") via ';'. Labels live in the first frame so every output backend (collapsed/flamegraph/ raw/chrometrace/speedscope) picks them up without per-backend branching, and Pyroscope/Parca can parse the key=value pairs as labels within that frame. Refs ccfos#329.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
First PR toward issue #329 (multi-dimension profiling capture). Adds opt-in dimension capture + label injection in the Go profiler pipeline. The three lock-contention profilers (mutex/spinlock/rwlock) will follow as separate PRs once the label format is signed off here.
Why
Closes one third of issue #329's acceptance criteria ("PID/TGID/cgroup/进程组维度采集可用" + "多维度标签正确注入"). Today profiler output has no per-sample dimension context, so aggregating or filtering profiles by cgroup/process-group downstream isn't possible. This PR adds the Go-side capture + injection; the three lock profilers will feed off the same machinery.
How
Opt-in by default, byte-identical when off. A new
ParseOption.Dimensionsstruct selects which labels to emit; zero value = no injection, so existing output is unchanged.Carriers (all
omitempty, so legacy JSON/data round-trips clean):SampleOutput.TGID/.CgroupPath/.ProcessGroup— multi-PID path (ParseCollapsedData/ParseRawDatawith a JSON sample array)ParseInput.SampleDimensions— single-PID pathInjection happens at the existing first-frame construction point (
profiler.go:354inparseCommonData, and theheaderFrameblock inparseMultiProcessData). The new helper renders the requested dimensions in canonical pprof form and appends them to the existingthreadName#pidheader via;:Putting labels in the first frame means every output backend (collapsed/flamegraph/raw/chrometrace/speedscope — all under
internal/profiler/output/) picks them up without per-backend branching, and Pyroscope/Parca can still parse thekey=valuepairs as labels within that frame.Why pprof canonical form (
key=value) over Brendan Gregg collapsed form (key_value)? It's what Pyroscope and Parca natively ingest. If maintainers prefer form B from the design comment, it's a one-line change inappendDimension.API contract
ParseOptionDimensions Dimensions(zero value off)SampleOutputJSONtgid,cgroup_path,process_group(all omitempty)ParseInputSampleDimensions SampleDimensions(zero value off)parseCommonDatasignaturesampleDims SampleDimensionsparamTesting
New file
internal/profiler/profiler_test.go(first test file for this package):TestDimensions_Enabled— gate function: zero value disabled, every flag combo enabled.TestBuildDimensionLabels(6 cases) — pprof form for every dimension combo, including PID=0 skip, separator-in-cgroup-path, all-requested-but-unset skip.TestParseCommonData_DimensionInjection_Off— back-compat: zero Dimensions → no label, output unchanged.TestParseCommonData_DimensionInjection_On— opt-in path: labels appended to header.TestParseCommonData_DimensionInjection_NilOpt—nilParseOption must not panic (matches existing nil-opt tolerance inopt.SampleRate).TestParseRawData_MultiPID_DimensionInjection— multi-PID path: each sample's own dimensions land in its own header.TestSampleOutput_JSONRoundTrip(3 cases) — legacy JSON unmarshals clean; new fields round-trip; zero values omitempty.TestParseRawData_LegacyInput_Unchanged— contract guard: even when the sample carries dimension values, opt-out produces no labels.All passing under
go test ./internal/profiler/ -count=1on Linux 6.8;go vet ./internal/profiler/clean;go build ./cmd/...clean.Verification note
BPF isn't touched in this PR — it's pure Go and fully testable on the server. The three lock-contention profilers (mutex/spinlock/rwlock) come in follow-up PRs and will reuse this label-injection machinery.
Checklist
go vetcleanRefs #329.