Skip to content

Commit b2b5865

Browse files
ernadoclaude
andcommitted
refactor(log): log through gotd/log instead of zap
Make the structured logger the github.com/gotd/log port: Options.Logger, Bot.Logger() and pool.Options.Logger are now log.Logger, and internal logging uses log.For(...).Info/Warn/Error with log attrs. The library no longer imports zap. Breaking: wrap *zap.Logger with logzap.New (examples updated). Add Bot.logger() helper. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 89a42c7 commit b2b5865

12 files changed

Lines changed: 64 additions & 52 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ messages follow [Conventional Commits](https://www.conventionalcommits.org/).
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- **Logging port** — the library now logs through `github.com/gotd/log` instead
13+
of zap directly. `Options.Logger` and `Bot.Logger()` (and `pool.Options.Logger`)
14+
are now `log.Logger`. **Breaking:** wrap a `*zap.Logger` with
15+
`github.com/gotd/log/logzap.New` (or a `*slog.Logger` with `logslog.New`). The
16+
library no longer depends on zap.
17+
1018
### Added
1119

1220
- **Rich messages** (Bot API 10.1) — `SendRichMessage`/`SendRichHTML`/

bot.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ import (
77

88
"github.com/go-faster/errors"
99
"github.com/gotd/log"
10-
"github.com/gotd/log/logzap"
1110
"github.com/gotd/td/telegram"
1211
"github.com/gotd/td/telegram/message"
1312
"github.com/gotd/td/telegram/peers"
1413
"github.com/gotd/td/telegram/updates"
1514
"github.com/gotd/td/tg"
16-
"go.uber.org/zap"
1715
)
1816

1917
// Bot is a Telegram Bot API client implemented over MTProto.
@@ -22,7 +20,7 @@ import (
2220
// Run to connect and serve. Bot is safe for concurrent use once running.
2321
type Bot struct {
2422
token string
25-
log *zap.Logger
23+
log log.Logger
2624

2725
client *telegram.Client
2826
raw *tg.Client
@@ -60,9 +58,7 @@ func New(token string, opt Options) (*Bot, error) {
6058
return nil, errors.New("AppID and AppHash are required (see https://my.telegram.org)")
6159
}
6260
opt.setDefaults()
63-
64-
// gotd/td logs through the github.com/gotd/log port; bridge the zap logger.
65-
lg := logzap.New(opt.Logger)
61+
lg := opt.Logger
6662

6763
disp := tg.NewUpdateDispatcher()
6864

@@ -83,7 +79,7 @@ func New(token string, opt Options) (*Bot, error) {
8379
AccessHasher: pm,
8480
Logger: log.Named(lg, "gaps"),
8581
OnChannelTooLong: func(channelID int64) {
86-
opt.Logger.Warn("Channel too long", zap.Int64("channel_id", channelID))
82+
log.For(lg).Warn(context.Background(), "Channel too long", log.Int64("channel_id", channelID))
8783
},
8884
})
8985

@@ -146,10 +142,10 @@ func (b *Bot) publishCommands(ctx context.Context) {
146142
return
147143
}
148144
if err := b.SetMyCommands(ctx, cmds); err != nil {
149-
b.log.Warn("Register bot commands", zap.Error(err))
145+
b.logger().Warn(ctx, "Register bot commands", log.Error(err))
150146
return
151147
}
152-
b.log.Debug("Registered bot commands", zap.Int("count", len(cmds)))
148+
b.logger().Debug(ctx, "Registered bot commands", log.Int("count", len(cmds)))
153149
}
154150

155151
// Run connects, authorizes as a bot, and blocks serving updates until ctx is
@@ -187,9 +183,9 @@ func (b *Bot) Run(ctx context.Context) error {
187183
return b.gaps.Run(ctx, b.raw, me.ID, updates.AuthOptions{
188184
IsBot: true,
189185
OnStart: func(ctx context.Context) {
190-
b.log.Info("Bot started",
191-
zap.Int64("id", me.ID),
192-
zap.String("username", me.Username),
186+
b.logger().Info(ctx, "Bot started",
187+
log.Int64("id", me.ID),
188+
log.String("username", me.Username),
193189
)
194190
b.publishCommands(ctx)
195191
if b.onStart != nil {
@@ -218,8 +214,11 @@ func (b *Bot) Peers() *peers.Manager { return b.peers }
218214
// Self returns the bot's own user. It is nil until Run has authorized.
219215
func (b *Bot) Self() *tg.User { return b.self }
220216

221-
// Logger returns the bot's zap logger.
222-
func (b *Bot) Logger() *zap.Logger { return b.log }
217+
// Logger returns the bot's structured logger (the github.com/gotd/log port).
218+
func (b *Bot) Logger() log.Logger { return b.log }
219+
220+
// logger wraps the bot's logger in an ergonomic Helper for internal logging.
221+
func (b *Bot) logger() log.Helper { return log.For(b.log) }
223222

224223
func (b *Bot) setRunCtx(ctx context.Context) {
225224
b.runMu.Lock()

examples/advanced/main.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import (
1919
"strings"
2020
"time"
2121

22+
glog "github.com/gotd/log"
23+
"github.com/gotd/log/logzap"
2224
"go.uber.org/zap"
2325

2426
"github.com/gotd/td/telegram/message/rich"
@@ -29,7 +31,7 @@ import (
2931
const samplePhotoURL = "https://upload.wikimedia.org/wikipedia/commons/3/3a/Cat03.jpg"
3032

3133
func main() {
32-
log, _ := zap.NewDevelopment()
34+
log, _ := zap.NewProduction()
3335
defer func() { _ = log.Sync() }()
3436

3537
appID, err := strconv.Atoi(os.Getenv("APP_ID"))
@@ -40,7 +42,7 @@ func main() {
4042
bot, err := botapi.New(os.Getenv("BOT_TOKEN"), botapi.Options{
4143
AppID: appID,
4244
AppHash: os.Getenv("APP_HASH"),
43-
Logger: log,
45+
Logger: logzap.New(log),
4446
FloodWait: true, // transparently wait out flood limits
4547
})
4648
if err != nil {
@@ -220,7 +222,7 @@ func registerCommands(bot *botapi.Bot) {
220222
go func() {
221223
time.Sleep(5 * time.Second)
222224
if _, err := c.Bot.SendMessage(ctx, chat, "⏰ Here's your reminder!"); err != nil {
223-
c.Bot.Logger().Warn("background reminder failed", zap.Error(err))
225+
glog.For(c.Bot.Logger()).Warn(ctx, "background reminder failed", glog.Error(err))
224226
}
225227
}()
226228
_, err := c.Reply("OK, I'll remind you in 5 seconds.")

examples/buttons/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"strconv"
1616
"time"
1717

18+
"github.com/gotd/log/logzap"
1819
"go.uber.org/zap"
1920

2021
"github.com/gotd/botapi"
@@ -35,7 +36,7 @@ func menu() *botapi.InlineKeyboardMarkup {
3536
}
3637

3738
func main() {
38-
log, _ := zap.NewDevelopment()
39+
log, _ := zap.NewProduction()
3940
defer func() { _ = log.Sync() }()
4041

4142
appID, err := strconv.Atoi(os.Getenv("APP_ID"))
@@ -46,7 +47,7 @@ func main() {
4647
bot, err := botapi.New(os.Getenv("BOT_TOKEN"), botapi.Options{
4748
AppID: appID,
4849
AppHash: os.Getenv("APP_HASH"),
49-
Logger: log,
50+
Logger: logzap.New(log),
5051
})
5152
if err != nil {
5253
log.Fatal("Create bot", zap.Error(err))

examples/echo/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ import (
1414
"strconv"
1515
"time"
1616

17+
"github.com/gotd/log/logzap"
1718
"go.uber.org/zap"
1819

1920
"github.com/gotd/botapi"
2021
)
2122

2223
func main() {
23-
log, _ := zap.NewDevelopment()
24+
log, _ := zap.NewProduction()
2425
defer func() { _ = log.Sync() }()
2526

2627
appID, err := strconv.Atoi(os.Getenv("APP_ID"))
@@ -31,7 +32,7 @@ func main() {
3132
bot, err := botapi.New(os.Getenv("BOT_TOKEN"), botapi.Options{
3233
AppID: appID,
3334
AppHash: os.Getenv("APP_HASH"),
34-
Logger: log,
35+
Logger: logzap.New(log),
3536
})
3637
if err != nil {
3738
log.Fatal("Create bot", zap.Error(err))

examples/inline/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@ import (
1515
"strconv"
1616
"strings"
1717

18+
"github.com/gotd/log/logzap"
1819
"go.uber.org/zap"
1920

2021
"github.com/gotd/botapi"
2122
)
2223

2324
func main() {
24-
log, _ := zap.NewDevelopment()
25+
log, _ := zap.NewProduction()
2526
defer func() { _ = log.Sync() }()
2627

2728
appID, err := strconv.Atoi(os.Getenv("APP_ID"))
@@ -32,7 +33,7 @@ func main() {
3233
bot, err := botapi.New(os.Getenv("BOT_TOKEN"), botapi.Options{
3334
AppID: appID,
3435
AppHash: os.Getenv("APP_HASH"),
35-
Logger: log,
36+
Logger: logzap.New(log),
3637
})
3738
if err != nil {
3839
log.Fatal("Create bot", zap.Error(err))

examples/media/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"strconv"
2121
"time"
2222

23+
"github.com/gotd/log/logzap"
2324
"go.uber.org/zap"
2425

2526
"github.com/gotd/botapi"
@@ -29,7 +30,7 @@ import (
2930
const samplePhotoURL = "https://upload.wikimedia.org/wikipedia/commons/3/3a/Cat03.jpg"
3031

3132
func main() {
32-
log, _ := zap.NewDevelopment()
33+
log, _ := zap.NewProduction()
3334
defer func() { _ = log.Sync() }()
3435

3536
appID, err := strconv.Atoi(os.Getenv("APP_ID"))
@@ -40,7 +41,7 @@ func main() {
4041
bot, err := botapi.New(os.Getenv("BOT_TOKEN"), botapi.Options{
4142
AppID: appID,
4243
AppHash: os.Getenv("APP_HASH"),
43-
Logger: log,
44+
Logger: logzap.New(log),
4445
})
4546
if err != nil {
4647
log.Fatal("Create bot", zap.Error(err))

handler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"context"
55
"sync"
66

7-
"go.uber.org/zap"
7+
"github.com/gotd/log"
88
)
99

1010
// Context is passed to a Handler. It embeds the request context (so it can be
@@ -93,7 +93,7 @@ func (b *Bot) route(ctx context.Context, u *Update) {
9393
}
9494
c := &Context{Context: ctx, Bot: b, Update: u}
9595
if err := h(c); err != nil {
96-
b.log.Error("Handler error", zap.Error(err))
96+
b.logger().Error(ctx, "Handler error", log.Error(err))
9797
}
9898
return
9999
}

middleware.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"runtime/debug"
66
"time"
77

8-
"go.uber.org/zap"
8+
"github.com/gotd/log"
99
)
1010

1111
// Recover wraps a handler so a panic is recovered, logged with its stack, and
@@ -15,9 +15,9 @@ func Recover() Middleware {
1515
return func(c *Context) (err error) {
1616
defer func() {
1717
if r := recover(); r != nil {
18-
c.Bot.log.Error("Recovered from panic in handler",
19-
zap.Any("panic", r),
20-
zap.ByteString("stack", debug.Stack()),
18+
c.Bot.logger().Error(c, "Recovered from panic in handler",
19+
log.Any("panic", r),
20+
log.String("stack", string(debug.Stack())),
2121
)
2222
err = &Error{Code: 500, Description: "Internal Server Error: handler panicked"}
2323
}
@@ -47,10 +47,10 @@ func Logging() Middleware {
4747
return func(c *Context) error {
4848
err := next(c)
4949
if err != nil {
50-
c.Bot.log.Warn("Update handled with error",
51-
zap.Int("update_id", c.Update.UpdateID), zap.Error(err))
50+
c.Bot.logger().Warn(c, "Update handled with error",
51+
log.Int("update_id", c.Update.UpdateID), log.Error(err))
5252
} else {
53-
c.Bot.log.Debug("Update handled", zap.Int("update_id", c.Update.UpdateID))
53+
c.Bot.logger().Debug(c, "Update handled", log.Int("update_id", c.Update.UpdateID))
5454
}
5555
return err
5656
}

on.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package botapi
33
import (
44
"context"
55

6+
"github.com/gotd/log"
67
"github.com/gotd/td/tg"
7-
"go.uber.org/zap"
88
)
99

1010
// installHandlers wires the raw tg.UpdateDispatcher to the Bot API router. It is
@@ -58,7 +58,7 @@ func (b *Bot) dispatchMessage(ctx context.Context, msg tg.MessageClass, edited b
5858

5959
m, err := b.messageFromTg(ctx, msg)
6060
if err != nil {
61-
b.log.Error("Convert message", zap.Error(err))
61+
b.logger().Error(ctx, "Convert message", log.Error(err))
6262
return
6363
}
6464
if m == nil {

0 commit comments

Comments
 (0)