diff --git a/.chloggen/init_valkey_receiver.yaml b/.chloggen/init_valkey_receiver.yaml new file mode 100644 index 0000000000000..b2560285058d7 --- /dev/null +++ b/.chloggen/init_valkey_receiver.yaml @@ -0,0 +1,27 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: 'new_component' + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: valkeyreceiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Init code for Valkey receiver + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [33787] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 77c67f4cca3ac..77eab7584e123 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -300,6 +300,7 @@ receiver/systemdreceiver/ @open-telemetry receiver/tcplogreceiver/ @open-telemetry/collector-contrib-approvers @djaglowski receiver/tlscheckreceiver/ @open-telemetry/collector-contrib-approvers @atoulme @michael-burt receiver/udplogreceiver/ @open-telemetry/collector-contrib-approvers @djaglowski +receiver/valkeyreceiver/ @open-telemetry/collector-contrib-approvers @dmitryax @rogercoll receiver/vcenterreceiver/ @open-telemetry/collector-contrib-approvers @schmikei @StefanKurek receiver/wavefrontreceiver/ @open-telemetry/collector-contrib-approvers @samiura receiver/webhookeventreceiver/ @open-telemetry/collector-contrib-approvers @atoulme @shalper2 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 0c198fb6e2725..ccb5d02e90416 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -303,6 +303,7 @@ body: - receiver/tcplog - receiver/tlscheck - receiver/udplog + - receiver/valkey - receiver/vcenter - receiver/wavefront - receiver/webhookevent diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index 49330e636b379..167b615d79f4d 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -297,6 +297,7 @@ body: - receiver/tcplog - receiver/tlscheck - receiver/udplog + - receiver/valkey - receiver/vcenter - receiver/wavefront - receiver/webhookevent diff --git a/.github/ISSUE_TEMPLATE/other.yaml b/.github/ISSUE_TEMPLATE/other.yaml index b97e7fca91a6f..2e576eb1437c1 100644 --- a/.github/ISSUE_TEMPLATE/other.yaml +++ b/.github/ISSUE_TEMPLATE/other.yaml @@ -297,6 +297,7 @@ body: - receiver/tcplog - receiver/tlscheck - receiver/udplog + - receiver/valkey - receiver/vcenter - receiver/wavefront - receiver/webhookevent diff --git a/.github/ISSUE_TEMPLATE/unmaintained.yaml b/.github/ISSUE_TEMPLATE/unmaintained.yaml index bcc1e2032c2d3..9efd3be354411 100644 --- a/.github/ISSUE_TEMPLATE/unmaintained.yaml +++ b/.github/ISSUE_TEMPLATE/unmaintained.yaml @@ -302,6 +302,7 @@ body: - receiver/tcplog - receiver/tlscheck - receiver/udplog + - receiver/valkey - receiver/vcenter - receiver/wavefront - receiver/webhookevent diff --git a/cmd/otelcontribcol/builder-config.yaml b/cmd/otelcontribcol/builder-config.yaml index d41e17e373ff4..9304b6eb059b6 100644 --- a/cmd/otelcontribcol/builder-config.yaml +++ b/cmd/otelcontribcol/builder-config.yaml @@ -166,7 +166,7 @@ receivers: - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/haproxyreceiver v0.118.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver v0.118.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/httpcheckreceiver v0.118.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/huaweicloudcesreceiver v0.118.0 + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/huaweicloudcesreceiver v0.118.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/influxdbreceiver v0.118.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/iisreceiver v0.118.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver v0.118.0 @@ -217,6 +217,7 @@ receivers: - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/syslogreceiver v0.118.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/tcplogreceiver v0.118.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/udplogreceiver v0.118.0 + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver v0.118.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/vcenterreceiver v0.118.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/wavefrontreceiver v0.118.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/webhookeventreceiver v0.118.0 @@ -347,6 +348,7 @@ replaces: - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza => ../../pkg/stanza - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/fluentforwardreceiver => ../../receiver/fluentforwardreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/redisreceiver => ../../receiver/redisreceiver + - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver => ../../receiver/valkeyreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/extension/basicauthextension => ../../extension/basicauthextension - github.com/open-telemetry/opentelemetry-collector-contrib/exporter/influxdbexporter => ../../exporter/influxdbexporter - github.com/open-telemetry/opentelemetry-collector-contrib/exporter/alertmanagerexporter => ../../exporter/alertmanagerexporter diff --git a/receiver/valkeyreceiver/Makefile b/receiver/valkeyreceiver/Makefile new file mode 100644 index 0000000000000..c1496226e5905 --- /dev/null +++ b/receiver/valkeyreceiver/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common \ No newline at end of file diff --git a/receiver/valkeyreceiver/README.md b/receiver/valkeyreceiver/README.md new file mode 100644 index 0000000000000..1d0162776ad40 --- /dev/null +++ b/receiver/valkeyreceiver/README.md @@ -0,0 +1,53 @@ +# Valkey Receiver + + +| Status | | +| ------------- |-----------| +| Stability | [development]: metrics | +| Distributions | [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Areceiver%2Fvalkey%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Fvalkey) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Areceiver%2Fvalkey%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Fvalkey) | +| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@dmitryax](https://www.github.com/dmitryax), [@rogercoll](https://www.github.com/rogercoll) | + +[development]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#development +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + + +The Valkey receiver is designed to retrieve Valkey INFO data from a single +Valkey instance, build metrics from that data, and send them to the next consumer at a +configurable interval. + +## Details + +The Valkey INFO command returns information and statistics about a Valkey +server (see [https://valkey.io/commands/info/](https://valkey.io/commands/info/) for +details). The Valkey receiver extracts values from the result and converts them to open +telemetry metrics. Details about the metrics produced by the Valkey receiver +can be found by browsing [the metadata file](./metadata.yaml). + +## Configuration + +The following settings are required: + +- `endpoint` (no default): The hostname and port of the Valkey instance, +separated by a colon. + +The following settings are optional: + +- `collection_interval` (default = `10s`): This receiver runs on an interval. +Each time it runs, it queries Valkey, creates metrics, and sends them to the +next consumer. The `collection_interval` configuration option tells this +receiver the duration between runs. This value must be a string readable by +Golang's `ParseDuration` function (example: `1h30m`). Valid time units are +`ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. +- `tls`: see [TLS Configuration Settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configtls/README.md#tls-configuration-settings) for the full set of available options. + +Example: + +```yaml +receivers: + valkey: + endpoint: "localhost:6379" + collection_interval: 10s +``` + +The full list of settings exposed for this receiver are documented [here](./config.go). diff --git a/receiver/valkeyreceiver/client.go b/receiver/valkeyreceiver/client.go new file mode 100644 index 0000000000000..e52d551a0d452 --- /dev/null +++ b/receiver/valkeyreceiver/client.go @@ -0,0 +1,69 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +package valkeyreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver" + +import ( + "context" + "fmt" + "strings" + + "github.com/valkey-io/valkey-go" +) + +var attrDelimiter = "\r\n" + +// Interface for a Valkey client. Implementation can be faked for testing. +type client interface { + // retrieves a string of key/value pairs of valkey metadata + retrieveInfo(context.Context) (map[string]string, error) + // close release Valkey client connection pool + close() error +} + +// Wraps a real Valkey client, implements `client` interface. +type valkeyClient struct { + client valkey.Client +} + +var _ client = (*valkeyClient)(nil) + +// Creates a new real Valkey client from the passed-in valkey.Options. +func newValkeyClient(options valkey.ClientOption) (client, error) { + innerClient, err := valkey.NewClient(options) + if err != nil { + return nil, err + } + return &valkeyClient{innerClient}, nil +} + +// Retrieve Valkey INFO. We retrieve all of the 'sections'. +func (c *valkeyClient) retrieveInfo(ctx context.Context) (map[string]string, error) { + str, err := c.client.Do(ctx, c.client.B().Info().Build()).ToString() + if err != nil { + return nil, err + } + + return parseRawDataMap(str) +} + +func parseRawDataMap(data string) (map[string]string, error) { + attrs := make(map[string]string) + lines := strings.Split(data, attrDelimiter) + for _, line := range lines { + if len(line) == 0 || strings.HasPrefix(line, "#") { + continue + } + key, value, found := strings.Cut(line, ":") + if !found { + return nil, fmt.Errorf("could not cut line %q using \":\" as delimiter", line) + } + attrs[key] = value + } + return attrs, nil +} + +// close client to release connection pool. +func (c *valkeyClient) close() error { + c.client.Close() + return nil +} diff --git a/receiver/valkeyreceiver/config.go b/receiver/valkeyreceiver/config.go new file mode 100644 index 0000000000000..ba7308914777d --- /dev/null +++ b/receiver/valkeyreceiver/config.go @@ -0,0 +1,40 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package valkeyreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver" + +import ( + "fmt" + "net" + + "go.opentelemetry.io/collector/config/confignet" + "go.opentelemetry.io/collector/config/configtls" + "go.opentelemetry.io/collector/scraper/scraperhelper" + + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver/internal/metadata" +) + +type Config struct { + scraperhelper.ControllerConfig `mapstructure:",squash"` + + // The target endpoint. + confignet.AddrConfig `mapstructure:",squash"` + + TLS configtls.ClientConfig `mapstructure:"tls,omitempty"` + + MetricsBuilderConfig metadata.MetricsBuilderConfig `mapstructure:",squash"` +} + +// configInfo holds configuration information to be used as resource/metrics attributes. +type configInfo struct { + Address string + Port string +} + +func newConfigInfo(cfg *Config) (configInfo, error) { + address, port, err := net.SplitHostPort(cfg.Endpoint) + if err != nil { + return configInfo{}, fmt.Errorf("invalid endpoint %q: %w", cfg.Endpoint, err) + } + return configInfo{Address: address, Port: port}, nil +} diff --git a/receiver/valkeyreceiver/doc.go b/receiver/valkeyreceiver/doc.go new file mode 100644 index 0000000000000..853b582df0b8c --- /dev/null +++ b/receiver/valkeyreceiver/doc.go @@ -0,0 +1,6 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:generate ../../.tools/mdatagen metadata.yaml + +package valkeyreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver" diff --git a/receiver/valkeyreceiver/documentation.md b/receiver/valkeyreceiver/documentation.md new file mode 100644 index 0000000000000..420983e11b418 --- /dev/null +++ b/receiver/valkeyreceiver/documentation.md @@ -0,0 +1,35 @@ +[comment]: <> (Code generated by mdatagen. DO NOT EDIT.) + +# valkey + +## Default Metrics + +The following metrics are emitted by default. Each of them can be disabled by applying the following configuration: + +```yaml +metrics: + : + enabled: false +``` + +### valkey.client.connection.count + +The number of connections that are currently in state described by the state attribute + +| Unit | Metric Type | Value Type | +| ---- | ----------- | ---------- | +| {connection} | Gauge | Int | + +#### Attributes + +| Name | Description | Values | +| ---- | ----------- | ------ | +| valkey.client.connection.state | The state of a connection in the pool | Str: ``used``, ``blocked``, ``tracking`` | + +## Resource Attributes + +| Name | Description | Values | Enabled | +| ---- | ----------- | ------ | ------- | +| server.address | Valkey server's address | Any Str | false | +| server.port | Valkey server's port | Any Str | false | +| valkey.version | Valkey server's version. | Any Str | true | diff --git a/receiver/valkeyreceiver/factory.go b/receiver/valkeyreceiver/factory.go new file mode 100644 index 0000000000000..261748ef24ca0 --- /dev/null +++ b/receiver/valkeyreceiver/factory.go @@ -0,0 +1,66 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package valkeyreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver" + +import ( + "context" + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/confignet" + "go.opentelemetry.io/collector/config/configtls" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/scraper" + "go.opentelemetry.io/collector/scraper/scraperhelper" + + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver/internal/metadata" +) + +// NewFactory creates a factory for Valkey receiver. +func NewFactory() receiver.Factory { + return receiver.NewFactory( + metadata.Type, + createDefaultConfig, + receiver.WithMetrics(createMetricsReceiver, metadata.MetricsStability)) +} + +func createDefaultConfig() component.Config { + scs := scraperhelper.NewDefaultControllerConfig() + scs.CollectionInterval = 10 * time.Second + return &Config{ + AddrConfig: confignet.AddrConfig{ + Transport: confignet.TransportTypeTCP, + }, + TLS: configtls.ClientConfig{ + Insecure: true, + }, + ControllerConfig: scs, + MetricsBuilderConfig: metadata.DefaultMetricsBuilderConfig(), + } +} + +func createMetricsReceiver( + _ context.Context, + set receiver.Settings, + cfg component.Config, + consumer consumer.Metrics, +) (receiver.Metrics, error) { + oCfg := cfg.(*Config) + + scrp, err := newValkeyScraper(oCfg, set) + if err != nil { + return nil, err + } + + scraper, err := scraper.NewMetrics( + scraper.ScrapeMetricsFunc(scrp.scrape), + scraper.WithShutdown(scrp.shutdown), + ) + if err != nil { + return nil, err + } + + return scraperhelper.NewScraperControllerReceiver(&oCfg.ControllerConfig, set, consumer, scraperhelper.AddScraper(metadata.Type, scraper)) +} diff --git a/receiver/valkeyreceiver/generated_component_test.go b/receiver/valkeyreceiver/generated_component_test.go new file mode 100644 index 0000000000000..7af8cfd3a7dac --- /dev/null +++ b/receiver/valkeyreceiver/generated_component_test.go @@ -0,0 +1,69 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package valkeyreceiver + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "valkey", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +func TestComponentLifecycle(t *testing.T) { + factory := NewFactory() + + tests := []struct { + name string + createFn func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) + }{ + + { + name: "metrics", + createFn: func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) { + return factory.CreateMetrics(ctx, set, cfg, consumertest.NewNop()) + }, + }, + } + + cm, err := confmaptest.LoadConf("metadata.yaml") + require.NoError(t, err) + cfg := factory.CreateDefaultConfig() + sub, err := cm.Sub("tests::config") + require.NoError(t, err) + require.NoError(t, sub.Unmarshal(&cfg)) + + for _, tt := range tests { + t.Run(tt.name+"-shutdown", func(t *testing.T) { + c, err := tt.createFn(context.Background(), receivertest.NewNopSettings(), cfg) + require.NoError(t, err) + err = c.Shutdown(context.Background()) + require.NoError(t, err) + }) + t.Run(tt.name+"-lifecycle", func(t *testing.T) { + firstRcvr, err := tt.createFn(context.Background(), receivertest.NewNopSettings(), cfg) + require.NoError(t, err) + host := componenttest.NewNopHost() + require.NoError(t, err) + require.NoError(t, firstRcvr.Start(context.Background(), host)) + require.NoError(t, firstRcvr.Shutdown(context.Background())) + secondRcvr, err := tt.createFn(context.Background(), receivertest.NewNopSettings(), cfg) + require.NoError(t, err) + require.NoError(t, secondRcvr.Start(context.Background(), host)) + require.NoError(t, secondRcvr.Shutdown(context.Background())) + }) + } +} diff --git a/receiver/valkeyreceiver/generated_package_test.go b/receiver/valkeyreceiver/generated_package_test.go new file mode 100644 index 0000000000000..7a4005cd7a771 --- /dev/null +++ b/receiver/valkeyreceiver/generated_package_test.go @@ -0,0 +1,13 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package valkeyreceiver + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/valkeyreceiver/go.mod b/receiver/valkeyreceiver/go.mod new file mode 100644 index 0000000000000..281f204b3efb4 --- /dev/null +++ b/receiver/valkeyreceiver/go.mod @@ -0,0 +1,115 @@ +module github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver + +go 1.22.7 + +require ( + github.com/google/go-cmp v0.6.0 + github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.117.0 + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden v0.118.0 + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.118.0 + github.com/stretchr/testify v1.10.0 + github.com/testcontainers/testcontainers-go v0.35.0 + github.com/valkey-io/valkey-go v1.0.45 + go.opentelemetry.io/collector/component v0.118.1-0.20250123125445-24f88da7b583 + go.opentelemetry.io/collector/component/componenttest v0.118.1-0.20250123125445-24f88da7b583 + go.opentelemetry.io/collector/config/confignet v1.23.0 + go.opentelemetry.io/collector/config/configtls v1.23.0 + go.opentelemetry.io/collector/confmap v1.23.0 + go.opentelemetry.io/collector/consumer v1.24.1-0.20250123125445-24f88da7b583 + go.opentelemetry.io/collector/consumer/consumertest v0.118.1-0.20250123125445-24f88da7b583 + go.opentelemetry.io/collector/filter v0.117.0 + go.opentelemetry.io/collector/pdata v1.24.1-0.20250123125445-24f88da7b583 + go.opentelemetry.io/collector/receiver v0.118.1-0.20250123125445-24f88da7b583 + go.opentelemetry.io/collector/receiver/receivertest v0.118.1-0.20250123125445-24f88da7b583 + go.opentelemetry.io/collector/scraper v0.117.0 + go.opentelemetry.io/collector/scraper/scraperhelper v0.117.0 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 +) + +require ( + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v27.3.1+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.2 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.118.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shirou/gopsutil/v3 v3.24.5 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/collector/config/configopaque v1.23.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.118.1-0.20250123125445-24f88da7b583 // indirect + go.opentelemetry.io/collector/consumer/consumererror v0.118.1-0.20250123125445-24f88da7b583 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.118.1-0.20250123125445-24f88da7b583 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.118.1-0.20250123125445-24f88da7b583 // indirect + go.opentelemetry.io/collector/pipeline v0.118.1-0.20250123125445-24f88da7b583 // indirect + go.opentelemetry.io/collector/receiver/xreceiver v0.118.1-0.20250123125445-24f88da7b583 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/sdk v1.34.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect + go.opentelemetry.io/proto/otlp v1.4.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect + google.golang.org/grpc v1.69.4 // indirect + google.golang.org/protobuf v1.36.3 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil => ../../pkg/pdatautil + +replace github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal => ../../internal/coreinternal + +replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest => ../../pkg/pdatatest + +replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden => ../../pkg/golden diff --git a/receiver/valkeyreceiver/go.sum b/receiver/valkeyreceiver/go.sum new file mode 100644 index 0000000000000..2111559d4b7ea --- /dev/null +++ b/receiver/valkeyreceiver/go.sum @@ -0,0 +1,269 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +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/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +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.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +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/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.2 h1:I2rtLRqXRy1p01m/utEtpZSSA6dcJbgGVuE27kW2PzQ= +github.com/knadh/koanf/v2 v2.1.2/go.mod h1:Gphfaen0q1Fc1HTgJgSTC4oRX9R2R5ErYMZJy8fLJBo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= +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.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +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= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= +github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo= +github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/valkey-io/valkey-go v1.0.45 h1:d2ksu+FvKEy9pU9CCMZ94ABTLm2kNHU0jxEJZRqpFA4= +github.com/valkey-io/valkey-go v1.0.45/go.mod h1:BXlVAPIL9rFQinSFM+N32JfWzfCaUAqBpZkc4vPY6fM= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/collector/component v0.118.1-0.20250123125445-24f88da7b583 h1:j8aeyY8Zhv2jzxyqFysoZ1RRGDFMV8UlGdOx4/8V5/w= +go.opentelemetry.io/collector/component v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:/fqrkzmOXsqm4boZaVtxi5YIz39/i8K8Wqd9oryz8Iw= +go.opentelemetry.io/collector/component/componenttest v0.118.1-0.20250123125445-24f88da7b583 h1:dQ/TorvDpM6JDmO5h9+STjEKlc5EHJ0J580/NkFed4o= +go.opentelemetry.io/collector/component/componenttest v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:eug78n4rxt5hdCSDWZ50wpYZXAl0ho/w6IsNtVZzQII= +go.opentelemetry.io/collector/config/confignet v1.23.0 h1:gq90GDgQFSjAeFkDeIkstkBwYrD8feUjqEWCrIJhFGA= +go.opentelemetry.io/collector/config/confignet v1.23.0/go.mod h1:ZppUH1hgUJOubawEsxsQ9MzEYFytqo2GnVSS7d4CVxc= +go.opentelemetry.io/collector/config/configopaque v1.23.0 h1:SEnEzOHufGc4KGOjQq8zKIQuDBmRFl9ncZ3qs1SRpJk= +go.opentelemetry.io/collector/config/configopaque v1.23.0/go.mod h1:sW0t0iI/VfRL9VYX7Ik6XzVgPcR+Y5kejTLsYcMyDWs= +go.opentelemetry.io/collector/config/configtelemetry v0.118.1-0.20250123125445-24f88da7b583 h1:Zn/SsRcYWqoFHeLAU4ZPmqj086yS/RZI8OWM8Srr0oA= +go.opentelemetry.io/collector/config/configtelemetry v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:SlBEwQg0qly75rXZ6W1Ig8jN25KBVBkFIIAUI1GiAAE= +go.opentelemetry.io/collector/config/configtls v1.23.0 h1:52q9dAV923hHn1aoYQyKGnrRXCPvTTT3DXurtxcpZaQ= +go.opentelemetry.io/collector/config/configtls v1.23.0/go.mod h1:cjMoqKm4MX9sc9qyEW5/kRepiKLuDYqFofGa0f/rqFE= +go.opentelemetry.io/collector/confmap v1.23.0 h1:EY+auc0kbyZ4HIfkLYeJyLDCZIFzMA1u8QRGW4bC1Ag= +go.opentelemetry.io/collector/confmap v1.23.0/go.mod h1:Rrhs+MWoaP6AswZp+ReQ2VO9dfOfcUjdjiSHBsG+nec= +go.opentelemetry.io/collector/consumer v1.24.1-0.20250123125445-24f88da7b583 h1:TbnwJmdaKaGztRZ0tWeJ7pCRirNdz9MeDwwk+WZslHs= +go.opentelemetry.io/collector/consumer v1.24.1-0.20250123125445-24f88da7b583/go.mod h1:YyTWeyBUYlVi983ylJAY5qHnCajq67on3A59OpS6A/I= +go.opentelemetry.io/collector/consumer/consumererror v0.118.1-0.20250123125445-24f88da7b583 h1:Cr3hudfh+YNB6F+wWlsLzZza3XvdkYApQsOgQ1Z739g= +go.opentelemetry.io/collector/consumer/consumererror v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:/fhqEIxH0hmnDa6zm38XzsdURr5GrlC9oKO70JVorHU= +go.opentelemetry.io/collector/consumer/consumertest v0.118.1-0.20250123125445-24f88da7b583 h1:QV2iN4kyzyTJq/472xHM9xDv8FZ2u3eSCnMSDhdfB54= +go.opentelemetry.io/collector/consumer/consumertest v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:fOVRcSFNghbaDpTJtTVHvFEQHeAAW8WEX0dYWbPpgBc= +go.opentelemetry.io/collector/consumer/xconsumer v0.118.1-0.20250123125445-24f88da7b583 h1:kVq7l/BjtuqjWSBuYAA6pEB2ucYF/6qOXGOyrFgKhzk= +go.opentelemetry.io/collector/consumer/xconsumer v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:Ij9o9d7hZb4be6ql6yqMR7xy5fcFR0SSD6RRIYWlu88= +go.opentelemetry.io/collector/filter v0.117.0 h1:iQAbrho8TzcOxoroJDiQnvy1KvfTqwwNAhtg/sXYYAE= +go.opentelemetry.io/collector/filter v0.117.0/go.mod h1:MUyBRsy3IKVixSWIfA9BXzHhx24LHo4y38uQmFlqddA= +go.opentelemetry.io/collector/pdata v1.24.1-0.20250123125445-24f88da7b583 h1:dXIRezA9B0F1c0enm5U0jzTu4BDbxankZHpRbTiKItc= +go.opentelemetry.io/collector/pdata v1.24.1-0.20250123125445-24f88da7b583/go.mod h1:6lE9r5x41Z9GyvTSBetXSHRikhiZZK5ApmFtX35ZbXc= +go.opentelemetry.io/collector/pdata/pprofile v0.118.1-0.20250123125445-24f88da7b583 h1:INMmM3orAT8nI5LO6T+BvTgM00vL/O8ttCDTljn17sU= +go.opentelemetry.io/collector/pdata/pprofile v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:iD66/nCk+xHh4q/1FBcYBQTEZKZuejggZBkm14/cobA= +go.opentelemetry.io/collector/pdata/testdata v0.118.0 h1:5N0w1SX9KIRkwvtkrpzQgXy9eGk3vfNG0ds6mhEPMIM= +go.opentelemetry.io/collector/pdata/testdata v0.118.0/go.mod h1:UY+GHV5bOC1BnFburOZ0wiHReJj1XbW12mi2Ogbc5Lw= +go.opentelemetry.io/collector/pipeline v0.118.1-0.20250123125445-24f88da7b583 h1:RKMWMoxRzs5x11tKmU5MhoCzu+Ms1cIBwe2y/dpDPWo= +go.opentelemetry.io/collector/pipeline v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:qE3DmoB05AW0C3lmPvdxZqd/H4po84NPzd5MrqgtL74= +go.opentelemetry.io/collector/receiver v0.118.1-0.20250123125445-24f88da7b583 h1:EFwikkSzWBqYw9dRc6cbsXxEMGh0cAF3Y8MfPd+HWmE= +go.opentelemetry.io/collector/receiver v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:w9MEboroi3iac6nRLdAyTxX9C2+WMdMfWm4UZJnX1UY= +go.opentelemetry.io/collector/receiver/receivertest v0.118.1-0.20250123125445-24f88da7b583 h1:24Tp2Qmxilsm4LkwcOosANkznMzV4jzhI2H4Tz58n3E= +go.opentelemetry.io/collector/receiver/receivertest v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:x9N91YI3onF0+enjYegcHYOb50Of2xO05c8EyE/baJ0= +go.opentelemetry.io/collector/receiver/xreceiver v0.118.1-0.20250123125445-24f88da7b583 h1:J4Pqe4mB7+clH50XeXqfAStYD7a/9Y0mG6C7aFi0k/w= +go.opentelemetry.io/collector/receiver/xreceiver v0.118.1-0.20250123125445-24f88da7b583/go.mod h1:WLPXXIuodY7quBgqCz3OIsPNdBMLDej5nUIbiyyfoUc= +go.opentelemetry.io/collector/scraper v0.117.0 h1:FFBM6Pzc3L0sTronrceanvqxT74Nurbi8usUSImexJ0= +go.opentelemetry.io/collector/scraper v0.117.0/go.mod h1:6dM+85+aNPWfu63H+m8ZZutxDYCrWVXJ1yylR0jB9kA= +go.opentelemetry.io/collector/scraper/scraperhelper v0.117.0 h1:jyQ7cdanR541XKSryExBNYKZVvVw27Sos1Rb88Sf/II= +go.opentelemetry.io/collector/scraper/scraperhelper v0.117.0/go.mod h1:zt7M+HIlYJHdnFC5smM8AaczZevVHYkaG1yjnq26/i8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg= +go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +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/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +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/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +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/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +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.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/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 h1:pgr/4QbFyktUv9CtQ/Fq4gzEE6/Xs7iCXbktaGzLHbQ= +google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697/go.mod h1:+D9ySVjN8nY8YCVjc5O7PZDIdZporIDY3KaGfJunh88= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 h1:LWZqQOEjDyONlF1H6afSWpAL/znlREo2tHfLoe+8LMA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/receiver/valkeyreceiver/integration_test.go b/receiver/valkeyreceiver/integration_test.go new file mode 100644 index 0000000000000..faea6a342e045 --- /dev/null +++ b/receiver/valkeyreceiver/integration_test.go @@ -0,0 +1,58 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:build integration + +package valkeyreceiver + +import ( + "fmt" + "path/filepath" + "testing" + "time" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" + "go.opentelemetry.io/collector/component" + + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/scraperinttest" + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest" +) + +const valkeyPort = "6379" + +func TestIntegration(t *testing.T) { + t.Run("8", integrationTest("8.0")) +} + +func integrationTest(version string) func(*testing.T) { + return scraperinttest.NewIntegrationTest( + NewFactory(), + scraperinttest.WithContainerRequest( + testcontainers.ContainerRequest{ + Image: fmt.Sprintf("valkey/valkey:%s", version), + ExposedPorts: []string{valkeyPort}, + WaitingFor: wait.ForListeningPort(valkeyPort).WithStartupTimeout(2 * time.Minute), + }), + scraperinttest.WithCustomConfig( + func(t *testing.T, cfg component.Config, ci *scraperinttest.ContainerInfo) { + rCfg := cfg.(*Config) + rCfg.MetricsBuilderConfig.ResourceAttributes.ServerPort.Enabled = true + rCfg.MetricsBuilderConfig.ResourceAttributes.ServerAddress.Enabled = true + rCfg.Endpoint = fmt.Sprintf("%s:%s", ci.Host(t), ci.MappedPort(t, valkeyPort)) + }), + scraperinttest.WithExpectedFile(filepath.Join("testdata", "all-metrics", "output-metrics.yaml")), + scraperinttest.WithCompareOptions( + pmetrictest.IgnoreMetricValues(), + pmetrictest.IgnoreMetricDataPointsOrder(), + pmetrictest.IgnoreStartTimestamp(), + pmetrictest.IgnoreTimestamp(), + pmetrictest.ChangeResourceAttributeValue("server.address", func(_ string) string { + return "localhost" + }), + pmetrictest.ChangeResourceAttributeValue("server.port", func(_ string) string { + return valkeyPort + }), + ), + ).Run +} diff --git a/receiver/valkeyreceiver/internal/metadata/generated_config.go b/receiver/valkeyreceiver/internal/metadata/generated_config.go new file mode 100644 index 0000000000000..269c888449ae8 --- /dev/null +++ b/receiver/valkeyreceiver/internal/metadata/generated_config.go @@ -0,0 +1,100 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/confmap" + "go.opentelemetry.io/collector/filter" +) + +// MetricConfig provides common config for a particular metric. +type MetricConfig struct { + Enabled bool `mapstructure:"enabled"` + + enabledSetByUser bool +} + +func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(ms) + if err != nil { + return err + } + ms.enabledSetByUser = parser.IsSet("enabled") + return nil +} + +// MetricsConfig provides config for valkey metrics. +type MetricsConfig struct { + ValkeyClientConnectionCount MetricConfig `mapstructure:"valkey.client.connection.count"` +} + +func DefaultMetricsConfig() MetricsConfig { + return MetricsConfig{ + ValkeyClientConnectionCount: MetricConfig{ + Enabled: true, + }, + } +} + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` + // Experimental: MetricsInclude defines a list of filters for attribute values. + // If the list is not empty, only metrics with matching resource attribute values will be emitted. + MetricsInclude []filter.Config `mapstructure:"metrics_include"` + // Experimental: MetricsExclude defines a list of filters for attribute values. + // If the list is not empty, metrics with matching resource attribute values will not be emitted. + // MetricsInclude has higher priority than MetricsExclude. + MetricsExclude []filter.Config `mapstructure:"metrics_exclude"` + + enabledSetByUser bool +} + +func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(rac) + if err != nil { + return err + } + rac.enabledSetByUser = parser.IsSet("enabled") + return nil +} + +// ResourceAttributesConfig provides config for valkey resource attributes. +type ResourceAttributesConfig struct { + ServerAddress ResourceAttributeConfig `mapstructure:"server.address"` + ServerPort ResourceAttributeConfig `mapstructure:"server.port"` + ValkeyVersion ResourceAttributeConfig `mapstructure:"valkey.version"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + ServerAddress: ResourceAttributeConfig{ + Enabled: false, + }, + ServerPort: ResourceAttributeConfig{ + Enabled: false, + }, + ValkeyVersion: ResourceAttributeConfig{ + Enabled: true, + }, + } +} + +// MetricsBuilderConfig is a configuration for valkey metrics builder. +type MetricsBuilderConfig struct { + Metrics MetricsConfig `mapstructure:"metrics"` + ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func DefaultMetricsBuilderConfig() MetricsBuilderConfig { + return MetricsBuilderConfig{ + Metrics: DefaultMetricsConfig(), + ResourceAttributes: DefaultResourceAttributesConfig(), + } +} diff --git a/receiver/valkeyreceiver/internal/metadata/generated_config_test.go b/receiver/valkeyreceiver/internal/metadata/generated_config_test.go new file mode 100644 index 0000000000000..9890615031c4b --- /dev/null +++ b/receiver/valkeyreceiver/internal/metadata/generated_config_test.go @@ -0,0 +1,115 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestMetricsBuilderConfig(t *testing.T) { + tests := []struct { + name string + want MetricsBuilderConfig + }{ + { + name: "default", + want: DefaultMetricsBuilderConfig(), + }, + { + name: "all_set", + want: MetricsBuilderConfig{ + Metrics: MetricsConfig{ + ValkeyClientConnectionCount: MetricConfig{Enabled: true}, + }, + ResourceAttributes: ResourceAttributesConfig{ + ServerAddress: ResourceAttributeConfig{Enabled: true}, + ServerPort: ResourceAttributeConfig{Enabled: true}, + ValkeyVersion: ResourceAttributeConfig{Enabled: true}, + }, + }, + }, + { + name: "none_set", + want: MetricsBuilderConfig{ + Metrics: MetricsConfig{ + ValkeyClientConnectionCount: MetricConfig{Enabled: false}, + }, + ResourceAttributes: ResourceAttributesConfig{ + ServerAddress: ResourceAttributeConfig{Enabled: false}, + ServerPort: ResourceAttributeConfig{Enabled: false}, + ValkeyVersion: ResourceAttributeConfig{Enabled: false}, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := loadMetricsBuilderConfig(t, tt.name) + diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(MetricConfig{}, ResourceAttributeConfig{})) + require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff) + }) + } +} + +func loadMetricsBuilderConfig(t *testing.T, name string) MetricsBuilderConfig { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(name) + require.NoError(t, err) + cfg := DefaultMetricsBuilderConfig() + require.NoError(t, sub.Unmarshal(&cfg)) + return cfg +} + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + ServerAddress: ResourceAttributeConfig{Enabled: true}, + ServerPort: ResourceAttributeConfig{Enabled: true}, + ValkeyVersion: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + ServerAddress: ResourceAttributeConfig{Enabled: false}, + ServerPort: ResourceAttributeConfig{Enabled: false}, + ValkeyVersion: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := loadResourceAttributesConfig(t, tt.name) + diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})) + require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff) + }) + } +} + +func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, sub.Unmarshal(&cfg)) + return cfg +} diff --git a/receiver/valkeyreceiver/internal/metadata/generated_metrics.go b/receiver/valkeyreceiver/internal/metadata/generated_metrics.go new file mode 100644 index 0000000000000..1ce4786f7e542 --- /dev/null +++ b/receiver/valkeyreceiver/internal/metadata/generated_metrics.go @@ -0,0 +1,268 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/filter" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver" +) + +// AttributeValkeyClientConnectionState specifies the value valkey.client.connection.state attribute. +type AttributeValkeyClientConnectionState int + +const ( + _ AttributeValkeyClientConnectionState = iota + AttributeValkeyClientConnectionStateUsed + AttributeValkeyClientConnectionStateBlocked + AttributeValkeyClientConnectionStateTracking +) + +// String returns the string representation of the AttributeValkeyClientConnectionState. +func (av AttributeValkeyClientConnectionState) String() string { + switch av { + case AttributeValkeyClientConnectionStateUsed: + return "used" + case AttributeValkeyClientConnectionStateBlocked: + return "blocked" + case AttributeValkeyClientConnectionStateTracking: + return "tracking" + } + return "" +} + +// MapAttributeValkeyClientConnectionState is a helper map of string to AttributeValkeyClientConnectionState attribute value. +var MapAttributeValkeyClientConnectionState = map[string]AttributeValkeyClientConnectionState{ + "used": AttributeValkeyClientConnectionStateUsed, + "blocked": AttributeValkeyClientConnectionStateBlocked, + "tracking": AttributeValkeyClientConnectionStateTracking, +} + +type metricValkeyClientConnectionCount struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills valkey.client.connection.count metric with initial data. +func (m *metricValkeyClientConnectionCount) init() { + m.data.SetName("valkey.client.connection.count") + m.data.SetDescription("The number of connections that are currently in state described by the state attribute") + m.data.SetUnit("{connection}") + m.data.SetEmptyGauge() + m.data.Gauge().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricValkeyClientConnectionCount) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, valkeyClientConnectionStateAttributeValue string) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) + dp.Attributes().PutStr("valkey.client.connection.state", valkeyClientConnectionStateAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricValkeyClientConnectionCount) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricValkeyClientConnectionCount) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricValkeyClientConnectionCount(cfg MetricConfig) metricValkeyClientConnectionCount { + m := metricValkeyClientConnectionCount{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +// MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations +// required to produce metric representation defined in metadata and user config. +type MetricsBuilder struct { + config MetricsBuilderConfig // config of the metrics builder. + startTime pcommon.Timestamp // start time that will be applied to all recorded data points. + metricsCapacity int // maximum observed number of metrics per resource. + metricsBuffer pmetric.Metrics // accumulates metrics data before emitting. + buildInfo component.BuildInfo // contains version information. + resourceAttributeIncludeFilter map[string]filter.Filter + resourceAttributeExcludeFilter map[string]filter.Filter + metricValkeyClientConnectionCount metricValkeyClientConnectionCount +} + +// MetricBuilderOption applies changes to default metrics builder. +type MetricBuilderOption interface { + apply(*MetricsBuilder) +} + +type metricBuilderOptionFunc func(mb *MetricsBuilder) + +func (mbof metricBuilderOptionFunc) apply(mb *MetricsBuilder) { + mbof(mb) +} + +// WithStartTime sets startTime on the metrics builder. +func WithStartTime(startTime pcommon.Timestamp) MetricBuilderOption { + return metricBuilderOptionFunc(func(mb *MetricsBuilder) { + mb.startTime = startTime + }) +} + +func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.Settings, options ...MetricBuilderOption) *MetricsBuilder { + mb := &MetricsBuilder{ + config: mbc, + startTime: pcommon.NewTimestampFromTime(time.Now()), + metricsBuffer: pmetric.NewMetrics(), + buildInfo: settings.BuildInfo, + metricValkeyClientConnectionCount: newMetricValkeyClientConnectionCount(mbc.Metrics.ValkeyClientConnectionCount), + resourceAttributeIncludeFilter: make(map[string]filter.Filter), + resourceAttributeExcludeFilter: make(map[string]filter.Filter), + } + if mbc.ResourceAttributes.ServerAddress.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["server.address"] = filter.CreateFilter(mbc.ResourceAttributes.ServerAddress.MetricsInclude) + } + if mbc.ResourceAttributes.ServerAddress.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["server.address"] = filter.CreateFilter(mbc.ResourceAttributes.ServerAddress.MetricsExclude) + } + if mbc.ResourceAttributes.ServerPort.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["server.port"] = filter.CreateFilter(mbc.ResourceAttributes.ServerPort.MetricsInclude) + } + if mbc.ResourceAttributes.ServerPort.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["server.port"] = filter.CreateFilter(mbc.ResourceAttributes.ServerPort.MetricsExclude) + } + if mbc.ResourceAttributes.ValkeyVersion.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["valkey.version"] = filter.CreateFilter(mbc.ResourceAttributes.ValkeyVersion.MetricsInclude) + } + if mbc.ResourceAttributes.ValkeyVersion.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["valkey.version"] = filter.CreateFilter(mbc.ResourceAttributes.ValkeyVersion.MetricsExclude) + } + + for _, op := range options { + op.apply(mb) + } + return mb +} + +// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted metrics. +func (mb *MetricsBuilder) NewResourceBuilder() *ResourceBuilder { + return NewResourceBuilder(mb.config.ResourceAttributes) +} + +// updateCapacity updates max length of metrics and resource attributes that will be used for the slice capacity. +func (mb *MetricsBuilder) updateCapacity(rm pmetric.ResourceMetrics) { + if mb.metricsCapacity < rm.ScopeMetrics().At(0).Metrics().Len() { + mb.metricsCapacity = rm.ScopeMetrics().At(0).Metrics().Len() + } +} + +// ResourceMetricsOption applies changes to provided resource metrics. +type ResourceMetricsOption interface { + apply(pmetric.ResourceMetrics) +} + +type resourceMetricsOptionFunc func(pmetric.ResourceMetrics) + +func (rmof resourceMetricsOptionFunc) apply(rm pmetric.ResourceMetrics) { + rmof(rm) +} + +// WithResource sets the provided resource on the emitted ResourceMetrics. +// It's recommended to use ResourceBuilder to create the resource. +func WithResource(res pcommon.Resource) ResourceMetricsOption { + return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) { + res.CopyTo(rm.Resource()) + }) +} + +// WithStartTimeOverride overrides start time for all the resource metrics data points. +// This option should be only used if different start time has to be set on metrics coming from different resources. +func WithStartTimeOverride(start pcommon.Timestamp) ResourceMetricsOption { + return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) { + var dps pmetric.NumberDataPointSlice + metrics := rm.ScopeMetrics().At(0).Metrics() + for i := 0; i < metrics.Len(); i++ { + switch metrics.At(i).Type() { + case pmetric.MetricTypeGauge: + dps = metrics.At(i).Gauge().DataPoints() + case pmetric.MetricTypeSum: + dps = metrics.At(i).Sum().DataPoints() + } + for j := 0; j < dps.Len(); j++ { + dps.At(j).SetStartTimestamp(start) + } + } + }) +} + +// EmitForResource saves all the generated metrics under a new resource and updates the internal state to be ready for +// recording another set of data points as part of another resource. This function can be helpful when one scraper +// needs to emit metrics from several resources. Otherwise calling this function is not required, +// just `Emit` function can be called instead. +// Resource attributes should be provided as ResourceMetricsOption arguments. +func (mb *MetricsBuilder) EmitForResource(options ...ResourceMetricsOption) { + rm := pmetric.NewResourceMetrics() + ils := rm.ScopeMetrics().AppendEmpty() + ils.Scope().SetName("github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver") + ils.Scope().SetVersion(mb.buildInfo.Version) + ils.Metrics().EnsureCapacity(mb.metricsCapacity) + mb.metricValkeyClientConnectionCount.emit(ils.Metrics()) + + for _, op := range options { + op.apply(rm) + } + for attr, filter := range mb.resourceAttributeIncludeFilter { + if val, ok := rm.Resource().Attributes().Get(attr); ok && !filter.Matches(val.AsString()) { + return + } + } + for attr, filter := range mb.resourceAttributeExcludeFilter { + if val, ok := rm.Resource().Attributes().Get(attr); ok && filter.Matches(val.AsString()) { + return + } + } + + if ils.Metrics().Len() > 0 { + mb.updateCapacity(rm) + rm.MoveTo(mb.metricsBuffer.ResourceMetrics().AppendEmpty()) + } +} + +// Emit returns all the metrics accumulated by the metrics builder and updates the internal state to be ready for +// recording another set of metrics. This function will be responsible for applying all the transformations required to +// produce metric representation defined in metadata and user config, e.g. delta or cumulative. +func (mb *MetricsBuilder) Emit(options ...ResourceMetricsOption) pmetric.Metrics { + mb.EmitForResource(options...) + metrics := mb.metricsBuffer + mb.metricsBuffer = pmetric.NewMetrics() + return metrics +} + +// RecordValkeyClientConnectionCountDataPoint adds a data point to valkey.client.connection.count metric. +func (mb *MetricsBuilder) RecordValkeyClientConnectionCountDataPoint(ts pcommon.Timestamp, val int64, valkeyClientConnectionStateAttributeValue AttributeValkeyClientConnectionState) { + mb.metricValkeyClientConnectionCount.recordDataPoint(mb.startTime, ts, val, valkeyClientConnectionStateAttributeValue.String()) +} + +// Reset resets metrics builder to its initial state. It should be used when external metrics source is restarted, +// and metrics builder should update its startTime and reset it's internal state accordingly. +func (mb *MetricsBuilder) Reset(options ...MetricBuilderOption) { + mb.startTime = pcommon.NewTimestampFromTime(time.Now()) + for _, op := range options { + op.apply(mb) + } +} diff --git a/receiver/valkeyreceiver/internal/metadata/generated_metrics_test.go b/receiver/valkeyreceiver/internal/metadata/generated_metrics_test.go new file mode 100644 index 0000000000000..5f8a707d68cb1 --- /dev/null +++ b/receiver/valkeyreceiver/internal/metadata/generated_metrics_test.go @@ -0,0 +1,120 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver/receivertest" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" +) + +type testDataSet int + +const ( + testDataSetDefault testDataSet = iota + testDataSetAll + testDataSetNone +) + +func TestMetricsBuilder(t *testing.T) { + tests := []struct { + name string + metricsSet testDataSet + resAttrsSet testDataSet + expectEmpty bool + }{ + { + name: "default", + }, + { + name: "all_set", + metricsSet: testDataSetAll, + resAttrsSet: testDataSetAll, + }, + { + name: "none_set", + metricsSet: testDataSetNone, + resAttrsSet: testDataSetNone, + expectEmpty: true, + }, + { + name: "filter_set_include", + resAttrsSet: testDataSetAll, + }, + { + name: "filter_set_exclude", + resAttrsSet: testDataSetAll, + expectEmpty: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + start := pcommon.Timestamp(1_000_000_000) + ts := pcommon.Timestamp(1_000_001_000) + observedZapCore, observedLogs := observer.New(zap.WarnLevel) + settings := receivertest.NewNopSettings() + settings.Logger = zap.New(observedZapCore) + mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, tt.name), settings, WithStartTime(start)) + + expectedWarnings := 0 + + assert.Equal(t, expectedWarnings, observedLogs.Len()) + + defaultMetricsCount := 0 + allMetricsCount := 0 + + defaultMetricsCount++ + allMetricsCount++ + mb.RecordValkeyClientConnectionCountDataPoint(ts, 1, AttributeValkeyClientConnectionStateUsed) + + rb := mb.NewResourceBuilder() + rb.SetServerAddress("server.address-val") + rb.SetServerPort("server.port-val") + rb.SetValkeyVersion("valkey.version-val") + res := rb.Emit() + metrics := mb.Emit(WithResource(res)) + + if tt.expectEmpty { + assert.Equal(t, 0, metrics.ResourceMetrics().Len()) + return + } + + assert.Equal(t, 1, metrics.ResourceMetrics().Len()) + rm := metrics.ResourceMetrics().At(0) + assert.Equal(t, res, rm.Resource()) + assert.Equal(t, 1, rm.ScopeMetrics().Len()) + ms := rm.ScopeMetrics().At(0).Metrics() + if tt.metricsSet == testDataSetDefault { + assert.Equal(t, defaultMetricsCount, ms.Len()) + } + if tt.metricsSet == testDataSetAll { + assert.Equal(t, allMetricsCount, ms.Len()) + } + validatedMetrics := make(map[string]bool) + for i := 0; i < ms.Len(); i++ { + switch ms.At(i).Name() { + case "valkey.client.connection.count": + assert.False(t, validatedMetrics["valkey.client.connection.count"], "Found a duplicate in the metrics slice: valkey.client.connection.count") + validatedMetrics["valkey.client.connection.count"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "The number of connections that are currently in state described by the state attribute", ms.At(i).Description()) + assert.Equal(t, "{connection}", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeInt, dp.ValueType()) + assert.Equal(t, int64(1), dp.IntValue()) + attrVal, ok := dp.Attributes().Get("valkey.client.connection.state") + assert.True(t, ok) + assert.EqualValues(t, "used", attrVal.Str()) + } + } + }) + } +} diff --git a/receiver/valkeyreceiver/internal/metadata/generated_resource.go b/receiver/valkeyreceiver/internal/metadata/generated_resource.go new file mode 100644 index 0000000000000..555ef3ad18523 --- /dev/null +++ b/receiver/valkeyreceiver/internal/metadata/generated_resource.go @@ -0,0 +1,50 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/pdata/pcommon" +) + +// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml. +// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines. +type ResourceBuilder struct { + config ResourceAttributesConfig + res pcommon.Resource +} + +// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application. +func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder { + return &ResourceBuilder{ + config: rac, + res: pcommon.NewResource(), + } +} + +// SetServerAddress sets provided value as "server.address" attribute. +func (rb *ResourceBuilder) SetServerAddress(val string) { + if rb.config.ServerAddress.Enabled { + rb.res.Attributes().PutStr("server.address", val) + } +} + +// SetServerPort sets provided value as "server.port" attribute. +func (rb *ResourceBuilder) SetServerPort(val string) { + if rb.config.ServerPort.Enabled { + rb.res.Attributes().PutStr("server.port", val) + } +} + +// SetValkeyVersion sets provided value as "valkey.version" attribute. +func (rb *ResourceBuilder) SetValkeyVersion(val string) { + if rb.config.ValkeyVersion.Enabled { + rb.res.Attributes().PutStr("valkey.version", val) + } +} + +// Emit returns the built resource and resets the internal builder state. +func (rb *ResourceBuilder) Emit() pcommon.Resource { + r := rb.res + rb.res = pcommon.NewResource() + return r +} diff --git a/receiver/valkeyreceiver/internal/metadata/generated_resource_test.go b/receiver/valkeyreceiver/internal/metadata/generated_resource_test.go new file mode 100644 index 0000000000000..37ba211212608 --- /dev/null +++ b/receiver/valkeyreceiver/internal/metadata/generated_resource_test.go @@ -0,0 +1,52 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResourceBuilder(t *testing.T) { + for _, tt := range []string{"default", "all_set", "none_set"} { + t.Run(tt, func(t *testing.T) { + cfg := loadResourceAttributesConfig(t, tt) + rb := NewResourceBuilder(cfg) + rb.SetServerAddress("server.address-val") + rb.SetServerPort("server.port-val") + rb.SetValkeyVersion("valkey.version-val") + + res := rb.Emit() + assert.Equal(t, 0, rb.Emit().Attributes().Len()) // Second call should return empty Resource + + switch tt { + case "default": + assert.Equal(t, 1, res.Attributes().Len()) + case "all_set": + assert.Equal(t, 3, res.Attributes().Len()) + case "none_set": + assert.Equal(t, 0, res.Attributes().Len()) + return + default: + assert.Failf(t, "unexpected test case: %s", tt) + } + + val, ok := res.Attributes().Get("server.address") + assert.Equal(t, tt == "all_set", ok) + if ok { + assert.EqualValues(t, "server.address-val", val.Str()) + } + val, ok = res.Attributes().Get("server.port") + assert.Equal(t, tt == "all_set", ok) + if ok { + assert.EqualValues(t, "server.port-val", val.Str()) + } + val, ok = res.Attributes().Get("valkey.version") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "valkey.version-val", val.Str()) + } + }) + } +} diff --git a/receiver/valkeyreceiver/internal/metadata/generated_status.go b/receiver/valkeyreceiver/internal/metadata/generated_status.go new file mode 100644 index 0000000000000..7b10b936b3ff4 --- /dev/null +++ b/receiver/valkeyreceiver/internal/metadata/generated_status.go @@ -0,0 +1,16 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("valkey") + ScopeName = "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver" +) + +const ( + MetricsStability = component.StabilityLevelDevelopment +) diff --git a/receiver/valkeyreceiver/internal/metadata/testdata/config.yaml b/receiver/valkeyreceiver/internal/metadata/testdata/config.yaml new file mode 100644 index 0000000000000..f3edf70b0ebed --- /dev/null +++ b/receiver/valkeyreceiver/internal/metadata/testdata/config.yaml @@ -0,0 +1,51 @@ +default: +all_set: + metrics: + valkey.client.connection.count: + enabled: true + resource_attributes: + server.address: + enabled: true + server.port: + enabled: true + valkey.version: + enabled: true +none_set: + metrics: + valkey.client.connection.count: + enabled: false + resource_attributes: + server.address: + enabled: false + server.port: + enabled: false + valkey.version: + enabled: false +filter_set_include: + resource_attributes: + server.address: + enabled: true + metrics_include: + - regexp: ".*" + server.port: + enabled: true + metrics_include: + - regexp: ".*" + valkey.version: + enabled: true + metrics_include: + - regexp: ".*" +filter_set_exclude: + resource_attributes: + server.address: + enabled: true + metrics_exclude: + - strict: "server.address-val" + server.port: + enabled: true + metrics_exclude: + - strict: "server.port-val" + valkey.version: + enabled: true + metrics_exclude: + - strict: "valkey.version-val" diff --git a/receiver/valkeyreceiver/metadata.yaml b/receiver/valkeyreceiver/metadata.yaml new file mode 100644 index 0000000000000..a3afccf1c46fe --- /dev/null +++ b/receiver/valkeyreceiver/metadata.yaml @@ -0,0 +1,48 @@ +type: valkey + +status: + class: receiver + stability: + development: [metrics] + distributions: [contrib] + codeowners: + active: [dmitryax, rogercoll] + +resource_attributes: + valkey.version: + description: Valkey server's version. + enabled: true + type: string + server.address: + description: Valkey server's address + enabled: false + type: string + server.port: + description: Valkey server's port + enabled: false + type: string + +attributes: + valkey.client.connection.state: + description: The state of a connection in the pool + type: string + enum: + - used + - blocked + - tracking + +metrics: + valkey.client.connection.count: + enabled: true + description: The number of connections that are currently in state described by the state attribute + unit: "{connection}" + gauge: + value_type: int + monotonic: false + aggregation_temporality: cumulative + attributes: [valkey.client.connection.state] + + +tests: + config: + endpoint: localhost:6379 diff --git a/receiver/valkeyreceiver/receiver.go b/receiver/valkeyreceiver/receiver.go new file mode 100644 index 0000000000000..5eec2d520150b --- /dev/null +++ b/receiver/valkeyreceiver/receiver.go @@ -0,0 +1,107 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package valkeyreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver" + +import ( + "context" + "fmt" + "strconv" + "time" + + "github.com/valkey-io/valkey-go" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver" + "go.uber.org/zap" + + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver/internal/metadata" +) + +type valkeyScraper struct { + client client + settings component.TelemetrySettings + cfg *Config + mb *metadata.MetricsBuilder + configInfo configInfo + logger *zap.Logger +} + +func newValkeyScraper(cfg *Config, settings receiver.Settings) (*valkeyScraper, error) { + configInfo, err := newConfigInfo(cfg) + if err != nil { + return nil, err + } + + return &valkeyScraper{ + cfg: cfg, + settings: settings.TelemetrySettings, + mb: metadata.NewMetricsBuilder(cfg.MetricsBuilderConfig, settings), + configInfo: configInfo, + logger: settings.Logger, + }, nil +} + +func (vs *valkeyScraper) shutdown(context.Context) error { + if vs.client != nil { + return vs.client.close() + } + return nil +} + +func (vs *valkeyScraper) scrape(ctx context.Context) (pmetric.Metrics, error) { + if vs.client == nil { + opts := valkey.ClientOption{ + InitAddress: []string{vs.cfg.Endpoint}, + } + + var err error + if opts.TLSConfig, err = vs.cfg.TLS.LoadTLSConfig(context.Background()); err != nil { + return pmetric.Metrics{}, err + } + if vs.client, err = newValkeyClient(opts); err != nil { + return pmetric.Metrics{}, err + } + } + + result, err := vs.client.retrieveInfo(ctx) + if err != nil { + return pmetric.Metrics{}, err + } + + // connected_clients + now := pcommon.NewTimestampFromTime(time.Now()) + vs.recordConnectionMetrics(now, result) + + rb := vs.mb.NewResourceBuilder() + rb.SetValkeyVersion(getValkeyVersion(result)) + rb.SetServerAddress(vs.configInfo.Address) + rb.SetServerPort(vs.configInfo.Port) + return vs.mb.Emit(metadata.WithResource(rb.Emit())), nil +} + +// getValkeyVersion retrieves version string from 'redis_version' Valkey info key-value pairs +// e.g. "redis_version:5.0.7" +func getValkeyVersion(info map[string]string) string { + if str, ok := info["redis_version"]; ok { + return str + } + return "unknown" +} + +func (vs *valkeyScraper) recordConnectionMetrics(now pcommon.Timestamp, info map[string]string) { + recordConnection := func(infoKey string, attribute metadata.AttributeValkeyClientConnectionState) { + if val, ok := info[infoKey]; ok { + if i, err := strconv.ParseInt(val, 10, 64); err == nil { + vs.mb.RecordValkeyClientConnectionCountDataPoint(now, i, attribute) + } else { + vs.logger.Error(fmt.Errorf("could not parse field %s from key %s as integer: %w", val, infoKey, err).Error()) + } + } + } + + recordConnection("connected_clients", metadata.AttributeValkeyClientConnectionStateUsed) + recordConnection("blocked_clients", metadata.AttributeValkeyClientConnectionStateBlocked) + recordConnection("tracking_clients", metadata.AttributeValkeyClientConnectionStateTracking) +} diff --git a/receiver/valkeyreceiver/receiver_test.go b/receiver/valkeyreceiver/receiver_test.go new file mode 100644 index 0000000000000..142207a3510f1 --- /dev/null +++ b/receiver/valkeyreceiver/receiver_test.go @@ -0,0 +1,63 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package valkeyreceiver + +import ( + "context" + _ "embed" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/receiver/receivertest" + + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden" + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest" +) + +//go:embed testdata/all-metrics/raw_info.txt +var rawInfo string + +type mockClient struct{} + +func (mockClient) retrieveInfo(context.Context) (map[string]string, error) { + return parseRawDataMap(rawInfo) +} + +func (mockClient) close() error { + return nil +} + +var _ client = (*mockClient)(nil) + +func TestScrape(t *testing.T) { + // TODO: change to test table for testing multiple clients output + goldenDir := filepath.Join("testdata", "all-metrics") + settings := receivertest.NewNopSettings() + cfg := createDefaultConfig().(*Config) + cfg.Endpoint = "localhost:6379" + cfg.MetricsBuilderConfig.ResourceAttributes.ServerPort.Enabled = true + cfg.MetricsBuilderConfig.ResourceAttributes.ServerAddress.Enabled = true + scraper, err := newValkeyScraper(cfg, settings) + + require.NoError(t, err) + scraper.client = mockClient{} + + metrics, err := scraper.scrape(context.Background()) + require.NoError(t, err) + + expectedMetrics, err := golden.ReadMetrics(filepath.Join(goldenDir, "output-metrics.yaml")) + require.NoError(t, err) + + require.NoError(t, pmetrictest.CompareMetrics(expectedMetrics, metrics, pmetrictest.IgnoreMetricDataPointsOrder(), pmetrictest.IgnoreTimestamp(), pmetrictest.IgnoreStartTimestamp(), pmetrictest.ChangeResourceAttributeValue("server.address", func(_ string) string { + return "localhost" + }), + pmetrictest.ChangeResourceAttributeValue("server.port", func(_ string) string { + return "6379" + }), + )) + + err = scraper.shutdown(context.Background()) + require.NoError(t, err) +} diff --git a/receiver/valkeyreceiver/testdata/all-metrics/output-metrics.yaml b/receiver/valkeyreceiver/testdata/all-metrics/output-metrics.yaml new file mode 100644 index 0000000000000..be1345a3727fa --- /dev/null +++ b/receiver/valkeyreceiver/testdata/all-metrics/output-metrics.yaml @@ -0,0 +1,43 @@ +resourceMetrics: + - resource: + attributes: + - key: valkey.version + value: + stringValue: 7.2.4 + - key: server.address + value: + stringValue: localhost + - key: server.port + value: + stringValue: "32787" + scopeMetrics: + - metrics: + - description: The number of connections that are currently in state described by the state attribute + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: valkey.client.connection.state + value: + stringValue: blocked + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "1" + attributes: + - key: valkey.client.connection.state + value: + stringValue: tracking + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "1" + attributes: + - key: valkey.client.connection.state + value: + stringValue: used + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: valkey.client.connection.count + unit: '{connection}' + scope: + name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver + version: latest diff --git a/receiver/valkeyreceiver/testdata/all-metrics/raw_info.txt b/receiver/valkeyreceiver/testdata/all-metrics/raw_info.txt new file mode 100644 index 0000000000000..d2cd23c2ac39c --- /dev/null +++ b/receiver/valkeyreceiver/testdata/all-metrics/raw_info.txt @@ -0,0 +1,230 @@ +txt:# Server +redis_version:7.2.4 +server_name:valkey +valkey_version:8.0.1 +redis_git_sha1:00000000 +redis_git_dirty:0 +redis_build_id:b5fcc5ff6824bfbe +server_mode:standalone +os:Linux 6.12.4-arch1-1 x86_64 +arch_bits:64 +monotonic_clock:POSIX clock_gettime +multiplexing_api:epoll +gcc_version:12.2.0 +process_id:1 +process_supervised:no +run_id:4696ce3c4381c93858d03274ffff54a68db12f09 +tcp_port:6379 +server_time_usec:1735063850046939 +uptime_in_seconds:636 +uptime_in_days:0 +hz:10 +configured_hz:10 +lru_clock:7010602 +executable:/data/valkey-server +config_file: +io_threads_active:0 +availability_zone: +listener0:name=tcp,bind=*,bind=-::*,port=6379 + +# Clients +connected_clients:1 +cluster_connections:0 +maxclients:10000 +client_recent_max_input_buffer:0 +client_recent_max_output_buffer:0 +blocked_clients:0 +tracking_clients:1 +pubsub_clients:0 +watching_clients:0 +clients_in_timeout_table:0 +total_watched_keys:0 +total_blocking_keys:0 +total_blocking_keys_on_nokey:0 + +# Memory +used_memory:1101288 +used_memory_human:1.05M +used_memory_rss:16199680 +used_memory_rss_human:15.45M +used_memory_peak:1101288 +used_memory_peak_human:1.05M +used_memory_peak_perc:100.00% +used_memory_overhead:912128 +used_memory_startup:911944 +used_memory_dataset:189160 +used_memory_dataset_perc:99.90% +allocator_allocated:1780640 +allocator_active:1908736 +allocator_resident:7331840 +allocator_muzzy:0 +total_system_memory:33297350656 +total_system_memory_human:31.01G +used_memory_lua:31744 +used_memory_vm_eval:31744 +used_memory_lua_human:31.00K +used_memory_scripts_eval:0 +number_of_cached_scripts:0 +number_of_functions:0 +number_of_libraries:0 +used_memory_vm_functions:33792 +used_memory_vm_total:65536 +used_memory_vm_total_human:64.00K +used_memory_functions:184 +used_memory_scripts:184 +used_memory_scripts_human:184B +maxmemory:0 +maxmemory_human:0B +maxmemory_policy:noeviction +allocator_frag_ratio:1.07 +allocator_frag_bytes:128096 +allocator_rss_ratio:3.84 +allocator_rss_bytes:5423104 +rss_overhead_ratio:2.21 +rss_overhead_bytes:8867840 +mem_fragmentation_ratio:15.27 +mem_fragmentation_bytes:15138720 +mem_not_counted_for_evict:0 +mem_replication_backlog:0 +mem_total_replication_buffers:0 +mem_clients_slaves:0 +mem_clients_normal:0 +mem_cluster_links:0 +mem_aof_buffer:0 +mem_allocator:jemalloc-5.3.0 +mem_overhead_db_hashtable_rehashing:0 +active_defrag_running:0 +lazyfree_pending_objects:0 +lazyfreed_objects:0 + +# Persistence +loading:0 +async_loading:0 +current_cow_peak:0 +current_cow_size:0 +current_cow_size_age:0 +current_fork_perc:0.00 +current_save_keys_processed:0 +current_save_keys_total:0 +rdb_changes_since_last_save:0 +rdb_bgsave_in_progress:0 +rdb_last_save_time:1735063214 +rdb_last_bgsave_status:ok +rdb_last_bgsave_time_sec:-1 +rdb_current_bgsave_time_sec:-1 +rdb_saves:0 +rdb_last_cow_size:0 +rdb_last_load_keys_expired:0 +rdb_last_load_keys_loaded:0 +aof_enabled:0 +aof_rewrite_in_progress:0 +aof_rewrite_scheduled:0 +aof_last_rewrite_time_sec:-1 +aof_current_rewrite_time_sec:-1 +aof_last_bgrewrite_status:ok +aof_rewrites:0 +aof_rewrites_consecutive_failures:0 +aof_last_write_status:ok +aof_last_cow_size:0 +module_fork_in_progress:0 +module_fork_last_cow_size:0 + +# Stats +total_connections_received:5 +total_commands_processed:32 +instantaneous_ops_per_sec:0 +total_net_input_bytes:1157 +total_net_output_bytes:23927 +total_net_repl_input_bytes:0 +total_net_repl_output_bytes:0 +instantaneous_input_kbps:0.00 +instantaneous_output_kbps:0.00 +instantaneous_input_repl_kbps:0.00 +instantaneous_output_repl_kbps:0.00 +rejected_connections:0 +sync_full:0 +sync_partial_ok:0 +sync_partial_err:0 +expired_keys:0 +expired_stale_perc:0.00 +expired_time_cap_reached_count:0 +expire_cycle_cpu_milliseconds:6 +evicted_keys:0 +evicted_clients:0 +evicted_scripts:0 +total_eviction_exceeded_time:0 +current_eviction_exceeded_time:0 +keyspace_hits:0 +keyspace_misses:0 +pubsub_channels:0 +pubsub_patterns:0 +pubsubshard_channels:0 +latest_fork_usec:0 +total_forks:0 +migrate_cached_sockets:0 +slave_expires_tracked_keys:0 +active_defrag_hits:0 +active_defrag_misses:0 +active_defrag_key_hits:0 +active_defrag_key_misses:0 +total_active_defrag_time:0 +current_active_defrag_time:0 +tracking_total_keys:0 +tracking_total_items:0 +tracking_total_prefixes:0 +unexpected_error_replies:0 +total_error_replies:5 +dump_payload_sanitizations:0 +total_reads_processed:22 +total_writes_processed:17 +io_threaded_reads_processed:0 +io_threaded_writes_processed:0 +io_threaded_freed_objects:0 +io_threaded_poll_processed:0 +io_threaded_total_prefetch_batches:0 +io_threaded_total_prefetch_entries:0 +client_query_buffer_limit_disconnections:0 +client_output_buffer_limit_disconnections:0 +reply_buffer_shrinks:1 +reply_buffer_expands:0 +eventloop_cycles:6366 +eventloop_duration_sum:785038 +eventloop_duration_cmd_sum:192 +instantaneous_eventloop_cycles_per_sec:9 +instantaneous_eventloop_duration_usec:111 +acl_access_denied_auth:0 +acl_access_denied_cmd:0 +acl_access_denied_key:0 +acl_access_denied_channel:0 + +# Replication +role:master +connected_slaves:0 +replicas_waiting_psync:0 +master_failover_state:no-failover +master_replid:98fe17ad8267e5c4afdb732cbd69ac962f45a2b3 +master_replid2:0000000000000000000000000000000000000000 +master_repl_offset:0 +second_repl_offset:-1 +repl_backlog_active:0 +repl_backlog_size:10485760 +repl_backlog_first_byte_offset:0 +repl_backlog_histlen:0 + +# CPU +used_cpu_sys:0.317747 +used_cpu_user:0.516715 +used_cpu_sys_children:0.000000 +used_cpu_user_children:0.002436 +used_cpu_sys_main_thread:0.319071 +used_cpu_user_main_thread:0.514337 + +# Modules + +# Errorstats +errorstat_ERR:count=5 + +# Cluster +cluster_enabled:0 + +# Keyspace diff --git a/reports/distributions/contrib.yaml b/reports/distributions/contrib.yaml index 7a98d9742fbb6..1ed1877e6927e 100644 --- a/reports/distributions/contrib.yaml +++ b/reports/distributions/contrib.yaml @@ -194,6 +194,7 @@ components: - tcplog - tlscheck - udplog + - valkey - vcenter - wavefront - webhookevent diff --git a/versions.yaml b/versions.yaml index efcf483ba3331..07fafe2274a4c 100644 --- a/versions.yaml +++ b/versions.yaml @@ -231,7 +231,7 @@ module-sets: - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/googlecloudspannerreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/haproxyreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver - - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/huaweicloudcesreceiver + - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/huaweicloudcesreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/httpcheckreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/iisreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/influxdbreceiver @@ -291,6 +291,7 @@ module-sets: - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/tcplogreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/tlscheckreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/udplogreceiver + - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/valkeyreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/vcenterreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/wavefrontreceiver - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/webhookeventreceiver