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
Tracing: Migrate Google Cloud (Stackdriver) client to OpenTelemetry #4838
Changes from 11 commits
1671d8d
7f296bc
6e30e79
fa5d04f
1c56643
4a9d838
8f7b63b
99b2d44
f423f98
0e33409
f754549
b8346a3
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 |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// Copyright (c) The Thanos Authors. | ||
// Licensed under the Apache License 2.0. | ||
|
||
package google_cloud | ||
|
||
import ( | ||
"context" | ||
"os" | ||
|
||
cloudtrace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace" | ||
"github.com/go-kit/log" | ||
"github.com/go-kit/log/level" | ||
"github.com/prometheus/common/version" | ||
"github.com/thanos-io/thanos/pkg/tracing/migration" | ||
"go.opentelemetry.io/otel/attribute" | ||
"go.opentelemetry.io/otel/sdk/resource" | ||
tracesdk "go.opentelemetry.io/otel/sdk/trace" | ||
semconv "go.opentelemetry.io/otel/semconv/v1.4.0" | ||
"gopkg.in/yaml.v2" | ||
) | ||
|
||
// Config - YAML configuration. | ||
type Config struct { | ||
ServiceName string `yaml:"service_name"` | ||
ProjectId string `yaml:"project_id"` | ||
SampleFactor uint64 `yaml:"sample_factor"` | ||
} | ||
|
||
// NewTracerProvider create tracer provider from YAML. | ||
func NewTracerProvider(ctx context.Context, logger log.Logger, conf []byte) (*tracesdk.TracerProvider, error) { | ||
config := Config{} | ||
if err := yaml.Unmarshal(conf, &config); err != nil { | ||
return nil, err | ||
} | ||
|
||
exporter, err := cloudtrace.New( | ||
cloudtrace.WithContext(ctx), | ||
cloudtrace.WithProjectID(config.ProjectId), | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return newTracerProvider(ctx, logger, tracesdk.NewBatchSpanProcessor(exporter), | ||
config.SampleFactor, config.ServiceName), nil | ||
} | ||
|
||
func newTracerProvider(ctx context.Context, logger log.Logger, processor tracesdk.SpanProcessor, sampleFactor uint64, serviceName string) *tracesdk.TracerProvider { | ||
// Even if resource.New returns error, the resource will be valid - log the error and continue. | ||
resource, err := resource.New(ctx, resource.WithAttributes(collectAttributes(serviceName)...)) | ||
if err != nil { | ||
level.Warn(logger).Log("msg", "detecting resources for tracing provider failed", "err", err) | ||
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. If there is an error, should we return it or do we need to deal with it in line 67 as well? 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. If there's an error, we should still receive valid (although possibly empty) |
||
} | ||
|
||
fraction := 1 / float64(sampleFactor) | ||
if sampleFactor == 0 { | ||
fraction = 0 | ||
} | ||
|
||
tp := tracesdk.NewTracerProvider( | ||
tracesdk.WithSpanProcessor(processor), | ||
tracesdk.WithSampler( | ||
migration.SamplerWithOverride( | ||
tracesdk.ParentBased(tracesdk.TraceIDRatioBased(fraction)), | ||
migration.ForceTracingAttributeKey, | ||
), | ||
), | ||
tracesdk.WithResource(resource), | ||
) | ||
|
||
return tp | ||
} | ||
|
||
func collectAttributes(serviceName string) []attribute.KeyValue { | ||
attr := []attribute.KeyValue{ | ||
semconv.ServiceNameKey.String(serviceName), | ||
attribute.String("binary_revision", version.Revision), | ||
} | ||
|
||
if len(os.Args) > 1 { | ||
attr = append(attr, attribute.String("binary_cmd", os.Args[1])) | ||
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 do we need to have binary Infos to attributes? Maybe remove this or at least make this configurable? 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. Opentelemetry specification says lots of semantic_conventions , we should use it as possible. like 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. Honestly, this was purely to keep the behavior, attribute name etc. the same as it is now, as we wanted to make the change as 'backwards compatible' as possible. But yes, OTEL has more detailed guidance on semantic conventions and I'm definitely planning to follow them as we move the rest of the instrumentation to OTEL. However, if the feeling is that this can be changed already here, I'm happy to follow through. 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. LGTM |
||
} | ||
|
||
return attr | ||
} |
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.
1.3.1 has released.
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.
Thanks, I'll update to latest version!