Skip to content

Digging deeper

Telegram logging

Send selected log records to Telegram chats with a non-blocking slog handler.

Last updated:

Set the variables and the app logger fans out to stderr and Telegram (slog.NewMultiHandler):

.env
TELEGRAM_BOT_TOKEN=123456:ABC...   # never logged
TELEGRAM_CHAT_ID=-1001234567890
TELEGRAM_MIN_LEVEL=error           # debug, info, warn, error
TELEGRAM_THREAD_ID=42              # optional forum topic
TELEGRAM_LOG=true                  # false: no log forwarding, app.Telegram only for Send/Contact
TELEGRAM_RATE_LIMIT=20             # optional cap on forwarded log records per minute (0: none)
Go
app.Telegram.Contact(ctx, map[string]string{"name": in.Name, "message": in.Message}) // never filtered by level
app.Telegram.Send(ctx, "<b>Deploy</b> finished")                                     // pre-formatted HTML

// In a queued job: deliver now and return the error so the job retries.
err := app.Telegram.ContactSync(ctx, fields) // or SendSync; telegram.ErrDisabled when not configured

// Only forward the records you mark (Filter sees log records, never Send/Contact).
vukem.WithTelegram(func(c *telegram.Config) {
	c.Filter = func(_ context.Context, r slog.Record) bool { return r.Level >= telegram.LevelFatal }
})

Use the handler directly for per-level chats or custom error handling:

Go
tg := telegram.NewHandler(telegram.Config{
	BotToken: token, ChatID: "-100", ChatIDs: map[slog.Level]string{telegram.LevelFatal: "-200"},
	MinLevel: slog.LevelWarn, AppName: "Shop", Env: "production", Silent: true, OnError: report,
})
defer tg.Close(ctx)
log := slog.New(slog.NewMultiHandler(base, tg))
FeatureDetail
Levelsdebug, info, warn, error plus telegram.LevelSuccess and telegram.LevelFatal
FormatTelegram HTML: level emoji, app, environment, UTC time, then message and attributes (groups dotted, error chains as "caused by") in a <pre> block; all content escaped; truncated to 4096 characters without cutting tags or entities
Reliabilitybounded queue (drops and reports when full), per-request timeout, one retry after HTTP 429 honouring retry_after (capped), OnError (never reentrant; records logged from it or carrying its error are not forwarded, so it may log through the app logger), drained by app.Shutdown; SendSync / ContactSync skip the queue and return the error, bounded by the per-request timeout and ctx
Log forwardingon by default for records at MinLevel+; TELEGRAM_LOG=false turns it off; Filter and RateLimit (TELEGRAM_RATE_LIMIT per minute) narrow it; vukem.WithTelegram edits the config in code
Securitythe token is a config.Secret, redacted from errors; vukem about shows only on/off; disabled when token or chat is missing

Ported from the maintainer's TypeScript telegram-logger.