fix(tracing): treat resource detector errors as non-fatal
processOwnerDetector calls os/user.Current(), which fails in non-cgo builds when the running UID has no /etc/passwd entry and $USER is unset (common on hardened/distroless containers). It returns a plain error, not ErrPartialResource, so the previous gate let the error escape and SetupSDK aborted process startup. Resource detection is documented as best-effort; downgrade any detector error to a warning and fall back to an empty resource if the SDK returns nil. The signature is preserved.
This commit is contained in:
@@ -6,7 +6,6 @@ package otlpresource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
@@ -21,8 +20,11 @@ type Options struct {
|
||||
Environment string // added as attribute "environment"
|
||||
}
|
||||
|
||||
// New builds the shared OTel resource. Non-fatal partial/schema errors are
|
||||
// logged via the provided slog logger and a usable resource is still returned.
|
||||
// New builds the shared OTel resource. Resource detection is best-effort:
|
||||
// any detector error is logged via the provided slog logger and a usable
|
||||
// resource is still returned. The returned error is currently always nil; the
|
||||
// signature is preserved so future callers can distinguish hard failures if
|
||||
// the contract changes.
|
||||
func New(ctx context.Context, log *slog.Logger, opts Options) (*resource.Resource, error) {
|
||||
detectors := []resource.Option{
|
||||
resource.WithFromEnv(), // OTEL_SERVICE_NAME / OTEL_RESOURCE_ATTRIBUTES
|
||||
@@ -41,12 +43,16 @@ func New(ctx context.Context, log *slog.Logger, opts Options) (*resource.Resourc
|
||||
resource.WithAttributes(attribute.String("environment", opts.Environment)))
|
||||
}
|
||||
|
||||
// Detector failures (e.g. processOwnerDetector hitting user.Current() in
|
||||
// a non-cgo build with no /etc/passwd entry and unset $USER) must not be
|
||||
// fatal. Downgrade everything to a warning and fall back to an empty
|
||||
// resource if the SDK returns nil.
|
||||
res, err := resource.New(ctx, detectors...)
|
||||
if errors.Is(err, resource.ErrPartialResource) || errors.Is(err, resource.ErrSchemaURLConflict) {
|
||||
if log != nil {
|
||||
if err != nil && log != nil {
|
||||
log.Warn("otel resource setup", "err", err)
|
||||
}
|
||||
if res == nil {
|
||||
res = resource.Empty()
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
go install github.com/goreleaser/goreleaser/v2@v2.14.1
|
||||
go install github.com/goreleaser/goreleaser/v2@v2.15.4
|
||||
|
||||
if [ ! -z "${harbor_username:-}" ]; then
|
||||
DOCKER_FILE=~/.docker/config.json
|
||||
|
||||
Reference in New Issue
Block a user