diff --git a/.gitignore b/.gitignore index fe0b3c7f..5346f1da 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.dll *.so *.dylib +**/.gocache # Test binary, built with `go test -c` *.test @@ -39,4 +40,4 @@ opentelemetry-go # Telegraf artifacts config.toml -out.json \ No newline at end of file +out.json**/.gocache diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/Makefile b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/Makefile new file mode 100644 index 00000000..ded7a360 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/README.md b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/README.md new file mode 100644 index 00000000..8a7b00d3 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/README.md @@ -0,0 +1,11 @@ +# Sketch Metrics Processor + +This processor maintains Count-Min sketches over incoming metric datapoints (inspired by the Telegraf `countmin` aggregator). Each batch updates per-metric sketches keyed by tag dimensions, then emits a synthetic metric containing: + +- Serialized Count-Min sketch payload (`countmin` attribute, bytes) +- Rows/columns/count metadata +- Approximate top-k heavy hitters (`topk` attribute, JSON) + +Use `tag_keys` to explicitly choose which tags participate in the sketch. If omitted, all tags except those in `group_by` are used. Set `drop_original: true` to forward only the sketch metric. + +See `config.go` for configuration details. diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/component_test.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/component_test.go new file mode 100644 index 00000000..6784db8b --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/component_test.go @@ -0,0 +1,23 @@ +package sketchcountminprocessor + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/processor/processortest" +) + +func TestComponentLifecycle(t *testing.T) { + factory := NewFactory() + cfg := factory.CreateDefaultConfig() + + processor, err := factory.CreateMetrics(context.Background(), processortest.NewNopSettings(typeStr), cfg, consumertest.NewNop()) + require.NoError(t, err) + + host := componenttest.NewNopHost() + require.NoError(t, processor.Start(context.Background(), host)) + require.NoError(t, processor.Shutdown(context.Background())) +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/config.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/config.go new file mode 100644 index 00000000..4a865c1b --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/config.go @@ -0,0 +1,58 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sketchcountminprocessor // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/sketchmetricsprocessor" + +import ( + "fmt" + + "go.opentelemetry.io/collector/component" +) + +// Config defines configuration for the sketchmetrics processor. +// +// It is intentionally similar to the Telegraf countmin aggregator: +// +// [[aggregators.countmin]] +// +// measurement = "countmin" +// tag_keys = ["machineid", "tenant"] +// group_by = ["scrape_url"] +// rows = 3 +// columns = 4096 +// seed = 11400714819323198485 +// top_k = 20 +type Config struct { + // Name of the metric to emit (equivalent to Telegraf Measurement). + Measurement string `mapstructure:"measurement"` + + // TagKeys explicitly specify which tag keys are used as the "by(...)" dimensions + // for top-k. If empty, all tags except GroupBy will be used. + TagKeys []string `mapstructure:"tag_keys"` + + // GroupBy defines tags that partition the population into sub-groups. + // For each unique combination of group_by tags we maintain a separate set of sketches. + GroupBy []string `mapstructure:"group_by"` + + // Count-Min sketch parameters. + Rows int `mapstructure:"rows"` + Columns int `mapstructure:"columns"` + Seed uint64 `mapstructure:"seed"` + TopK int `mapstructure:"top_k"` + + // If true, original input metrics are dropped and only sketch metrics are forwarded. + DropOriginal bool `mapstructure:"drop_original"` +} + +var _ component.Config = (*Config)(nil) + +// Validate checks if the processor configuration is valid. +func (c *Config) Validate() error { + if c.TopK < 0 { + return fmt.Errorf("sketchmetrics: top_k must be >= 0") + } + if c.Rows < 0 || c.Columns < 0 { + return fmt.Errorf("sketchmetrics: rows/columns must be >= 0") + } + return nil +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/config_test.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/config_test.go new file mode 100644 index 00000000..7b0eae9f --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/config_test.go @@ -0,0 +1,26 @@ +package sketchcountminprocessor + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestConfigValidate(t *testing.T) { + cfg := Config{ + Measurement: "countmin", + Rows: 3, + Columns: 4, + TopK: 10, + } + assert.NoError(t, cfg.Validate()) + + cfg.TopK = -1 + assert.Error(t, cfg.Validate()) + cfg.TopK = 1 + cfg.Rows = -1 + assert.Error(t, cfg.Validate()) + cfg.Rows = 1 + cfg.Columns = -1 + assert.Error(t, cfg.Validate()) +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/countmin.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/countmin.go new file mode 100644 index 00000000..57ceb7a8 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/countmin.go @@ -0,0 +1,149 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sketchcountminprocessor + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "hash" + "io" + "math" + + "github.com/cespare/xxhash/v2" +) + +const ( + defaultRows = 3 + defaultColumns = 4096 + defaultSeed = 0x9e3779b185ebca87 +) + +var errInvalidConfig = errors.New("sketchmetrics: missing config") + +type CountMinSketch struct { + rows int + cols int + total float64 + table []float32 + salts []uint64 + hashes []hash.Hash64 + topk *TopKHeap +} + +func NewCountMinSketch(rows, cols int, seed uint64, topk int) (*CountMinSketch, error) { + if rows <= 0 || cols <= 0 { + return nil, fmt.Errorf("countmin: invalid dimensions rows=%d cols=%d", rows, cols) + } + cms := &CountMinSketch{ + rows: rows, + cols: cols, + table: make([]float32, rows*cols), + salts: make([]uint64, rows), + hashes: make([]hash.Hash64, rows), + topk: NewTopKHeap(topk), + } + for i := 0; i < rows; i++ { + cms.salts[i] = mixSeed(seed, uint64(i)) + cms.hashes[i] = xxhash.New() + } + return cms, nil +} + +func (c *CountMinSketch) Insert(key string, weight float64) { + if weight == 0 { + return + } + estimate := math.MaxFloat64 + for row := 0; row < c.rows; row++ { + h := c.hashes[row] + h.Reset() + var saltBuf [8]byte + binary.LittleEndian.PutUint64(saltBuf[:], c.salts[row]) + h.Write(saltBuf[:]) + io.WriteString(h, key) + idx := int(h.Sum64() % uint64(c.cols)) + c.table[row*c.cols+idx] += float32(weight) + value := float64(c.table[row*c.cols+idx]) + if value < estimate { + estimate = value + } + } + c.total += weight + if estimate == math.MaxFloat64 { + estimate = 0 + } + if c.topk != nil { + c.topk.Update(key, estimate) + } +} + +func (c *CountMinSketch) Rows() int { + return c.rows +} + +func (c *CountMinSketch) Columns() int { + return c.cols +} + +func (c *CountMinSketch) Total() float64 { + return c.total +} + +func (c *CountMinSketch) TopKEntries() []TopKEntry { + if c.topk == nil { + return nil + } + return c.topk.Entries() +} + +func (c *CountMinSketch) MarshalBinary() ([]byte, error) { + buf := &bytes.Buffer{} + if err := binary.Write(buf, binary.BigEndian, uint32(countMinMagic)); err != nil { + return nil, err + } + if err := binary.Write(buf, binary.BigEndian, uint16(countMinVersion)); err != nil { + return nil, err + } + if err := binary.Write(buf, binary.BigEndian, uint16(c.rows)); err != nil { + return nil, err + } + if err := binary.Write(buf, binary.BigEndian, uint32(c.cols)); err != nil { + return nil, err + } + if err := binary.Write(buf, binary.BigEndian, c.total); err != nil { + return nil, err + } + if err := binary.Write(buf, binary.BigEndian, uint16(len(c.salts))); err != nil { + return nil, err + } + for _, salt := range c.salts { + if err := binary.Write(buf, binary.BigEndian, salt); err != nil { + return nil, err + } + } + for _, v := range c.table { + if err := binary.Write(buf, binary.BigEndian, v); err != nil { + return nil, err + } + } + return buf.Bytes(), nil +} + +const ( + countMinMagic = 0x434d5331 // "CMS1" + countMinVersion = 1 +) + +func mixSeed(base uint64, row uint64) uint64 { + const prime uint64 = 0x100000001b3 + value := base ^ (row * prime) + value ^= value >> 33 + value *= 0xff51afd7ed558ccd + value ^= value >> 33 + value *= 0xc4ceb9fe1a85ec53 + value ^= value >> 33 + return value +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/doc.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/doc.go new file mode 100644 index 00000000..3bd0e13d --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/doc.go @@ -0,0 +1,8 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:generate mdatagen metadata.yaml + +// Package sketchmetricsprocessor maintains Count-Min sketches over incoming metrics and +// emits serialized sketches and approximate top-k summaries. +package sketchcountminprocessor // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/sketchmetricsprocessor" diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/factory.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/factory.go new file mode 100644 index 00000000..40cebb21 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/factory.go @@ -0,0 +1,64 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sketchcountminprocessor // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/sketchmetricsprocessor" + +import ( + "context" + "fmt" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/processor/processorhelper" +) + +var typeStr = component.MustNewType("sketchmetrics") + +var capabilities = consumer.Capabilities{MutatesData: true} + +// NewFactory returns a new factory for the sketchmetrics processor. +func NewFactory() processor.Factory { + return processor.NewFactory( + typeStr, + createDefaultConfig, + processor.WithMetrics(createMetricsProcessor, component.StabilityLevelAlpha), + ) +} + +func createDefaultConfig() component.Config { + return &Config{ + Measurement: "countmin", + Rows: 3, + Columns: 4096, + Seed: 0x9e3779b185ebca87, + TopK: 20, + DropOriginal: false, + } +} + +func createMetricsProcessor( + ctx context.Context, + set processor.Settings, + cfg component.Config, + next consumer.Metrics, +) (processor.Metrics, error) { + config, ok := cfg.(*Config) + if !ok { + return nil, fmt.Errorf("sketchmetrics: invalid config type %T", cfg) + } + + p, err := newProcessor(config, set.Logger) + if err != nil { + return nil, err + } + + return processorhelper.NewMetrics( + ctx, + set, + cfg, + next, + p.processMetrics, + processorhelper.WithCapabilities(capabilities), + ) +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/factory_test.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/factory_test.go new file mode 100644 index 00000000..7a630586 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/factory_test.go @@ -0,0 +1,35 @@ +package sketchcountminprocessor + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/pipeline" + "go.opentelemetry.io/collector/processor/processortest" +) + +func TestFactory_CreateDefaultConfig(t *testing.T) { + factory := NewFactory() + cfg := factory.CreateDefaultConfig() + require.NoError(t, componenttest.CheckConfigStruct(cfg)) +} + +func TestFactory_CreateMetrics(t *testing.T) { + factory := NewFactory() + cfg := factory.CreateDefaultConfig() + + mp, err := factory.CreateMetrics(t.Context(), processortest.NewNopSettings(typeStr), cfg, consumertest.NewNop()) + require.NoError(t, err) + require.NotNil(t, mp) +} + +func TestFactory_CreateTracesNotSupported(t *testing.T) { + factory := NewFactory() + cfg := factory.CreateDefaultConfig() + + tp, err := factory.CreateTraces(t.Context(), processortest.NewNopSettings(typeStr), cfg, consumertest.NewNop()) + require.Nil(t, tp) + require.Equal(t, pipeline.ErrSignalNotSupported, err) +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/generated_package_test.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/generated_package_test.go new file mode 100644 index 00000000..1da3967d --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/generated_package_test.go @@ -0,0 +1,13 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package sketchcountminprocessor + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/go.mod b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/go.mod new file mode 100644 index 00000000..a77331c3 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/go.mod @@ -0,0 +1,98 @@ +module github.com/open-telemetry/opentelemetry-collector-contrib/processor/sketchcountminprocessor + +go 1.24.0 + +require ( + github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.141.0 + github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter v0.141.0 + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.141.0 + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.141.0 + github.com/stretchr/testify v1.11.1 + github.com/cespare/xxhash/v2 v2.3.0 + go.opentelemetry.io/collector/component v1.47.0 + go.opentelemetry.io/collector/component/componenttest v0.141.0 + go.opentelemetry.io/collector/confmap v1.47.0 + go.opentelemetry.io/collector/confmap/xconfmap v0.141.0 + go.opentelemetry.io/collector/consumer v1.47.0 + go.opentelemetry.io/collector/consumer/consumertest v0.141.0 + go.opentelemetry.io/collector/pdata v1.47.0 + go.opentelemetry.io/collector/pipeline v1.47.0 + go.opentelemetry.io/collector/processor v1.47.0 + go.opentelemetry.io/collector/processor/processorhelper v0.141.0 + go.opentelemetry.io/collector/processor/processortest v0.141.0 + go.opentelemetry.io/otel v1.38.0 + go.uber.org/goleak v1.3.0 +) + +require ( + github.com/alecthomas/participle/v2 v2.1.4 // indirect + github.com/antchfx/xmlquery v1.5.0 // indirect + github.com/antchfx/xpath v1.3.5 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/elastic/go-grok v0.3.1 // indirect + github.com/elastic/lunes v0.2.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/goccy/go-json v0.10.5 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/knadh/koanf/maps v0.1.2 // indirect + github.com/knadh/koanf/providers/confmap v1.0.0 // indirect + github.com/knadh/koanf/v2 v2.3.0 // indirect + github.com/magefile/mage v1.15.0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.141.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/twmb/murmur3 v1.1.8 // indirect + github.com/ua-parser/uap-go v0.0.0-20240611065828-3a4781585db6 // indirect + github.com/zeebo/xxh3 v1.0.2 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/collector/component/componentstatus v0.141.0 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.141.0 // indirect + go.opentelemetry.io/collector/featuregate v1.47.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.141.0 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.141.0 // indirect + go.opentelemetry.io/collector/processor/xprocessor v0.141.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/sdk v1.38.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.1 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect + golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest => ../../pkg/pdatatest + +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/internal/filter => ../../internal/filter + +replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl => ../../pkg/ottl + +retract ( + v0.76.2 + v0.76.1 + v0.65.0 +) + +replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden => ../../pkg/golden diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/go.sum b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/go.sum new file mode 100644 index 00000000..744cf36a --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/go.sum @@ -0,0 +1,234 @@ +github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= +github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/participle/v2 v2.1.4 h1:W/H79S8Sat/krZ3el6sQMvMaahJ+XcM9WSI2naI7w2U= +github.com/alecthomas/participle/v2 v2.1.4/go.mod h1:8tqVbpTX20Ru4NfYQgZf4mP18eXPTBViyMWiArNEgGI= +github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/antchfx/xmlquery v1.5.0 h1:uAi+mO40ZWfyU6mlUBxRVvL6uBNZ6LMU4M3+mQIBV4c= +github.com/antchfx/xmlquery v1.5.0/go.mod h1:lJfWRXzYMK1ss32zm1GQV3gMIW/HFey3xDZmkP1SuNc= +github.com/antchfx/xpath v1.3.5 h1:PqbXLC3TkfeZyakF5eeh3NTWEbYl4VHNVeufANzDbKQ= +github.com/antchfx/xpath v1.3.5/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= +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/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/elastic/go-grok v0.3.1 h1:WEhUxe2KrwycMnlvMimJXvzRa7DoByJB4PVUIE1ZD/U= +github.com/elastic/go-grok v0.3.1/go.mod h1:n38ls8ZgOboZRgKcjMY8eFeZFMmcL9n2lP0iHhIDk64= +github.com/elastic/lunes v0.2.0 h1:WI3bsdOTuaYXVe2DS1KbqA7u7FOHN4o8qJw80ZyZoQs= +github.com/elastic/lunes v0.2.0/go.mod h1:u3W/BdONWTrh0JjNZ21C907dDc+cUZttZrGa625nf2k= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/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-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +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/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +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/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo= +github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v1.0.0 h1:mHKLJTE7iXEys6deO5p6olAiZdG5zwp8Aebir+/EaRE= +github.com/knadh/koanf/providers/confmap v1.0.0/go.mod h1:txHYHiI2hAtF0/0sCmcuol4IDcuQbKTybiB1nOcUo1A= +github.com/knadh/koanf/v2 v2.3.0 h1:Qg076dDRFHvqnKG97ZEsi9TAg2/nFTa9hCdcSa1lvlM= +github.com/knadh/koanf/v2 v2.3.0/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28= +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/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= +github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +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/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/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +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/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= +github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +github.com/ua-parser/uap-go v0.0.0-20240611065828-3a4781585db6 h1:SIKIoA4e/5Y9ZOl0DCe3eVMLPOQzJxgZpfdHHeauNTM= +github.com/ua-parser/uap-go v0.0.0-20240611065828-3a4781585db6/go.mod h1:BUbeWZiieNxAuuADTBNb3/aeje6on3DhU3rpWsQSB1E= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/collector/component v1.47.0 h1:wXvcjNhpWUU4OJph7KyxENkbfnGrfDURa+L/rvPTHyo= +go.opentelemetry.io/collector/component v1.47.0/go.mod h1:Hz9fcIbc7tOA4hIjvW5bb1rJJc2TH0gtQEvDBaZLUUA= +go.opentelemetry.io/collector/component/componentstatus v0.141.0 h1:WoMJdv2ofwHJDXzMP6DvYPqREaqOcGw+gkXG7S+PJvc= +go.opentelemetry.io/collector/component/componentstatus v0.141.0/go.mod h1:upr5QxmYLEZ7PKMCZHImQcp3xNM4VXtZnAKuhhHopg4= +go.opentelemetry.io/collector/component/componenttest v0.141.0 h1:dYdFbm52+e2DwrJ0bEoo7qVOPDuFXl9E/FfaqViIfPU= +go.opentelemetry.io/collector/component/componenttest v0.141.0/go.mod h1:EI7SUBy8Grxso69j2KYf3BYv8rkJjFgxlmWf5ElcWdk= +go.opentelemetry.io/collector/confmap v1.47.0 h1:iXx4Pm1VbGboQCuY442mbBgihPv6gNpEItsod4rkW04= +go.opentelemetry.io/collector/confmap v1.47.0/go.mod h1:ipnIWHs3VdMOxkIjQnOw3Qou2hjXZELrphHuqjTh4QM= +go.opentelemetry.io/collector/confmap/xconfmap v0.141.0 h1:EhxPYLvUERsE4eThocTsmL1mDeSXn0AOX7Ta4GAjLNY= +go.opentelemetry.io/collector/confmap/xconfmap v0.141.0/go.mod h1:c4f/AT97CxQ5fYaCclj9fGnD0E2+5hLvL4fNQ7YkEEo= +go.opentelemetry.io/collector/consumer v1.47.0 h1:eriMvNAsityaea361luVfNe8wp6QKWJQoU4d4i3tyOA= +go.opentelemetry.io/collector/consumer v1.47.0/go.mod h1:wBsF8koieun0CK4laZLN2MvGKNqad8gwQa+1jXWWn5k= +go.opentelemetry.io/collector/consumer/consumertest v0.141.0 h1:Q5X7rOI8I5xj35Q1NQiwGJsJ4OZx1n7szw3MbOfNgiM= +go.opentelemetry.io/collector/consumer/consumertest v0.141.0/go.mod h1:yjSSOFx0oBjH2fouw0TTN/U82hYyJPq35ClIZrpz60g= +go.opentelemetry.io/collector/consumer/xconsumer v0.141.0 h1:qR9H8tWo6NtPBDBv3fz8J8QBkqbnaU8vwUvtIO3QeZo= +go.opentelemetry.io/collector/consumer/xconsumer v0.141.0/go.mod h1:Ud55EhQ0cgqDTtnvHQNjtktLGMeefOzF6SFk0bLheOc= +go.opentelemetry.io/collector/featuregate v1.47.0 h1:LuJnDngViDzPKds5QOGxVYNL1QCCVWN/m61lHTV8Pf4= +go.opentelemetry.io/collector/featuregate v1.47.0/go.mod h1:d0tiRzVYrytB6LkcYgz2ESFTv7OktRPQe0QEQcPt1L4= +go.opentelemetry.io/collector/internal/testutil v0.141.0 h1:/rUGApojPtUPMN3rFfApNgEjAt03rCGt2qxNxGGs/4A= +go.opentelemetry.io/collector/internal/testutil v0.141.0/go.mod h1:YAD9EAkwh/l5asZNbEBEUCqEjoL1OKMjAMoPjPqH76c= +go.opentelemetry.io/collector/pdata v1.47.0 h1:4Mk0mo2RlKCUPomV8ISm+Yx/STFtuSn88yjiCePHkGA= +go.opentelemetry.io/collector/pdata v1.47.0/go.mod h1:yMdjdWZBNA8wLFCQXOCLb0RfcpZOxp7exH+bN7udWO0= +go.opentelemetry.io/collector/pdata/pprofile v0.141.0 h1:15lbbHKzPIG4aVT6hsJO7XZLvMrGll+i36es/FEgn7c= +go.opentelemetry.io/collector/pdata/pprofile v0.141.0/go.mod h1:gUtWKniP3O0jXYVDISp1y3dCbYFIyglFw6B8ATyrrWs= +go.opentelemetry.io/collector/pdata/testdata v0.141.0 h1:AfjNbZ/DUSr0aiP4H+z7pqrzTuBQFaT6oca0zaJ3gCA= +go.opentelemetry.io/collector/pdata/testdata v0.141.0/go.mod h1:/KX316ZF30G4eUQadM+SPUqCCPoiAkhMxcvAu4uM72I= +go.opentelemetry.io/collector/pipeline v1.47.0 h1:Ql2cfIopfo/e0Y6r/Fw3mNorKYi8MAoA7zgouzAN8eI= +go.opentelemetry.io/collector/pipeline v1.47.0/go.mod h1:xUrAqiebzYbrgxyoXSkk6/Y3oi5Sy3im2iCA51LwUAI= +go.opentelemetry.io/collector/processor v1.47.0 h1:WA4AP+w+ohFItWx0eG5iGEvLCE70Le5wC2Uw7YVN1Vg= +go.opentelemetry.io/collector/processor v1.47.0/go.mod h1:XaC3o+kNM5wq7ET+FJt+9hTnqqICmruylBpVerb+TZo= +go.opentelemetry.io/collector/processor/processorhelper v0.141.0 h1:4NCArw4JJsJ8YNtbcJXYNOczQ9gon+m1yGV5VPh8Lwk= +go.opentelemetry.io/collector/processor/processorhelper v0.141.0/go.mod h1:idjJbBjKlBmXnhWwiqKG8AYBJmdowNn82F36OhBcMwg= +go.opentelemetry.io/collector/processor/processortest v0.141.0 h1:HY/o+CkKTU2Db96TfugwfMKkRFcaJb2vxPUHluS5/F8= +go.opentelemetry.io/collector/processor/processortest v0.141.0/go.mod h1:n0QKOTH2m2vVbDGdIHvDmIEHU02LOQtuCzzN4BJgK5U= +go.opentelemetry.io/collector/processor/xprocessor v0.141.0 h1:rlvqx4aW7dgrYqWrNTkq1+IDiWOKdX/DDZPxk1DQMVw= +go.opentelemetry.io/collector/processor/xprocessor v0.141.0/go.mod h1:jSSsP1pFgkxN4MvVsyZA1MI5DKhN+kg9Y27Ev0lEwqs= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.opentelemetry.io/proto/slim/otlp v1.9.0 h1:fPVMv8tP3TrsqlkH1HWYUpbCY9cAIemx184VGkS6vlE= +go.opentelemetry.io/proto/slim/otlp v1.9.0/go.mod h1:xXdeJJ90Gqyll+orzUkY4bOd2HECo5JofeoLpymVqdI= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0 h1:o13nadWDNkH/quoDomDUClnQBpdQQ2Qqv0lQBjIXjE8= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0/go.mod h1:Gyb6Xe7FTi/6xBHwMmngGoHqL0w29Y4eW8TGFzpefGA= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0 h1:EiUYvtwu6PMrMHVjcPfnsG3v+ajPkbUeH+IL93+QYyk= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0/go.mod h1:mUUHKFiN2SST3AhJ8XhJxEoeVW12oqfXog0Bo8W3Ec4= +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.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 h1:6/3JGEh1C88g7m+qzzTbl3A0FtsLguXieqofVLU/JAo= +golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +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.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +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.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/internal/metadata/generated_status.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/internal/metadata/generated_status.go new file mode 100644 index 00000000..aa3dcdff --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/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("sketchcountmin") + ScopeName = "github.com/open-telemetry/opentelemetry-collector-contrib/processor/sketchcountminprocessor" +) + +const ( + MetricsStability = component.StabilityLevelAlpha +) diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/metadata.yaml b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/metadata.yaml new file mode 100644 index 00000000..4cee6df3 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/metadata.yaml @@ -0,0 +1,13 @@ +type: sketchmetrics + +status: + class: processor + stability: + alpha: [metrics] + distributions: [contrib] + codeowners: + active: [] + +tests: + config: + measurement: countmin diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/otlp_sender/go.mod b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/otlp_sender/go.mod new file mode 100644 index 00000000..0a3351f2 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/otlp_sender/go.mod @@ -0,0 +1,28 @@ +module example.com/otlp_sender + +go 1.24 + +require ( + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/sdk/metric v1.24.0 +) + +require ( + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/grpc v1.61.1 // indirect + google.golang.org/protobuf v1.32.0 // indirect +) diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/otlp_sender/go.sum b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/otlp_sender/go.sum new file mode 100644 index 00000000..4c1a6a04 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/otlp_sender/go.sum @@ -0,0 +1,56 @@ +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/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/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +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/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 h1:f2jriWfOdldanBwS9jNBdeOKAQN7b4ugAMaNu1/1k9g= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0/go.mod h1:B+bcQI1yTY+N0vqMpoZbEN7+XU4tNM0DmUiOwebFJWI= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/otlp_sender/main.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/otlp_sender/main.go new file mode 100644 index 00000000..8b90f14a --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/otlp_sender/main.go @@ -0,0 +1,62 @@ +package main + +import ( + "context" + "log" + "time" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" + metricapi "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" +) + +// Minimal OTLP metric sender for exercising the sketchmetrics processor. +func main() { + ctx := context.Background() + + exp, err := otlpmetricgrpc.New(ctx, + otlpmetricgrpc.WithEndpoint("localhost:4317"), + otlpmetricgrpc.WithInsecure(), + ) + if err != nil { + log.Fatalf("create exporter: %v", err) + } + + res, err := resource.Merge( + resource.Default(), + resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceName("demo-service"), + attribute.String("region", "us-east"), + ), + ) + if err != nil { + log.Fatalf("create resource: %v", err) + } + + provider := metric.NewMeterProvider( + metric.WithResource(res), + metric.WithReader(metric.NewPeriodicReader(exp, metric.WithInterval(2*time.Second))), + ) + defer provider.Shutdown(ctx) // best-effort shutdown + + otel.SetMeterProvider(provider) + meter := provider.Meter("demo-sender") + counter, err := meter.Float64Counter("requests_total") + if err != nil { + log.Fatalf("create counter: %v", err) + } + + attrs := []attribute.KeyValue{ + attribute.String("method", "GET"), + attribute.String("status", "200"), + } + counter.Add(ctx, 5, metricapi.WithAttributes(attrs...)) + + // allow export to run + time.Sleep(3 * time.Second) +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/sketch.yaml b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/sketch.yaml new file mode 100644 index 00000000..83be6fca --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/sketch.yaml @@ -0,0 +1,25 @@ +receivers: + otlp: + protocols: + grpc: + +processors: + sketchmetrics: + measurement: countmin + tag_keys: [method, status] + group_by: [service.name] + rows: 3 + columns: 4096 + top_k: 5 + drop_original: false + +exporters: + debug: + verbosity: detailed # emit full metric contents + +service: + pipelines: + metrics: + receivers: [otlp] + processors: [sketchmetrics] + exporters: [debug] diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/sketchmetrics.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/sketchmetrics.go new file mode 100644 index 00000000..ecfc3171 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/sketchmetrics.go @@ -0,0 +1,312 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sketchmetricsprocessor + +import ( + "context" + "encoding/json" + "sort" + "strconv" + "strings" + "sync" + "time" + + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.uber.org/zap" +) + +// processor maintains Count-Min sketches keyed by metric name, group-by tag values, and tag key. +// Each incoming datapoint updates the relevant sketches; the processor then emits a synthetic +// metric (configured via Measurement) containing the serialized sketches and optional top-k +// entries while optionally forwarding the original data. +type sketchProcessor struct { + cfg Config + groupByKeys map[string]struct{} + cache map[string]*aggregate + mu sync.Mutex + logger *zap.Logger +} + +type aggregate struct { + measurement string + groupTags map[string]string + sketches map[string]*CountMinSketch +} + +func newProcessor(cfg *Config, logger *zap.Logger) (*sketchProcessor, error) { + if cfg == nil { + return nil, errInvalidConfig + } + if err := cfg.Validate(); err != nil { + return nil, err + } + normalized := *cfg + if normalized.Measurement == "" { + normalized.Measurement = "countmin" + } + if normalized.Rows <= 0 { + normalized.Rows = defaultRows + } + if normalized.Columns <= 0 { + normalized.Columns = defaultColumns + } + if normalized.Seed == 0 { + normalized.Seed = defaultSeed + } + + groupBy := make(map[string]struct{}, len(normalized.GroupBy)) + for _, key := range normalized.GroupBy { + groupBy[key] = struct{}{} + } + + return &sketchProcessor{ + cfg: normalized, + groupByKeys: groupBy, + cache: make(map[string]*aggregate), + logger: logger, + }, nil +} + +func (p *sketchProcessor) processMetrics(_ context.Context, md pmetric.Metrics) (pmetric.Metrics, error) { + p.mu.Lock() + defer p.mu.Unlock() + + p.consume(md) + + if p.cfg.DropOriginal { + md = pmetric.NewMetrics() + } + p.appendSketchMetrics(md) + return md, nil +} + +func (p *sketchProcessor) consume(md pmetric.Metrics) { + rms := md.ResourceMetrics() + for i := 0; i < rms.Len(); i++ { + rm := rms.At(i) + baseTags := map[string]string{} + copyAttributes(rm.Resource().Attributes(), baseTags) + + sms := rm.ScopeMetrics() + for j := 0; j < sms.Len(); j++ { + metrics := sms.At(j).Metrics() + for k := 0; k < metrics.Len(); k++ { + p.consumeMetric(metrics.At(k), baseTags) + } + } + } +} + +func (p *sketchProcessor) consumeMetric(metric pmetric.Metric, baseTags map[string]string) { + switch metric.Type() { + case pmetric.MetricTypeGauge: + dps := metric.Gauge().DataPoints() + for i := 0; i < dps.Len(); i++ { + p.consumeNumberDataPoint(metric.Name(), dps.At(i), baseTags) + } + case pmetric.MetricTypeSum: + dps := metric.Sum().DataPoints() + for i := 0; i < dps.Len(); i++ { + p.consumeNumberDataPoint(metric.Name(), dps.At(i), baseTags) + } + default: + // Other metric types are ignored. + } +} + +func (p *sketchProcessor) consumeNumberDataPoint(metricName string, dp pmetric.NumberDataPoint, baseTags map[string]string) { + value, ok := numberValue(dp) + if !ok { + return + } + + tags := make(map[string]string, len(baseTags)+dp.Attributes().Len()) + for k, v := range baseTags { + tags[k] = v + } + copyAttributes(dp.Attributes(), tags) + + groupTags := make(map[string]string, len(p.groupByKeys)) + for key := range p.groupByKeys { + if v, ok := tags[key]; ok { + groupTags[key] = v + } + } + cacheKey := aggregateKey(metricName, groupTags) + agg, ok := p.cache[cacheKey] + if !ok { + agg = &aggregate{ + measurement: metricName, + groupTags: copyStringMap(groupTags), + sketches: make(map[string]*CountMinSketch), + } + p.cache[cacheKey] = agg + } + + keys := p.effectiveTagKeys(tags) + if len(keys) == 0 { + return + } + valueKey := joinTagValues(tags, keys) + + for _, tagKey := range keys { + sk, ok := agg.sketches[tagKey] + if !ok { + derived := deriveSeed(p.cfg.Seed, agg.measurement, tagKey) + var err error + sk, err = NewCountMinSketch(p.cfg.Rows, p.cfg.Columns, derived, p.cfg.TopK) + if err != nil { + p.logger.Warn("sketchmetrics: failed to create sketch", zap.String("measurement", agg.measurement), zap.String("tag_key", tagKey), zap.Error(err)) + continue + } + agg.sketches[tagKey] = sk + } + sk.Insert(valueKey, value) + } +} + +func (p *sketchProcessor) appendSketchMetrics(md pmetric.Metrics) { + if len(p.cache) == 0 { + return + } + + rm := md.ResourceMetrics().AppendEmpty() + sm := rm.ScopeMetrics().AppendEmpty() + sm.Scope().SetName("sketchmetricsprocessor") + metric := sm.Metrics().AppendEmpty() + metric.SetName(p.cfg.Measurement) + gauge := metric.SetEmptyGauge() + dps := gauge.DataPoints() + now := pcommon.NewTimestampFromTime(time.Now()) + + for _, agg := range p.cache { + for tagKey, sketch := range agg.sketches { + dp := dps.AppendEmpty() + dp.SetTimestamp(now) + dp.SetDoubleValue(sketch.Total()) + attrs := dp.Attributes() + for k, v := range agg.groupTags { + attrs.PutStr(k, v) + } + attrs.PutStr("source_measurement", agg.measurement) + attrs.PutStr("tag_key", tagKey) + attrs.PutInt("rows", int64(sketch.Rows())) + attrs.PutInt("columns", int64(sketch.Columns())) + attrs.PutDouble("count", sketch.Total()) + + if payload, err := sketch.MarshalBinary(); err != nil { + p.logger.Warn("sketchmetrics: failed to serialize sketch", zap.String("measurement", agg.measurement), zap.String("tag_key", tagKey), zap.Error(err)) + } else { + attrs.PutEmptyBytes("countmin").FromRaw(payload) + } + if top := sketch.TopKEntries(); len(top) > 0 { + if encoded, err := json.Marshal(top); err != nil { + p.logger.Warn("sketchmetrics: failed to serialize topk", zap.String("measurement", agg.measurement), zap.String("tag_key", tagKey), zap.Error(err)) + } else { + attrs.PutEmptyBytes("topk").FromRaw(encoded) + } + } + } + } +} + +func (p *sketchProcessor) effectiveTagKeys(all map[string]string) []string { + if len(p.cfg.TagKeys) > 0 { + return p.cfg.TagKeys + } + keys := make([]string, 0, len(all)) + for key := range all { + if _, skip := p.groupByKeys[key]; skip { + continue + } + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} + +func numberValue(dp pmetric.NumberDataPoint) (float64, bool) { + switch dp.ValueType() { + case pmetric.NumberDataPointValueTypeDouble: + return dp.DoubleValue(), true + case pmetric.NumberDataPointValueTypeInt: + return float64(dp.IntValue()), true + default: + return 0, false + } +} + +func copyAttributes(attrs pcommon.Map, dst map[string]string) { + attrs.Range(func(k string, v pcommon.Value) bool { + dst[k] = valueAsString(v) + return true + }) +} + +func valueAsString(v pcommon.Value) string { + switch v.Type() { + case pcommon.ValueTypeStr: + return v.Str() + case pcommon.ValueTypeBool: + return strconv.FormatBool(v.Bool()) + case pcommon.ValueTypeInt: + return strconv.FormatInt(v.Int(), 10) + case pcommon.ValueTypeDouble: + return strconv.FormatFloat(v.Double(), 'f', -1, 64) + case pcommon.ValueTypeBytes: + return string(v.Bytes().AsRaw()) + default: + return v.AsString() + } +} + +func aggregateKey(measurement string, tags map[string]string) string { + if len(tags) == 0 { + return measurement + } + keys := make([]string, 0, len(tags)) + for k := range tags { + keys = append(keys, k) + } + sort.Strings(keys) + var b strings.Builder + b.WriteString(measurement) + for _, k := range keys { + b.WriteString(",") + b.WriteString(k) + b.WriteString("=") + b.WriteString(tags[k]) + } + return b.String() +} + +func copyStringMap(src map[string]string) map[string]string { + if len(src) == 0 { + return nil + } + out := make(map[string]string, len(src)) + for k, v := range src { + out[k] = v + } + return out +} + +func joinTagValues(tags map[string]string, keys []string) string { + if len(keys) == 0 { + return "" + } + var b strings.Builder + for i, key := range keys { + if i > 0 { + b.WriteString(",") + } + b.WriteString(key) + b.WriteString("=") + if v, ok := tags[key]; ok { + b.WriteString(v) + } + } + return b.String() +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/sketchmetrics_test.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/sketchmetrics_test.go new file mode 100644 index 00000000..e4de6df5 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/sketchmetrics_test.go @@ -0,0 +1,74 @@ +package sketchcountminprocessor + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.uber.org/zap" +) + +func TestProcessMetrics_AppendsSketch(t *testing.T) { + cfg := createDefaultConfig().(*Config) + cfg.TopK = 3 + cfg.DropOriginal = true + cfg.TagKeys = []string{"method", "status"} + + p, err := newProcessor(cfg, zap.NewNop()) + require.NoError(t, err) + + in := buildTestMetrics() + out, err := p.processMetrics(context.Background(), in) + require.NoError(t, err) + + // DropOriginal should remove the source metric, leaving only the sketch metric. + require.Equal(t, 1, out.ResourceMetrics().Len()) + sm := out.ResourceMetrics().At(0).ScopeMetrics() + require.Equal(t, 1, sm.Len()) + metric := sm.At(0).Metrics().At(0) + require.Equal(t, cfg.Measurement, metric.Name()) + dps := metric.Gauge().DataPoints() + require.Equal(t, 2, dps.Len()) // one per tag key (method,status) + + for i := 0; i < dps.Len(); i++ { + dp := dps.At(i) + attrs := dp.Attributes() + val, ok := attrs.Get("source_measurement") + require.True(t, ok) + require.Equal(t, "requests_total", val.Str()) + require.Greater(t, dp.DoubleValue(), 0.0) + _, hasCountMin := attrs.Get("countmin") + _, hasRows := attrs.Get("rows") + _, hasCols := attrs.Get("columns") + require.True(t, hasCountMin) + require.True(t, hasRows) + require.True(t, hasCols) + } +} + +func buildTestMetrics() pmetric.Metrics { + metrics := pmetric.NewMetrics() + rm := metrics.ResourceMetrics().AppendEmpty() + rm.Resource().Attributes().PutStr("tenant", "acme") + m := rm.ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() + m.SetName("requests_total") + dps := m.SetEmptyGauge().DataPoints() + + dp1 := dps.AppendEmpty() + dp1.Attributes().PutStr("method", "GET") + dp1.Attributes().PutStr("status", "200") + dp1.Attributes().PutStr("region", "us-east") + dp1.SetDoubleValue(5) + dp1.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + + dp2 := dps.AppendEmpty() + dp2.Attributes().PutStr("method", "POST") + dp2.Attributes().PutStr("status", "500") + dp2.Attributes().PutStr("region", "us-east") + dp2.SetDoubleValue(2) + dp2.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return metrics +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/testdata/config.yaml b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/testdata/config.yaml new file mode 100644 index 00000000..aa2e3441 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/testdata/config.yaml @@ -0,0 +1,7 @@ +sketchmetrics/default: + measurement: "countmin" + rows: 3 + columns: 4096 + seed: 11400714819323198485 + top_k: 5 + drop_original: false diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/topk.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/topk.go new file mode 100644 index 00000000..e3afce84 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/topk.go @@ -0,0 +1,139 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sketchmetricsprocessor + +import "sort" + +// TopKEntry represents a heavy hitter entry. +type TopKEntry struct { + Key string `json:"key"` + Count float64 `json:"count"` +} + +type heapItem struct { + key string + count float64 +} + +// TopKHeap maintains approximate heavy hitters using a bounded min-heap. +type TopKHeap struct { + heap []heapItem + limit int +} + +// NewTopKHeap creates a heap limited to k entries. Returns nil if k <= 0. +func NewTopKHeap(k int) *TopKHeap { + if k <= 0 { + return nil + } + return &TopKHeap{ + heap: make([]heapItem, 0, k), + limit: k, + } +} + +func (h *TopKHeap) leftChild(i int) int { + return 2*i + 1 +} + +func (h *TopKHeap) rightChild(i int) int { + return 2*i + 2 +} + +func (h *TopKHeap) parent(i int) int { + return (i - 1) / 2 +} + +func (h *TopKHeap) swap(i, j int) { + h.heap[i], h.heap[j] = h.heap[j], h.heap[i] +} + +func (h *TopKHeap) updateOrderDown(i int) bool { + n := len(h.heap) + orig := i + for i < n { + l := h.leftChild(i) + r := h.rightChild(i) + smallest := i + if l < n && h.heap[l].count < h.heap[smallest].count { + smallest = l + } + if r < n && h.heap[r].count < h.heap[smallest].count { + smallest = r + } + if smallest == i { + break + } + h.swap(i, smallest) + i = smallest + } + return i != orig +} + +func (h *TopKHeap) updateOrderUp(i int) { + for i > 0 { + p := h.parent(i) + if h.heap[p].count > h.heap[i].count { + h.swap(p, i) + i = p + } else { + break + } + } +} + +// Update inserts or updates the given key with its latest approximate count. +func (h *TopKHeap) Update(key string, count float64) { + if h == nil || count <= 0 { + return + } + if idx, ok := h.find(key); ok { + h.heap[idx].count = count + if !h.updateOrderDown(idx) { + h.updateOrderUp(idx) + } + return + } + if len(h.heap) < h.limit { + h.heap = append(h.heap, heapItem{ + key: key, + count: count, + }) + h.updateOrderUp(len(h.heap) - 1) + return + } + if len(h.heap) == 0 || h.heap[0].count >= count { + return + } + h.heap[0].key = key + h.heap[0].count = count + h.updateOrderDown(0) +} + +func (h *TopKHeap) find(key string) (int, bool) { + for i, item := range h.heap { + if item.key == key { + return i, true + } + } + return -1, false +} + +// Entries returns the heap contents sorted descending by count. +func (h *TopKHeap) Entries() []TopKEntry { + if h == nil || len(h.heap) == 0 { + return nil + } + entries := make([]TopKEntry, len(h.heap)) + for i, item := range h.heap { + entries[i] = TopKEntry{ + Key: item.key, + Count: item.count, + } + } + sort.Slice(entries, func(i, j int) bool { + return entries[i].Count > entries[j].Count + }) + return entries +} diff --git a/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/util.go b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/util.go new file mode 100644 index 00000000..869f5417 --- /dev/null +++ b/opentelemetry-collector-contrib-patch/processor/sketchcountminprocessor/util.go @@ -0,0 +1,22 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sketchcountminprocessor + +import ( + "encoding/binary" + "io" + + "github.com/cespare/xxhash/v2" +) + +func deriveSeed(base uint64, parts ...string) uint64 { + h := xxhash.New() + var buf [8]byte + binary.LittleEndian.PutUint64(buf[:], base) + h.Write(buf[:]) + for _, part := range parts { + io.WriteString(h, part) + } + return h.Sum64() +} diff --git a/opentelemetry-collector-patch/README.md b/opentelemetry-collector-patch/README.md new file mode 100644 index 00000000..2e636fbc --- /dev/null +++ b/opentelemetry-collector-patch/README.md @@ -0,0 +1,3 @@ +# OpenTelemetry Collector Plugins/Patches + +Copies of modified files from the vendored `opentelemetry-collector` tree are stored here by `backup_collector_plugins.sh` for easier review and portability. Run `restore_collector_plugins.sh` to sync them back into the repository. diff --git a/opentelemetry-collector-patch/cmd/builder/builder-sketch.yaml b/opentelemetry-collector-patch/cmd/builder/builder-sketch.yaml new file mode 100644 index 00000000..62844271 --- /dev/null +++ b/opentelemetry-collector-patch/cmd/builder/builder-sketch.yaml @@ -0,0 +1,17 @@ +dist: + name: otelcol-sketch + description: custom build with sketchmetrics + output_path: ./bin + version: 0.0.1 + module: github.com/example/otelcol-sketch + +receivers: + - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.141.0 + +processors: + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/sketchcountminprocessor v0.0.0 +exporters: + - gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.141.0 + +replaces: + - github.com/open-telemetry/opentelemetry-collector-contrib/processor/sketchcountminprocessor => ../../../../opentelemetry-collector-contrib/processor/sketchcountminprocessor