From 4aefd9ca7a96792c6b18d1e66e914c845c7153fb Mon Sep 17 00:00:00 2001 From: hainenber Date: Tue, 16 Apr 2024 21:53:22 +0700 Subject: [PATCH 1/9] feat(pyroscope/scrape): add support for configuring CPU profile's duration scraped by `pyroscope.scrape` Signed-off-by: hainenber --- CHANGELOG.md | 2 + .../reference/components/pyroscope.scrape.md | 7 ++- internal/component/pyroscope/scrape/scrape.go | 36 ++++++----- .../component/pyroscope/scrape/scrape_test.go | 10 +++ internal/component/pyroscope/scrape/target.go | 6 +- .../component/pyroscope/scrape/target_test.go | 63 +++++++++++++++++++ 6 files changed, 107 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13ff316031..d125860954 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ Main (unreleased) - In `prometheus.exporter.kafka`, the interpolation table used to compute estimated lag metrics is now pruned on `metadata_refresh_interval` instead of `prune_interval_seconds`. (@wildum) +- Add support for configuring CPU profile's duration scraped by `pyroscope.scrape`. (@hainenber) + ### Bugfixes - Fixed issue with defaults for Beyla component not being applied correctly. (marctc) diff --git a/docs/sources/reference/components/pyroscope.scrape.md b/docs/sources/reference/components/pyroscope.scrape.md index 3365306139..b02e3651dd 100644 --- a/docs/sources/reference/components/pyroscope.scrape.md +++ b/docs/sources/reference/components/pyroscope.scrape.md @@ -65,6 +65,7 @@ Name | Type | Description `params` | `map(list(string))` | A set of query parameters with which the target is scraped. | | no `scrape_interval` | `duration` | How frequently to scrape the targets of this scrape configuration. | `"15s"` | no `scrape_timeout` | `duration` | The timeout for scraping targets of this configuration. Must be larger than `scrape_interval`. | `"18s"` | no +`profiling_duration`| `duration` | The duration for a delta profiling to be scraped. Must be larger than 1 second. | `"14s"` | no `scheme` | `string` | The URL scheme with which to fetch metrics from targets. | `"http"` | no `bearer_token_file` | `string` | File containing a bearer token to authenticate with. | | no `bearer_token` | `secret` | Bearer token to authenticate with. | | no @@ -395,8 +396,10 @@ When the `delta` argument is `false`, the [pprof][] HTTP query will be instantan When the `delta` argument is `true`: * The [pprof][] HTTP query will run for a certain amount of time. * A `seconds` parameter is automatically added to the HTTP request. -* The `seconds` used will be equal to `scrape_interval - 1`. - For example, if `scrape_interval` is `"15s"`, `seconds` will be 14 seconds. +* The default value for the `seconds` query parameter is `scrape_interval - 1`. + If you set `profiling_duration`, then `seconds` is assigned the same value as `profiling_duration`. + For example, if you set `scrape_interval` to `"15s"`, then `seconds` defaults to `14s`. + If you set `profiling_duration` to `16s`, then `seconds is set to `16s` regardless of the `scrape_interval` value. If the HTTP endpoint is `/debug/pprof/profile`, then the HTTP query will become `/debug/pprof/profile?seconds=14` ## Exported fields diff --git a/internal/component/pyroscope/scrape/scrape.go b/internal/component/pyroscope/scrape/scrape.go index 5647aea5a1..4a1ac8bbf8 100644 --- a/internal/component/pyroscope/scrape/scrape.go +++ b/internal/component/pyroscope/scrape/scrape.go @@ -21,15 +21,17 @@ import ( ) const ( - pprofMemory string = "memory" - pprofBlock string = "block" - pprofGoroutine string = "goroutine" - pprofMutex string = "mutex" - pprofProcessCPU string = "process_cpu" - pprofFgprof string = "fgprof" - pprofGoDeltaProfMemory string = "godeltaprof_memory" - pprofGoDeltaProfBlock string = "godeltaprof_block" - pprofGoDeltaProfMutex string = "godeltaprof_mutex" + pprofMemory string = "memory" + pprofBlock string = "block" + pprofGoroutine string = "goroutine" + pprofMutex string = "mutex" + pprofProcessCPU string = "process_cpu" + pprofFgprof string = "fgprof" + pprofGoDeltaProfMemory string = "godeltaprof_memory" + pprofGoDeltaProfBlock string = "godeltaprof_block" + pprofGoDeltaProfMutex string = "godeltaprof_mutex" + defaultScrapeInterval time.Duration = 15 * time.Second + defaultProfilingDuration time.Duration = 14 * time.Second ) func init() { @@ -60,6 +62,8 @@ type Arguments struct { ScrapeTimeout time.Duration `alloy:"scrape_timeout,attr,optional"` // The URL scheme with which to fetch metrics from targets. Scheme string `alloy:"scheme,attr,optional"` + // The duration for a profile to be scrapped. + ProfilingDuration time.Duration `river:"profiling_duration,attr,optional"` // todo(ctovena): add support for limits. // // An uncompressed response body larger than this many bytes will cause the @@ -192,11 +196,12 @@ var DefaultArguments = NewDefaultArguments() // NewDefaultArguments create the default settings for a scrape job. func NewDefaultArguments() Arguments { return Arguments{ - Scheme: "http", - HTTPClientConfig: component_config.DefaultHTTPClientConfig, - ScrapeInterval: 15 * time.Second, - ScrapeTimeout: 10 * time.Second, - ProfilingConfig: DefaultProfilingConfig, + Scheme: "http", + HTTPClientConfig: component_config.DefaultHTTPClientConfig, + ScrapeInterval: 15 * time.Second, + ScrapeTimeout: 10 * time.Second, + ProfilingConfig: DefaultProfilingConfig, + ProfilingDuration: defaultProfilingDuration, } } @@ -218,6 +223,9 @@ func (arg *Arguments) Validate() error { if target.Enabled && target.Delta && arg.ScrapeInterval.Seconds() < 2 { return fmt.Errorf("scrape_interval must be at least 2 seconds when using delta profiling") } + if target.Enabled && target.Delta && arg.ProfilingDuration.Seconds() <= 1 { + return fmt.Errorf("profiling_duration must be larger then 1 second when using delta profiling") + } } // We must explicitly Validate because HTTPClientConfig is squashed and it won't run otherwise diff --git a/internal/component/pyroscope/scrape/scrape_test.go b/internal/component/pyroscope/scrape/scrape_test.go index e08120f1c8..a4b4226022 100644 --- a/internal/component/pyroscope/scrape/scrape_test.go +++ b/internal/component/pyroscope/scrape/scrape_test.go @@ -151,6 +151,16 @@ func TestUnmarshalConfig(t *testing.T) { `, expectedErr: "scrape_interval must be at least 2 seconds when using delta profiling", }, + "invalid cpu profiling_duration": { + in: ` + targets = [] + forward_to = null + scrape_timeout = "1s" + scrape_interval = "10s" + profiling_duration = "1s" + `, + expectedErr: "profiling_duration must be larger then 1 second when using delta profiling", + }, "allow short scrape_intervals without delta": { in: ` targets = [] diff --git a/internal/component/pyroscope/scrape/target.go b/internal/component/pyroscope/scrape/target.go index 736d75b43f..a05bbfb0b0 100644 --- a/internal/component/pyroscope/scrape/target.go +++ b/internal/component/pyroscope/scrape/target.go @@ -406,7 +406,11 @@ func targetsFromGroup(group *targetgroup.Group, cfg Arguments, targetTypes map[s } if pcfg, found := targetTypes[profType]; found && pcfg.Delta { - params.Add("seconds", strconv.Itoa(int((cfg.ScrapeInterval)/time.Second)-1)) + seconds := (cfg.ScrapeInterval)/time.Second - 1 + if cfg.ProfilingDuration != defaultProfilingDuration { + seconds = (cfg.ProfilingDuration) / time.Second + } + params.Add("seconds", strconv.Itoa(int(seconds))) } targets = append(targets, NewTarget(lbls, origLabels, params)) } diff --git a/internal/component/pyroscope/scrape/target_test.go b/internal/component/pyroscope/scrape/target_test.go index b4d6fd2aa6..ba8231a6a9 100644 --- a/internal/component/pyroscope/scrape/target_test.go +++ b/internal/component/pyroscope/scrape/target_test.go @@ -4,6 +4,7 @@ import ( "net/url" "sort" "testing" + "time" "github.com/prometheus/common/model" "github.com/prometheus/prometheus/discovery/targetgroup" @@ -236,3 +237,65 @@ func Test_targetsFromGroup(t *testing.T) { require.Equal(t, expected, active) require.Empty(t, dropped) } + +func Test_targetsFromGroup_withSpecifiedProfilingDuration(t *testing.T) { + args := NewDefaultArguments() + args.ProfilingConfig.Block.Enabled = false + args.ProfilingConfig.Goroutine.Enabled = false + args.ProfilingConfig.Mutex.Enabled = false + args.ProfilingDuration = 20 * time.Second + + active, dropped, err := targetsFromGroup(&targetgroup.Group{ + Targets: []model.LabelSet{ + {model.AddressLabel: "localhost:9090"}, + }, + Labels: model.LabelSet{ + "foo": "bar", + }, + }, args, args.ProfilingConfig.AllTargets()) + expected := []*Target{ + // unspecified + NewTarget( + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9090", + serviceNameLabel: "unspecified", + model.MetricNameLabel: pprofMemory, + ProfilePath: "/debug/pprof/allocs", + model.SchemeLabel: "http", + "foo": "bar", + "instance": "localhost:9090", + }), + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9090", + model.MetricNameLabel: pprofMemory, + ProfilePath: "/debug/pprof/allocs", + model.SchemeLabel: "http", + "foo": "bar", + }), + url.Values{}), + NewTarget( + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9090", + serviceNameLabel: "unspecified", + model.MetricNameLabel: pprofProcessCPU, + ProfilePath: "/debug/pprof/profile", + model.SchemeLabel: "http", + "foo": "bar", + "instance": "localhost:9090", + }), + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9090", + model.MetricNameLabel: pprofProcessCPU, + ProfilePath: "/debug/pprof/profile", + model.SchemeLabel: "http", + "foo": "bar", + }), + url.Values{"seconds": []string{"20"}}), + } + + require.NoError(t, err) + sort.Sort(Targets(active)) + sort.Sort(Targets(expected)) + require.Equal(t, expected, active) + require.Empty(t, dropped) +} From 4e08a856e2e3aea4ee243192d74399b3e86b28d8 Mon Sep 17 00:00:00 2001 From: hainenber Date: Tue, 16 Apr 2024 22:30:52 +0700 Subject: [PATCH 2/9] fix(ci): correct token identifier for Alloy marshaling Signed-off-by: hainenber --- internal/component/pyroscope/scrape/scrape.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/component/pyroscope/scrape/scrape.go b/internal/component/pyroscope/scrape/scrape.go index 4a1ac8bbf8..94cf175aff 100644 --- a/internal/component/pyroscope/scrape/scrape.go +++ b/internal/component/pyroscope/scrape/scrape.go @@ -63,7 +63,7 @@ type Arguments struct { // The URL scheme with which to fetch metrics from targets. Scheme string `alloy:"scheme,attr,optional"` // The duration for a profile to be scrapped. - ProfilingDuration time.Duration `river:"profiling_duration,attr,optional"` + ProfilingDuration time.Duration `alloy:"profiling_duration,attr,optional"` // todo(ctovena): add support for limits. // // An uncompressed response body larger than this many bytes will cause the From 7773517288eab114fefa3ad6d048f50fc1a87a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90=E1=BB=97=20Tr=E1=BB=8Dng=20H=E1=BA=A3i?= <41283691+hainenber@users.noreply.github.com> Date: Thu, 18 Apr 2024 17:31:48 +0700 Subject: [PATCH 3/9] Update pyroscope.scrape.md Co-authored-by: Paschalis Tsilias --- docs/sources/reference/components/pyroscope.scrape.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/reference/components/pyroscope.scrape.md b/docs/sources/reference/components/pyroscope.scrape.md index b02e3651dd..0b2d3b8106 100644 --- a/docs/sources/reference/components/pyroscope.scrape.md +++ b/docs/sources/reference/components/pyroscope.scrape.md @@ -399,7 +399,7 @@ When the `delta` argument is `true`: * The default value for the `seconds` query parameter is `scrape_interval - 1`. If you set `profiling_duration`, then `seconds` is assigned the same value as `profiling_duration`. For example, if you set `scrape_interval` to `"15s"`, then `seconds` defaults to `14s`. - If you set `profiling_duration` to `16s`, then `seconds is set to `16s` regardless of the `scrape_interval` value. + If you set `profiling_duration` to `16s`, then `seconds` is set to `16s` regardless of the `scrape_interval` value. If the HTTP endpoint is `/debug/pprof/profile`, then the HTTP query will become `/debug/pprof/profile?seconds=14` ## Exported fields From e835d35d778534774517282487d35f904468a290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90=E1=BB=97=20Tr=E1=BB=8Dng=20H=E1=BA=A3i?= <41283691+hainenber@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:34:04 +0700 Subject: [PATCH 4/9] Update internal/component/pyroscope/scrape/scrape.go Co-authored-by: Paschalis Tsilias --- internal/component/pyroscope/scrape/scrape.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/component/pyroscope/scrape/scrape.go b/internal/component/pyroscope/scrape/scrape.go index 94cf175aff..1c236e83dc 100644 --- a/internal/component/pyroscope/scrape/scrape.go +++ b/internal/component/pyroscope/scrape/scrape.go @@ -31,7 +31,7 @@ const ( pprofGoDeltaProfBlock string = "godeltaprof_block" pprofGoDeltaProfMutex string = "godeltaprof_mutex" defaultScrapeInterval time.Duration = 15 * time.Second - defaultProfilingDuration time.Duration = 14 * time.Second + defaultProfilingDuration time.Duration = defaultScrapeInterval - 1 * time.Second ) func init() { From 5304d84008af7ce7d6fbdb89b17dd2628dc63ceb Mon Sep 17 00:00:00 2001 From: hainenber Date: Fri, 19 Apr 2024 22:51:00 +0700 Subject: [PATCH 5/9] feat(pyroscope/scrape): set `scrape_interval` as upper limit for `profiling_duration` Signed-off-by: hainenber --- docs/sources/reference/components/pyroscope.scrape.md | 5 +++-- internal/component/pyroscope/scrape/scrape.go | 11 ++++++++--- internal/component/pyroscope/scrape/scrape_test.go | 10 ++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/sources/reference/components/pyroscope.scrape.md b/docs/sources/reference/components/pyroscope.scrape.md index 0b2d3b8106..de3493d9d9 100644 --- a/docs/sources/reference/components/pyroscope.scrape.md +++ b/docs/sources/reference/components/pyroscope.scrape.md @@ -398,8 +398,9 @@ When the `delta` argument is `true`: * A `seconds` parameter is automatically added to the HTTP request. * The default value for the `seconds` query parameter is `scrape_interval - 1`. If you set `profiling_duration`, then `seconds` is assigned the same value as `profiling_duration`. - For example, if you set `scrape_interval` to `"15s"`, then `seconds` defaults to `14s`. - If you set `profiling_duration` to `16s`, then `seconds` is set to `16s` regardless of the `scrape_interval` value. + However, the `profiling_duration` cannot be larger than `scrape_interval`. + For example, if you set `scrape_interval` to `"15s"`, then `seconds` defaults to `14s` + If you set `profiling_duration` to `16s`, then `scrape_interval` must be set to at least `17s`. If the HTTP endpoint is `/debug/pprof/profile`, then the HTTP query will become `/debug/pprof/profile?seconds=14` ## Exported fields diff --git a/internal/component/pyroscope/scrape/scrape.go b/internal/component/pyroscope/scrape/scrape.go index 1c236e83dc..93f256356f 100644 --- a/internal/component/pyroscope/scrape/scrape.go +++ b/internal/component/pyroscope/scrape/scrape.go @@ -31,7 +31,7 @@ const ( pprofGoDeltaProfBlock string = "godeltaprof_block" pprofGoDeltaProfMutex string = "godeltaprof_mutex" defaultScrapeInterval time.Duration = 15 * time.Second - defaultProfilingDuration time.Duration = defaultScrapeInterval - 1 * time.Second + defaultProfilingDuration time.Duration = defaultScrapeInterval - 1*time.Second ) func init() { @@ -223,8 +223,13 @@ func (arg *Arguments) Validate() error { if target.Enabled && target.Delta && arg.ScrapeInterval.Seconds() < 2 { return fmt.Errorf("scrape_interval must be at least 2 seconds when using delta profiling") } - if target.Enabled && target.Delta && arg.ProfilingDuration.Seconds() <= 1 { - return fmt.Errorf("profiling_duration must be larger then 1 second when using delta profiling") + if target.Enabled && target.Delta { + if arg.ProfilingDuration.Seconds() <= 1 { + return fmt.Errorf("profiling_duration must be larger than 1 second when using delta profiling") + } + if arg.ProfilingDuration.Seconds() >= arg.ScrapeInterval.Seconds() { + return fmt.Errorf("profiling_duration must be smaller than scrape_interval when using delta profiling") + } } } diff --git a/internal/component/pyroscope/scrape/scrape_test.go b/internal/component/pyroscope/scrape/scrape_test.go index a4b4226022..80a0ebf667 100644 --- a/internal/component/pyroscope/scrape/scrape_test.go +++ b/internal/component/pyroscope/scrape/scrape_test.go @@ -161,6 +161,16 @@ func TestUnmarshalConfig(t *testing.T) { `, expectedErr: "profiling_duration must be larger then 1 second when using delta profiling", }, + "erroneous cpu profiling_duration": { + in: ` + targets = [] + forward_to = null + scrape_timeout = "1s" + scrape_interval = "10s" + profiling_duration = "12s" + `, + expectedErr: "profiling_duration must be smaller than scrape_interval when using delta profiling", + }, "allow short scrape_intervals without delta": { in: ` targets = [] From 777562f943c5f23e75b9b76f421d86f725e6ca4c Mon Sep 17 00:00:00 2001 From: hainenber Date: Fri, 19 Apr 2024 23:01:20 +0700 Subject: [PATCH 6/9] chore(pyroscope/scrape): fix expected error's typo in unit test Signed-off-by: hainenber --- internal/component/pyroscope/scrape/scrape_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/component/pyroscope/scrape/scrape_test.go b/internal/component/pyroscope/scrape/scrape_test.go index 80a0ebf667..e4abc2bc22 100644 --- a/internal/component/pyroscope/scrape/scrape_test.go +++ b/internal/component/pyroscope/scrape/scrape_test.go @@ -159,7 +159,7 @@ func TestUnmarshalConfig(t *testing.T) { scrape_interval = "10s" profiling_duration = "1s" `, - expectedErr: "profiling_duration must be larger then 1 second when using delta profiling", + expectedErr: "profiling_duration must be larger than 1 second when using delta profiling", }, "erroneous cpu profiling_duration": { in: ` From fd9c97c54cc00474e8559b5f69a6536c83c5a0bb Mon Sep 17 00:00:00 2001 From: hainenber Date: Fri, 19 Apr 2024 23:13:56 +0700 Subject: [PATCH 7/9] chore(pyroscope/scrape): configure proper configs for expected HTTPClientConfig error Signed-off-by: hainenber --- internal/component/pyroscope/scrape/scrape_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/component/pyroscope/scrape/scrape_test.go b/internal/component/pyroscope/scrape/scrape_test.go index e4abc2bc22..10a5c9c9dd 100644 --- a/internal/component/pyroscope/scrape/scrape_test.go +++ b/internal/component/pyroscope/scrape/scrape_test.go @@ -195,7 +195,8 @@ func TestUnmarshalConfig(t *testing.T) { targets = [] forward_to = null scrape_timeout = "5s" - scrape_interval = "2s" + scrape_interval = "3s" + profiling_duration = "2s" bearer_token = "token" bearer_token_file = "/path/to/file.token" `, From 581b8879317177d4575329f680bc6e503714c9f5 Mon Sep 17 00:00:00 2001 From: hainenber Date: Tue, 16 Apr 2024 21:53:22 +0700 Subject: [PATCH 8/9] feat(pyroscope/scrape): add support for configuring CPU profile's duration scraped by `pyroscope.scrape` Signed-off-by: hainenber --- .../component/pyroscope/scrape/target_test.go | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/internal/component/pyroscope/scrape/target_test.go b/internal/component/pyroscope/scrape/target_test.go index ba8231a6a9..d7793a6156 100644 --- a/internal/component/pyroscope/scrape/target_test.go +++ b/internal/component/pyroscope/scrape/target_test.go @@ -299,3 +299,50 @@ func Test_targetsFromGroup_withSpecifiedProfilingDuration(t *testing.T) { require.Equal(t, expected, active) require.Empty(t, dropped) } + +// Test that the godeltaprof is not surfaced publicly +func Test_NewTarget_godeltaprof(t *testing.T) { + withGodeltaprof := NewTarget( + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9094", + serviceNameLabel: "docker-container", + model.MetricNameLabel: pprofGoDeltaProfMemory, + ProfilePath: "/debug/pprof/delta_heap", + model.SchemeLabel: "http", + "foo": "bar", + "instance": "localhost:9094", + }), + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9094", + "__meta_docker_container_name": "docker-container", + model.MetricNameLabel: pprofGoDeltaProfMemory, + ProfilePath: "/debug/pprof/delta_heap", + model.SchemeLabel: "http", + "foo": "bar", + }), + url.Values{}, + ) + withoutGodeltaprof := NewTarget( + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9094", + serviceNameLabel: "docker-container", + model.MetricNameLabel: pprofMemory, + ProfilePath: "/debug/pprof/heap", + model.SchemeLabel: "http", + "foo": "bar", + "instance": "localhost:9094", + }), + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9094", + "__meta_docker_container_name": "docker-container", + model.MetricNameLabel: pprofMemory, + ProfilePath: "/debug/pprof/heap", + model.SchemeLabel: "http", + "foo": "bar", + }), + url.Values{}, + ) + + require.NotEqual(t, withGodeltaprof.allLabels, withoutGodeltaprof.allLabels) + require.Equal(t, withGodeltaprof.publicLabels, withoutGodeltaprof.publicLabels) +} From f3d89f6c6cb3ca80c67da1b4fd0c1947a144e08e Mon Sep 17 00:00:00 2001 From: hainenber Date: Wed, 1 May 2024 17:53:15 +0700 Subject: [PATCH 9/9] feat(pyroscope/scrape): rename `profiling_duration` to more comprehensible `delta_profiling_duration` + stricter validation Signed-off-by: hainenber --- .../reference/components/pyroscope.scrape.md | 8 +- internal/component/pyroscope/scrape/scrape.go | 22 ++--- .../component/pyroscope/scrape/scrape_test.go | 14 +-- internal/component/pyroscope/scrape/target.go | 4 +- .../component/pyroscope/scrape/target_test.go | 98 +++++++++---------- 5 files changed, 73 insertions(+), 73 deletions(-) diff --git a/docs/sources/reference/components/pyroscope.scrape.md b/docs/sources/reference/components/pyroscope.scrape.md index de3493d9d9..422e79da1b 100644 --- a/docs/sources/reference/components/pyroscope.scrape.md +++ b/docs/sources/reference/components/pyroscope.scrape.md @@ -65,7 +65,7 @@ Name | Type | Description `params` | `map(list(string))` | A set of query parameters with which the target is scraped. | | no `scrape_interval` | `duration` | How frequently to scrape the targets of this scrape configuration. | `"15s"` | no `scrape_timeout` | `duration` | The timeout for scraping targets of this configuration. Must be larger than `scrape_interval`. | `"18s"` | no -`profiling_duration`| `duration` | The duration for a delta profiling to be scraped. Must be larger than 1 second. | `"14s"` | no +`delta_profiling_duration`| `duration` | The duration for a delta profiling to be scraped. Must be larger than 1 second. | `"14s"` | no `scheme` | `string` | The URL scheme with which to fetch metrics from targets. | `"http"` | no `bearer_token_file` | `string` | File containing a bearer token to authenticate with. | | no `bearer_token` | `secret` | Bearer token to authenticate with. | | no @@ -397,10 +397,10 @@ When the `delta` argument is `true`: * The [pprof][] HTTP query will run for a certain amount of time. * A `seconds` parameter is automatically added to the HTTP request. * The default value for the `seconds` query parameter is `scrape_interval - 1`. - If you set `profiling_duration`, then `seconds` is assigned the same value as `profiling_duration`. - However, the `profiling_duration` cannot be larger than `scrape_interval`. + If you set `delta_profiling_duration`, then `seconds` is assigned the same value as `delta_profiling_duration`. + However, the `delta_profiling_duration` cannot be larger than `scrape_interval`. For example, if you set `scrape_interval` to `"15s"`, then `seconds` defaults to `14s` - If you set `profiling_duration` to `16s`, then `scrape_interval` must be set to at least `17s`. + If you set `delta_profiling_duration` to `16s`, then `scrape_interval` must be set to at least `17s`. If the HTTP endpoint is `/debug/pprof/profile`, then the HTTP query will become `/debug/pprof/profile?seconds=14` ## Exported fields diff --git a/internal/component/pyroscope/scrape/scrape.go b/internal/component/pyroscope/scrape/scrape.go index 93f256356f..ff994fcb4a 100644 --- a/internal/component/pyroscope/scrape/scrape.go +++ b/internal/component/pyroscope/scrape/scrape.go @@ -63,7 +63,7 @@ type Arguments struct { // The URL scheme with which to fetch metrics from targets. Scheme string `alloy:"scheme,attr,optional"` // The duration for a profile to be scrapped. - ProfilingDuration time.Duration `alloy:"profiling_duration,attr,optional"` + DeltaProfilingDuration time.Duration `alloy:"delta_profiling_duration,attr,optional"` // todo(ctovena): add support for limits. // // An uncompressed response body larger than this many bytes will cause the @@ -196,12 +196,12 @@ var DefaultArguments = NewDefaultArguments() // NewDefaultArguments create the default settings for a scrape job. func NewDefaultArguments() Arguments { return Arguments{ - Scheme: "http", - HTTPClientConfig: component_config.DefaultHTTPClientConfig, - ScrapeInterval: 15 * time.Second, - ScrapeTimeout: 10 * time.Second, - ProfilingConfig: DefaultProfilingConfig, - ProfilingDuration: defaultProfilingDuration, + Scheme: "http", + HTTPClientConfig: component_config.DefaultHTTPClientConfig, + ScrapeInterval: 15 * time.Second, + ScrapeTimeout: 10 * time.Second, + ProfilingConfig: DefaultProfilingConfig, + DeltaProfilingDuration: defaultProfilingDuration, } } @@ -224,11 +224,11 @@ func (arg *Arguments) Validate() error { return fmt.Errorf("scrape_interval must be at least 2 seconds when using delta profiling") } if target.Enabled && target.Delta { - if arg.ProfilingDuration.Seconds() <= 1 { - return fmt.Errorf("profiling_duration must be larger than 1 second when using delta profiling") + if arg.DeltaProfilingDuration.Seconds() <= 1 { + return fmt.Errorf("delta_profiling_duration must be larger than 1 second when using delta profiling") } - if arg.ProfilingDuration.Seconds() >= arg.ScrapeInterval.Seconds() { - return fmt.Errorf("profiling_duration must be smaller than scrape_interval when using delta profiling") + if arg.DeltaProfilingDuration.Seconds() > arg.ScrapeInterval.Seconds()-1 { + return fmt.Errorf("delta_profiling_duration must be at least 1 second smaller than scrape_interval when using delta profiling") } } } diff --git a/internal/component/pyroscope/scrape/scrape_test.go b/internal/component/pyroscope/scrape/scrape_test.go index 10a5c9c9dd..4d8ae93990 100644 --- a/internal/component/pyroscope/scrape/scrape_test.go +++ b/internal/component/pyroscope/scrape/scrape_test.go @@ -151,25 +151,25 @@ func TestUnmarshalConfig(t *testing.T) { `, expectedErr: "scrape_interval must be at least 2 seconds when using delta profiling", }, - "invalid cpu profiling_duration": { + "invalid cpu delta_profiling_duration": { in: ` targets = [] forward_to = null scrape_timeout = "1s" scrape_interval = "10s" - profiling_duration = "1s" + delta_profiling_duration = "1s" `, - expectedErr: "profiling_duration must be larger than 1 second when using delta profiling", + expectedErr: "delta_profiling_duration must be larger than 1 second when using delta profiling", }, - "erroneous cpu profiling_duration": { + "erroneous cpu delta_profiling_duration": { in: ` targets = [] forward_to = null scrape_timeout = "1s" scrape_interval = "10s" - profiling_duration = "12s" + delta_profiling_duration = "12s" `, - expectedErr: "profiling_duration must be smaller than scrape_interval when using delta profiling", + expectedErr: "delta_profiling_duration must be at least 1 second smaller than scrape_interval when using delta profiling", }, "allow short scrape_intervals without delta": { in: ` @@ -196,7 +196,7 @@ func TestUnmarshalConfig(t *testing.T) { forward_to = null scrape_timeout = "5s" scrape_interval = "3s" - profiling_duration = "2s" + delta_profiling_duration = "2s" bearer_token = "token" bearer_token_file = "/path/to/file.token" `, diff --git a/internal/component/pyroscope/scrape/target.go b/internal/component/pyroscope/scrape/target.go index a05bbfb0b0..c7dd581e9e 100644 --- a/internal/component/pyroscope/scrape/target.go +++ b/internal/component/pyroscope/scrape/target.go @@ -407,8 +407,8 @@ func targetsFromGroup(group *targetgroup.Group, cfg Arguments, targetTypes map[s if pcfg, found := targetTypes[profType]; found && pcfg.Delta { seconds := (cfg.ScrapeInterval)/time.Second - 1 - if cfg.ProfilingDuration != defaultProfilingDuration { - seconds = (cfg.ProfilingDuration) / time.Second + if cfg.DeltaProfilingDuration != defaultProfilingDuration { + seconds = (cfg.DeltaProfilingDuration) / time.Second } params.Add("seconds", strconv.Itoa(int(seconds))) } diff --git a/internal/component/pyroscope/scrape/target_test.go b/internal/component/pyroscope/scrape/target_test.go index d7793a6156..f7e825ff3a 100644 --- a/internal/component/pyroscope/scrape/target_test.go +++ b/internal/component/pyroscope/scrape/target_test.go @@ -238,12 +238,59 @@ func Test_targetsFromGroup(t *testing.T) { require.Empty(t, dropped) } -func Test_targetsFromGroup_withSpecifiedProfilingDuration(t *testing.T) { +// Test that the godeltaprof is not surfaced publicly +func Test_NewTarget_godeltaprof(t *testing.T) { + withGodeltaprof := NewTarget( + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9094", + serviceNameLabel: "docker-container", + model.MetricNameLabel: pprofGoDeltaProfMemory, + ProfilePath: "/debug/pprof/delta_heap", + model.SchemeLabel: "http", + "foo": "bar", + "instance": "localhost:9094", + }), + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9094", + "__meta_docker_container_name": "docker-container", + model.MetricNameLabel: pprofGoDeltaProfMemory, + ProfilePath: "/debug/pprof/delta_heap", + model.SchemeLabel: "http", + "foo": "bar", + }), + url.Values{}, + ) + withoutGodeltaprof := NewTarget( + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9094", + serviceNameLabel: "docker-container", + model.MetricNameLabel: pprofMemory, + ProfilePath: "/debug/pprof/heap", + model.SchemeLabel: "http", + "foo": "bar", + "instance": "localhost:9094", + }), + labels.FromMap(map[string]string{ + model.AddressLabel: "localhost:9094", + "__meta_docker_container_name": "docker-container", + model.MetricNameLabel: pprofMemory, + ProfilePath: "/debug/pprof/heap", + model.SchemeLabel: "http", + "foo": "bar", + }), + url.Values{}, + ) + + require.NotEqual(t, withGodeltaprof.allLabels, withoutGodeltaprof.allLabels) + require.Equal(t, withGodeltaprof.publicLabels, withoutGodeltaprof.publicLabels) +} + +func Test_targetsFromGroup_withSpecifiedDeltaProfilingDuration(t *testing.T) { args := NewDefaultArguments() args.ProfilingConfig.Block.Enabled = false args.ProfilingConfig.Goroutine.Enabled = false args.ProfilingConfig.Mutex.Enabled = false - args.ProfilingDuration = 20 * time.Second + args.DeltaProfilingDuration = 20 * time.Second active, dropped, err := targetsFromGroup(&targetgroup.Group{ Targets: []model.LabelSet{ @@ -299,50 +346,3 @@ func Test_targetsFromGroup_withSpecifiedProfilingDuration(t *testing.T) { require.Equal(t, expected, active) require.Empty(t, dropped) } - -// Test that the godeltaprof is not surfaced publicly -func Test_NewTarget_godeltaprof(t *testing.T) { - withGodeltaprof := NewTarget( - labels.FromMap(map[string]string{ - model.AddressLabel: "localhost:9094", - serviceNameLabel: "docker-container", - model.MetricNameLabel: pprofGoDeltaProfMemory, - ProfilePath: "/debug/pprof/delta_heap", - model.SchemeLabel: "http", - "foo": "bar", - "instance": "localhost:9094", - }), - labels.FromMap(map[string]string{ - model.AddressLabel: "localhost:9094", - "__meta_docker_container_name": "docker-container", - model.MetricNameLabel: pprofGoDeltaProfMemory, - ProfilePath: "/debug/pprof/delta_heap", - model.SchemeLabel: "http", - "foo": "bar", - }), - url.Values{}, - ) - withoutGodeltaprof := NewTarget( - labels.FromMap(map[string]string{ - model.AddressLabel: "localhost:9094", - serviceNameLabel: "docker-container", - model.MetricNameLabel: pprofMemory, - ProfilePath: "/debug/pprof/heap", - model.SchemeLabel: "http", - "foo": "bar", - "instance": "localhost:9094", - }), - labels.FromMap(map[string]string{ - model.AddressLabel: "localhost:9094", - "__meta_docker_container_name": "docker-container", - model.MetricNameLabel: pprofMemory, - ProfilePath: "/debug/pprof/heap", - model.SchemeLabel: "http", - "foo": "bar", - }), - url.Values{}, - ) - - require.NotEqual(t, withGodeltaprof.allLabels, withoutGodeltaprof.allLabels) - require.Equal(t, withGodeltaprof.publicLabels, withoutGodeltaprof.publicLabels) -}