Logger
Structured Logging with Privacy
Using `createLogger` from `@epheme/core` — Pino-based logging with automatic redaction of sensitive fields.
Setting up the logger
const { createLogger, requestLogger } = require('@epheme/core');
const express = require('express');
const app = express();
// Create a logger instance
const logger = createLogger({
service: 'my-app',
component: 'server',
tenant: 'acme' // optional, if multi-tenant
});
// Add Pino HTTP middleware for request logging
app.use(requestLogger());
// Use the logger throughout your app
app.get('/health', (req, res) => {
logger.info({ msg: 'health check' });
res.json({ ok: true });
});
app.post('/register', (req, res) => {
const { email } = req.body;
logger.info({ email }, 'user registration attempt');
res.json({ registered: true });
});
app.use((err, req, res, next) => {
logger.error({ err }, 'unhandled error');
res.status(500).json({ error: 'Server error' });
});
app.listen(3000);
The logger automatically redacts these sensitive fields in all output:
deviceId, deviceJwt, userId, jwt, token, pat, patId, sessionId,
roomId, shareId, inviteToken, ip, remoteAddress, authorization,
cookie, password, secret, apiKey, body
Even if you log these fields, they'll be removed before output to prevent credential leaks.
const logger = createLogger({ service: 'my-app' });
// Different log levels
logger.debug({ foo: 'bar' }, 'debug message');
logger.info({ count: 42 }, 'info message');
logger.warn({ warning: 'something' }, 'warning message');
logger.error({ err }, 'error message with error object');
// Structured fields are logged to JSON
logger.info({ userId: '123', action: 'login' }, 'user login');
// Output: { "level":30, "time":"...", "userId":"[REDACTED]", "action":"login", ... }
// Request logger catches requests automatically
// No need to manually log each request — middleware does it for you
LOG_LEVELenv var (default: 'debug' in dev, 'info' in prod)LOG_PRETTY(default: true in TTY, false in production)NODE_ENV(affects level and formatting)