REPOSITORY / ScuroNeko/Laniakea

Wiki

KNOWLEDGE REPOSITORY
4
Logging
ScuroNeko edited this page 2026-05-20 13:19:27 +03:00

Logging

Russian version: Logging-RU

Laniakea has several logger layers: the main bot logger, an optional request logger, per-plugin loggers, and internal API or uploader loggers. This page explains how they are created, how they relate to each other, and where to customize them.

Logger layers

The bot runtime can involve these loggers:

  • the main bot logger;
  • the optional request logger;
  • plugin loggers;
  • internal tgapi.API and tgapi.Uploader loggers.

These layers exist for different reasons:

  • the bot logger covers lifecycle and high-level routing behavior;
  • the request logger captures raw update payloads;
  • plugin loggers let one module emit context-specific logs;
  • internal API and uploader loggers help trace Telegram traffic and low-level behavior.

Main bot logger

The main bot logger is created during bot construction.

It is used for:

  • startup and shutdown messages;
  • middleware and runner warnings;
  • bot-level operational logs;
  • fallback logging when no plugin-specific logger is available.

You can access it with:

logger := bot.GetLogger()

Request logger

The request logger is optional and enabled through BotOpts.UseRequestLogger.

It is used for raw update logging after getUpdates succeeds. When enabled, the bot serializes each update and logs it through RequestLogger.

This is useful for:

  • debugging update shapes;
  • investigating routing issues;
  • capturing real payload samples for tests.

Because it can be noisy, it is usually best enabled selectively.

Plugin loggers

Each registered plugin can have its own logger.

Ways plugin loggers are set:

  • explicitly with Plugin.SetLogger(...) before AddPlugins(...);
  • implicitly by the bot, which creates a default logger if the plugin has none at registration time.

During handler execution, MessageContext.Logger is set to:

  • the matched plugin logger when one exists;
  • otherwise the bot logger.

That means handler-local logs naturally follow plugin boundaries when possible.

MessageContext.Logger

Inside handlers and middleware, the easiest logger to use is ctx.Logger.

It already reflects the current execution context:

  • plugin logger for matched plugin routes;
  • bot logger as fallback.

This makes it the recommended logger for most application code inside handlers.

Debug mode

Use Bot.Debug(true) or BotOpts.Debug to enable debug-level logging.

Debug(true) updates:

  • the bot logger;
  • the request logger, if enabled;
  • already registered plugin loggers.

This is helpful when you want to increase verbosity after bot creation.

File logging

Laniakea can write logs to files when:

  • WriteToFile is enabled;
  • LoggerBasePath is configured or defaults to ./.

By default, file logging creates:

  • main.log for the bot logger;
  • requests.log for the request logger.

If file writer creation fails, the logger falls back to stdout logging rather than crashing the bot.

Shared logger policy

The helper constructors in utils apply a shared logging policy:

  • JSON stdout output by default;
  • a prefix such as BOT, REQUESTS, API, or UPLOADER;
  • the chosen log level.

This gives the library a consistent baseline logging style across components.

App-data logger writers

AddAppDataLoggerWriter(...) lets you attach a writer derived from your app data or shared dependency context to multiple loggers at once.

When it succeeds, the writer is attached to:

  • the main bot logger;
  • the request logger if present;
  • API and uploader loggers;
  • already registered plugin loggers.

Important nuance:

  • call it after AddPlugins(...) if plugin loggers should receive the writer;
  • plugins registered later do not automatically inherit previously attached app-data writers.

If app data is unset or nil, the method logs a warning and skips the writer.

Plugin logger customization

Plugin logger APIs:

  • SetLogger(...)
  • RemoveLogger()

These should be called before AddPlugins(...), because plugin registration is a snapshot point for configuration.

If you mutate the original plugin logger after registration, the bot's internal copy is not guaranteed to reflect that change.

Logging and errors

When handler errors flow through ctx.error(...), the error is logged with the current context logger after the user-facing response is sent.

This means:

  • returned command errors are logged under the plugin logger when one exists;
  • otherwise they are logged under the main bot logger.

Related page:

Practical patterns

Turn on debug logging

opts := (&laniakea.BotOpts{}).
	SetToken("TOKEN").
	SetDebug(true)

Enable request logging

opts := (&laniakea.BotOpts{}).
	SetToken("TOKEN").
	SetUseRequestLogger(true)

Provide a custom plugin logger

plugin := laniakea.NewPlugin[*App]("admin")
plugin.SetLogger(customLogger)

Attach app-data-backed logging

bot.SetAppData(db)
bot.AddPlugins(plugin)
bot.AddAppDataLoggerWriter(func(db *sql.DB) slog.LoggerWriter {
	return newDBWriter(db)
})

Recommendations

  • Use ctx.Logger inside handlers instead of reaching for global loggers directly.
  • Enable request logging when debugging update routing, then turn it back down.
  • Treat plugin loggers as a useful boundary for large bots with multiple modules.
  • Call AddAppDataLoggerWriter(...) only after the bot has valid app data.