-
Notifications
You must be signed in to change notification settings - Fork 597
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update OpenTelemetry and use an internal package
The "autoexport" and "autoprop" packages import and configure standard exporters according to the current Specification, 1.39.0. The correct correlation of logs to trace context uses underscores now. The "google.golang.org/grpc" module raised its required Go version to 1.22.7 this release but has since reverted that change. The "spancheck" linter reminds us to call "Span.End" after calling "tracing.Start". Issue: PGO-1954 See: https://opentelemetry.io/docs/specs/otel See: https://opentelemetry.io/docs/specs/otel/compatibility/logging_trace_context See: https://www.github.com/open-telemetry/opentelemetry-go/issues/5969
- Loading branch information
Showing
23 changed files
with
468 additions
and
207 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,79 +6,91 @@ package main | |
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"errors" | ||
"net/http" | ||
"os" | ||
|
||
"go.opentelemetry.io/contrib/exporters/autoexport" | ||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" | ||
"go.opentelemetry.io/contrib/propagators/autoprop" | ||
"go.opentelemetry.io/otel" | ||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace" | ||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" | ||
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace" | ||
"go.opentelemetry.io/otel/sdk/resource" | ||
"go.opentelemetry.io/otel/sdk/trace" | ||
) | ||
semconv "go.opentelemetry.io/otel/semconv/v1.27.0" | ||
|
||
func initOpenTelemetry(ctx context.Context) (func(context.Context), error) { | ||
// At the time of this writing, the SDK (go.opentelemetry.io/[email protected]) | ||
// does not automatically initialize any exporter. We import the OTLP and | ||
// stdout exporters and configure them below. Much of the OTLP exporter can | ||
// be configured through environment variables. | ||
// | ||
// - https://github.com/open-telemetry/opentelemetry-go/issues/2310 | ||
// - https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/sdk-environment-variables.md | ||
"github.com/crunchydata/postgres-operator/internal/logging" | ||
) | ||
|
||
switch os.Getenv("OTEL_TRACES_EXPORTER") { | ||
case "json": | ||
var closer io.Closer | ||
filename := os.Getenv("OTEL_JSON_FILE") | ||
options := []stdouttrace.Option{} | ||
func initOpenTelemetry(ctx context.Context) (func(context.Context) error, error) { | ||
var started []interface{ Shutdown(context.Context) error } | ||
|
||
if filename != "" { | ||
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to open exporter file: %w", err) | ||
} | ||
closer = file | ||
options = append(options, stdouttrace.WithWriter(file)) | ||
// shutdown returns the results of calling all the Shutdown methods in started. | ||
var shutdown = func(ctx context.Context) error { | ||
var err error | ||
for _, s := range started { | ||
err = errors.Join(err, s.Shutdown(ctx)) | ||
} | ||
started = nil | ||
return err | ||
} | ||
|
||
exporter, err := stdouttrace.New(options...) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to initialize stdout exporter: %w", err) | ||
} | ||
// The default for OTEL_PROPAGATORS is "tracecontext,baggage". | ||
otel.SetTextMapPropagator(autoprop.NewTextMapPropagator()) | ||
|
||
provider := trace.NewTracerProvider(trace.WithBatcher(exporter)) | ||
flush := func(ctx context.Context) { | ||
_ = provider.Shutdown(ctx) | ||
if closer != nil { | ||
_ = closer.Close() | ||
} | ||
} | ||
// Skip any remaining setup when OTEL_SDK_DISABLED is exactly "true". | ||
// - https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables | ||
if os.Getenv("OTEL_SDK_DISABLED") == "true" { | ||
return shutdown, nil | ||
} | ||
|
||
otel.SetTracerProvider(provider) | ||
return flush, nil | ||
log := logging.FromContext(ctx).WithName("open-telemetry") | ||
otel.SetLogger(log) | ||
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) { | ||
// TODO(events): Emit this as an event instead. | ||
log.V(1).Info(semconv.ExceptionEventName, | ||
string(semconv.ExceptionMessageKey), err) | ||
})) | ||
|
||
case "otlp": | ||
client := otlptracehttp.NewClient() | ||
exporter, err := otlptrace.New(context.TODO(), client) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to initialize OTLP exporter: %w", err) | ||
} | ||
// Build a resource from the OTEL_RESOURCE_ATTRIBUTES and OTEL_SERVICE_NAME environment variables. | ||
// - https://opentelemetry.io/docs/languages/go/resources | ||
self, _ := resource.Merge(resource.NewSchemaless( | ||
semconv.ServiceVersion(versionString), | ||
), resource.Default()) | ||
|
||
provider := trace.NewTracerProvider(trace.WithBatcher(exporter)) | ||
flush := func(ctx context.Context) { | ||
_ = provider.Shutdown(ctx) | ||
// Provide defaults for some other detectable attributes. | ||
if r, err := resource.New(ctx, | ||
resource.WithProcessRuntimeName(), | ||
resource.WithProcessRuntimeVersion(), | ||
resource.WithProcessRuntimeDescription(), | ||
); err == nil { | ||
self, _ = resource.Merge(r, self) | ||
} | ||
if r, err := resource.New(ctx, | ||
resource.WithHost(), | ||
resource.WithOS(), | ||
); err == nil { | ||
self, _ = resource.Merge(r, self) | ||
} | ||
|
||
// The default for OTEL_TRACES_EXPORTER is "otlp" but we prefer "none". | ||
// Only assign an exporter when the environment variable is set. | ||
if os.Getenv("OTEL_TRACES_EXPORTER") != "" { | ||
exporter, err := autoexport.NewSpanExporter(ctx) | ||
if err != nil { | ||
return nil, errors.Join(err, shutdown(ctx)) | ||
} | ||
|
||
// The defaults for this batch processor come from the OTEL_BSP_* environment variables. | ||
// - https://pkg.go.dev/go.opentelemetry.io/otel/sdk/internal/env | ||
provider := trace.NewTracerProvider( | ||
trace.WithBatcher(exporter), | ||
trace.WithResource(self), | ||
) | ||
started = append(started, provider) | ||
otel.SetTracerProvider(provider) | ||
return flush, nil | ||
} | ||
|
||
// $OTEL_TRACES_EXPORTER is unset or unknown, so no TracerProvider has been assigned. | ||
// The default at this time is a single "no-op" tracer. | ||
|
||
return func(context.Context) {}, nil | ||
return shutdown, nil | ||
} | ||
|
||
// otelTransportWrapper creates a function that wraps the provided net/http.RoundTripper | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright 2017 - 2024 Crunchy Data Solutions, Inc. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"runtime" | ||
) | ||
|
||
var userAgent string | ||
var versionString string | ||
|
||
func initVersion() { | ||
command := "unknown" | ||
if len(os.Args) > 0 && len(os.Args[0]) > 0 { | ||
command = filepath.Base(os.Args[0]) | ||
} | ||
if len(versionString) > 0 { | ||
command += "/" + versionString | ||
} | ||
userAgent = fmt.Sprintf("%s (%s/%s)", command, runtime.GOOS, runtime.GOARCH) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.