-
Notifications
You must be signed in to change notification settings - Fork 179
Initial attempt at OpenTelemetry support #873
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
76d9ea2
0cb50df
390c716
21dc617
4a6a07c
786a79e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,11 @@ import ( | |
| "fmt" | ||
| "io" | ||
| "log" | ||
| "net/http" | ||
| "path" | ||
|
|
||
| "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" | ||
|
|
||
| "github.com/buchgr/bazel-remote/v2/cache" | ||
| "github.com/buchgr/bazel-remote/v2/cache/disk/casblob" | ||
| "github.com/buchgr/bazel-remote/v2/utils/backendproxy" | ||
|
|
@@ -58,7 +61,7 @@ func New( | |
| MaxIdleConns int, | ||
|
|
||
| storageMode string, accessLogger cache.Logger, | ||
| errorLogger cache.Logger, numUploaders, maxQueuedUploads int) cache.Proxy { | ||
| errorLogger cache.Logger, numUploaders, maxQueuedUploads int, otelEnabled bool) cache.Proxy { | ||
|
|
||
| fmt.Println("Using S3 backend.") | ||
|
|
||
|
|
@@ -78,14 +81,20 @@ func New( | |
| tr.MaxIdleConns = MaxIdleConns | ||
| tr.MaxIdleConnsPerHost = MaxIdleConns | ||
|
|
||
| // Wrap transport with OTEL instrumentation if enabled | ||
| var transport http.RoundTripper = tr | ||
| if otelEnabled { | ||
| transport = otelhttp.NewTransport(tr) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not |
||
| } | ||
|
|
||
| // Initialize minio client with credentials | ||
| opts := &minio.Options{ | ||
| Creds: Credentials, | ||
| BucketLookup: BucketLookupType, | ||
|
|
||
| Region: Region, | ||
| Secure: secure, | ||
| Transport: tr, | ||
| Transport: transport, | ||
| } | ||
| minioCore, err = minio.NewCore(Endpoint, opts) | ||
| if err != nil { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,19 @@ import ( | |
| yaml "gopkg.in/yaml.v3" | ||
| ) | ||
|
|
||
| // OtelTracingConfig stores the OpenTelemetry tracing configuration. | ||
| type OtelTracingConfig struct { | ||
| Enabled bool `yaml:"enabled"` | ||
| ExporterEndpoint string `yaml:"exporter_endpoint"` | ||
| ServiceName string `yaml:"service_name"` | ||
| SampleRate float64 `yaml:"sample_rate"` | ||
| } | ||
|
|
||
| // OtelConfig stores the OpenTelemetry configuration. | ||
| type OtelConfig struct { | ||
| Tracing *OtelTracingConfig `yaml:"tracing,omitempty"` | ||
| } | ||
|
|
||
| // GoogleCloudStorageConfig stores the configuration of a GCS proxy backend. | ||
| type GoogleCloudStorageConfig struct { | ||
| Bucket string `yaml:"bucket"` | ||
|
|
@@ -127,6 +140,7 @@ type Config struct { | |
| LogTimezone string `yaml:"log_timezone"` | ||
| MaxBlobSize int64 `yaml:"max_blob_size"` | ||
| MaxProxyBlobSize int64 `yaml:"max_proxy_blob_size"` | ||
| Otel *OtelConfig `yaml:"otel,omitempty"` | ||
|
|
||
| // Fields that are created by combinations of the flags above. | ||
| ProxyBackend cache.Proxy | ||
|
|
@@ -173,6 +187,7 @@ func newFromArgs(dir string, maxSize int, storageMode string, zstdImplementation | |
| ldap *LDAPConfig, | ||
| s3 *S3CloudStorageConfig, | ||
| azblob *AzBlobStorageConfig, | ||
| otel *OtelConfig, | ||
| disableHTTPACValidation bool, | ||
| disableGRPCACDepsCheck bool, | ||
| enableACKeyInstanceMangling bool, | ||
|
|
@@ -210,6 +225,7 @@ func newFromArgs(dir string, maxSize int, storageMode string, zstdImplementation | |
| HTTPBackend: hc, | ||
| GRPCBackend: grpcb, | ||
| LDAP: ldap, | ||
| Otel: otel, | ||
| IdleTimeout: idleTimeout, | ||
| DisableHTTPACValidation: disableHTTPACValidation, | ||
| DisableGRPCACDepsCheck: disableGRPCACDepsCheck, | ||
|
|
@@ -500,6 +516,36 @@ func validateConfig(c *Config) error { | |
| return errors.New("'log_timezone' must be set to either \"UTC\", \"local\" or \"none\"") | ||
| } | ||
|
|
||
| // Validate OpenTelemetry tracing configuration | ||
| if c.Otel != nil && c.Otel.Tracing != nil && c.Otel.Tracing.Enabled { | ||
| if c.Otel.Tracing.ExporterEndpoint == "" { | ||
| // Check standard OTEL env vars | ||
| if endpoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT"); endpoint != "" { | ||
| c.Otel.Tracing.ExporterEndpoint = endpoint | ||
| } else if endpoint := os.Getenv("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"); endpoint != "" { | ||
| c.Otel.Tracing.ExporterEndpoint = endpoint | ||
| } else { | ||
| return errors.New("when 'otel.tracing.enabled' is true, either 'otel.tracing.exporter_endpoint' must be set or OTEL_EXPORTER_OTLP_ENDPOINT env var must be defined") | ||
| } | ||
| } | ||
|
|
||
| if c.Otel.Tracing.ServiceName == "" { | ||
| if name := os.Getenv("OTEL_SERVICE_NAME"); name != "" { | ||
| c.Otel.Tracing.ServiceName = name | ||
| } else { | ||
| c.Otel.Tracing.ServiceName = "bazel-remote" | ||
| } | ||
| } | ||
|
|
||
| if c.Otel.Tracing.SampleRate == 0 { | ||
| c.Otel.Tracing.SampleRate = 1.0 // Default to 100% sampling | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this default risky?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think typically a user from my experience would expect to get all the traces that're being emitted, now if they have too much data, they can either filter the trace spans out in the otel-collector or override this config. |
||
| } | ||
|
|
||
| if c.Otel.Tracing.SampleRate < 0.0 || c.Otel.Tracing.SampleRate > 1.0 { | ||
| return errors.New("'otel.tracing.sample_rate' must be between 0.0 and 1.0") | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
|
|
@@ -643,6 +689,18 @@ func get(ctx *cli.Context) (*Config, error) { | |
| } | ||
| } | ||
|
|
||
| var otel *OtelConfig | ||
| if ctx.Bool("otel.tracing.enabled") { | ||
| otel = &OtelConfig{ | ||
| Tracing: &OtelTracingConfig{ | ||
| Enabled: ctx.Bool("otel.tracing.enabled"), | ||
| ExporterEndpoint: ctx.String("otel.tracing.exporter_endpoint"), | ||
| ServiceName: ctx.String("otel.tracing.service_name"), | ||
| SampleRate: ctx.Float64("otel.tracing.sample_rate"), | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| return newFromArgs( | ||
| ctx.String("dir"), | ||
| ctx.Int("max_size"), | ||
|
|
@@ -666,6 +724,7 @@ func get(ctx *cli.Context) (*Config, error) { | |
| ldap, | ||
| s3, | ||
| azblob, | ||
| otel, | ||
| ctx.Bool("disable_http_ac_validation"), | ||
| ctx.Bool("disable_grpc_ac_deps_check"), | ||
| ctx.Bool("enable_ac_key_instance_mangling"), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like NewTransport does this internally, so we can skip it.