diff --git a/server/config/config.go b/server/config/config.go index dee41b86de5..9941ff6373c 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -171,11 +171,13 @@ type ServerConfig struct { EnableGRPCGateway bool - // ExperimentalEnableDistributedTracing enables distributed tracing using OpenTelemetry protocol. - ExperimentalEnableDistributedTracing bool // ExperimentalTracerOptions are options for OpenTelemetry gRPC interceptor. + // Deprecated in v3.6 and will be decommissioned in v3.7. + // TODO: remove in v3.7 ExperimentalTracerOptions []otelgrpc.Option + TracerOptions []otelgrpc.Option + WatchProgressNotifyInterval time.Duration // UnsafeNoFsync disables all uses of fsync. @@ -211,6 +213,9 @@ type ServerConfig struct { // ServerFeatureGate is a server level feature gate ServerFeatureGate featuregate.FeatureGate + + // EnableDistributedTracing enables distributed tracing using OpenTelemetry protocol. + EnableDistributedTracing bool `json:"enable-distributed-tracing"` } // VerifyBootstrap sanity-checks the initial config for bootstrap case diff --git a/server/embed/config.go b/server/embed/config.go index 3a382056834..e609a49695c 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -97,8 +97,13 @@ const ( DefaultLogRotationConfig = `{"maxsize": 100, "maxage": 0, "maxbackups": 0, "localtime": false, "compress": false}` // ExperimentalDistributedTracingAddress is the default collector address. + // Deprecated in v3.6 and will be decommissioned in v3.7. + // TODO: delete in v3.7 ExperimentalDistributedTracingAddress = "localhost:4317" + // ExperimentalDistributedTracingServiceName is the default etcd service name. + // Deprecated in v3.6 and will be decommissioned in v3.7. + // TODO: delete in v3.7 ExperimentalDistributedTracingServiceName = "etcd" // DefaultStrictReconfigCheck is the default value for "--strict-reconfig-check" flag. @@ -133,7 +138,11 @@ var ( // This is the mapping from the non boolean `experimental-` to the new flags. // TODO: delete in v3.7 experimentalNonBoolFlagMigrationMap = map[string]string{ - "experimental-compact-hash-check-time": "compact-hash-check-time", + "experimental-compact-hash-check-time": "compact-hash-check-time", + "experimental-distributed-tracing-address": "distributed-tracing-address", + "experimental-distributed-tracing-service-name": "distributed-tracing-service-name", + "experimental-distributed-tracing-instance-id": "distributed-tracing-instance-id", + "experimental-distributed-tracing-sampling-rate": "distributed-tracing-sampling-rate", } ) @@ -408,23 +417,33 @@ type Config struct { ListenMetricsUrls []url.URL ListenMetricsUrlsJSON string `json:"listen-metrics-urls"` - // ExperimentalEnableDistributedTracing indicates if experimental tracing using OpenTelemetry is enabled. + // ExperimentalEnableDistributedTracing enables distributed tracing using OpenTelemetry protocol. + // Deprecated in v3.6 and will be decommissioned in v3.7. + // TODO: delete in v3.7 ExperimentalEnableDistributedTracing bool `json:"experimental-enable-distributed-tracing"` - // ExperimentalDistributedTracingAddress is the address of the OpenTelemetry Collector. - // Can only be set if ExperimentalEnableDistributedTracing is true. + // ExperimentalDistributedTracingAddress is the address of OpenTelemetry collector. + // Deprecated in v3.6 and will be decommissioned in v3.7. + // TODO: delete in v3.7 ExperimentalDistributedTracingAddress string `json:"experimental-distributed-tracing-address"` // ExperimentalDistributedTracingServiceName is the name of the service. - // Can only be used if ExperimentalEnableDistributedTracing is true. + // Deprecated in v3.6 and will be decommissioned in v3.7. + // TODO: delete in v3.7 ExperimentalDistributedTracingServiceName string `json:"experimental-distributed-tracing-service-name"` // ExperimentalDistributedTracingServiceInstanceID is the ID key of the service. - // This ID must be unique, as helps to distinguish instances of the same service - // that exist at the same time. - // Can only be used if ExperimentalEnableDistributedTracing is true. + // Deprecated in v3.6 and will be decommissioned in v3.7. + // TODO: delete in v3.7 ExperimentalDistributedTracingServiceInstanceID string `json:"experimental-distributed-tracing-instance-id"` - // ExperimentalDistributedTracingSamplingRatePerMillion is the number of samples to collect per million spans. - // Defaults to 0. + // ExperimentalDistributedTracingSamplingRatePerMillion is the number of samples. + // Deprecated in v3.6 and will be decommissioned in v3.7. + // TODO: delete in v3.7 ExperimentalDistributedTracingSamplingRatePerMillion int `json:"experimental-distributed-tracing-sampling-rate"` + EnableDistributedTracing bool `json:"enable-distributed-tracing"` + DistributedTracingAddress string `json:"distributed-tracing-address"` + DistributedTracingServiceName string `json:"distributed-tracing-service-name"` + DistributedTracingServiceInstanceID string `json:"distributed-tracing-instance-id"` + DistributedTracingSamplingRatePerMillion int `json:"distributed-tracing-sampling-rate"` + // Logger is logger options: currently only supports "zap". // "capnslog" is removed in v3.5. Logger string `json:"logger"` @@ -654,6 +673,11 @@ func (cfg *Config) AddFlags(fs *flag.FlagSet) { fs.DurationVar(&cfg.GRPCKeepAliveTimeout, "grpc-keepalive-timeout", cfg.GRPCKeepAliveTimeout, "Additional duration of wait before closing a non-responsive connection (0 to disable).") fs.BoolVar(&cfg.SocketOpts.ReusePort, "socket-reuse-port", cfg.SocketOpts.ReusePort, "Enable to set socket option SO_REUSEPORT on listeners allowing rebinding of a port already in use.") fs.BoolVar(&cfg.SocketOpts.ReuseAddress, "socket-reuse-address", cfg.SocketOpts.ReuseAddress, "Enable to set socket option SO_REUSEADDR on listeners allowing binding to an address in `TIME_WAIT` state.") + fs.BoolVar(&cfg.EnableDistributedTracing, "enable-distributed-tracing", false, "Enable distributed tracing using OpenTelemetry protocol") + fs.StringVar(&cfg.DistributedTracingAddress, "distributed-tracing-address", ExperimentalDistributedTracingAddress, "Address for distributed tracing used for OpenTelemetry Tracing") + fs.StringVar(&cfg.DistributedTracingServiceName, "distributed-tracing-service-name", ExperimentalDistributedTracingServiceName, "Configures service name for distributed tracing") + fs.StringVar(&cfg.DistributedTracingServiceInstanceID, "distributed-tracing-instance-id", "", "Configures service instance ID for distributed tracing") + fs.IntVar(&cfg.DistributedTracingSamplingRatePerMillion, "distributed-tracing-sampling-rate", 0, "Number of samples to collect per million spans") fs.Var(flags.NewUint32Value(cfg.MaxConcurrentStreams), "max-concurrent-streams", "Maximum concurrent streams that each client can open at a time.") @@ -755,11 +779,11 @@ func (cfg *Config) AddFlags(fs *flag.FlagSet) { fs.StringVar(&cfg.Metrics, "metrics", cfg.Metrics, "Set level of detail for exported metrics, specify 'extensive' to include server side grpc histogram metrics") // experimental distributed tracing - fs.BoolVar(&cfg.ExperimentalEnableDistributedTracing, "experimental-enable-distributed-tracing", false, "Enable experimental distributed tracing using OpenTelemetry Tracing.") - fs.StringVar(&cfg.ExperimentalDistributedTracingAddress, "experimental-distributed-tracing-address", ExperimentalDistributedTracingAddress, "Address for distributed tracing used for OpenTelemetry Tracing (if enabled with experimental-enable-distributed-tracing flag).") - fs.StringVar(&cfg.ExperimentalDistributedTracingServiceName, "experimental-distributed-tracing-service-name", ExperimentalDistributedTracingServiceName, "Configures service name for distributed tracing to be used to define service name for OpenTelemetry Tracing (if enabled with experimental-enable-distributed-tracing flag). 'etcd' is the default service name. Use the same service name for all instances of etcd.") - fs.StringVar(&cfg.ExperimentalDistributedTracingServiceInstanceID, "experimental-distributed-tracing-instance-id", "", "Configures service instance ID for distributed tracing to be used to define service instance ID key for OpenTelemetry Tracing (if enabled with experimental-enable-distributed-tracing flag). There is no default value set. This ID must be unique per etcd instance.") - fs.IntVar(&cfg.ExperimentalDistributedTracingSamplingRatePerMillion, "experimental-distributed-tracing-sampling-rate", 0, "Number of samples to collect per million spans for OpenTelemetry Tracing (if enabled with experimental-enable-distributed-tracing flag).") + fs.BoolVar(&cfg.ExperimentalEnableDistributedTracing, "experimental-enable-distributed-tracing", false, "Enable distributed tracing using OpenTelemetry protocol. "+"Deprecated in v3.6 and will be decommissioned in v3.7. Use --enable-distributed-tracing instead.") + fs.StringVar(&cfg.ExperimentalDistributedTracingAddress, "experimental-distributed-tracing-address", ExperimentalDistributedTracingAddress, "Address for distributed tracing. Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-address instead.") + fs.StringVar(&cfg.ExperimentalDistributedTracingServiceName, "experimental-distributed-tracing-service-name", ExperimentalDistributedTracingServiceName, "Service name for distributed tracing. Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-service-name instead.") + fs.StringVar(&cfg.ExperimentalDistributedTracingServiceInstanceID, "experimental-distributed-tracing-instance-id", "", "Service instance ID for distributed tracing. Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-instance-id instead.") + fs.IntVar(&cfg.ExperimentalDistributedTracingSamplingRatePerMillion, "experimental-distributed-tracing-sampling-rate", 0, "Samples per million for distributed tracing. Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-sampling-rate instead.") // auth fs.StringVar(&cfg.AuthToken, "auth-token", cfg.AuthToken, "Specify auth token specific options.") @@ -1012,6 +1036,10 @@ func (cfg *Config) Validate() error { } } + if cfg.FlagsExplicitlySet["experimental-enable-distributed-tracing"] && cfg.FlagsExplicitlySet["enable-distributed-tracing"] { + return fmt.Errorf("cannot set --experimental-enable-distributed-tracing and --enable-distributed-tracing at the same time") + } + if err := cfg.setupLogging(); err != nil { return err } diff --git a/server/embed/config_tracing.go b/server/embed/config_tracing.go index 7fd86e8610f..0ca90fdc52a 100644 --- a/server/embed/config_tracing.go +++ b/server/embed/config_tracing.go @@ -49,7 +49,7 @@ type tracingExporter struct { func newTracingExporter(ctx context.Context, cfg *Config) (*tracingExporter, error) { exporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure(), - otlptracegrpc.WithEndpoint(cfg.ExperimentalDistributedTracingAddress), + otlptracegrpc.WithEndpoint(cfg.DistributedTracingAddress), ) if err != nil { return nil, err @@ -57,14 +57,14 @@ func newTracingExporter(ctx context.Context, cfg *Config) (*tracingExporter, err res, err := resource.New(ctx, resource.WithAttributes( - semconv.ServiceNameKey.String(cfg.ExperimentalDistributedTracingServiceName), + semconv.ServiceNameKey.String(cfg.DistributedTracingServiceName), ), ) if err != nil { return nil, err } - if resWithIDKey := determineResourceWithIDKey(cfg.ExperimentalDistributedTracingServiceInstanceID); resWithIDKey != nil { + if resWithIDKey := determineResourceWithIDKey(cfg.DistributedTracingServiceInstanceID); resWithIDKey != nil { // Merge resources into a new // resource in case of duplicates. res, err = resource.Merge(res, resWithIDKey) @@ -77,7 +77,7 @@ func newTracingExporter(ctx context.Context, cfg *Config) (*tracingExporter, err tracesdk.WithBatcher(exporter), tracesdk.WithResource(res), tracesdk.WithSampler( - tracesdk.ParentBased(determineSampler(cfg.ExperimentalDistributedTracingSamplingRatePerMillion)), + tracesdk.ParentBased(determineSampler(cfg.DistributedTracingSamplingRatePerMillion)), ), ) @@ -95,10 +95,10 @@ func newTracingExporter(ctx context.Context, cfg *Config) (*tracingExporter, err cfg.logger.Debug( "distributed tracing enabled", - zap.String("address", cfg.ExperimentalDistributedTracingAddress), - zap.String("service-name", cfg.ExperimentalDistributedTracingServiceName), - zap.String("service-instance-id", cfg.ExperimentalDistributedTracingServiceInstanceID), - zap.Int("sampling-rate", cfg.ExperimentalDistributedTracingSamplingRatePerMillion), + zap.String("address", cfg.DistributedTracingAddress), + zap.String("service-name", cfg.DistributedTracingServiceName), + zap.String("service-instance-id", cfg.DistributedTracingServiceInstanceID), + zap.Int("sampling-rate", cfg.DistributedTracingSamplingRatePerMillion), ) return &tracingExporter{ diff --git a/server/embed/etcd.go b/server/embed/etcd.go index a40ef662499..191ea7fd9a4 100644 --- a/server/embed/etcd.go +++ b/server/embed/etcd.go @@ -168,59 +168,59 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { backendFreelistType := parseBackendFreelistType(cfg.BackendFreelistType) srvcfg := config.ServerConfig{ - Name: cfg.Name, - ClientURLs: cfg.AdvertiseClientUrls, - PeerURLs: cfg.AdvertisePeerUrls, - DataDir: cfg.Dir, - DedicatedWALDir: cfg.WalDir, - SnapshotCount: cfg.SnapshotCount, - SnapshotCatchUpEntries: cfg.SnapshotCatchUpEntries, - MaxSnapFiles: cfg.MaxSnapFiles, - MaxWALFiles: cfg.MaxWalFiles, - InitialPeerURLsMap: urlsmap, - InitialClusterToken: token, - DiscoveryURL: cfg.Durl, - DiscoveryProxy: cfg.Dproxy, - DiscoveryCfg: cfg.DiscoveryCfg, - NewCluster: cfg.IsNewCluster(), - PeerTLSInfo: cfg.PeerTLSInfo, - TickMs: cfg.TickMs, - ElectionTicks: cfg.ElectionTicks(), - InitialElectionTickAdvance: cfg.InitialElectionTickAdvance, - AutoCompactionRetention: autoCompactionRetention, - AutoCompactionMode: cfg.AutoCompactionMode, - QuotaBackendBytes: cfg.QuotaBackendBytes, - BackendBatchLimit: cfg.BackendBatchLimit, - BackendFreelistType: backendFreelistType, - BackendBatchInterval: cfg.BackendBatchInterval, - MaxTxnOps: cfg.MaxTxnOps, - MaxRequestBytes: cfg.MaxRequestBytes, - MaxConcurrentStreams: cfg.MaxConcurrentStreams, - SocketOpts: cfg.SocketOpts, - StrictReconfigCheck: cfg.StrictReconfigCheck, - ClientCertAuthEnabled: cfg.ClientTLSInfo.ClientCertAuth, - AuthToken: cfg.AuthToken, - BcryptCost: cfg.BcryptCost, - TokenTTL: cfg.AuthTokenTTL, - CORS: cfg.CORS, - HostWhitelist: cfg.HostWhitelist, - CorruptCheckTime: cfg.ExperimentalCorruptCheckTime, - CompactHashCheckTime: cfg.CompactHashCheckTime, - PreVote: cfg.PreVote, - Logger: cfg.logger, - ForceNewCluster: cfg.ForceNewCluster, - EnableGRPCGateway: cfg.EnableGRPCGateway, - ExperimentalEnableDistributedTracing: cfg.ExperimentalEnableDistributedTracing, - UnsafeNoFsync: cfg.UnsafeNoFsync, - EnableLeaseCheckpoint: cfg.ExperimentalEnableLeaseCheckpoint, - LeaseCheckpointPersist: cfg.ExperimentalEnableLeaseCheckpointPersist, - CompactionBatchLimit: cfg.ExperimentalCompactionBatchLimit, - CompactionSleepInterval: cfg.ExperimentalCompactionSleepInterval, - WatchProgressNotifyInterval: cfg.ExperimentalWatchProgressNotifyInterval, - DowngradeCheckTime: cfg.ExperimentalDowngradeCheckTime, - WarningApplyDuration: cfg.ExperimentalWarningApplyDuration, - WarningUnaryRequestDuration: cfg.WarningUnaryRequestDuration, - ExperimentalMemoryMlock: cfg.ExperimentalMemoryMlock, + Name: cfg.Name, + ClientURLs: cfg.AdvertiseClientUrls, + PeerURLs: cfg.AdvertisePeerUrls, + DataDir: cfg.Dir, + DedicatedWALDir: cfg.WalDir, + SnapshotCount: cfg.SnapshotCount, + SnapshotCatchUpEntries: cfg.SnapshotCatchUpEntries, + MaxSnapFiles: cfg.MaxSnapFiles, + MaxWALFiles: cfg.MaxWalFiles, + InitialPeerURLsMap: urlsmap, + InitialClusterToken: token, + DiscoveryURL: cfg.Durl, + DiscoveryProxy: cfg.Dproxy, + DiscoveryCfg: cfg.DiscoveryCfg, + NewCluster: cfg.IsNewCluster(), + PeerTLSInfo: cfg.PeerTLSInfo, + TickMs: cfg.TickMs, + ElectionTicks: cfg.ElectionTicks(), + InitialElectionTickAdvance: cfg.InitialElectionTickAdvance, + AutoCompactionRetention: autoCompactionRetention, + AutoCompactionMode: cfg.AutoCompactionMode, + QuotaBackendBytes: cfg.QuotaBackendBytes, + BackendBatchLimit: cfg.BackendBatchLimit, + BackendFreelistType: backendFreelistType, + BackendBatchInterval: cfg.BackendBatchInterval, + MaxTxnOps: cfg.MaxTxnOps, + MaxRequestBytes: cfg.MaxRequestBytes, + MaxConcurrentStreams: cfg.MaxConcurrentStreams, + SocketOpts: cfg.SocketOpts, + StrictReconfigCheck: cfg.StrictReconfigCheck, + ClientCertAuthEnabled: cfg.ClientTLSInfo.ClientCertAuth, + AuthToken: cfg.AuthToken, + BcryptCost: cfg.BcryptCost, + TokenTTL: cfg.AuthTokenTTL, + CORS: cfg.CORS, + HostWhitelist: cfg.HostWhitelist, + CorruptCheckTime: cfg.ExperimentalCorruptCheckTime, + CompactHashCheckTime: cfg.CompactHashCheckTime, + PreVote: cfg.PreVote, + Logger: cfg.logger, + ForceNewCluster: cfg.ForceNewCluster, + EnableGRPCGateway: cfg.EnableGRPCGateway, + EnableDistributedTracing: cfg.EnableDistributedTracing, + UnsafeNoFsync: cfg.UnsafeNoFsync, + EnableLeaseCheckpoint: cfg.ExperimentalEnableLeaseCheckpoint, + LeaseCheckpointPersist: cfg.ExperimentalEnableLeaseCheckpointPersist, + CompactionBatchLimit: cfg.ExperimentalCompactionBatchLimit, + CompactionSleepInterval: cfg.ExperimentalCompactionSleepInterval, + WatchProgressNotifyInterval: cfg.ExperimentalWatchProgressNotifyInterval, + DowngradeCheckTime: cfg.ExperimentalDowngradeCheckTime, + WarningApplyDuration: cfg.ExperimentalWarningApplyDuration, + WarningUnaryRequestDuration: cfg.WarningUnaryRequestDuration, + ExperimentalMemoryMlock: cfg.ExperimentalMemoryMlock, ExperimentalBootstrapDefragThresholdMegabytes: cfg.ExperimentalBootstrapDefragThresholdMegabytes, ExperimentalMaxLearners: cfg.ExperimentalMaxLearners, V2Deprecation: cfg.V2DeprecationEffective(), @@ -228,7 +228,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { ServerFeatureGate: cfg.ServerFeatureGate, } - if srvcfg.ExperimentalEnableDistributedTracing { + if srvcfg.EnableDistributedTracing { tctx := context.Background() tracingExporter, terr := newTracingExporter(tctx, cfg) if terr != nil { @@ -237,7 +237,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { e.tracingExporterShutdown = func() { tracingExporter.Close(tctx) } - srvcfg.ExperimentalTracerOptions = tracingExporter.opts + srvcfg.TracerOptions = tracingExporter.opts e.cfg.logger.Info( "distributed tracing setup enabled", diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index ca651e1669c..0ca3ed672e7 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -65,6 +65,11 @@ var ( "experimental-compact-hash-check-enabled": "--experimental-compact-hash-check-enabled is deprecated in 3.6 and will be decommissioned in 3.7. Use '--feature-gates=CompactHashCheck=true' instead.", "experimental-compact-hash-check-time": "--experimental-compact-hash-check-time is deprecated in 3.6 and will be decommissioned in 3.7. Use '--compact-hash-check-time' instead.", "experimental-txn-mode-write-with-shared-buffer": "--experimental-txn-mode-write-with-shared-buffer is deprecated in v3.6 and will be decommissioned in v3.7. Use '--feature-gates=TxnModeWriteWithSharedBuffer=true' instead.", + "experimental-enable-distributed-tracing": "--experimental-enable-distributed-tracing is deprecated in 3.6 and will be decommissioned in 3.7. Use --enable-distributed-tracing instead.", + "experimental-distributed-tracing-address": "--experimental-distributed-tracing-address is deprecated in 3.6 and will be decommissioned in 3.7. Use --distributed-tracing-address instead.", + "experimental-distributed-tracing-service-name": "--experimental-distributed-tracing-service-name is deprecated in 3.6 and will be decommissioned in 3.7. Use --distributed-tracing-service-name instead.", + "experimental-distributed-tracing-instance-id": "--experimental-distributed-tracing-instance-id is deprecated in 3.6 and will be decommissioned in 3.7. Use --distributed-tracing-instance-id instead.", + "experimental-distributed-tracing-sampling-rate": "--experimental-distributed-tracing-sampling-rate is deprecated in 3.6 and will be decommissioned in 3.7. Use --distributed-tracing-sampling-rate instead.", } ) @@ -195,6 +200,13 @@ func (cfg *config) parse(arguments []string) error { } } } + if cfg.ec.ExperimentalEnableDistributedTracing { + cfg.ec.EnableDistributedTracing = true + cfg.ec.DistributedTracingAddress = cfg.ec.ExperimentalDistributedTracingAddress + cfg.ec.DistributedTracingServiceName = cfg.ec.ExperimentalDistributedTracingServiceName + cfg.ec.DistributedTracingServiceInstanceID = cfg.ec.ExperimentalDistributedTracingServiceInstanceID + cfg.ec.DistributedTracingSamplingRatePerMillion = cfg.ec.ExperimentalDistributedTracingSamplingRatePerMillion + } // now logger is set up return err diff --git a/server/etcdmain/config_test.go b/server/etcdmain/config_test.go index b834f3d33ea..88ae56ac22e 100644 --- a/server/etcdmain/config_test.go +++ b/server/etcdmain/config_test.go @@ -653,3 +653,166 @@ func validateClusteringFlags(t *testing.T, cfg *config) { t.Errorf("advertise-client-urls = %v, want %v", cfg.ec.AdvertiseClientUrls, wcfg.ec.AdvertiseClientUrls) } } + +// TestDistributedTracingFlagMigration tests the migration from experimental +// distributed tracing flags to non-experimental ones. +// TODO(v3.7): delete this test when experimental flags are removed. +func TestDistributedTracingFlagMigration(t *testing.T) { + testCases := []struct { + name string + args []string // command line arguments + yamlConfig string // YAML configuration content + expectValues func(*config) error // function to verify expected values + expectErr bool + }{ + { + name: "use experimental flags", + args: []string{ + "--experimental-enable-distributed-tracing=true", + "--experimental-distributed-tracing-address=localhost:4318", + "--experimental-distributed-tracing-service-name=test-service", + "--experimental-distributed-tracing-instance-id=instance-1", + "--experimental-distributed-tracing-sampling-rate=1000", + }, + expectValues: func(cfg *config) error { + if !cfg.ec.EnableDistributedTracing { + return fmt.Errorf("expected EnableDistributedTracing to be true") + } + if cfg.ec.DistributedTracingAddress != "localhost:4318" { + return fmt.Errorf("expected DistributedTracingAddress to be localhost:4318, got %s", cfg.ec.DistributedTracingAddress) + } + if cfg.ec.DistributedTracingServiceName != "test-service" { + return fmt.Errorf("expected DistributedTracingServiceName to be test-service, got %s", cfg.ec.DistributedTracingServiceName) + } + if cfg.ec.DistributedTracingServiceInstanceID != "instance-1" { + return fmt.Errorf("expected DistributedTracingServiceInstanceID to be instance-1, got %s", cfg.ec.DistributedTracingServiceInstanceID) + } + if cfg.ec.DistributedTracingSamplingRatePerMillion != 1000 { + return fmt.Errorf("expected DistributedTracingSamplingRatePerMillion to be 1000, got %d", cfg.ec.DistributedTracingSamplingRatePerMillion) + } + return nil + }, + }, + { + name: "use regular flags", + args: []string{ + "--enable-distributed-tracing=true", + "--distributed-tracing-address=localhost:4319", + "--distributed-tracing-service-name=new-service", + "--distributed-tracing-instance-id=instance-2", + "--distributed-tracing-sampling-rate=2000", + }, + expectValues: func(cfg *config) error { + if !cfg.ec.EnableDistributedTracing { + return fmt.Errorf("expected EnableDistributedTracing to be true") + } + if cfg.ec.DistributedTracingAddress != "localhost:4319" { + return fmt.Errorf("expected DistributedTracingAddress to be localhost:4319, got %s", cfg.ec.DistributedTracingAddress) + } + if cfg.ec.DistributedTracingServiceName != "new-service" { + return fmt.Errorf("expected DistributedTracingServiceName to be new-service, got %s", cfg.ec.DistributedTracingServiceName) + } + if cfg.ec.DistributedTracingServiceInstanceID != "instance-2" { + return fmt.Errorf("expected DistributedTracingServiceInstanceID to be instance-2, got %s", cfg.ec.DistributedTracingServiceInstanceID) + } + if cfg.ec.DistributedTracingSamplingRatePerMillion != 2000 { + return fmt.Errorf("expected DistributedTracingSamplingRatePerMillion to be 2000, got %d", cfg.ec.DistributedTracingSamplingRatePerMillion) + } + return nil + }, + }, + { + name: "config file with experimental flags", + yamlConfig: ` +experimental-enable-distributed-tracing: true +experimental-distributed-tracing-address: "localhost:4318" +experimental-distributed-tracing-service-name: "test-service" +experimental-distributed-tracing-instance-id: "instance-1" +experimental-distributed-tracing-sampling-rate: 1000 +`, + expectValues: func(cfg *config) error { + if !cfg.ec.EnableDistributedTracing { + return fmt.Errorf("expected EnableDistributedTracing to be true") + } + if cfg.ec.DistributedTracingAddress != "localhost:4318" { + return fmt.Errorf("expected DistributedTracingAddress to be localhost:4318, got %s", cfg.ec.DistributedTracingAddress) + } + if cfg.ec.DistributedTracingServiceName != "test-service" { + return fmt.Errorf("expected DistributedTracingServiceName to be test-service, got %s", cfg.ec.DistributedTracingServiceName) + } + if cfg.ec.DistributedTracingServiceInstanceID != "instance-1" { + return fmt.Errorf("expected DistributedTracingServiceInstanceID to be instance-1, got %s", cfg.ec.DistributedTracingServiceInstanceID) + } + if cfg.ec.DistributedTracingSamplingRatePerMillion != 1000 { + return fmt.Errorf("expected DistributedTracingSamplingRatePerMillion to be 1000, got %d", cfg.ec.DistributedTracingSamplingRatePerMillion) + } + return nil + }, + }, + { + name: "config file with regular flags", + yamlConfig: ` +enable-distributed-tracing: true +distributed-tracing-address: "localhost:4319" +distributed-tracing-service-name: "new-service" +distributed-tracing-instance-id: "instance-2" +distributed-tracing-sampling-rate: 2000 +`, + expectValues: func(cfg *config) error { + if !cfg.ec.EnableDistributedTracing { + return fmt.Errorf("expected EnableDistributedTracing to be true") + } + if cfg.ec.DistributedTracingAddress != "localhost:4319" { + return fmt.Errorf("expected DistributedTracingAddress to be localhost:4319, got %s", cfg.ec.DistributedTracingAddress) + } + if cfg.ec.DistributedTracingServiceName != "new-service" { + return fmt.Errorf("expected DistributedTracingServiceName to be new-service, got %s", cfg.ec.DistributedTracingServiceName) + } + if cfg.ec.DistributedTracingServiceInstanceID != "instance-2" { + return fmt.Errorf("expected DistributedTracingServiceInstanceID to be instance-2, got %s", cfg.ec.DistributedTracingServiceInstanceID) + } + if cfg.ec.DistributedTracingSamplingRatePerMillion != 2000 { + return fmt.Errorf("expected DistributedTracingSamplingRatePerMillion to be 2000, got %d", cfg.ec.DistributedTracingSamplingRatePerMillion) + } + return nil + }, + }, + { + name: "config file with both flags is error", + yamlConfig: ` +experimental-enable-distributed-tracing: true +enable-distributed-tracing: true +`, + expectErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cfg := newConfig() + + if tc.yamlConfig != "" { + tmpfile := mustCreateCfgFile(t, []byte(tc.yamlConfig)) + defer os.Remove(tmpfile.Name()) + + tc.args = []string{"--config-file=" + tmpfile.Name()} + } + + err := cfg.parse(tc.args) + if tc.expectErr { + if err == nil { + t.Error("expected error but got nil") + } + return + } + + if err != nil { + t.Fatal(err) + } + + if err := tc.expectValues(cfg); err != nil { + t.Error(err) + } + }) + } +} diff --git a/server/etcdmain/help.go b/server/etcdmain/help.go index aed619c548f..0f36a9e23b6 100644 --- a/server/etcdmain/help.go +++ b/server/etcdmain/help.go @@ -260,17 +260,29 @@ Logging: --warning-unary-request-duration '300ms' Set time duration after which a warning is logged if a unary request takes more than this duration. -Experimental distributed tracing: +Distributed Tracing: + --enable-distributed-tracing 'false' + Enable distributed tracing using OpenTelemetry protocol. + --distributed-tracing-address 'localhost:4317' + Address for distributed tracing used for OpenTelemetry Tracing. + --distributed-tracing-service-name 'etcd' + Configures service name for distributed tracing. + --distributed-tracing-instance-id '' + Configures service instance ID for distributed tracing. + --distributed-tracing-sampling-rate '0' + Number of samples to collect per million spans for distributed tracing. + +Experimental distributed tracing (deprecated): --experimental-enable-distributed-tracing 'false' - Enable experimental distributed tracing. + Enable distributed tracing. Deprecated in v3.6 and will be decommissioned in v3.7. Use --enable-distributed-tracing instead. --experimental-distributed-tracing-address 'localhost:4317' - Distributed tracing collector address. + Distributed tracing collector address. Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-address instead. --experimental-distributed-tracing-service-name 'etcd' - Distributed tracing service name, must be same across all etcd instances. + Distributed tracing service name. Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-service-name instead. --experimental-distributed-tracing-instance-id '' - Distributed tracing instance ID, must be unique per each etcd instance. + Distributed tracing instance ID. Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-instance-id instead. --experimental-distributed-tracing-sampling-rate '0' - Number of samples to collect per million spans for distributed tracing. Disabled by default. + Number of samples to collect per million spans. Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-sampling-rate instead. Experimental feature: --experimental-initial-corrupt-check 'false'. It's deprecated, and will be decommissioned in v3.7. Use '--feature-gates=InitialCorruptCheck=true' instead. diff --git a/server/etcdserver/api/v3rpc/grpc.go b/server/etcdserver/api/v3rpc/grpc.go index 32949207805..7bb531b7148 100644 --- a/server/etcdserver/api/v3rpc/grpc.go +++ b/server/etcdserver/api/v3rpc/grpc.go @@ -53,9 +53,9 @@ func Server(s *etcdserver.EtcdServer, tls *tls.Config, interceptor grpc.UnarySer grpc_prometheus.StreamServerInterceptor, } - if s.Cfg.ExperimentalEnableDistributedTracing { - chainUnaryInterceptors = append(chainUnaryInterceptors, otelgrpc.UnaryServerInterceptor(s.Cfg.ExperimentalTracerOptions...)) - chainStreamInterceptors = append(chainStreamInterceptors, otelgrpc.StreamServerInterceptor(s.Cfg.ExperimentalTracerOptions...)) + if s.Cfg.EnableDistributedTracing { + chainUnaryInterceptors = append(chainUnaryInterceptors, otelgrpc.UnaryServerInterceptor(s.Cfg.TracerOptions...)) + chainStreamInterceptors = append(chainStreamInterceptors, otelgrpc.StreamServerInterceptor(s.Cfg.TracerOptions...)) } opts = append(opts, grpc.ChainUnaryInterceptor(chainUnaryInterceptors...)) diff --git a/tests/integration/tracing_test.go b/tests/integration/tracing_test.go index 5b87208848a..417739e9403 100644 --- a/tests/integration/tracing_test.go +++ b/tests/integration/tracing_test.go @@ -57,10 +57,10 @@ func TestTracing(t *testing.T) { defer srv.Stop() cfg := integration.NewEmbedConfig(t, "default") - cfg.ExperimentalEnableDistributedTracing = true - cfg.ExperimentalDistributedTracingAddress = listener.Addr().String() - cfg.ExperimentalDistributedTracingServiceName = "integration-test-tracing" - cfg.ExperimentalDistributedTracingSamplingRatePerMillion = 100 + cfg.EnableDistributedTracing = true + cfg.DistributedTracingAddress = listener.Addr().String() + cfg.DistributedTracingServiceName = "integration-test-tracing" + cfg.DistributedTracingSamplingRatePerMillion = 100 // start an etcd instance with tracing enabled etcdSrv, err := embed.StartEtcd(cfg)