2 Commits

Author SHA1 Message Date
83ac0e3900 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.
2026-05-12 18:25:21 +00:00
9304bed55b docs(telemetry): correct tier from 5 to 1
telemetry has zero micro-lib dependencies — only the external OTel SDK.
Tier 1 reflects its actual position in the dependency graph. The Tier 5
label was misleading about push/tag ordering; telemetry can be released
independently of all other micro-lib modules.
2026-03-19 06:56:16 -06:00
7 changed files with 94 additions and 9 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/),
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
### Added
@@ -17,7 +35,7 @@ and this module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.
### 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
- 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

View File

@@ -8,7 +8,7 @@ Sets the three OTel global providers so that all micro-libs using the OTel globa
## Tier & Dependencies
**Tier 5** (application bootstrap only). Must never be imported by framework libraries (Tier 04).
**Tier 1** (no micro-lib dependencies; external OTel SDK only). Must never be imported by framework libraries.
Depends on:
- `go.opentelemetry.io/otel` and sub-packages — API and SDK
@@ -21,7 +21,7 @@ No micro-lib dependencies. No `launcher` dependency — telemetry has no Compone
## Key Design Decisions
- **Tier 5 / app-only** (ADR-001): Libraries use only the OTel API (no-op default). This module activates the real SDK. Importing it from a library is a mistake.
- **Tier 1 / app-only** (ADR-001): Libraries use only the OTel API (no-op default). This module activates the real SDK. Importing it from a library is a mistake.
- **Three-signal OTLP bootstrap** (ADR-002): `New(ctx, cfg)` sets up traces → Tempo, metrics → Mimir, logs → Loki, all over a single OTLP gRPC endpoint. W3C TraceContext + Baggage propagation is set globally.
- **Global provider strategy** (ADR-003): Libraries call `otel.Tracer(...)` / `otel.Meter(...)` / `global.Logger(...)`. After `telemetry.New`, those calls route to the real SDK with no library changes required.
- **No `launcher.Component`**: Telemetry is not a lifecycle component. The caller defers the returned shutdown function directly in `main`. This keeps the module dependency graph minimal and the interface simple.

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
go 1.25.0
go 1.26
require (
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)
shutdown := func(ctx context.Context) error {
return errors.Join(
tp.Shutdown(ctx),
mp.Shutdown(ctx),
lp.Shutdown(ctx),
)
var errs []error
if err := tp.Shutdown(ctx); err != nil {
errs = append(errs, &providerErr{"trace", err})
}
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
}
// 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.
func newResource(cfg Config) *resource.Resource {
r, _ := resource.Merge(