From d8b211032bd8925341233b69c90f417a859d15e7 Mon Sep 17 00:00:00 2001 From: Raghuram Kannan <78465537+FlamingSaint@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:29:39 +0530 Subject: [PATCH] Enable SPM in Jaeger v2 (#5681) ## Which problem is this PR solving? - This PR is a part of the issue #5632 ## Description of the changes - Added a new docker-compose file - Added the configuration file which will be used for enabling SPM in v2 ## How was this change tested? - Run `make dev-v2` inside `docker-compose/monitor` ## Checklist - [x] I have read https://github.com/jaegertracing/jaeger/blob/master/CONTRIBUTING_GUIDELINES.md - [x] I have signed all commits - [x] I have added unit tests for the new functionality - [x] I have run lint and test steps successfully - for `jaeger`: `make lint test` - for `jaeger-ui`: `yarn lint` and `yarn test` --------- Signed-off-by: FlamingSaint Signed-off-by: Raghuram Kannan <78465537+FlamingSaint@users.noreply.github.com> Signed-off-by: Yuri Shkuro Signed-off-by: Yuri Shkuro Co-authored-by: Yuri Shkuro Co-authored-by: Yuri Shkuro --- .github/workflows/ci-e2e-spm.yml | 17 +- cmd/jaeger/internal/components.go | 2 + .../storageexporter/exporter_test.go | 16 +- .../internal/extension/jaegerquery/config.go | 14 +- .../internal/extension/jaegerquery/server.go | 28 ++- .../extension/jaegerquery/server_test.go | 95 ++++++++- .../extension/jaegerstorage/config.go | 19 +- .../extension/jaegerstorage/config_test.go | 11 ++ .../extension/jaegerstorage/extension.go | 92 +++++++-- .../extension/jaegerstorage/extension_test.go | 64 ++++++- .../storagecleaner/extension_test.go | 14 +- cmd/query/app/querysvc/query_service.go | 1 + docker-compose/monitor/Makefile | 16 +- docker-compose/monitor/docker-compose-v2.yml | 51 +++++ docker-compose/monitor/docker-compose.yml | 12 +- docker-compose/monitor/jaeger-v2-config.yml | 48 +++++ .../otel-collector-config-connector.yml | 12 +- docker-compose/monitor/prometheus.yml | 2 +- go.mod | 5 +- go.sum | 180 +++++++++++++++++- pkg/prometheus/config/config.go | 28 ++- .../config/{empty_test.go => config_test.go} | 13 ++ plugin/metrics/prometheus/factory.go | 16 ++ plugin/metrics/prometheus/factory_test.go | 15 ++ plugin/metrics/prometheus/options.go | 10 +- scripts/spm-integration-test.sh | 44 ++++- 26 files changed, 738 insertions(+), 87 deletions(-) create mode 100644 docker-compose/monitor/docker-compose-v2.yml create mode 100644 docker-compose/monitor/jaeger-v2-config.yml rename pkg/prometheus/config/{empty_test.go => config_test.go} (74%) diff --git a/.github/workflows/ci-e2e-spm.yml b/.github/workflows/ci-e2e-spm.yml index 8f58de52f91..eb987af1ba7 100644 --- a/.github/workflows/ci-e2e-spm.yml +++ b/.github/workflows/ci-e2e-spm.yml @@ -18,6 +18,14 @@ permissions: jobs: spm: runs-on: ubuntu-latest + strategy: + matrix: + mode: + - name: v1 + binary: all-in-one + - name: v2 + binary: jaeger + steps: - name: Harden Runner uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 @@ -38,11 +46,6 @@ jobs: - name: Setup Node.js version uses: ./.github/actions/setup-node.js - - - name: Temporary - only run the build - run: - cd docker-compose/monitor && make build - + - name: Run SPM Test - run: ./scripts/spm-integration-test.sh - + run: bash scripts/spm-integration-test.sh -b ${{ matrix.mode.binary }} diff --git a/cmd/jaeger/internal/components.go b/cmd/jaeger/internal/components.go index f7161ffef22..7a615785b4d 100644 --- a/cmd/jaeger/internal/components.go +++ b/cmd/jaeger/internal/components.go @@ -6,6 +6,7 @@ package internal import ( "github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver" @@ -90,6 +91,7 @@ func (b builders) build() (otelcol.Factories, error) { // add-ons storageexporter.NewFactory(), // generic exporter to Jaeger v1 spanstore.SpanWriter kafkaexporter.NewFactory(), + prometheusexporter.NewFactory(), // elasticsearch.NewFactory(), ) if err != nil { diff --git a/cmd/jaeger/internal/exporters/storageexporter/exporter_test.go b/cmd/jaeger/internal/exporters/storageexporter/exporter_test.go index cfe7a2b1e50..54dedab391e 100644 --- a/cmd/jaeger/internal/exporters/storageexporter/exporter_test.go +++ b/cmd/jaeger/internal/exporters/storageexporter/exporter_test.go @@ -39,10 +39,13 @@ import ( ) type mockStorageExt struct { - name string - factory *factoryMocks.Factory + name string + factory *factoryMocks.Factory + metricsFactory *factoryMocks.MetricsFactory } +var _ jaegerstorage.Extension = (*mockStorageExt)(nil) + func (*mockStorageExt) Start(context.Context, component.Host) error { panic("not implemented") } @@ -51,13 +54,20 @@ func (*mockStorageExt) Shutdown(context.Context) error { panic("not implemented") } -func (m *mockStorageExt) Factory(name string) (storage.Factory, bool) { +func (m *mockStorageExt) TraceStorageFactory(name string) (storage.Factory, bool) { if m.name == name { return m.factory, true } return nil, false } +func (m *mockStorageExt) MetricStorageFactory(name string) (storage.MetricsFactory, bool) { + if m.name == name { + return m.metricsFactory, true + } + return nil, false +} + func TestExporterConfigError(t *testing.T) { config := createDefaultConfig().(*Config) err := config.Validate() diff --git a/cmd/jaeger/internal/extension/jaegerquery/config.go b/cmd/jaeger/internal/extension/jaegerquery/config.go index ec5de1bb69c..9abaf0c1a64 100644 --- a/cmd/jaeger/internal/extension/jaegerquery/config.go +++ b/cmd/jaeger/internal/extension/jaegerquery/config.go @@ -18,14 +18,12 @@ var _ component.ConfigValidator = (*Config)(nil) // Config represents the configuration for jaeger-query, type Config struct { queryApp.QueryOptionsBase `mapstructure:",squash"` - - TraceStoragePrimary string `valid:"required" mapstructure:"trace_storage"` - TraceStorageArchive string `valid:"optional" mapstructure:"trace_storage_archive"` - - HTTP confighttp.ServerConfig `mapstructure:",squash"` - GRPC configgrpc.ServerConfig `mapstructure:",squash"` - - Tenancy tenancy.Options `mapstructure:"multi_tenancy"` + TraceStoragePrimary string `valid:"required" mapstructure:"trace_storage"` + TraceStorageArchive string `valid:"optional" mapstructure:"trace_storage_archive"` + MetricStorage string `valid:"optional" mapstructure:"metric_storage"` + HTTP confighttp.ServerConfig `mapstructure:",squash"` + GRPC configgrpc.ServerConfig `mapstructure:",squash"` + Tenancy tenancy.Options `mapstructure:"multi_tenancy"` } func (cfg *Config) Validate() error { diff --git a/cmd/jaeger/internal/extension/jaegerquery/server.go b/cmd/jaeger/internal/extension/jaegerquery/server.go index d4dfa53715d..c2221175d79 100644 --- a/cmd/jaeger/internal/extension/jaegerquery/server.go +++ b/cmd/jaeger/internal/extension/jaegerquery/server.go @@ -18,6 +18,7 @@ import ( "github.com/jaegertracing/jaeger/pkg/telemetery" "github.com/jaegertracing/jaeger/pkg/tenancy" "github.com/jaegertracing/jaeger/plugin/metrics/disabled" + "github.com/jaegertracing/jaeger/storage/metricsstore" ) var ( @@ -67,7 +68,12 @@ func (s *server) Start(_ context.Context, host component.Host) error { return err } qs := querysvc.NewQueryService(spanReader, depReader, opts) - metricsQueryService, _ := disabled.NewMetricsReader() + + mqs, err := s.createMetricReader(host) + if err != nil { + return err + } + tm := tenancy.NewManager(&s.config.Tenancy) // TODO OTel-collector does not initialize the tracer currently @@ -89,7 +95,7 @@ func (s *server) Start(_ context.Context, host component.Host) error { s.server, err = queryApp.NewServer( // TODO propagate healthcheck updates up to the collector's runtime qs, - metricsQueryService, + mqs, s.makeQueryOptions(), tm, telset, @@ -122,6 +128,24 @@ func (s *server) addArchiveStorage(opts *querysvc.QueryServiceOptions, host comp return nil } +func (s *server) createMetricReader(host component.Host) (metricsstore.Reader, error) { + if s.config.MetricStorage == "" { + s.telset.Logger.Info("Metric storage not configured") + return disabled.NewMetricsReader() + } + + mf, err := jaegerstorage.GetMetricsFactory(s.config.MetricStorage, host) + if err != nil { + return nil, fmt.Errorf("cannot find metrics storage factory: %w", err) + } + + metricsReader, err := mf.CreateMetricsReader() + if err != nil { + return nil, fmt.Errorf("cannot create metrics reader %w", err) + } + return metricsReader, err +} + func (s *server) makeQueryOptions() *queryApp.QueryOptions { return &queryApp.QueryOptions{ QueryOptionsBase: s.config.QueryOptionsBase, diff --git a/cmd/jaeger/internal/extension/jaegerquery/server_test.go b/cmd/jaeger/internal/extension/jaegerquery/server_test.go index 6ba3e963c5c..e51f7c697b1 100644 --- a/cmd/jaeger/internal/extension/jaegerquery/server_test.go +++ b/cmd/jaeger/internal/extension/jaegerquery/server_test.go @@ -26,6 +26,8 @@ import ( "github.com/jaegertracing/jaeger/storage" "github.com/jaegertracing/jaeger/storage/dependencystore" depsmocks "github.com/jaegertracing/jaeger/storage/dependencystore/mocks" + "github.com/jaegertracing/jaeger/storage/metricsstore" + metricsstoremocks "github.com/jaegertracing/jaeger/storage/metricsstore/mocks" "github.com/jaegertracing/jaeger/storage/spanstore" spanstoremocks "github.com/jaegertracing/jaeger/storage/spanstore/mocks" ) @@ -62,17 +64,43 @@ func (ff fakeFactory) Initialize(metrics.Factory, *zap.Logger) error { return nil } +type fakeMetricsFactory struct { + name string +} + +// Initialize implements storage.MetricsFactory. +func (fmf fakeMetricsFactory) Initialize(*zap.Logger) error { + if fmf.name == "need-initialize-error" { + return fmt.Errorf("test-error") + } + return nil +} + +func (fmf fakeMetricsFactory) CreateMetricsReader() (metricsstore.Reader, error) { + if fmf.name == "need-metrics-reader-error" { + return nil, fmt.Errorf("test-error") + } + return &metricsstoremocks.Reader{}, nil +} + type fakeStorageExt struct{} var _ jaegerstorage.Extension = (*fakeStorageExt)(nil) -func (fakeStorageExt) Factory(name string) (storage.Factory, bool) { +func (fakeStorageExt) TraceStorageFactory(name string) (storage.Factory, bool) { if name == "need-factory-error" { return nil, false } return fakeFactory{name: name}, true } +func (fakeStorageExt) MetricStorageFactory(name string) (storage.MetricsFactory, bool) { + if name == "need-factory-error" { + return nil, false + } + return fakeMetricsFactory{name: name}, true +} + func (fakeStorageExt) Start(context.Context, component.Host) error { return nil } @@ -105,6 +133,7 @@ func TestServerStart(t *testing.T) { config: &Config{ TraceStorageArchive: "jaeger_storage", TraceStoragePrimary: "jaeger_storage", + MetricStorage: "jaeger_metrics_storage", }, }, { @@ -136,6 +165,22 @@ func TestServerStart(t *testing.T) { }, expectedErr: "cannot find archive storage factory", }, + { + name: "metrics storage error", + config: &Config{ + MetricStorage: "need-factory-error", + TraceStoragePrimary: "jaeger_storage", + }, + expectedErr: "cannot find metrics storage factory", + }, + { + name: " metrics reader error", + config: &Config{ + MetricStorage: "need-metrics-reader-error", + TraceStoragePrimary: "jaeger_storage", + }, + expectedErr: "cannot create metrics reader", + }, } for _, tt := range tests { @@ -242,3 +287,51 @@ func TestServerAddArchiveStorage(t *testing.T) { }) } } + +func TestServerAddMetricsStorage(t *testing.T) { + host := componenttest.NewNopHost() + + tests := []struct { + name string + config *Config + extension component.Component + expectedOutput string + expectedErr string + }{ + { + name: "Metrics storage unset", + config: &Config{}, + expectedOutput: `{"level":"info","msg":"Metric storage not configured"}` + "\n", + expectedErr: "", + }, + { + name: "Metrics storage set", + config: &Config{ + MetricStorage: "random-value", + }, + expectedOutput: "", + expectedErr: "cannot find metrics storage factory: cannot find extension", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + logger, buf := testutils.NewLogger() + telemetrySettings := component.TelemetrySettings{ + Logger: logger, + } + server := newServer(tt.config, telemetrySettings) + if tt.extension != nil { + host = storagetest.NewStorageHost().WithExtension(jaegerstorage.ID, tt.extension) + } + _, err := server.createMetricReader(host) + if tt.expectedErr == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, tt.expectedErr) + } + + assert.Contains(t, buf.String(), tt.expectedOutput) + }) + } +} diff --git a/cmd/jaeger/internal/extension/jaegerstorage/config.go b/cmd/jaeger/internal/extension/jaegerstorage/config.go index 42d4630d29d..98d19d08270 100644 --- a/cmd/jaeger/internal/extension/jaegerstorage/config.go +++ b/cmd/jaeger/internal/extension/jaegerstorage/config.go @@ -13,6 +13,8 @@ import ( casCfg "github.com/jaegertracing/jaeger/pkg/cassandra/config" esCfg "github.com/jaegertracing/jaeger/pkg/es/config" + promCfg "github.com/jaegertracing/jaeger/pkg/prometheus/config" + "github.com/jaegertracing/jaeger/plugin/metrics/prometheus" "github.com/jaegertracing/jaeger/plugin/storage/badger" "github.com/jaegertracing/jaeger/plugin/storage/cassandra" "github.com/jaegertracing/jaeger/plugin/storage/es" @@ -23,6 +25,7 @@ import ( var ( _ component.ConfigValidator = (*Config)(nil) _ confmap.Unmarshaler = (*Backend)(nil) + _ confmap.Unmarshaler = (*MetricBackends)(nil) ) // Config contains configuration(s) for jaeger trace storage. @@ -31,7 +34,8 @@ var ( // We tried to alias this type directly to a map, but conf did not populated it correctly. // Note also that the Backend struct has a custom unmarshaler. type Config struct { - Backends map[string]Backend `mapstructure:"backends"` + Backends map[string]Backend `mapstructure:"backends"` + MetricBackends map[string]MetricBackends `mapstructure:"metric_backends"` } type Backend struct { @@ -43,6 +47,10 @@ type Backend struct { Opensearch *esCfg.Configuration `mapstructure:"opensearch"` } +type MetricBackends struct { + Prometheus *promCfg.Configuration `mapstructure:"prometheus"` +} + // Unmarshal implements confmap.Unmarshaler. This allows us to provide // defaults for different configs. It cannot be done in createDefaultConfig() // because at that time we don't know which backends the user wants to use. @@ -98,3 +106,12 @@ func (cfg *Config) Validate() error { } return nil } + +func (cfg *MetricBackends) Unmarshal(conf *confmap.Conf) error { + // apply defaults + if conf.IsSet("prometheus") { + v := prometheus.DefaultConfig() + cfg.Prometheus = &v + } + return conf.Unmarshal(cfg) +} diff --git a/cmd/jaeger/internal/extension/jaegerstorage/config_test.go b/cmd/jaeger/internal/extension/jaegerstorage/config_test.go index 3f4dd8cd74b..1b2718c4cda 100644 --- a/cmd/jaeger/internal/extension/jaegerstorage/config_test.go +++ b/cmd/jaeger/internal/extension/jaegerstorage/config_test.go @@ -107,3 +107,14 @@ backends: require.NoError(t, conf.Unmarshal(cfg)) assert.NotEmpty(t, cfg.Backends["some_storage"].Opensearch.Servers) } + +func TestConfigDefaultPrometheus(t *testing.T) { + conf := loadConf(t, ` +metric_backends: + some_metrics_storage: + prometheus: +`) + cfg := createDefaultConfig().(*Config) + require.NoError(t, conf.Unmarshal(cfg)) + assert.NotEmpty(t, cfg.MetricBackends["some_metrics_storage"].Prometheus.ServerURL) +} diff --git a/cmd/jaeger/internal/extension/jaegerstorage/extension.go b/cmd/jaeger/internal/extension/jaegerstorage/extension.go index 4f2e618d327..5e8d1061349 100644 --- a/cmd/jaeger/internal/extension/jaegerstorage/extension.go +++ b/cmd/jaeger/internal/extension/jaegerstorage/extension.go @@ -14,6 +14,7 @@ import ( "github.com/jaegertracing/jaeger/cmd/jaeger/internal/extension/jaegerstorage/factoryadapter" "github.com/jaegertracing/jaeger/internal/metrics/otelmetrics" + "github.com/jaegertracing/jaeger/plugin/metrics/prometheus" "github.com/jaegertracing/jaeger/plugin/storage/badger" "github.com/jaegertracing/jaeger/plugin/storage/cassandra" "github.com/jaegertracing/jaeger/plugin/storage/es" @@ -27,38 +28,47 @@ var _ Extension = (*storageExt)(nil) type Extension interface { extension.Extension - Factory(name string) (storage.Factory, bool) + TraceStorageFactory(name string) (storage.Factory, bool) + MetricStorageFactory(name string) (storage.MetricsFactory, bool) } type storageExt struct { - config *Config - telset component.TelemetrySettings - factories map[string]storage.Factory + config *Config + telset component.TelemetrySettings + factories map[string]storage.Factory + metricsFactories map[string]storage.MetricsFactory } // GetStorageFactory locates the extension in Host and retrieves a storage factory from it with the given name. func GetStorageFactory(name string, host component.Host) (storage.Factory, error) { - var comp component.Component - for id, ext := range host.GetExtensions() { - if id.Type() == componentType { - comp = ext - break - } + ext, err := findExtension(host) + if err != nil { + return nil, err } - if comp == nil { + f, ok := ext.TraceStorageFactory(name) + if !ok { return nil, fmt.Errorf( - "cannot find extension '%s' (make sure it's defined earlier in the config)", - componentType, + "cannot find definition of storage '%s' in the configuration for extension '%s'", + name, componentType, ) } - f, ok := comp.(Extension).Factory(name) + return f, nil +} + +// GetMetricsFactory locates the extension in Host and retrieves a metrics factory from it with the given name. +func GetMetricsFactory(name string, host component.Host) (storage.MetricsFactory, error) { + ext, err := findExtension(host) + if err != nil { + return nil, err + } + mf, ok := ext.MetricStorageFactory(name) if !ok { return nil, fmt.Errorf( - "cannot find definition of storage '%s' in the configuration for extension '%s'", + "cannot find metric storage '%s' declared by '%s' extension", name, componentType, ) } - return f, nil + return mf, nil } func GetStorageFactoryV2(name string, host component.Host) (spanstore.Factory, error) { @@ -70,11 +80,34 @@ func GetStorageFactoryV2(name string, host component.Host) (spanstore.Factory, e return factoryadapter.NewFactory(f), nil } +func findExtension(host component.Host) (Extension, error) { + var id component.ID + var comp component.Component + for i, ext := range host.GetExtensions() { + if i.Type() == componentType { + id, comp = i, ext + break + } + } + if comp == nil { + return nil, fmt.Errorf( + "cannot find extension '%s' (make sure it's defined earlier in the config)", + componentType, + ) + } + ext, ok := comp.(Extension) + if !ok { + return nil, fmt.Errorf("extension '%s' is not of expected type '%s'", id, componentType) + } + return ext, nil +} + func newStorageExt(config *Config, telset component.TelemetrySettings) *storageExt { return &storageExt{ - config: config, - telset: telset, - factories: make(map[string]storage.Factory), + config: config, + telset: telset, + factories: make(map[string]storage.Factory), + metricsFactories: make(map[string]storage.MetricsFactory), } } @@ -104,6 +137,20 @@ func (s *storageExt) Start(_ context.Context, _ component.Host) error { } s.factories[storageName] = factory } + + for metricStorageName, cfg := range s.config.MetricBackends { + s.telset.Logger.Sugar().Infof("Initializing metrics storage '%s'", metricStorageName) + var metricsFactory storage.MetricsFactory + var err error + if cfg.Prometheus != nil { + metricsFactory, err = prometheus.NewFactoryWithConfig(*cfg.Prometheus, s.telset.Logger) + } + if err != nil { + return fmt.Errorf("failed to initialize metrics storage '%s': %w", metricStorageName, err) + } + s.metricsFactories[metricStorageName] = metricsFactory + } + return nil } @@ -120,7 +167,12 @@ func (s *storageExt) Shutdown(context.Context) error { return errors.Join(errs...) } -func (s *storageExt) Factory(name string) (storage.Factory, bool) { +func (s *storageExt) TraceStorageFactory(name string) (storage.Factory, bool) { f, ok := s.factories[name] return f, ok } + +func (s *storageExt) MetricStorageFactory(name string) (storage.MetricsFactory, bool) { + mf, ok := s.metricsFactories[name] + return mf, ok +} diff --git a/cmd/jaeger/internal/extension/jaegerstorage/extension_test.go b/cmd/jaeger/internal/extension/jaegerstorage/extension_test.go index b05ef36474a..472b160fb13 100644 --- a/cmd/jaeger/internal/extension/jaegerstorage/extension_test.go +++ b/cmd/jaeger/internal/extension/jaegerstorage/extension_test.go @@ -23,6 +23,7 @@ import ( esCfg "github.com/jaegertracing/jaeger/pkg/es/config" "github.com/jaegertracing/jaeger/pkg/metrics" + promCfg "github.com/jaegertracing/jaeger/pkg/prometheus/config" "github.com/jaegertracing/jaeger/plugin/storage/badger" "github.com/jaegertracing/jaeger/plugin/storage/cassandra" "github.com/jaegertracing/jaeger/plugin/storage/grpc" @@ -62,11 +63,28 @@ func TestStorageFactoryBadHostError(t *testing.T) { } func TestStorageFactoryBadNameError(t *testing.T) { - host := storagetest.NewStorageHost().WithExtension(ID, startStorageExtension(t, "foo")) + host := storagetest.NewStorageHost().WithExtension(ID, startStorageExtension(t, "foo", "")) _, err := GetStorageFactory("bar", host) require.ErrorContains(t, err, "cannot find definition of storage 'bar'") } +func TestMetricsFactoryBadHostError(t *testing.T) { + _, err := GetMetricsFactory("something", componenttest.NewNopHost()) + require.ErrorContains(t, err, "cannot find extension") +} + +func TestMetricsFactoryBadNameError(t *testing.T) { + host := storagetest.NewStorageHost().WithExtension(ID, startStorageExtension(t, "", "foo")) + _, err := GetMetricsFactory("bar", host) + require.ErrorContains(t, err, "cannot find metric storage 'bar'") +} + +func TestStorageExtensionType(t *testing.T) { + host := storagetest.NewStorageHost().WithExtension(ID, startStorageExtension(t, "", "foo")) + _, err := findExtension(host) + require.NoError(t, err) +} + func TestStorageFactoryBadShutdownError(t *testing.T) { shutdownError := fmt.Errorf("shutdown error") ext := storageExt{ @@ -86,7 +104,8 @@ func TestGetFactoryV2Error(t *testing.T) { func TestGetFactory(t *testing.T) { const name = "foo" - host := storagetest.NewStorageHost().WithExtension(ID, startStorageExtension(t, name)) + const metricname = "bar" + host := storagetest.NewStorageHost().WithExtension(ID, startStorageExtension(t, name, metricname)) f, err := GetStorageFactory(name, host) require.NoError(t, err) require.NotNil(t, f) @@ -94,6 +113,10 @@ func TestGetFactory(t *testing.T) { f2, err := GetStorageFactoryV2(name, host) require.NoError(t, err) require.NotNil(t, f2) + + f3, err := GetMetricsFactory(metricname, host) + require.NoError(t, err) + require.NotNil(t, f3) } func TestBadger(t *testing.T) { @@ -132,6 +155,22 @@ func TestGRPC(t *testing.T) { require.NoError(t, ext.Shutdown(ctx)) } +func TestPrometheus(t *testing.T) { + ext := makeStorageExtenion(t, &Config{ + MetricBackends: map[string]MetricBackends{ + "foo": { + Prometheus: &promCfg.Configuration{ + ServerURL: "localhost:12345", + }, + }, + }, + }) + ctx := context.Background() + err := ext.Start(ctx, componenttest.NewNopHost()) + require.NoError(t, err) + require.NoError(t, ext.Shutdown(ctx)) +} + func TestStartError(t *testing.T) { ext := makeStorageExtenion(t, &Config{ Backends: map[string]Backend{ @@ -143,6 +182,18 @@ func TestStartError(t *testing.T) { require.ErrorContains(t, err, "empty configuration") } +func TestMetricsStorageStartError(t *testing.T) { + ext := makeStorageExtenion(t, &Config{ + MetricBackends: map[string]MetricBackends{ + "foo": { + Prometheus: &promCfg.Configuration{}, + }, + }, + }) + err := ext.Start(context.Background(), componenttest.NewNopHost()) + require.ErrorContains(t, err, "failed to initialize metrics storage 'foo'") +} + func testElasticsearchOrOpensearch(t *testing.T, cfg Backend) { ext := makeStorageExtenion(t, &Config{ Backends: map[string]Backend{ @@ -222,7 +273,7 @@ func makeStorageExtenion(t *testing.T, config *Config) component.Component { return ext } -func startStorageExtension(t *testing.T, memstoreName string) component.Component { +func startStorageExtension(t *testing.T, memstoreName string, promstoreName string) component.Component { config := &Config{ Backends: map[string]Backend{ memstoreName: { @@ -231,6 +282,13 @@ func startStorageExtension(t *testing.T, memstoreName string) component.Componen }, }, }, + MetricBackends: map[string]MetricBackends{ + promstoreName: { + Prometheus: &promCfg.Configuration{ + ServerURL: "localhost:12345", + }, + }, + }, } require.NoError(t, config.Validate()) diff --git a/cmd/jaeger/internal/integration/storagecleaner/extension_test.go b/cmd/jaeger/internal/integration/storagecleaner/extension_test.go index 6f1290cf0b9..4c130fdc245 100644 --- a/cmd/jaeger/internal/integration/storagecleaner/extension_test.go +++ b/cmd/jaeger/internal/integration/storagecleaner/extension_test.go @@ -37,8 +37,9 @@ func (f *PurgerFactory) Purge(_ context.Context) error { } type mockStorageExt struct { - name string - factory storage.Factory + name string + factory storage.Factory + metricsFactory storage.MetricsFactory } func (*mockStorageExt) Start(context.Context, component.Host) error { @@ -49,13 +50,20 @@ func (*mockStorageExt) Shutdown(context.Context) error { panic("not implemented") } -func (m *mockStorageExt) Factory(name string) (storage.Factory, bool) { +func (m *mockStorageExt) TraceStorageFactory(name string) (storage.Factory, bool) { if m.name == name { return m.factory, true } return nil, false } +func (m *mockStorageExt) MetricStorageFactory(name string) (storage.MetricsFactory, bool) { + if m.name == name { + return m.metricsFactory, true + } + return nil, false +} + func TestStorageCleanerExtension(t *testing.T) { tests := []struct { name string diff --git a/cmd/query/app/querysvc/query_service.go b/cmd/query/app/querysvc/query_service.go index 2144928acb2..06ec79d94a4 100644 --- a/cmd/query/app/querysvc/query_service.go +++ b/cmd/query/app/querysvc/query_service.go @@ -44,6 +44,7 @@ type QueryServiceOptions struct { // StorageCapabilities is a feature flag for query service type StorageCapabilities struct { ArchiveStorage bool `json:"archiveStorage"` + // TODO: Maybe add metrics Storage here // SupportRegex bool // SupportTagFilter bool } diff --git a/docker-compose/monitor/Makefile b/docker-compose/monitor/Makefile index f6628dffd3b..e5d53688124 100644 --- a/docker-compose/monitor/Makefile +++ b/docker-compose/monitor/Makefile @@ -1,22 +1,30 @@ +BINARY ?= all-in-one # Default value uses v1 binary + .PHONY: build build: clean-jaeger - cd ../../ && make build-all-in-one-linux + cd ../../ && make build-$(BINARY) GOOS=linux cd ../../ && make create-baseimg PLATFORMS=linux/$(shell go env GOARCH) cd ../../ && docker buildx build --target release \ - --tag jaegertracing/all-in-one:dev \ + --tag jaegertracing/$(BINARY):dev \ --build-arg base_image=localhost:5000/baseimg_alpine:latest \ --build-arg debug_image=not-used \ --build-arg TARGETARCH=$(shell go env GOARCH) \ --load \ - cmd/all-in-one + cmd/$(BINARY) # starts up the system required for SPM using the latest otel image and a development jaeger image. # Note: the jaeger "dev" image can be built with "make build". .PHONY: dev dev: export JAEGER_IMAGE_TAG = dev -dev: +dev: docker compose -f docker-compose.yml up $(DOCKER_COMPOSE_ARGS) +.PHONY: dev-v2 +dev-v2: export JAEGER_IMAGE_TAG = dev +dev-v2: export BINARY = jaeger +dev-v2: build + docker compose -f docker-compose-v2.yml up $(DOCKER_COMPOSE_ARGS) + .PHONY: clean-jaeger clean-jaeger: # Also cleans up intermediate cached containers. diff --git a/docker-compose/monitor/docker-compose-v2.yml b/docker-compose/monitor/docker-compose-v2.yml new file mode 100644 index 00000000000..5bddd2cc658 --- /dev/null +++ b/docker-compose/monitor/docker-compose-v2.yml @@ -0,0 +1,51 @@ +version: "3.5" +services: + jaeger: + networks: + backend: + # This is the host name used in Prometheus scrape configuration. + aliases: [spm_metrics_source] + image: jaegertracing/jaeger:${JAEGER_IMAGE_TAG:-latest} + volumes: + - "./jaeger-ui.json:/etc/jaeger/jaeger-ui.json" # Do we need this for v2 ? Seems to be running without this. + - "./jaeger-v2-config.yml:/etc/jaeger/config.yml" + command: ["--config", "/etc/jaeger/config.yml"] + ports: + - "16686:16686" + - "8889:8889" + + microsim: + networks: + - backend + image: yurishkuro/microsim:v0.4.1 + command: "-d 24h -s 500ms" + environment: + - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://jaeger:4318/v1/traces + depends_on: + - jaeger + + prometheus: + networks: + - backend + image: prom/prometheus:latest + volumes: + - "./prometheus.yml:/etc/prometheus/prometheus.yml" + ports: + - "9090:9090" + + grafana: + networks: + - backend + image: grafana/grafana:latest + volumes: + - ./grafana.ini:/etc/grafana/grafana.ini + - ./datasource.yml:/etc/grafana/provisioning/datasources/datasource.yaml + environment: + - GF_AUTH_ANONYMOUS_ENABLED=true + - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin + - GF_AUTH_DISABLE_LOGIN_FORM=true + ports: + - 3000:3000 + +networks: + backend: diff --git a/docker-compose/monitor/docker-compose.yml b/docker-compose/monitor/docker-compose.yml index 61e9170148c..3f288201eb9 100644 --- a/docker-compose/monitor/docker-compose.yml +++ b/docker-compose/monitor/docker-compose.yml @@ -17,15 +17,21 @@ services: - PROMETHEUS_QUERY_NORMALIZE_DURATION=true ports: - "16686:16686" + otel_collector: networks: - - backend + backend: + # This is the host name used in Prometheus scrape configuration. + aliases: [spm_metrics_source] image: otel/opentelemetry-collector-contrib:${OTEL_IMAGE_TAG:-0.89.0} volumes: - ${OTEL_CONFIG_SRC:-./otel-collector-config-connector.yml}:/etc/otelcol/otel-collector-config.yml command: --config /etc/otelcol/otel-collector-config.yml depends_on: - jaeger + ports: + - "8889:8889" + microsim: networks: - backend @@ -36,6 +42,7 @@ services: - OTEL_EXPORTER_OTLP_INSECURE=true depends_on: - otel_collector + prometheus: networks: - backend @@ -44,6 +51,7 @@ services: - "./prometheus.yml:/etc/prometheus/prometheus.yml" ports: - "9090:9090" + grafana: networks: - backend @@ -56,7 +64,7 @@ services: - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin - GF_AUTH_DISABLE_LOGIN_FORM=true ports: - - 3000:3000 + - "3000:3000" networks: backend: diff --git a/docker-compose/monitor/jaeger-v2-config.yml b/docker-compose/monitor/jaeger-v2-config.yml new file mode 100644 index 00000000000..bc7160c5bb8 --- /dev/null +++ b/docker-compose/monitor/jaeger-v2-config.yml @@ -0,0 +1,48 @@ +service: + extensions: [jaeger_storage, jaeger_query] + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [jaeger_storage_exporter, spanmetrics] + metrics/spanmetrics: + receivers: [spanmetrics] + exporters: [prometheus] + telemetry: + logs: + level: DEBUG + +extensions: + jaeger_query: + trace_storage: some_storage + metric_storage: some_metrics_storage + jaeger_storage: + backends: + some_storage: + memory: + max_traces: 100000 + metric_backends: + some_metrics_storage: + prometheus: + endpoint: http://prometheus:9090 + normalize_calls: true + normalize_duration: true + +connectors: + spanmetrics: + +receivers: + otlp: + protocols: + grpc: + http: + endpoint: "0.0.0.0:4318" + +processors: + batch: + +exporters: + jaeger_storage_exporter: + trace_storage: some_storage + prometheus: + endpoint: "0.0.0.0:8889" diff --git a/docker-compose/monitor/otel-collector-config-connector.yml b/docker-compose/monitor/otel-collector-config-connector.yml index 038f5f86c29..72d577d4321 100644 --- a/docker-compose/monitor/otel-collector-config-connector.yml +++ b/docker-compose/monitor/otel-collector-config-connector.yml @@ -1,9 +1,4 @@ receivers: - jaeger: - protocols: - thrift_http: - endpoint: "0.0.0.0:14278" - otlp: protocols: grpc: @@ -27,11 +22,12 @@ processors: service: pipelines: traces: - receivers: [otlp, jaeger] + receivers: [otlp] processors: [batch] exporters: [spanmetrics, otlp] - # The exporter name in this pipeline must match the spanmetrics.metrics_exporter name. - # The receiver is just a dummy and never used; added to pass validation requiring at least one receiver in a pipeline. + + # The metrics pipeline receives generated span metrics from 'spanmetrics' connector + # and pushes to Prometheus exporter, which makes them available for scraping on :8889. metrics/spanmetrics: receivers: [spanmetrics] exporters: [prometheus] diff --git a/docker-compose/monitor/prometheus.yml b/docker-compose/monitor/prometheus.yml index 4dfa620887f..5ca0a6293cc 100644 --- a/docker-compose/monitor/prometheus.yml +++ b/docker-compose/monitor/prometheus.yml @@ -6,4 +6,4 @@ global: scrape_configs: - job_name: aggregated-trace-metrics static_configs: - - targets: ['otel_collector:8889'] + - targets: ['spm_metrics_source:8889'] diff --git a/go.mod b/go.mod index cf46248a6d2..62ec869cbe0 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/olivere/elastic v6.2.37+incompatible github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector v0.105.0 github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter v0.105.0 + github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter v0.105.0 github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.105.0 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger v0.105.0 github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver v0.105.0 @@ -93,6 +94,8 @@ require ( ) require ( + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry v0.105.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus v0.105.0 // indirect go.opentelemetry.io/collector/internal/globalgates v0.105.0 // indirect go.opentelemetry.io/collector/pdata/pprofile v0.105.0 // indirect go.opentelemetry.io/collector/pdata/testdata v0.105.0 // indirect @@ -103,7 +106,7 @@ require ( require ( github.com/IBM/sarama v1.43.2 // indirect - github.com/aws/aws-sdk-go v1.53.11 // indirect + github.com/aws/aws-sdk-go v1.53.16 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect diff --git a/go.sum b/go.sum index 6128a76429a..5269dcc2d67 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,50 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= +cloud.google.com/go/auth v0.5.1 h1:0QNO7VThG54LUzKiQxv8C6x1YX7lUrzlAa1nVLF8CIw= +cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= +cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= +cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Code-Hex/go-generics-cache v1.5.1 h1:6vhZGc5M7Y/YD8cIUcY8kcuQLB4cHR7U+0KMqAA0KcU= +github.com/Code-Hex/go-generics-cache v1.5.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/IBM/sarama v1.43.2 h1:HABeEqRUh32z8yzY2hGB/j8mHSzC/HA9zlEjqFNCzSw= github.com/IBM/sarama v1.43.2/go.mod h1:Kyo4WkF24Z+1nz7xeVUFWIuKVV8RS3wM8mkvPKMdXFQ= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Shopify/sarama v1.33.0 h1:2K4mB9M4fo46sAM7t6QTsmSO8dLX1OqznLM7vn3OjZ8= github.com/Shopify/sarama v1.33.0/go.mod h1:lYO7LwEBkE0iAeTl94UfPSrDaavFzSFlmn+5isARATQ= github.com/Shopify/toxiproxy/v2 v2.3.0 h1:62YkpiP4bzdhKMH+6uC5E95y608k3zDwdzuBMsnn3uQ= github.com/Shopify/toxiproxy/v2 v2.3.0/go.mod h1:KvQTtB6RjCJY4zqNJn7C7JDFgsG5uoHYDirfUfpIm0c= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 h1:ez/4by2iGztzR4L0zgAOR8lTQK9VlyBVVd7G4omaOQs= +github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/apache/thrift v0.20.0 h1:631+KvYbsBZxmuJjYwhezVsrfc/TbqtZV4QcxOX1fOI= github.com/apache/thrift v0.20.0/go.mod h1:hOk1BQqcp2OLzGsyVXdfMk7YFlMxK3aoEVhjD06QhB8= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.53.11 h1:KcmduYvX15rRqt4ZU/7jKkmDxU/G87LJ9MUI0yQJh00= -github.com/aws/aws-sdk-go v1.53.11/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.53.16 h1:8oZjKQO/ml1WLUZw5hvF7pvYjPf8o9f57Wldoy/q9Qc= +github.com/aws/aws-sdk-go v1.53.16/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= @@ -33,6 +61,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -43,12 +73,24 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= +github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/digitalocean/godo v1.117.0 h1:WVlTe09melDYTd7VCVyvHcNWbgB+uI1O115+5LOtdSw= +github.com/digitalocean/godo v1.117.0/go.mod h1:Vk0vpCot2HOAJwc5WE8wljZGtJ3ZtWIc8MQ8rF38sdo= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= +github.com/docker/docker v26.1.4+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/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= @@ -63,10 +105,18 @@ github.com/elastic/elastic-transport-go/v8 v8.6.0 h1:Y2S/FBjx1LlCv5m6pWAF2kDJAHo github.com/elastic/elastic-transport-go/v8 v8.6.0/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk= github.com/elastic/go-elasticsearch/v8 v8.14.0 h1:1ywU8WFReLLcxE1WJqii3hTtbPUE2hc38ZK/j4mMFow= github.com/elastic/go-elasticsearch/v8 v8.14.0/go.mod h1:WRvnlGkSuZyp83M2U8El/LGXpCjYLrvlkSgkAH4O5I4= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -80,6 +130,10 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= 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= @@ -89,15 +143,27 @@ github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= 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-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= +github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= +github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= +github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= +github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= +github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= +github.com/go-resty/resty/v2 v2.13.1 h1:x+LHXBI2nMB1vqndymf26quycC4aggYJ7DECYbiz03g= +github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96ORAI6Q7d+0= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= +github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/gocql/gocql v1.6.0 h1:IdFdOTbnpbd0pDhl4REKQDM+Q0SzKXQ1Yh+YZZ8T/qU= github.com/gocql/gocql v1.6.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= @@ -123,6 +189,8 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -134,10 +202,22 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= +github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= +github.com/gophercloud/gophercloud v1.12.0 h1:Jrz16vPAL93l80q16fp8NplrTCp93y7rZh2P3Q4Yq7g= +github.com/gophercloud/gophercloud v1.12.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= @@ -145,17 +225,35 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/consul/api v1.29.1 h1:UEwOjYJrd3lG1x5w7HxDRMGiAUPrb3f103EoeKuuEcc= +github.com/hashicorp/consul/api v1.29.1/go.mod h1:lumfRkY/coLuqMICkI7Fh3ylMG31mQSRZyef2c5YvJI= +github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= +github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -167,9 +265,19 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/nomad/api v0.0.0-20240604134157-e73d8bb1140d h1:KHq+mAzWSkumj4PDoXc5VZbycPGcmYu8tohgVLQ6SIc= +github.com/hashicorp/nomad/api v0.0.0-20240604134157-e73d8bb1140d/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE= +github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= +github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/hetznercloud/hcloud-go/v2 v2.9.0 h1:s0N6R7Zoi2DPfMtUF5o9VeUBzTtHVY6MIkHOQnfu/AY= +github.com/hetznercloud/hcloud-go/v2 v2.9.0/go.mod h1:qtW/TuU7Bs16ibXl/ktJarWqU2LwHr7eGlwoilHxtgg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/ionos-cloud/sdk-go/v6 v6.1.11 h1:J/uRN4UWO3wCyGOeDdMKv8LWRzKu6UIkLEaes38Kzh8= +github.com/ionos-cloud/sdk-go/v6 v6.1.11/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= @@ -206,6 +314,8 @@ github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPgh github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= github.com/knadh/koanf/v2 v2.1.1/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= +github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -215,20 +325,34 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lightstep/go-expohisto v1.0.0 h1:UPtTS1rGdtehbbAF7o/dhkWLTDI73UifG8LbfQI7cA4= github.com/lightstep/go-expohisto v1.0.0/go.mod h1:xDXD0++Mu2FOaItXtdDfksfgxfV0z1TMPa+e/EUd0cs= +github.com/linode/linodego v1.35.0 h1:rIhUeCHBLEDlkoRnOTwzSGzljQ3ksXwLxacmXnrV+Do= +github.com/linode/linodego v1.35.0/go.mod h1:JxuhOEAMfSxun6RU5/MgTKH2GGTmFrhKRj3wL1NFin0= github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY= github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= +github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= 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/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE= github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 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/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= @@ -258,6 +382,8 @@ github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsc github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector v0.105.0/go.mod h1:45iX3DRsbK2XlbHzEWtIvud56FE2XdC7crKIne4DUaU= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter v0.105.0 h1:HcFHS9xNt2nI9yphhvvgWekr9zsP2jVi8IQUckAxCUk= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter v0.105.0/go.mod h1:DB9+mDKgg/nO+vZca48EWvCTcOjHyjOeJKAbP+WfPXU= +github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter v0.105.0 h1:L3zHDcjdhyvZatjv0jGAR9ShWYY4a9sDCBcdxCxdKcU= +github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter v0.105.0/go.mod h1:plLxFSlZzwEa06qc/1pVH1EQISsnSsMX9PwXYKEB/sg= github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.105.0 h1:HmimWATFFNI8o6n52DXTS2EjFRa6aETNqmA3MBGAxSI= github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.105.0/go.mod h1:DoCIQkjzSFD/rRq9rsI4kzYKcHRn6B7g7txILM18dHQ= github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.105.0 h1:kHHL4A9wL6TxM2sIUEXUpFXGPxrW7u002FJK+majI0s= @@ -272,28 +398,42 @@ github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.105.0 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.105.0/go.mod h1:hzu5KvOYEH5W9OpVc+iRXUAvj7GHcLyyR4qjIH+hOhQ= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.105.0 h1:hs7TaJClEAhHrj71XcaYqlYnIOpOYQgoHqhnnBNrOK8= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.105.0/go.mod h1:ehzaiDdkrww7l1Stvse5GCOAsAZOpFcgeIbB/2PqFs4= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry v0.105.0 h1:wKujcXESoQPBWIxYIET7YP6lN2idX8oZRsNl8iWXum0= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry v0.105.0/go.mod h1:n9awPzI+erPm8NB8yL/UusWvF5P741BbHv5bcWYMXrc= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/azure v0.105.0 h1:PfbW/oTNBNOCzantcwnGXMuc+qhMSUhdcWnfO0qXEhs= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/azure v0.105.0/go.mod h1:NZsH4m+WpkVKuUYK6Te0Z012jjhfmVcVL3M1W/0Hw4w= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger v0.105.0 h1:EIMptO6ZZeP734nBLxNVftrWA+OEGtgsxarNH7rao2A= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger v0.105.0/go.mod h1:/2F91Hsx7RAn/FENz/7MRbHBkBYQ/uX6t4tYJfyeBfM= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus v0.105.0 h1:hKpdsx8wzn/wA3hAavSEVKLUBfkYkpfXpudT+VUxucA= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus v0.105.0/go.mod h1:1Tq47AVtrvxnohU1Is3EV/zv2ifPwdRSW735xG+zvFU= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/zipkin v0.105.0 h1:60worMGZbZFw6djolg/CVExX6DPQoXgfM4pmdZj2b7E= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/zipkin v0.105.0/go.mod h1:Nhq0L1GhTdyl/Td94xCiys0kJMO9lOsezhYRXz0MTvQ= github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver v0.105.0 h1:KGvKn2n/tV5aG3JlryEgXnnSVnY0O6YFWGOY72OI8MY= github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver v0.105.0/go.mod h1:NKh0a5RFTHnvxRRmjlV96ZzSc5xZrHr1yPRWxskjBB0= github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver v0.105.0 h1:JADJYzFGjD3c7eVKYYAHxMFE9rBtMTEPM/4t8C8ww3Q= github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver v0.105.0/go.mod h1:rGyiKbLfQyHk5Q+ZSGs4wH8kb2J+SbIlEiytjB/cDdI= +github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver v0.105.0 h1:s2kcmrILHXgutAl3Slol4xlDUMJTYjEU7kppk3DkZ2s= +github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver v0.105.0/go.mod h1:gBmEBZB1odOni3kBpY+EbOBcXOK3tDu2eoqegdSeXtY= github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver v0.105.0 h1:JLYDrRk4oJB5CZY49Q1AhvpN8Tnl8faPG0CqpnDOFIw= github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver v0.105.0/go.mod h1:73LyO27uXzwtEZrSq/7b1wi5FG9aHx6TUVcCDaxJ5mw= +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/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= +github.com/ovh/go-ovh v1.5.1 h1:P8O+7H+NQuFK9P/j4sFW5C0fvSS2DnHYGPwdVCp45wI= +github.com/ovh/go-ovh v1.5.1/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -311,8 +451,12 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= +github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/prometheus v0.53.0 h1:vOnhpUKrDv954jnVBvhG/ZQJ3kqscnKI+Hbdwo2tAhc= +github.com/prometheus/prometheus v0.53.0/go.mod h1:RZDkzs+ShMBDkAPQkLEaLBXpjmDcjhNxU2drUVPgKUU= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/relvacode/iso8601 v1.4.0 h1:GsInVSEJfkYuirYFxa80nMLbH2aydgZpIf52gYZXUJs= @@ -330,6 +474,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27 h1:yGAraK1uUjlhSXgNMIy8o/J4LFNcy7yeipBqt9N9mVg= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= github.com/shirou/gopsutil/v4 v4.24.6 h1:9qqCSYF2pgOU+t+NgJtp7Co5+5mHF/HyKBUckySQL64= github.com/shirou/gopsutil/v4 v4.24.6/go.mod h1:aoebb2vxetJ/yIDZISmduFvVNPHqXQ9SEJwRXxkf0RA= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -382,6 +528,8 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMW github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= +github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= @@ -570,6 +718,8 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -631,6 +781,8 @@ golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= 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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -639,6 +791,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -652,6 +806,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= 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= @@ -662,6 +818,8 @@ gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +google.golang.org/api v0.183.0 h1:PNMeRDwo1pJdgNcFQ9GstuLe/noWKIc89pRWRLMvLwE= +google.golang.org/api v0.183.0/go.mod h1:q43adC5/pHoSZTx5h2mSmdF7NcyfW9JuDyIOJAgS9ZQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -715,4 +873,22 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= +k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= +k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= +k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= +k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= +k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= +k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/pkg/prometheus/config/config.go b/pkg/prometheus/config/config.go index 122b831dea1..54ee6ea9398 100644 --- a/pkg/prometheus/config/config.go +++ b/pkg/prometheus/config/config.go @@ -17,19 +17,27 @@ package config import ( "time" + "github.com/asaskevich/govalidator" + "github.com/jaegertracing/jaeger/pkg/config/tlscfg" ) // Configuration describes the options to customize the storage behavior. type Configuration struct { - ServerURL string - ConnectTimeout time.Duration - TLS tlscfg.Options - TokenFilePath string - TokenOverrideFromContext bool - - MetricNamespace string - LatencyUnit string - NormalizeCalls bool - NormalizeDuration bool + ServerURL string `valid:"required" mapstructure:"endpoint"` + ConnectTimeout time.Duration `mapstructure:"connect_timeout"` + TLS tlscfg.Options + + TokenFilePath string `mapstructure:"token_file_path"` + TokenOverrideFromContext bool `mapstructure:"token_override_from_context"` + + MetricNamespace string `mapstructure:"metric_namespace"` + LatencyUnit string `mapstructure:"latency_unit"` + NormalizeCalls bool `mapstructure:"normalize_calls"` + NormalizeDuration bool `mapstructure:"normalize_duration"` +} + +func (c *Configuration) Validate() error { + _, err := govalidator.ValidateStruct(c) + return err } diff --git a/pkg/prometheus/config/empty_test.go b/pkg/prometheus/config/config_test.go similarity index 74% rename from pkg/prometheus/config/empty_test.go rename to pkg/prometheus/config/config_test.go index 2b7fcf4a4b8..d49f95c1141 100644 --- a/pkg/prometheus/config/empty_test.go +++ b/pkg/prometheus/config/config_test.go @@ -17,9 +17,22 @@ package config import ( "testing" + "github.com/stretchr/testify/require" + "github.com/jaegertracing/jaeger/pkg/testutils" ) +func TestValidate(t *testing.T) { + cfg := Configuration{ + ServerURL: "localhost:1234", + } + err := cfg.Validate() + require.NoError(t, err) + cfg = Configuration{} + err = cfg.Validate() + require.Error(t, err) +} + func TestMain(m *testing.M) { testutils.VerifyGoLeaks(m) } diff --git a/plugin/metrics/prometheus/factory.go b/plugin/metrics/prometheus/factory.go index a806942eb46..48fe906196e 100644 --- a/plugin/metrics/prometheus/factory.go +++ b/plugin/metrics/prometheus/factory.go @@ -22,6 +22,7 @@ import ( "go.opentelemetry.io/otel/trace" "go.uber.org/zap" + "github.com/jaegertracing/jaeger/pkg/prometheus/config" "github.com/jaegertracing/jaeger/plugin" prometheusstore "github.com/jaegertracing/jaeger/plugin/metrics/prometheus/metricsstore" "github.com/jaegertracing/jaeger/storage/metricsstore" @@ -66,3 +67,18 @@ func (f *Factory) Initialize(logger *zap.Logger) error { func (f *Factory) CreateMetricsReader() (metricsstore.Reader, error) { return prometheusstore.NewMetricsReader(f.options.Configuration, f.logger, f.tracer) } + +func NewFactoryWithConfig( + cfg config.Configuration, + logger *zap.Logger, +) (*Factory, error) { + if err := cfg.Validate(); err != nil { + return nil, err + } + f := NewFactory() + f.options = &Options{ + Configuration: cfg, + } + f.Initialize(logger) + return f, nil +} diff --git a/plugin/metrics/prometheus/factory_test.go b/plugin/metrics/prometheus/factory_test.go index bd49eca32d5..cc677fb7f61 100644 --- a/plugin/metrics/prometheus/factory_test.go +++ b/plugin/metrics/prometheus/factory_test.go @@ -24,6 +24,7 @@ import ( "go.uber.org/zap" "github.com/jaegertracing/jaeger/pkg/config" + promCfg "github.com/jaegertracing/jaeger/pkg/prometheus/config" "github.com/jaegertracing/jaeger/pkg/testutils" "github.com/jaegertracing/jaeger/storage" ) @@ -134,6 +135,20 @@ func TestFailedTLSOptions(t *testing.T) { t.Errorf("f.InitFromViper did not panic") } +func TestEmptyFactoryConfig(t *testing.T) { + cfg := promCfg.Configuration{} + _, err := NewFactoryWithConfig(cfg, zap.NewNop()) + require.Error(t, err) +} + +func TestFactoryConfig(t *testing.T) { + cfg := promCfg.Configuration{ + ServerURL: "localhost:1234", + } + _, err := NewFactoryWithConfig(cfg, zap.NewNop()) + require.NoError(t, err) +} + func TestMain(m *testing.M) { testutils.VerifyGoLeaks(m) } diff --git a/plugin/metrics/prometheus/options.go b/plugin/metrics/prometheus/options.go index 80cf09e3070..2b4bd221a94 100644 --- a/plugin/metrics/prometheus/options.go +++ b/plugin/metrics/prometheus/options.go @@ -55,9 +55,8 @@ type Options struct { config.Configuration `mapstructure:",squash"` } -// NewOptions creates a new Options struct. -func NewOptions() *Options { - defaultConfig := config.Configuration{ +func DefaultConfig() config.Configuration { + return config.Configuration{ ServerURL: defaultServerURL, ConnectTimeout: defaultConnectTimeout, @@ -66,9 +65,12 @@ func NewOptions() *Options { NormalizeCalls: defaultNormalizeCalls, NormalizeDuration: defaultNormalizeCalls, } +} +// NewOptions creates a new Options struct. +func NewOptions() *Options { return &Options{ - Configuration: defaultConfig, + Configuration: DefaultConfig(), } } diff --git a/scripts/spm-integration-test.sh b/scripts/spm-integration-test.sh index 61e99911206..b9cf9204a8a 100755 --- a/scripts/spm-integration-test.sh +++ b/scripts/spm-integration-test.sh @@ -2,8 +2,34 @@ set -euf -o pipefail +print_help() { + echo "Usage: $0 [-b binary]" + echo "-b: Which binary to build: 'all-in-one' (default) or 'jaeger' (v2)" + echo "-h: Print help" + exit 1 +} + +BINARY='all-in-one' compose_file=docker-compose/monitor/docker-compose.yml -timeout=300 + +while getopts "b:h" opt; do + case "${opt}" in + b) + BINARY=${OPTARG} + ;; + *) + print_help + ;; + esac +done + +set -x + +if [ "$BINARY" == "jaeger" ]; then + compose_file=docker-compose/monitor/docker-compose-v2.yml +fi + +timeout=600 end_time=$((SECONDS + timeout)) success="false" @@ -12,7 +38,7 @@ check_service_health() { local url=$2 echo "Checking health of service: $service_name at $url" - local wait_seconds=10 + local wait_seconds=3 local curl_params=( --silent --output @@ -39,7 +65,7 @@ wait_for_services() { check_service_health "Jaeger" "http://localhost:16686" check_service_health "Prometheus" "http://localhost:9090/graph" # Grafana is not actually important for the functional test, - # but it at least validates that the docker-compose file is correct. + # but we still validate that the docker-compose file is correct. check_service_health "Grafana" "http://localhost:3000" } @@ -63,9 +89,9 @@ validate_service_metrics() { echo "Metric datapoints found for service '$service': " "${metric_points[@]}" # Check that atleast some values are non-zero after the threshold local non_zero_count=0 - local expected_non_zero_count=3 + local expected_non_zero_count=4 local zero_count=0 - local expected_max_zero_count=3 + local expected_max_zero_count=4 for value in "${metric_points[@]}"; do if [[ $(echo "$value > 0.0" | bc) == "1" ]]; then non_zero_count=$((non_zero_count + 1)) @@ -79,7 +105,7 @@ validate_service_metrics() { fi done if [ $non_zero_count -lt $expected_non_zero_count ]; then - echo "⏳ Expecting at least 3 non-zero data points" + echo "⏳ Expecting at least 4 non-zero data points" return 1 fi return 0 @@ -122,7 +148,11 @@ teardown_services() { } main() { - (cd docker-compose/monitor && make build && make dev DOCKER_COMPOSE_ARGS="-d") + if [ "$BINARY" == "jaeger" ]; then + (cd docker-compose/monitor && make build BINARY="$BINARY" && make dev-v2 DOCKER_COMPOSE_ARGS="-d") + else + (cd docker-compose/monitor && make build BINARY="$BINARY" && make dev DOCKER_COMPOSE_ARGS="-d") + fi wait_for_services check_spm success="true"