From 1cbfbabe7ab311a09c2ef1304bbfb7b5c050d04b Mon Sep 17 00:00:00 2001 From: Ian Kerins Date: Sat, 5 Oct 2024 15:02:24 -0400 Subject: [PATCH] Use upstream ecs-agent types for deserializing API responses This project rolls its own types for deserializing ECS task metadata and container stats responses. Maintaining these types can be tedious, as the documentation of these API endpoints is underspecified, in the sense that properties included in API responses are broadly available in the documentation, but their precise types (including whether properties are optional) are sometimes not. If we roll our own types, we are stuck reverse-engineering the specifics of the ECS API responses, which is made more tedious by the fact that these can differ between EC2 and Fargate. Good news: rolling our own types is not necessary. The ECS Agent is open source and written in Go. We can depend on it as a library, purely to get at the structs that it uses for API responses. We were already doing a similar thing for docker stats; this is just more comprehensive. (The ECS Agent project itself depends on the same docker library we were using for these stats, and includes them in its API responses.) Switching to these ECS Agent types has revealed situations in which our types were incorrect, silently relying on implicit type conversions of JSON values in Go's JSON deserializer. One of these situations was resulting in actually invalid data being served: ECS tasks on EC2 need not specify task-level resource limits at all, such that these properties are optional on the JSON response, but our types for them were not pointers, such that we were incorrectly reporting derived metrics as zero, when they really should not exist at all. The downsides of doing this: - The ECS Agent project has no detectable Go module version. I am not an expert on this, but I think it's related to a single repo containing multiple Go modules. I don't think this is a big deal, as the existing docker dependency already did not have a Go module version. - We have to upgrade to go 1.21, as the ECS agent project declares that it requires it in its go.mod. - Binary size grows, about 12MB -> 18MB on my laptop. I am surprised that simply switching to use these structs blew up binary size so much, but I don't think binary size is taken very seriously in the Go ecosystem anyway, so I don't think this is a big problem. I think these downsides are worth it in that, going forward, we can more reliably develop metrics derived from ECS Agent API responses, because we're using types that are much more likely to be correct. I plan to add more metrics, and improve existing ones, using these types in the future. I have validated these changes by recording output on EC2 and Fargate before and after this change here: https://github.com/isker/ecs-exporter-cdk/tree/master/experiments/use-official-types. The resulting diffs are as expected. Signed-off-by: Ian Kerins --- .circleci/config.yml | 2 +- .promu.yml | 2 +- ecscollector/collector.go | 58 ++++++++++++--------- ecsmetadata/client.go | 103 +++++++------------------------------- go.mod | 24 +++++---- go.sum | 75 ++++++++++++++++++--------- 6 files changed, 117 insertions(+), 147 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ee2ed01..cbc1ad9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,7 +6,7 @@ executors: # Whenever the Go version is updated here, .promu.yml should also be updated. golang: docker: - - image: cimg/go:1.20 + - image: cimg/go:1.23 jobs: test: executor: golang diff --git a/.promu.yml b/.promu.yml index 14983d5..dc4641b 100644 --- a/.promu.yml +++ b/.promu.yml @@ -1,7 +1,7 @@ go: # Whenever the Go version is updated here, .travis.yml and # .circle/config.yml should also be updated. - version: 1.20 + version: 1.21 repository: path: github.com/prometheus-community/ecs_exporter build: diff --git a/ecscollector/collector.go b/ecscollector/collector.go index 8873dca..87fff94 100644 --- a/ecscollector/collector.go +++ b/ecscollector/collector.go @@ -19,6 +19,7 @@ import ( "context" "fmt" "log" + "time" "github.com/prometheus-community/ecs_exporter/ecsmetadata" "github.com/prometheus/client_golang/prometheus" @@ -179,25 +180,32 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) { metadata.Revision, metadata.DesiredStatus, metadata.KnownStatus, - metadata.PullStartedAt, - metadata.PullStoppedAt, + metadata.PullStartedAt.Format(time.RFC3339Nano), + metadata.PullStoppedAt.Format(time.RFC3339Nano), metadata.AvailabilityZone, metadata.LaunchType, ) - ch <- prometheus.MustNewConstMetric( - svcCpuLimitDesc, - prometheus.GaugeValue, - float64(metadata.Limits.CPU), - svcLabels..., - ) - - ch <- prometheus.MustNewConstMetric( - svcMemLimitDesc, - prometheus.GaugeValue, - float64(metadata.Limits.Memory), - svcLabels..., - ) + // Task CPU/memory limits are optional when running on EC2 - the relevant + // limits may only exist at the container level. + if metadata.Limits != nil { + if metadata.Limits.CPU != nil { + ch <- prometheus.MustNewConstMetric( + svcCpuLimitDesc, + prometheus.GaugeValue, + *metadata.Limits.CPU, + metadata.TaskARN, + ) + } + if metadata.Limits.Memory != nil { + ch <- prometheus.MustNewConstMetric( + svcMemLimitDesc, + prometheus.GaugeValue, + float64(*metadata.Limits.Memory), + metadata.TaskARN, + ) + } + } stats, err := c.client.RetrieveTaskStats(ctx) if err != nil { @@ -205,9 +213,9 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) { return } for _, container := range metadata.Containers { - s := stats[container.DockerID] + s := stats[container.ID] if s == nil { - log.Printf("Couldn't find container with ID %q in stats", container.DockerID) + log.Printf("Couldn't find container with ID %q in stats", container.ID) continue } @@ -248,14 +256,14 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) { networkLabelVals := append(labelVals, iface) for desc, value := range map[*prometheus.Desc]float64{ - networkRxBytesDesc: netStats.RxBytes, - networkRxPacketsDesc: netStats.RxPackets, - networkRxDroppedDesc: netStats.RxDropped, - networkRxErrorsDesc: netStats.RxErrors, - networkTxBytesDesc: netStats.TxBytes, - networkTxPacketsDesc: netStats.TxPackets, - networkTxDroppedDesc: netStats.TxDropped, - networkTxErrorsDesc: netStats.TxErrors, + networkRxBytesDesc: float64(netStats.RxBytes), + networkRxPacketsDesc: float64(netStats.RxPackets), + networkRxDroppedDesc: float64(netStats.RxDropped), + networkRxErrorsDesc: float64(netStats.RxErrors), + networkTxBytesDesc: float64(netStats.TxBytes), + networkTxPacketsDesc: float64(netStats.TxPackets), + networkTxDroppedDesc: float64(netStats.TxDropped), + networkTxErrorsDesc: float64(netStats.TxErrors), } { ch <- prometheus.MustNewConstMetric( desc, diff --git a/ecsmetadata/client.go b/ecsmetadata/client.go index ba1ea79..6c1ddbe 100644 --- a/ecsmetadata/client.go +++ b/ecsmetadata/client.go @@ -24,7 +24,7 @@ import ( "net/url" "os" - dockertypes "github.com/docker/docker/api/types" + tmdsv4 "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state" ) type Client struct { @@ -58,14 +58,26 @@ func NewClientFromEnvironment() (*Client, error) { return NewClient(endpoint), nil } -func (c *Client) RetrieveTaskStats(ctx context.Context) (map[string]*ContainerStats, error) { - out := make(map[string]*ContainerStats) +func (c *Client) RetrieveTaskStats(ctx context.Context) (map[string]*tmdsv4.StatsResponse, error) { + // https://github.com/aws/amazon-ecs-agent/blob/cf8c7a6b65043c550533f330b10aef6d0a342214/agent/handlers/v4/tmdsstate.go#L202 + out := make(map[string]*tmdsv4.StatsResponse) err := c.request(ctx, c.endpoint+"/task/stats", &out) return out, err } -func (c *Client) RetrieveTaskMetadata(ctx context.Context) (*TaskMetadata, error) { - var out TaskMetadata +func (c *Client) RetrieveTaskMetadata(ctx context.Context) (*tmdsv4.TaskResponse, error) { + // https://github.com/aws/amazon-ecs-agent/blob/cf8c7a6b65043c550533f330b10aef6d0a342214/agent/handlers/v4/tmdsstate.go#L174 + // + // Note that EC2 and Fargate return slightly different task metadata + // responses. At time of writing, as per the documentation, only EC2 has `ServiceName`, + // while only Fargate has `EphemeralStorageMetrics`, `ClockDrift`, and + // `Containers[].Snapshotter`. Ref: + // https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-metadata-endpoint-v4-fargate-response.html + // https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-metadata-endpoint-v4-response.html + // + // But `TaskResponse` is the _union_ of these two responses. It has all the + // fields. + var out tmdsv4.TaskResponse err := c.request(ctx, c.endpoint+"/task", &out) return &out, err } @@ -88,84 +100,3 @@ func (c *Client) request(ctx context.Context, uri string, out interface{}) error } return json.Unmarshal(body, out) } - -type ContainerStats struct { - Name string `json:"name"` - ID string `json:"id"` - NumProcs float64 `json:"num_procs"` - Read string `json:"read"` - PreRead string `json:"preread"` - - CPUStats dockertypes.CPUStats `json:"cpu_stats"` - PreCPUStats dockertypes.CPUStats `json:"precpu_stats"` - MemoryStats dockertypes.MemoryStats `json:"memory_stats"` - BlkioStats dockertypes.BlkioStats `json:"blkio_stats"` - - Networks map[string]struct { - RxBytes float64 `json:"rx_bytes"` - RxPackets float64 `json:"rx_packets"` - RxErrors float64 `json:"rx_errors"` - RxDropped float64 `json:"rx_dropped"` - TxBytes float64 `json:"tx_bytes"` - TxPackets float64 `json:"tx_packets"` - TxErrors float64 `json:"tx_errors"` - TxDropped float64 `json:"tx_dropped"` - } `json:"networks"` - - NetworkRateStats struct { - RxBytesPerSec float64 `json:"rx_bytes_per_sec"` - TxBytesPerSec float64 `json:"tx_bytes_per_sec"` - } `json:"network_rate_stats"` -} - -type TaskMetadataLimits struct { - CPU float64 `json:"CPU"` - Memory float64 `json:"Memory"` -} - -type TaskMetadata struct { - Cluster string `json:"Cluster"` - TaskARN string `json:"TaskARN"` - Family string `json:"Family"` - Revision string `json:"Revision"` - DesiredStatus string `json:"DesiredStatus"` - KnownStatus string `json:"KnownStatus"` - Limits TaskMetadataLimits `json:"Limits"` - PullStartedAt string `json:"PullStartedAt"` - PullStoppedAt string `json:"PullStoppedAt"` - AvailabilityZone string `json:"AvailabilityZone"` - LaunchType string `json:"LaunchType"` - Containers []struct { - DockerID string `json:"DockerId"` - Name string `json:"Name"` - DockerName string `json:"DockerName"` - Image string `json:"Image"` - ImageID string `json:"ImageID"` - Labels map[string]string `json:"Labels"` - DesiredStatus string `json:"DesiredStatus"` - KnownStatus string `json:"KnownStatus"` - CreatedAt string `json:"CreatedAt"` - StartedAt string `json:"StartedAt"` - Type string `json:"Type"` - Networks []struct { - NetworkMode string `json:"NetworkMode"` - IPv4Addresses []string `json:"IPv4Addresses"` - IPv6Addresses []string `json:"IPv6Addresses"` - AttachmentIndex float64 `json:"AttachmentIndex"` - MACAddress string `json:"MACAddress"` - IPv4SubnetCIDRBlock string `json:"IPv4SubnetCIDRBlock"` - IPv6SubnetCIDRBlock string `json:"IPv6SubnetCIDRBlock"` - DomainNameServers []string `json:"DomainNameServers"` - DomainNameSearchList []string `json:"DomainNameSearchList"` - PrivateDNSName string `json:"PrivateDNSName"` - SubnetGatewayIpv4Address string `json:"SubnetGatewayIpv4Address"` - } `json:"Networks"` - ClockDrift []struct { - ClockErrorBound float64 `json:"ClockErrorBound"` - ReferenceTimestamp string `json:"ReferenceTimestamp"` - ClockSynchronizationStatus string `json:"ClockSynchronizationStatus"` - } `json:"ClockDrift"` - ContainerARN string `json:"ContainerARN"` - LogDriver string `json:"LogDriver"` - } `json:"Containers"` -} diff --git a/go.mod b/go.mod index c48c04d..fe8a0a3 100644 --- a/go.mod +++ b/go.mod @@ -1,28 +1,32 @@ module github.com/prometheus-community/ecs_exporter -go 1.20 +go 1.22 require ( - github.com/docker/docker v24.0.2+incompatible + github.com/aws/amazon-ecs-agent/ecs-agent v0.0.0-20240920192628-cf8c7a6b6504 github.com/prometheus/client_golang v1.15.1 ) require ( + github.com/aws/aws-sdk-go v1.51.3 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 // indirect + github.com/docker/docker v24.0.9+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-units v0.4.0 // indirect - github.com/gogo/protobuf v1.1.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/image-spec v1.1.0-rc3 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect - golang.org/x/sys v0.6.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect - gotest.tools/v3 v3.3.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/sys v0.25.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect ) diff --git a/go.sum b/go.sum index ec112c6..68b37ef 100644 --- a/go.sum +++ b/go.sum @@ -1,29 +1,46 @@ +github.com/aws/amazon-ecs-agent/ecs-agent v0.0.0-20240920192628-cf8c7a6b6504 h1:GCqRAsQkz8ssbQ2Kyy7hjbgld7uAoKY3GNwwDf0XSFk= +github.com/aws/amazon-ecs-agent/ecs-agent v0.0.0-20240920192628-cf8c7a6b6504/go.mod h1:mQ9gdfxZBa2v0TknkosGTps/oZRKpn9dvKTVh1C64Ac= +github.com/aws/aws-sdk-go v1.51.3 h1:OqSyEXcJwf/XhZNVpMRgKlLA9nmbo5X8dwbll4RWxq8= +github.com/aws/aws-sdk-go v1.51.3/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs= +github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/docker/docker v24.0.2+incompatible h1:eATx+oLz9WdNVkQrr0qjQ8HvRJ4bOOxfzEo8R+dA3cg= -github.com/docker/docker v24.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= +github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= +github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -36,38 +53,48 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= -gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=