From 3b7bbac685dffbafdea344d9363d3f2fb79bfeae Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 15 Jan 2026 17:04:57 +0100 Subject: [PATCH 1/2] multi-comments --- internal/driver/cli.go | 6 +++--- internal/driver/driver_test.go | 15 +++++++++++++-- internal/driver/fetch.go | 4 ++-- .../testdata/pprof.cpu.comments.multiple_comments | 2 ++ 4 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 internal/driver/testdata/pprof.cpu.comments.multiple_comments diff --git a/internal/driver/cli.go b/internal/driver/cli.go index 7b8c3fc607..22a1bc4ef1 100644 --- a/internal/driver/cli.go +++ b/internal/driver/cli.go @@ -36,7 +36,7 @@ type source struct { Symbolize string HTTPHostport string HTTPDisableBrowser bool - Comment string + Comment []string AllFrames bool } @@ -52,7 +52,7 @@ func parseFlags(o *plugin.Options) (*source, []string, error) { flagSymbolize := flag.String("symbolize", "", "Options for profile symbolization") flagBuildID := flag.String("buildid", "", "Override build id for first mapping") flagTimeout := flag.Int("timeout", -1, "Timeout in seconds for fetching a profile") - flagAddComment := flag.String("add_comment", "", "Free-form annotation to add to the profile") + flagAddComment := flag.StringList("add_comment", "", "Free-form annotation to add to the profile") flagAllFrames := flag.Bool("all_frames", false, "Ignore drop_frames and keep_frames regexps") // CPU profile options flagSeconds := flag.Int("seconds", -1, "Length of time for dynamic profiles") @@ -146,7 +146,7 @@ func parseFlags(o *plugin.Options) (*source, []string, error) { Symbolize: *flagSymbolize, HTTPHostport: *flagHTTP, HTTPDisableBrowser: *flagNoBrowser, - Comment: *flagAddComment, + Comment: dropEmpty(*flagAddComment), AllFrames: *flagAllFrames, } diff --git a/internal/driver/driver_test.go b/internal/driver/driver_test.go index d4efa75703..e405d67a6b 100644 --- a/internal/driver/driver_test.go +++ b/internal/driver/driver_test.go @@ -80,6 +80,7 @@ func TestParse(t *testing.T) { {"dot,addresses,flat,ignore=[X3]002,focus=[X1]000", "contention"}, {"dot,files,cum", "contention"}, {"comments,add_comment=some-comment", "cpu"}, + {"comments,add_comment=comment1,add_comment=comment2", "cpu"}, {"comments", "heap"}, {"tags", "cpu"}, {"tags,tagignore=tag[13],tagfocus=key[12]", "cpu"}, @@ -251,6 +252,11 @@ func addFlags(f *testFlags, flags []string) { f.ints[fields[0]] = i } else { f.strings[fields[0]] = fields[1] + // Add support for string lists + if f.stringLists == nil { + f.stringLists = make(map[string][]string) + } + f.stringLists[fields[0]] = append(f.stringLists[fields[0]], fields[1]) } } } @@ -285,6 +291,9 @@ func solutionFilename(source string, f *testFlags) string { if f.strings["unit"] != "minimum" { name = addString(name, f, []string{"unit"}) } + if len(f.stringLists["add_comment"]) > 1 { + name = append(name, "multiple_comments") + } return strings.Join(name, ".") } @@ -341,13 +350,15 @@ func (f testFlags) String(s, d, c string) *string { func (f testFlags) StringList(s, d, c string) *[]*string { if t, ok := f.stringLists[s]; ok { + fmt.Printf("DEBUG: StringList found %s: %v\n", s, t) // convert slice of strings to slice of string pointers before returning. tp := make([]*string, len(t)) - for i, v := range t { - tp[i] = &v + for i := range t { + tp[i] = &t[i] } return &tp } + fmt.Printf("DEBUG: StringList NOT found %s\n", s) return &[]*string{} } diff --git a/internal/driver/fetch.go b/internal/driver/fetch.go index 6d967a2037..7fa74b084e 100644 --- a/internal/driver/fetch.go +++ b/internal/driver/fetch.go @@ -89,8 +89,8 @@ func fetchProfiles(s *source, o *plugin.Options) (*profile.Profile, error) { p.RemoveUninteresting() unsourceMappings(p) - if s.Comment != "" { - p.Comments = append(p.Comments, s.Comment) + if len(s.Comment) > 0 { + p.Comments = append(p.Comments, s.Comment...) } // Save a copy of the merged profile if there is at least one remote source. diff --git a/internal/driver/testdata/pprof.cpu.comments.multiple_comments b/internal/driver/testdata/pprof.cpu.comments.multiple_comments new file mode 100644 index 0000000000..639c501eff --- /dev/null +++ b/internal/driver/testdata/pprof.cpu.comments.multiple_comments @@ -0,0 +1,2 @@ +comment1 +comment2 From 282fd6875ac16538c60eae4ba2f5cdb9a73158fd Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 15 Jan 2026 19:25:21 +0100 Subject: [PATCH 2/2] more --- internal/driver/cli.go | 4 ++-- internal/driver/driver_test.go | 6 ++---- internal/driver/fetch.go | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/internal/driver/cli.go b/internal/driver/cli.go index 22a1bc4ef1..a18ec1597e 100644 --- a/internal/driver/cli.go +++ b/internal/driver/cli.go @@ -36,7 +36,7 @@ type source struct { Symbolize string HTTPHostport string HTTPDisableBrowser bool - Comment []string + Comments []string AllFrames bool } @@ -146,7 +146,7 @@ func parseFlags(o *plugin.Options) (*source, []string, error) { Symbolize: *flagSymbolize, HTTPHostport: *flagHTTP, HTTPDisableBrowser: *flagNoBrowser, - Comment: dropEmpty(*flagAddComment), + Comments: dropEmpty(*flagAddComment), AllFrames: *flagAllFrames, } diff --git a/internal/driver/driver_test.go b/internal/driver/driver_test.go index e405d67a6b..9540ac3dc0 100644 --- a/internal/driver/driver_test.go +++ b/internal/driver/driver_test.go @@ -350,15 +350,13 @@ func (f testFlags) String(s, d, c string) *string { func (f testFlags) StringList(s, d, c string) *[]*string { if t, ok := f.stringLists[s]; ok { - fmt.Printf("DEBUG: StringList found %s: %v\n", s, t) // convert slice of strings to slice of string pointers before returning. tp := make([]*string, len(t)) - for i := range t { - tp[i] = &t[i] + for i, v := range t { + tp[i] = &v } return &tp } - fmt.Printf("DEBUG: StringList NOT found %s\n", s) return &[]*string{} } diff --git a/internal/driver/fetch.go b/internal/driver/fetch.go index 7fa74b084e..14e003d3a3 100644 --- a/internal/driver/fetch.go +++ b/internal/driver/fetch.go @@ -89,8 +89,8 @@ func fetchProfiles(s *source, o *plugin.Options) (*profile.Profile, error) { p.RemoveUninteresting() unsourceMappings(p) - if len(s.Comment) > 0 { - p.Comments = append(p.Comments, s.Comment...) + if len(s.Comments) > 0 { + p.Comments = append(p.Comments, s.Comments...) } // Save a copy of the merged profile if there is at least one remote source.