mirror of
https://github.com/linka-cloud/grpc.git
synced 2025-06-21 16:52:28 +00:00
fix(otel)!: do not use a global client
Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
This commit is contained in:
@ -41,15 +41,15 @@ func run(ctx context.Context, opts ...service.Option) {
|
|||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
ready := make(chan struct{})
|
ready := make(chan struct{})
|
||||||
|
|
||||||
otel.Configure(
|
p := otel.Configure(
|
||||||
// otel.WithDSN("http://127.0.0.1:4318"),
|
ctx,
|
||||||
otel.WithServiceName(name),
|
otel.WithServiceName(name),
|
||||||
otel.WithServiceVersion(version),
|
otel.WithServiceVersion(version),
|
||||||
otel.WithDeploymentEnvironment("tests"),
|
otel.WithDeploymentEnvironment("tests"),
|
||||||
otel.WithTraceSampler(sdktrace.AlwaysSample()),
|
otel.WithTraceSampler(sdktrace.AlwaysSample()),
|
||||||
otel.WithMetricPrometheusBridge(),
|
otel.WithMetricPrometheusBridge(),
|
||||||
)
|
)
|
||||||
defer otel.Shutdown(context.WithoutCancel(ctx))
|
defer p.Shutdown(ctx)
|
||||||
|
|
||||||
address := "0.0.0.0:9991"
|
address := "0.0.0.0:9991"
|
||||||
|
|
||||||
|
@ -15,6 +15,17 @@ import (
|
|||||||
|
|
||||||
const dummySpanName = "__dummy__"
|
const dummySpanName = "__dummy__"
|
||||||
|
|
||||||
|
type Provider interface {
|
||||||
|
TraceURL(span trace.Span) string
|
||||||
|
ReportError(ctx context.Context, err error, opts ...trace.EventOption)
|
||||||
|
ReportPanic(ctx context.Context, val any)
|
||||||
|
Shutdown(ctx context.Context) error
|
||||||
|
ForceFlush(ctx context.Context) error
|
||||||
|
TracerProvider() *sdktrace.TracerProvider
|
||||||
|
MeterProvider() *sdkmetric.MeterProvider
|
||||||
|
LoggerProvider() *sdklog.LoggerProvider
|
||||||
|
}
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
dsn *DSN
|
dsn *DSN
|
||||||
tracer trace.Tracer
|
tracer trace.Tracer
|
||||||
@ -32,6 +43,7 @@ func newClient(dsn *DSN) *client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) Shutdown(ctx context.Context) (lastErr error) {
|
func (c *client) Shutdown(ctx context.Context) (lastErr error) {
|
||||||
|
ctx = context.WithoutCancel(ctx)
|
||||||
if c.tp != nil {
|
if c.tp != nil {
|
||||||
if err := c.tp.Shutdown(ctx); err != nil {
|
if err := c.tp.Shutdown(ctx); err != nil {
|
||||||
lastErr = err
|
lastErr = err
|
||||||
@ -99,6 +111,30 @@ func (c *client) ReportPanic(ctx context.Context, val any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *client) TracerProvider() *sdktrace.TracerProvider {
|
||||||
|
if c.tp == nil {
|
||||||
|
return sdktrace.NewTracerProvider(
|
||||||
|
sdktrace.WithSampler(sdktrace.AlwaysSample()),
|
||||||
|
sdktrace.WithIDGenerator(newIDGenerator()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return c.tp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) MeterProvider() *sdkmetric.MeterProvider {
|
||||||
|
if c.mp == nil {
|
||||||
|
return sdkmetric.NewMeterProvider()
|
||||||
|
}
|
||||||
|
return c.mp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) LoggerProvider() *sdklog.LoggerProvider {
|
||||||
|
if c.lp == nil {
|
||||||
|
return sdklog.NewLoggerProvider()
|
||||||
|
}
|
||||||
|
return c.lp
|
||||||
|
}
|
||||||
|
|
||||||
func (c *client) reportPanic(ctx context.Context, val interface{}) {
|
func (c *client) reportPanic(ctx context.Context, val interface{}) {
|
||||||
span := trace.SpanFromContext(ctx)
|
span := trace.SpanFromContext(ctx)
|
||||||
if !span.IsRecording() {
|
if !span.IsRecording() {
|
||||||
|
@ -12,6 +12,8 @@ import (
|
|||||||
"go.opentelemetry.io/otel/sdk/resource"
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||||
|
|
||||||
|
"go.linka.cloud/grpc-toolkit/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
@ -62,7 +64,8 @@ func newConfig(opts []Option) *config {
|
|||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *config) newResource() *resource.Resource {
|
func (conf *config) newResource(ctx context.Context) *resource.Resource {
|
||||||
|
log := logger.C(ctx)
|
||||||
if conf.resource != nil {
|
if conf.resource != nil {
|
||||||
if len(conf.resourceAttributes) > 0 {
|
if len(conf.resourceAttributes) > 0 {
|
||||||
log.Warnf("WithResource overrides WithResourceAttributes (discarding %v)",
|
log.Warnf("WithResource overrides WithResourceAttributes (discarding %v)",
|
||||||
@ -75,8 +78,6 @@ func (conf *config) newResource() *resource.Resource {
|
|||||||
return conf.resource
|
return conf.resource
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.TODO()
|
|
||||||
|
|
||||||
res, err := resource.New(ctx,
|
res, err := resource.New(ctx,
|
||||||
resource.WithFromEnv(),
|
resource.WithFromEnv(),
|
||||||
resource.WithTelemetrySDK(),
|
resource.WithTelemetrySDK(),
|
||||||
|
@ -7,11 +7,14 @@ import (
|
|||||||
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
|
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
|
||||||
"go.opentelemetry.io/otel/log/global"
|
"go.opentelemetry.io/otel/log/global"
|
||||||
sdklog "go.opentelemetry.io/otel/sdk/log"
|
sdklog "go.opentelemetry.io/otel/sdk/log"
|
||||||
|
|
||||||
|
"go.linka.cloud/grpc-toolkit/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
func configureLogging(ctx context.Context, conf *config) *sdklog.LoggerProvider {
|
func configureLogging(ctx context.Context, conf *config) *sdklog.LoggerProvider {
|
||||||
|
log := logger.C(ctx)
|
||||||
var opts []sdklog.LoggerProviderOption
|
var opts []sdklog.LoggerProviderOption
|
||||||
if res := conf.newResource(); res != nil {
|
if res := conf.newResource(ctx); res != nil {
|
||||||
opts = append(opts, sdklog.WithResource(res))
|
opts = append(opts, sdklog.WithResource(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,11 +10,14 @@ import (
|
|||||||
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
|
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
|
||||||
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
||||||
"go.opentelemetry.io/otel/sdk/metric/metricdata"
|
"go.opentelemetry.io/otel/sdk/metric/metricdata"
|
||||||
|
|
||||||
|
"go.linka.cloud/grpc-toolkit/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
func configureMetrics(ctx context.Context, conf *config) *sdkmetric.MeterProvider {
|
func configureMetrics(ctx context.Context, conf *config) *sdkmetric.MeterProvider {
|
||||||
|
log := logger.C(ctx)
|
||||||
opts := conf.metricOptions
|
opts := conf.metricOptions
|
||||||
if res := conf.newResource(); res != nil {
|
if res := conf.newResource(ctx); res != nil {
|
||||||
opts = append(opts, sdkmetric.WithResource(res))
|
opts = append(opts, sdkmetric.WithResource(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
otel/otel.go
64
otel/otel.go
@ -4,17 +4,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel"
|
||||||
"go.opentelemetry.io/otel/propagation"
|
"go.opentelemetry.io/otel/propagation"
|
||||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
||||||
"go.opentelemetry.io/otel/trace"
|
|
||||||
|
|
||||||
"go.linka.cloud/grpc-toolkit/logger"
|
"go.linka.cloud/grpc-toolkit/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = logger.StandardLogger().WithField("name", "otel")
|
var dummy = newClient(&DSN{})
|
||||||
|
|
||||||
// Configure configures OpenTelemetry.
|
// Configure configures OpenTelemetry.
|
||||||
// By default, it:
|
// By default, it:
|
||||||
@ -23,27 +20,28 @@ var log = logger.StandardLogger().WithField("name", "otel")
|
|||||||
// - sets tracecontext + baggage composite context propagator.
|
// - sets tracecontext + baggage composite context propagator.
|
||||||
//
|
//
|
||||||
// You can use OTEL_DISABLED env var to completely skip otel configuration.
|
// You can use OTEL_DISABLED env var to completely skip otel configuration.
|
||||||
func Configure(opts ...Option) {
|
func Configure(ctx context.Context, opts ...Option) Provider {
|
||||||
if _, ok := os.LookupEnv("OTEL_DISABLED"); ok {
|
if _, ok := os.LookupEnv("OTEL_DISABLED"); ok {
|
||||||
return
|
return dummy
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.TODO()
|
log := logger.C(ctx)
|
||||||
|
|
||||||
conf := newConfig(opts)
|
conf := newConfig(opts)
|
||||||
|
|
||||||
if !conf.tracingEnabled && !conf.metricsEnabled && !conf.loggingEnabled {
|
if !conf.tracingEnabled && !conf.metricsEnabled && !conf.loggingEnabled {
|
||||||
return
|
return dummy
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(conf.dsn) == 0 {
|
if len(conf.dsn) == 0 {
|
||||||
log.Warn("no DSN provided (otel-go is disabled)")
|
log.Warn("no DSN provided (otel-go is disabled)")
|
||||||
return
|
return dummy
|
||||||
}
|
}
|
||||||
|
|
||||||
dsn, err := ParseDSN(conf.dsn[0])
|
dsn, err := ParseDSN(conf.dsn[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("invalid DSN: %s (otel is disabled)", err)
|
log.Warnf("invalid DSN: %s (otel is disabled)", err)
|
||||||
return
|
return dummy
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasSuffix(dsn.Host, ":4318") {
|
if strings.HasSuffix(dsn.Host, ":4318") {
|
||||||
@ -63,7 +61,7 @@ func Configure(opts ...Option) {
|
|||||||
client.lp = configureLogging(ctx, conf)
|
client.lp = configureLogging(ctx, conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
atomicClient.Store(client)
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
func configurePropagator(conf *config) {
|
func configurePropagator(conf *config) {
|
||||||
@ -76,47 +74,3 @@ func configurePropagator(conf *config) {
|
|||||||
}
|
}
|
||||||
otel.SetTextMapPropagator(textMapPropagator)
|
otel.SetTextMapPropagator(textMapPropagator)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
var (
|
|
||||||
fallbackClient = newClient(&DSN{})
|
|
||||||
atomicClient atomic.Value
|
|
||||||
)
|
|
||||||
|
|
||||||
func activeClient() *client {
|
|
||||||
v := atomicClient.Load()
|
|
||||||
if v == nil {
|
|
||||||
return fallbackClient
|
|
||||||
}
|
|
||||||
return v.(*client)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TraceURL(span trace.Span) string {
|
|
||||||
return activeClient().TraceURL(span)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReportError(ctx context.Context, err error, opts ...trace.EventOption) {
|
|
||||||
activeClient().ReportError(ctx, err, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReportPanic(ctx context.Context, val any) {
|
|
||||||
activeClient().ReportPanic(ctx, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Shutdown(ctx context.Context) error {
|
|
||||||
return activeClient().Shutdown(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ForceFlush(ctx context.Context) error {
|
|
||||||
return activeClient().ForceFlush(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TracerProvider() *sdktrace.TracerProvider {
|
|
||||||
return activeClient().tp
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLogger sets the logger to the given one.
|
|
||||||
func SetLogger(logger logger.Logger) {
|
|
||||||
log = logger
|
|
||||||
}
|
|
||||||
|
@ -15,15 +15,18 @@ import (
|
|||||||
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
|
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
|
||||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
|
||||||
|
"go.linka.cloud/grpc-toolkit/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
func configureTracing(ctx context.Context, conf *config) *sdktrace.TracerProvider {
|
func configureTracing(ctx context.Context, conf *config) *sdktrace.TracerProvider {
|
||||||
|
log := logger.C(ctx)
|
||||||
provider := conf.tracerProvider
|
provider := conf.tracerProvider
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
var opts []sdktrace.TracerProviderOption
|
var opts []sdktrace.TracerProviderOption
|
||||||
|
|
||||||
opts = append(opts, sdktrace.WithIDGenerator(newIDGenerator()))
|
opts = append(opts, sdktrace.WithIDGenerator(newIDGenerator()))
|
||||||
if res := conf.newResource(); res != nil {
|
if res := conf.newResource(ctx); res != nil {
|
||||||
opts = append(opts, sdktrace.WithResource(res))
|
opts = append(opts, sdktrace.WithResource(res))
|
||||||
}
|
}
|
||||||
if conf.traceSampler != nil {
|
if conf.traceSampler != nil {
|
||||||
|
Reference in New Issue
Block a user