SDK logging utilities for system and bots.
The SDK uses Loguru for logging and separates system logs from bot logs using tags and different sinks.
At a high level:
SYSTEM and written to logs/system.log.logs/echo_bot.log.Logs panel.from bot_sdk import setup_logging
# Call once at process start (e.g. in main.py)
setup_logging(level="INFO", json_logs=False)
DEBUG, INFO, WARNING, ERROR).True, use a JSON formatter (useful for log ingestion); when False, use a human-readable colored format.setup_logging() will:
logs/ directory exists next to your project.SYSTEM tag (extra["bot_name"] = "SYSTEM").stdout (human-readable, colored output).logs/system.log (plain text, one line per record, filtered to bot_name == "SYSTEM").Bots use their own tagged loggers so you can distinguish messages per bot and write to per-bot log files.
from bot_sdk import get_bot_logger
bot_logger = get_bot_logger("echo_bot", level="INFO")
bot_logger.info("EchoBot starting up")
bot_logger.debug("Some internal state: {}", {"foo": 1})
extra["bot_name"] = <bot_name>.logs/<bot_name>.log when a name is provided (e.g. logs/echo_bot.log).logs/bots.log as a shared fallback when no name is given.In most cases you don’t need to call get_bot_logger manually:
BaseBot via the SDK (e.g. BotRunner or the interactive console), the framework creates a bot-specific logger and injects it into your bot instance.self.logger:from bot_sdk import BaseBot, Message
class MyBot(BaseBot):
async def on_message(self, message: Message):
self.logger.info("Received message from {}", message.sender_full_name)
await self.send_reply(message, "Hello!")
When running the interactive console (async-zulip-bot / main.py):
Logs panel shows a live view of all Loguru output (system + all bots).SYSTEM, echo_bot) so you can see log origin at a glance.from bot_sdk import setup_logging
from loguru import logger
if __name__ == "__main__":
setup_logging(level="DEBUG")
logger.info("SDK starting...")
# Your startup logic here
from bot_sdk import BaseBot, Message
class LoggingBot(BaseBot):
async def on_start(self) -> None:
self.logger.info("{} started", self.__class__.__name__)
async def on_message(self, message: Message) -> None:
self.logger.debug("Incoming message: {}", message.content[:50])
await self.send_reply(message, "Got it!")