1- // Package slogadapter implements the Crucible telemetry interfaces on top of the
1+ // Package slog implements the Crucible telemetry interfaces on top of the
22// standard library's log/slog. It proves the telemetry seam end to end using
33// zero external dependencies: spans and metric instruments are emitted as
44// structured log records.
55//
6- // Import path: github.com/stablekernel/crucible/telemetry/slogadapter
6+ // Import path: github.com/stablekernel/crucible/telemetry/slog
77//
88// It is intended for development, tests, and environments where structured logs
99// are the only observability sink. For production tracing/metrics backends, use
2222//
2323// All durations are sourced from an injectable clock so emission is
2424// deterministic in tests.
25- package slogadapter
25+ package slog
2626
2727import (
2828 "context"
29- "log/slog"
29+ sl "log/slog"
3030 "sync/atomic"
3131 "time"
3232
@@ -35,7 +35,7 @@ import (
3535
3636// config holds resolved Option state.
3737type config struct {
38- logger * slog .Logger
38+ logger * sl .Logger
3939 now func () time.Time
4040 nextID func () uint64
4141}
@@ -46,7 +46,7 @@ type Option func(*config)
4646// WithLogger sets the slog.Logger the adapter emits to. The default discards all
4747// records (slog.New(slog.DiscardHandler)), keeping the adapter silent until a
4848// real logger is supplied.
49- func WithLogger (l * slog .Logger ) Option {
49+ func WithLogger (l * sl .Logger ) Option {
5050 return func (c * config ) {
5151 if l != nil {
5252 c .logger = l
@@ -78,7 +78,7 @@ func WithIDFn(next func() uint64) Option {
7878func resolve (opts ... Option ) config {
7979 ctr := new (atomic.Uint64 )
8080 c := config {
81- logger : slog .New (slog .DiscardHandler ),
81+ logger : sl .New (sl .DiscardHandler ),
8282 now : time .Now ,
8383 nextID : func () uint64 { return ctr .Add (1 ) },
8484 }
@@ -105,12 +105,12 @@ func (t *Tracer) Start(ctx context.Context, name string, attrs ...telemetry.Attr
105105 id := t .cfg .nextID ()
106106 parent , hasParent := ctx .Value (spanIDKey {}).(uint64 )
107107
108- logAttrs := []any {slog .String ("name" , name ), slog .Uint64 ("id" , id )}
108+ logAttrs := []any {sl .String ("name" , name ), sl .Uint64 ("id" , id )}
109109 if hasParent {
110- logAttrs = append (logAttrs , slog .Uint64 ("parent" , parent ))
110+ logAttrs = append (logAttrs , sl .Uint64 ("parent" , parent ))
111111 }
112112 logAttrs = append (logAttrs , attrArgs (attrs )... )
113- t .cfg .logger .LogAttrs (ctx , slog .LevelDebug , "span.start" , slog .Group ("span" , logAttrs ... ))
113+ t .cfg .logger .LogAttrs (ctx , sl .LevelDebug , "span.start" , sl .Group ("span" , logAttrs ... ))
114114
115115 s := & span {
116116 cfg : t .cfg ,
@@ -136,19 +136,19 @@ func (s *span) SetAttributes(attrs ...telemetry.Attr) {
136136 if s .ended {
137137 return
138138 }
139- args := append ([]any {slog .String ("name" , s .name ), slog .Uint64 ("id" , s .id )}, attrArgs (attrs )... )
140- s .cfg .logger .LogAttrs (context .Background (), slog .LevelDebug , "span.attributes" , slog .Group ("span" , args ... ))
139+ args := append ([]any {sl .String ("name" , s .name ), sl .Uint64 ("id" , s .id )}, attrArgs (attrs )... )
140+ s .cfg .logger .LogAttrs (context .Background (), sl .LevelDebug , "span.attributes" , sl .Group ("span" , args ... ))
141141}
142142
143143func (s * span ) RecordError (err error ) {
144144 if s .ended || err == nil {
145145 return
146146 }
147- s .cfg .logger .LogAttrs (context .Background (), slog .LevelError , "span.error" ,
148- slog .Group ("span" ,
149- slog .String ("name" , s .name ),
150- slog .Uint64 ("id" , s .id ),
151- slog .String ("error" , err .Error ()),
147+ s .cfg .logger .LogAttrs (context .Background (), sl .LevelError , "span.error" ,
148+ sl .Group ("span" ,
149+ sl .String ("name" , s .name ),
150+ sl .Uint64 ("id" , s .id ),
151+ sl .String ("error" , err .Error ()),
152152 ),
153153 )
154154}
@@ -167,20 +167,20 @@ func (s *span) End() {
167167 }
168168 s .ended = true
169169 args := []any {
170- slog .String ("name" , s .name ),
171- slog .Uint64 ("id" , s .id ),
172- slog .String ("status" , statusString (s .status )),
173- slog .Duration ("elapsed" , s .cfg .now ().Sub (s .start )),
170+ sl .String ("name" , s .name ),
171+ sl .Uint64 ("id" , s .id ),
172+ sl .String ("status" , statusString (s .status )),
173+ sl .Duration ("elapsed" , s .cfg .now ().Sub (s .start )),
174174 }
175175 if s .statusMsg != "" {
176- args = append (args , slog .String ("status_msg" , s .statusMsg ))
176+ args = append (args , sl .String ("status_msg" , s .statusMsg ))
177177 }
178- s .cfg .logger .LogAttrs (context .Background (), slog .LevelDebug , "span.end" , slog .Group ("span" , args ... ))
178+ s .cfg .logger .LogAttrs (context .Background (), sl .LevelDebug , "span.end" , sl .Group ("span" , args ... ))
179179}
180180
181181// Meter is a telemetry.Meter backed by slog.
182182type Meter struct {
183- logger * slog .Logger
183+ logger * sl .Logger
184184}
185185
186186// NewMeter returns a slog-backed Meter.
@@ -203,30 +203,30 @@ func (m *Meter) Gauge(name string, opts ...telemetry.InstrumentOption) telemetry
203203
204204// instrument backs Counter, Histogram, and Gauge: each logs a "metric" record.
205205type instrument struct {
206- logger * slog .Logger
206+ logger * sl .Logger
207207 name string
208208 kind string
209209 cfg telemetry.InstrumentConfig
210210}
211211
212212func (i * instrument ) Add (ctx context.Context , n int64 , attrs ... telemetry.Attr ) {
213- i .emit (ctx , slog .Int64 ("value" , n ), attrs )
213+ i .emit (ctx , sl .Int64 ("value" , n ), attrs )
214214}
215215
216216func (i * instrument ) Record (ctx context.Context , v float64 , attrs ... telemetry.Attr ) {
217- i .emit (ctx , slog .Float64 ("value" , v ), attrs )
217+ i .emit (ctx , sl .Float64 ("value" , v ), attrs )
218218}
219219
220- func (i * instrument ) emit (ctx context.Context , value slog .Attr , attrs []telemetry.Attr ) {
221- args := []any {slog .String ("name" , i .name ), slog .String ("kind" , i .kind ), value }
220+ func (i * instrument ) emit (ctx context.Context , value sl .Attr , attrs []telemetry.Attr ) {
221+ args := []any {sl .String ("name" , i .name ), sl .String ("kind" , i .kind ), value }
222222 if i .cfg .Unit != "" {
223- args = append (args , slog .String ("unit" , i .cfg .Unit ))
223+ args = append (args , sl .String ("unit" , i .cfg .Unit ))
224224 }
225225 if i .cfg .Description != "" {
226- args = append (args , slog .String ("description" , i .cfg .Description ))
226+ args = append (args , sl .String ("description" , i .cfg .Description ))
227227 }
228228 args = append (args , attrArgs (attrs )... )
229- i .logger .LogAttrs (ctx , slog .LevelDebug , "metric" , slog .Group ("metric" , args ... ))
229+ i .logger .LogAttrs (ctx , sl .LevelDebug , "metric" , sl .Group ("metric" , args ... ))
230230}
231231
232232// attrArgs nests the telemetry attributes under a single "attrs" group so their
@@ -241,7 +241,7 @@ func attrArgs(attrs []telemetry.Attr) []any {
241241 for i , a := range attrs {
242242 inner [i ] = a
243243 }
244- return []any {slog .Group ("attrs" , inner ... )}
244+ return []any {sl .Group ("attrs" , inner ... )}
245245}
246246
247247func statusString (c telemetry.StatusCode ) string {
0 commit comments