Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade agent to prometheus 2.51 #6754

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions docs/sources/flow/reference/components/prometheus.scrape.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ Name | Type | Description | Default | Required
`forward_to` | `list(MetricsReceiver)` | List of receivers to send scraped metrics to. | | yes
`job_name` | `string` | The value to use for the job label if not already set. | component name | no
`extra_metrics` | `bool` | Whether extra metrics should be generated for scrape targets. | `false` | no
`enable_protobuf_negotiation` | `bool` | Whether to enable protobuf negotiation with the client. | `false` | no
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this go into breaking changes documentation?

`honor_labels` | `bool` | Indicator whether the scraped metrics should remain unmodified. | `false` | no
`honor_timestamps` | `bool` | Indicator whether the scraped timestamps should be respected. | `true` | no
`track_timestamps_staleness` | `bool` | Indicator whether to track the staleness of the scraped timestamps. | `false` | no
`params` | `map(list(string))` | A set of query parameters with which the target is scraped. | | no
`scrape_classic_histograms` | `bool` | Whether to scrape a classic histogram that is also exposed as a native histogram. | `false` | no
`scrape_interval` | `duration` | How frequently to scrape the targets of this scrape configuration. | `"60s"` | no
`scrape_timeout` | `duration` | The timeout for scraping targets of this configuration. | `"10s"` | no
`scrape_protocols` | `list(string)` | The protocols to negotiate during a scrape with the client. | __see below__ | no
`metrics_path` | `string` | The HTTP resource path on which to fetch metrics from targets. | `/metrics` | no
`scheme` | `string` | The URL scheme with which to fetch metrics from targets. | | no
`body_size_limit` | `int` | An uncompressed response body larger than this many bytes causes the scrape to fail. 0 means no limit. | | no
Expand Down Expand Up @@ -92,6 +92,21 @@ Name | Type | Description | Default | Required
* It is recommended to set `track_timestamps_staleness` to `true` if the database where metrics are written to has enabled [out of order ingestion][mimir-ooo].
* If `track_timestamps_staleness` is set to `false`, samples with explicit timestamps will only be labeled as stale after a certain time period, which in Prometheus is 5 minutes by default.

The supported values for `scrape_protocols` are:
* `"PrometheusProto"`
* `"PrometheusText0.0.4"`
* `"OpenMetricsText0.0.1"`
* `"OpenMetricsText1.0.0"`

<!-- TODO: Is this true? They seem to change with native histograms settings:
https://github.com/prometheus/prometheus/pull/12738/files#diff-17f1012e0c2fbd9bcd8dff3c23b18ff4b6676eef3beca6f8a3e72e6a36633334R64-R68
-->
The default values are:
* `"PrometheusProto"`
* `"OpenMetricsText1.0.0"`
* `"OpenMetricsText0.0.1"`
* `"PrometheusText0.0.4"`

[prom-text-exposition-format]: https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format
[prom-staleness]: https://prometheus.io/docs/prometheus/latest/querying/basics/#staleness
[mimir-ooo]: https://grafana.com/docs/mimir/latest/configure/configure-out-of-order-samples-ingestion/
Expand Down Expand Up @@ -253,11 +268,8 @@ times out while scraping, or because the samples from the target could not be
processed. When the target is behaving normally, the `up` metric is set to
`1`.

To enable scraping of Prometheus' native histograms over gRPC, the
`enable_protobuf_negotiation` must be set to true. The
`scrape_classic_histograms` argument controls whether the component should also
scrape the 'classic' histogram equivalent of a native histogram, if it is
present.
The `scrape_classic_histograms` argument controls whether the component should also
scrape the 'classic' histogram equivalent of a native histogram, if it is present.

[in-memory traffic]: {{< relref "../../concepts/component_controller.md#in-memory-traffic" >}}
[run command]: {{< relref "../cli/run.md" >}}
Expand Down
137 changes: 72 additions & 65 deletions go.mod

Large diffs are not rendered by default.

339 changes: 142 additions & 197 deletions go.sum

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion internal/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package build

import (
"github.com/prometheus/client_golang/prometheus"
collectorversion "github.com/prometheus/client_golang/prometheus/collectors/version"
"github.com/prometheus/common/version"
)

Expand Down Expand Up @@ -34,7 +35,7 @@ func injectVersion() {
func NewCollector(program string) prometheus.Collector {
injectVersion()

return version.NewCollector(program)
return collectorversion.NewCollector(program)
}

// Print returns version information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ prometheus.scrape "scrape_prom_metrics" {
]
forward_to = [prometheus.remote_write.scrape_prom_metrics.receiver]
scrape_classic_histograms = true
enable_protobuf_negotiation = true
scrape_interval = "1s"
scrape_timeout = "500ms"
}
Expand Down
2 changes: 2 additions & 0 deletions internal/component/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,6 @@ import (
_ "github.com/grafana/agent/internal/component/remote/kubernetes/secret" // Import remote.kubernetes.secret
_ "github.com/grafana/agent/internal/component/remote/s3" // Import remote.s3
_ "github.com/grafana/agent/internal/component/remote/vault" // Import remote.vault

_ "github.com/grafana/agent/internal/util/otelfeaturegatefix" // Gracefully handle duplicate OTEL feature gates
)
5 changes: 2 additions & 3 deletions internal/component/discovery/aws/ec2.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,7 @@ func (args *EC2Arguments) Validate() error {

// New creates a new discovery.ec2 component.
func NewEC2(opts component.Options, args EC2Arguments) (component.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
conf := args.(EC2Arguments).Convert()
return promaws.NewEC2Discovery(conf, opts.Logger), nil
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
return args.(EC2Arguments).Convert()
})
}
5 changes: 2 additions & 3 deletions internal/component/discovery/aws/lightsail.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ func (args *LightsailArguments) Validate() error {

// New creates a new discovery.lightsail component.
func NewLightsail(opts component.Options, args LightsailArguments) (component.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
conf := args.(LightsailArguments).Convert()
return promaws.NewLightsailDiscovery(conf, opts.Logger), nil
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
return args.(LightsailArguments).Convert()
})
}
4 changes: 2 additions & 2 deletions internal/component/discovery/azure/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ func (a *Arguments) Convert() *prom_discovery.SDConfig {

// New returns a new instance of a discovery.azure component.
func New(opts component.Options, args Arguments) (*discovery.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
newArgs := args.(Arguments)
return prom_discovery.NewDiscovery(newArgs.Convert(), opts.Logger), nil
return newArgs.Convert()
})
}
4 changes: 2 additions & 2 deletions internal/component/discovery/consul/consul.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ func (args *Arguments) Convert() *prom_discovery.SDConfig {

// New returns a new instance of a discovery.consul component.
func New(opts component.Options, args Arguments) (*discovery.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
newArgs := args.(Arguments)
return prom_discovery.NewDiscovery(newArgs.Convert(), opts.Logger)
return newArgs.Convert()
})
}
4 changes: 2 additions & 2 deletions internal/component/discovery/consulagent/consulagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ func (args *Arguments) Convert() *SDConfig {

// New returns a new instance of a discovery.consulagent component.
func New(opts component.Options, args Arguments) (*discovery.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
newArgs := args.(Arguments)
return NewDiscovery(newArgs.Convert(), opts.Logger)
return newArgs.Convert()
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ type SDConfig struct {
TLSConfig config.TLSConfig `yaml:"tls_config,omitempty"`
}

// NewDiscovererMetrics implements discovery.DiscovererConfig.
func (c *SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics {
return newDiscovererMetrics(reg, rmi)
}

// Name returns the name of the Config.
func (*SDConfig) Name() string { return "consulagent" }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// This code is copied from Promtail (https://https://github.com/grafana/loki/tree/3b5ed8c3ec88/clients/pkg/promtail/discovery/consulagent).
// Some changes have been made to improve the component:
// - "Namespace: namespace" has been removed

// This code was adapted from the consul service discovery
// package in prometheus: https://github.com/prometheus/prometheus/blob/main/discovery/consul/metrics.go
// which is copyrighted: 2015 The Prometheus Authors
// and licensed under the Apache License, Version 2.0 (the "License");

package consulagent

import (
"github.com/prometheus/client_golang/prometheus"

"github.com/prometheus/prometheus/discovery"
)

var _ discovery.DiscovererMetrics = (*consulMetrics)(nil)

type consulMetrics struct {
rpcFailuresCount prometheus.Counter
rpcDuration *prometheus.SummaryVec

servicesRPCDuration prometheus.Observer
serviceRPCDuration prometheus.Observer

metricRegisterer discovery.MetricRegisterer
}

func newDiscovererMetrics(reg prometheus.Registerer, _ discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics {
m := &consulMetrics{
rpcFailuresCount: prometheus.NewCounter(
prometheus.CounterOpts{
Name: "sd_consulagent_rpc_failures_total",
Help: "The number of Consul Agent RPC call failures.",
}),
rpcDuration: prometheus.NewSummaryVec(
prometheus.SummaryOpts{
Name: "sd_consulagent_rpc_duration_seconds",
Help: "The duration of a Consul Agent RPC call in seconds.",
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
},
[]string{"endpoint", "call"},
),
}

m.metricRegisterer = discovery.NewMetricRegisterer(reg, []prometheus.Collector{
m.rpcFailuresCount,
m.rpcDuration,
})

// Initialize metric vectors.
m.servicesRPCDuration = m.rpcDuration.WithLabelValues("agent", "services")
m.serviceRPCDuration = m.rpcDuration.WithLabelValues("agent", "service")

return m
}

// Register implements discovery.DiscovererMetrics.
func (m *consulMetrics) Register() error {
return m.metricRegisterer.RegisterMetrics()
}

// Unregister implements discovery.DiscovererMetrics.
func (m *consulMetrics) Unregister() {
m.metricRegisterer.UnregisterMetrics()
}
4 changes: 2 additions & 2 deletions internal/component/discovery/digitalocean/digitalocean.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ func (a *Arguments) Convert() *prom_discovery.SDConfig {

// New returns a new instance of a discovery.digitalocean component.
func New(opts component.Options, args Arguments) (*discovery.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
newArgs := args.(Arguments)
return prom_discovery.NewDiscovery(newArgs.Convert(), opts.Logger)
return newArgs.Convert()
})
}
55 changes: 46 additions & 9 deletions internal/component/discovery/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,12 @@ type Exports struct {
Targets []Target `river:"targets,attr"`
}

// Discoverer is an alias for Prometheus' Discoverer interface, so users of this package don't need
// DiscovererConfig is an alias for Prometheus' discovery.Config interface, so users of this package don't need
// to import github.com/prometheus/prometheus/discover as well.
type Discoverer discovery.Discoverer
type DiscovererConfig discovery.Config

// Creator is a function provided by an implementation to create a concrete Discoverer instance.
type Creator func(component.Arguments) (Discoverer, error)
// Creator is a function provided by an implementation to create a concrete DiscovererConfig instance.
type Creator func(component.Arguments) DiscovererConfig

// Component is a reusable component for any discovery implementation.
// it will handle dynamic updates and exporting targets appropriately for a scrape implementation.
Expand All @@ -110,13 +110,36 @@ type Component struct {
newDiscoverer chan struct{}

creator Creator

sdMetrics discovery.DiscovererMetrics
refreshMetrics discovery.DiscovererMetrics
}

// New creates a discovery component given arguments and a concrete Discovery implementation function.
func New(o component.Options, args component.Arguments, creator Creator) (*Component, error) {
// The metrics stay the same, even if the config of the SD mechanism changes.
// This means it's ok to do the registration now, with the initial config.
// This is similar ot how Prometheus does it.
discConfig := creator(args)
//TODO(ptodev): Change upstream Prometheus to have NewDiscovererMetrics outside of discovery.Config,
// to show that it's independent of the config.

//TODO(ptodev): It looks messy to have a refresh metrics separate from the other SD metrics.
// Can we make this cleaner? The reason it was made like this currently,
// is so that metrics exposed by Prometheus executables don't change.
refreshMetrics := discovery.NewRefreshMetrics(o.Registerer)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels ugly, so we dont have to Register the the refreshMetrics but we do need to unregister them? And then since we can get a newdiscover on the channel we have to unregister there. The fact they aren't balanced from looking at the code makes it rough.

sdMetrics := discConfig.NewDiscovererMetrics(o.Registerer, refreshMetrics)

err := sdMetrics.Register()
if err != nil {
return nil, err
}

c := &Component{
opts: o,
creator: creator,
opts: o,
creator: creator,
sdMetrics: sdMetrics,
refreshMetrics: refreshMetrics,
// buffered to avoid deadlock from the first immediate update
newDiscoverer: make(chan struct{}, 1),
}
Expand All @@ -125,6 +148,9 @@ func New(o component.Options, args component.Arguments, creator Creator) (*Compo

// Run implements component.Component.
func (c *Component) Run(ctx context.Context) error {
var wg sync.WaitGroup
defer wg.Wait()

var cancel context.CancelFunc
for {
select {
Expand All @@ -145,14 +171,25 @@ func (c *Component) Run(ctx context.Context) error {
c.discMut.Lock()
disc := c.latestDisc
c.discMut.Unlock()
go c.runDiscovery(newCtx, disc)
wg.Add(1)
go func() {
c.runDiscovery(newCtx, disc)
c.sdMetrics.Unregister()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like it should break if we create the discovering multiple time in the Update.

c.refreshMetrics.Unregister()
wg.Done()
}()
}
}
}

// Update implements component.Component.
func (c *Component) Update(args component.Arguments) error {
disc, err := c.creator(args)
discConfig := c.creator(args)

disc, err := discConfig.NewDiscoverer(discovery.DiscovererOptions{
Logger: c.opts.Logger,
Metrics: c.sdMetrics,
})
if err != nil {
return err
}
Expand All @@ -174,7 +211,7 @@ var MaxUpdateFrequency = 5 * time.Second

// runDiscovery is a utility for consuming and forwarding target groups from a discoverer.
// It will handle collating targets (and clearing), as well as time based throttling of updates.
func (c *Component) runDiscovery(ctx context.Context, d Discoverer) {
func (c *Component) runDiscovery(ctx context.Context, d discovery.Discoverer) {
// all targets we have seen so far
cache := map[string]*targetgroup.Group{}

Expand Down
6 changes: 3 additions & 3 deletions internal/component/discovery/dns/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ func (args Arguments) Convert() dns.SDConfig {

// New returns a new instance of a discovery.dns component.
func New(opts component.Options, args Arguments) (*discovery.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
conf := args.(Arguments).Convert()
return dns.NewDiscovery(conf, opts.Logger), nil
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
newArgs := args.(Arguments).Convert()
return &newArgs
})
}
6 changes: 3 additions & 3 deletions internal/component/discovery/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ func (args Arguments) Convert() moby.DockerSDConfig {

// New returns a new instance of a discovery.docker component.
func New(opts component.Options, args Arguments) (*discovery.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
conf := args.(Arguments).Convert()
return moby.NewDockerDiscovery(&conf, opts.Logger)
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
newArgs := args.(Arguments).Convert()
return &newArgs
})
}
4 changes: 2 additions & 2 deletions internal/component/discovery/dockerswarm/dockerswarm.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ func (f *Filter) convert() prom_discovery.Filter {

// New returns a new instance of discovery.dockerswarm component.
func New(opts component.Options, args Arguments) (*discovery.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
newArgs := args.(Arguments)
return prom_discovery.NewDiscovery(newArgs.Convert(), opts.Logger)
return newArgs.Convert()
})
}
4 changes: 2 additions & 2 deletions internal/component/discovery/eureka/eureka.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ func (a *Arguments) Convert() *prom_discovery.SDConfig {
}

func New(opts component.Options, args Arguments) (*discovery.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
newArgs := args.(Arguments)
return prom_discovery.NewDiscovery(newArgs.Convert(), opts.Logger)
return newArgs.Convert()
})
}
4 changes: 2 additions & 2 deletions internal/component/discovery/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ func (a *Arguments) Convert() *prom_discovery.SDConfig {
}

func New(opts component.Options, args Arguments) (*discovery.Component, error) {
return discovery.New(opts, args, func(args component.Arguments) (discovery.Discoverer, error) {
return discovery.New(opts, args, func(args component.Arguments) discovery.DiscovererConfig {
newArgs := args.(Arguments)
return prom_discovery.NewDiscovery(newArgs.Convert(), opts.Logger), nil
return newArgs.Convert()
})
}
Loading
Loading