Skip to content

Commit 150c733

Browse files
authored
docs: update go observability reference with up-to-date logging approach (#59)
1 parent 73fc5f0 commit 150c733

1 file changed

Lines changed: 35 additions & 10 deletions

File tree

references/go/observability.md

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,43 +62,68 @@ logger.Info("Processing order") // includes orderId and customerId
6262

6363
## Customizing the Logger
6464

65-
Set a custom logger via `client.Options{Logger: myLogger}`. Implement the `log.Logger` interface (Debug, Info, Warn, Error methods).
65+
The SDK ships a single built-in **`slog` adapter** (`log.NewStructuredLogger`) and considers `slog` (go 1.21+) the universal bridge to other logging libraries.
6666

67-
### Using slog (Go 1.21+)
67+
### The `log.Logger` Interface
68+
69+
```go
70+
// go.temporal.io/sdk/log
71+
type Logger interface {
72+
Debug(msg string, keyvals ...interface{})
73+
Info(msg string, keyvals ...interface{})
74+
Warn(msg string, keyvals ...interface{})
75+
Error(msg string, keyvals ...interface{})
76+
}
77+
```
78+
79+
Optional companion interfaces: `WithLogger` (adds `.With()`) and `WithSkipCallers` (fixes caller frames).
80+
81+
### Using slog (Recommended)
6882

6983
```go
7084
import (
7185
"log/slog"
7286
"os"
7387

74-
tlog "go.temporal.io/sdk/log"
88+
"go.temporal.io/sdk/log"
7589
)
7690

7791
slogHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})
78-
logger := tlog.NewStructuredLogger(slog.New(slogHandler))
92+
logger := log.NewStructuredLogger(slog.New(slogHandler))
7993

8094
c, err := client.Dial(client.Options{
8195
Logger: logger,
8296
})
8397
```
8498

85-
### Using Third-Party Loggers (Logrus, Zap, etc.)
99+
### Using slog as a Bridge to Third-Party Loggers
86100

87-
Use the [logur](https://github.com/logur/logur) adapter package:
101+
Any third-party logger that can back an `slog.Handler` works with `log.NewStructuredLogger` — this includes zap, zerolog, logrus, and most modern Go logging libraries. The pattern is: create an `slog.Handler` from your logger, then wrap it with `log.NewStructuredLogger`.
102+
103+
**Example with Zap:**
88104

89105
```go
90106
import (
91-
"github.com/sirupsen/logrus"
92-
logrusadapter "logur.dev/adapter/logrus"
93-
"logur.dev/logur"
107+
"log/slog"
108+
109+
"go.uber.org/zap"
110+
"go.uber.org/zap/exp/zapslog"
111+
"go.temporal.io/sdk/log"
94112
)
95113

96-
logger := logur.LoggerToKV(logrusadapter.New(logrus.New()))
114+
zapLogger, _ := zap.NewProduction()
115+
handler := zapslog.NewHandler(zapLogger.Core())
116+
logger := log.NewStructuredLogger(slog.New(handler))
117+
97118
c, err := client.Dial(client.Options{
98119
Logger: logger,
99120
})
100121
```
101122

123+
### Direct Adapter (Alternative)
124+
125+
If you cannot use the slog bridge, you can implement the `log.Logger` interface directly. The Temporal samples repo has a ~60-line [zap adapter](https://github.com/temporalio/samples-go/blob/main/zapadapter/zap_adapter.go) that implements `Logger`, `WithLogger`, and `WithSkipCallers` and can be copied into your project.
126+
102127
## Metrics
103128

104129
Use the Tally library (`go.temporal.io/sdk/contrib/tally`) with Prometheus:

0 commit comments

Comments
 (0)