feat(telemetry)!: promote to v1.0.0 — named shutdown errors per provider, Go 1.26

Label each provider shutdown failure with its signal name (trace/metric/log).
Errors remain joined via errors.Join; individual causes still unwrappable.
Go directive bumped from 1.25 to 1.26. API committed as stable.
This commit is contained in:
2026-05-12 18:25:21 +00:00
parent 9304bed55b
commit 83ac0e3900
6 changed files with 92 additions and 7 deletions

1
.gitea/CODEOWNERS Normal file
View File

@@ -0,0 +1 @@
* @go/CoreDevelopers @go/Agents

View File

@@ -5,6 +5,24 @@ All notable changes to this module will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.0] - 2026-05-12
### Changed
- Go directive bumped from 1.25 to 1.26
- Shutdown function now wraps each provider error with a `providerErr` type that
prefixes the signal name (`"telemetry: trace provider shutdown: …"`,
`"telemetry: metric provider shutdown: …"`, `"telemetry: log provider shutdown: …"`).
The combined error is still joined with `errors.Join`; individual causes remain
unwrappable via `errors.As`. Previously, the three errors were joined without labels.
### Stabilization
- API committed as stable. `Config`, `New`, and the shutdown function signature
(`func(context.Context) error`) are unchanged from v0.9.0.
[1.0.0]: https://code.nochebuena.dev/go/telemetry/compare/v0.9.0...v1.0.0
## [0.9.0] - 2026-03-18 ## [0.9.0] - 2026-03-18
### Added ### Added
@@ -17,7 +35,7 @@ and this module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.
### Design Notes ### Design Notes
- This module is Tier 5 (application bootstrap only) and must never be imported by framework libraries; those libraries use only the OTel API, which defaults to no-ops until `New` is called and sets the global providers - This module is Tier 1 (no micro-lib dependencies) and must never be imported by framework libraries; those libraries use only the OTel API, which defaults to no-ops until `New` is called and sets the global providers
- All three signals share a single OTLP gRPC endpoint, matching the standard Grafana LGTM stack topology where Grafana Alloy receives all signals and fans them out to Tempo, Mimir, and Loki - All three signals share a single OTLP gRPC endpoint, matching the standard Grafana LGTM stack topology where Grafana Alloy receives all signals and fans them out to Tempo, Mimir, and Loki
- The module intentionally does not implement `launcher.Component`; the returned shutdown function is deferred directly in `main`, keeping the dependency graph free of `launcher` and the interface as simple as a single function call - The module intentionally does not implement `launcher.Component`; the returned shutdown function is deferred directly in `main`, keeping the dependency graph free of `launcher` and the interface as simple as a single function call

5
COMMIT.md Normal file
View File

@@ -0,0 +1,5 @@
feat(telemetry)!: promote to v1.0.0 — named shutdown errors per provider, Go 1.26
Label each provider shutdown failure with its signal name (trace/metric/log).
Errors remain joined via errors.Join; individual causes still unwrappable.
Go directive bumped from 1.25 to 1.26. API committed as stable.

46
RELEASE.md Normal file
View File

@@ -0,0 +1,46 @@
# v1.0.0
> `code.nochebuena.dev/go/telemetry`
## Overview
`telemetry` bootstraps the full OpenTelemetry SDK with OTLP gRPC exporters targeting
a Grafana Alloy collector. A single call to `New` sets all three OTel global providers
(traces → Tempo, metrics → Mimir, logs → Loki) and returns a shutdown function the
caller defers in `main`.
v1.0.0 adds named per-provider shutdown errors, bumps the Go directive to 1.26, and
commits the API as stable. No micro-lib dependencies are added.
## What Changed Since v0.9.0
### Named per-provider shutdown errors
The shutdown function now labels each provider failure individually:
```
telemetry: trace provider shutdown: <cause>
telemetry: metric provider shutdown: <cause>
telemetry: log provider shutdown: <cause>
```
Errors are still joined with `errors.Join`; individual causes remain accessible via
`errors.As`. Previously, provider shutdown failures were joined without labels, making
it impossible to identify which signal pipeline failed.
### Go directive bumped to 1.26
## Full API (stable)
- `Config``ServiceName`, `ServiceVersion`, `Environment`, `OTLPEndpoint`, `OTLPInsecure`
- `New(ctx, cfg) (func(context.Context) error, error)`
## Installation
```
go get code.nochebuena.dev/go/telemetry@v1.0.0
```
## Changelog
See [CHANGELOG.md](CHANGELOG.md#100---2026-05-12).

2
go.mod
View File

@@ -1,6 +1,6 @@
module code.nochebuena.dev/go/telemetry module code.nochebuena.dev/go/telemetry
go 1.25.0 go 1.26
require ( require (
go.opentelemetry.io/otel v1.42.0 go.opentelemetry.io/otel v1.42.0

View File

@@ -105,15 +105,30 @@ func New(ctx context.Context, cfg Config) (func(context.Context) error, error) {
global.SetLoggerProvider(lp) global.SetLoggerProvider(lp)
shutdown := func(ctx context.Context) error { shutdown := func(ctx context.Context) error {
return errors.Join( var errs []error
tp.Shutdown(ctx), if err := tp.Shutdown(ctx); err != nil {
mp.Shutdown(ctx), errs = append(errs, &providerErr{"trace", err})
lp.Shutdown(ctx), }
) if err := mp.Shutdown(ctx); err != nil {
errs = append(errs, &providerErr{"metric", err})
}
if err := lp.Shutdown(ctx); err != nil {
errs = append(errs, &providerErr{"log", err})
}
return errors.Join(errs...)
} }
return shutdown, nil return shutdown, nil
} }
// providerErr labels a shutdown error with the provider name.
type providerErr struct {
provider string
err error
}
func (e *providerErr) Error() string { return "telemetry: " + e.provider + " provider shutdown: " + e.err.Error() }
func (e *providerErr) Unwrap() error { return e.err }
// newResource builds an OTel resource with service identity and environment attributes. // newResource builds an OTel resource with service identity and environment attributes.
func newResource(cfg Config) *resource.Resource { func newResource(cfg Config) *resource.Resource {
r, _ := resource.Merge( r, _ := resource.Merge(