🍡 mochi

SSR framework for Svelte 5 + Bun with islands-based selective hydration

On this page

Logging

Mochi exposes one isomorphic logger with five methods. The same import works on the server, in SSR, in hydrated Svelte components, and in vanilla web components. A configurable level set on Mochi.serve() gates it.

import { logger } from 'mochi-framework';

logger.error('boom');
logger.warn('careful');
logger.info('starting up');
logger.log('verbose detail');
logger.debug('asset request');

Methods map to console.error / console.warn / console.info / console.log / console.debug. Each line is prefixed with a coloured [mochi]. A call below the configured level is a no-op with negligible overhead.

Log level

import { Mochi } from 'mochi-framework';

await Mochi.serve({
  port: 3333,
  routes,
  logger: { level: 'warn' },
});

level accepts 'silent' | 'error' | 'warn' | 'info' | 'log' | 'debug'. A method runs when its severity is at or above the active level. So 'warn' lets error and warn through and suppresses info, log, and debug.

LevelWhat you seeWhen to use
'silent'Nothing — no boot line, no requests, no errorsTests; CLI scripts that want no noise
'debug'Everything 'log' shows, plus per-asset request lines and fallbacksInvestigating asset fetches or unmatched routes
'log'Adds chatty client-side hydration traces and other verbose detailDebugging hydration / island lifecycle
'info'Boot line, page/api/file requests, file-change notifications, plus warnings/errorsDefault in development
'warn'Slow requests, 5xx responses, queue lifecycle, deprecations, recoverable problemsDefault in production
'error'Only handler failures and unhandled exceptionsProduction with a separate alerting pipeline

Which severity each event lands on is a framework default. Remap them per app with the consoleLogger:level filter.

If level is omitted, Mochi picks the default from the mode: 'info' in development, 'warn' in production.

The level applies on both server and client. The server sends its configured level to the browser, so client-side logger calls honour it too. Reload the page after changing the config to pick up a new level on the client.

Setting the level at runtime

import { setLogLevel, getLogLevel } from 'mochi-framework';

setLogLevel('error');
getLogLevel(); // 'error'

setLogLevel is for niche cases such as toggling verbosity from a feature flag. The serve-time config is the right place for normal use.

Relationship to mochiEvents

The event bus (mochiEvents) carries structured payloads to any subscriber you wire up, regardless of console output. The built-in consoleLogger() — the thing that prints request lines like GET /foo 200 12ms — is one consumer that subscribes to those events and calls logger.info / logger.warn per event. Plug Sentry, OpenTelemetry, or your own pipeline directly into mochiEvents. Use logger for ad-hoc messages.

See it in action

Live demos showing key concepts from this page