Only show guides for your app
console.log discipline, structured logs with pino, and Python's logging module — plus where those lines actually show up on the Console and Logs pages.
When something breaks while you're asleep, your logs are the only witness. Good logging turns "the server crashed, I have no idea why" into "the database timed out at 03:12, here's the line". This guide covers the discipline that makes logs useful, structured logging in Node and Python, and where every line ends up in the panel.
| At a glance | |
|---|---|
| You need | A Falix application server (Node.js or Python) |
| Plan | Any |
| Time | Twenty minutes |
Everything your app prints to standard output shows up live on the Console page — that's your main window while a server runs. Two Falix facts shape how you print:
Listening, so a startup log like Listening on port 25565 is both good practice and a status signal.print("...", flush=True), or the logging module below, so your lines appear immediately instead of getting stuck.The Logs page is a separate log-file browser with refresh/auto-refresh, download, share, and search (with optional regex). It shines for games that write log files; for application servers the Console is where the action is. See The Console.
console.log is fine — most bots and apps never need more. What matters is how you use it:
console.log('user banned', userId, guildId) beats console.log('done'). Log the values that let you reconstruct what happened.console.error. It writes to stderr, which keeps errors distinguishable from normal output.console.error('login failed', err) prints the stack trace; console.error('login failed') throws away the one clue that matters.Once an app grows, you'll want to dial verbosity up and down without editing code everywhere. A logger with levels does that. pino is small, fast, and outputs one JSON object per line:
const pino = require('pino');
const log = pino({ level: process.env.LOG_LEVEL || 'info' });
log.info({ port: 25565 }, 'service starting');
log.warn('low on memory');
log.error(new Error('database connection failed'), 'request failed');
log.debug('you only see this when LOG_LEVEL=debug');
Add pino to your package.json and it installs on start. Each call prints a JSON line with a numeric level — info is 30, warn 40, error 50, debug 20 — so {"level":50,...,"msg":"request failed"} is unmistakably an error, and the error's stack is captured as a field. Because the level comes from LOG_LEVEL, you can set that variable to debug when hunting a bug and back to info after, no code change. The Console shows the JSON as-is; for a prettier local view, the pino-pretty formatter exists, but raw JSON is perfectly readable and ideal for searching.
🎯 Good to know:
winstonis the other popular Node logger and works the same way (levels, structured output) — pick either. The habit (levels + context + errors as objects) matters more than the library.
Python's standard library logging module needs nothing installed. Configure it once at startup:
import logging, sys
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s %(message)s",
stream=sys.stdout,
)
log = logging.getLogger("myapp")
log.info("service starting on port %s", 25565)
log.warning("low on memory")
try:
risky()
except Exception:
log.exception("unhandled error while handling request")
That prints timestamped, levelled lines like 2026-07-18 04:03:39 INFO myapp service starting on port 25565, and log.exception(...) inside an except block logs your message plus the full traceback automatically — exactly what you want at 3am. Streaming to sys.stdout means the lines land on the Console immediately, sidestepping the buffering that plagues bare print.
| Level | Use it for |
|---|---|
| error | Something failed and needs attention — a crash, a failed request, a rejected login |
| warn | Something's off but survivable — a retry, a missing optional config, high memory |
| info | Normal milestones — startup, a command run, a scheduled job fired |
| debug | Detailed tracing you only want while investigating — off in normal running |
Whatever tool you use, always log these:
When you need help, don't retype errors — the panel shares them for you. Use the Share button on the Console (or the Logs page) to hand someone a link to the exact output, and the Logs page's regex search to find one error string in a wall of lines. See Getting help.
logging (streamed to stdout) or print(..., flush=True).LOG_LEVEL=info or warn) so debug lines drop out.console.error(msg, err) / log.exception(msg)) to capture the stack.