import { mkdirSync } from 'node:fs' import env from '#start/env' import app from '@adonisjs/core/services/app' import { defineConfig, syncDestination, targets, multistream, destination, } from '@adonisjs/core/logger' /** * En dev on duplique les logs vers `apps/api/storage/logs/app.log` pour * pouvoir grep / tail / partager facilement (notamment quand un job BullMQ * tourne en arrière-plan et qu'on veut voir si l'envoi mail s'est bien fait * sans devoir scroller le terminal). * * En prod on garde uniquement stdout (les logs sont collectés par K8s via * `kubectl logs`). * * Implémentation : on utilise `multistream` (pino) qui écrit en parallèle * - vers la sortie sync pretty (TTY) — la sortie habituelle dev * - vers le fichier app.log en JSON (parseable, grep-able) * * Plus fiable que `transport.targets` qui tourne dans un worker thread et * peut échouer silencieusement quand le path n'est pas accessible. */ const logFilePath = app.makePath('storage/logs/app.log') if (!app.inProduction) { mkdirSync(app.makePath('storage/logs'), { recursive: true }) } const prettyStream = !app.inProduction ? await syncDestination() : null const devDestination = !app.inProduction && prettyStream ? multistream([ // Sortie console pretty (sync) — c'est la sortie habituelle dev. { stream: prettyStream }, // Fichier JSON ligne — destination pino classique avec append+mkdir. { stream: destination({ dest: logFilePath, sync: true, append: true, mkdir: true, }), }, ]) : undefined const loggerConfig = defineConfig({ /** * Default logger name used by ctx.logger and app logger calls. */ default: 'app', loggers: { app: { /** * Toggle this logger on/off. */ enabled: true, /** * Logger name shown in log records. */ name: env.get('APP_NAME'), /** * Minimum level to output (trace, debug, info, warn, error, fatal). */ level: env.get('LOG_LEVEL'), /** * Dev : multistream (pretty stdout + JSON file). * Prod : pas de destination → AdonisJS bascule sur transport. */ destination: devDestination, /** * En prod : un seul transport vers stdout (collecté par K8s). * En dev : pas de transport — le multistream ci-dessus s'occupe de * tout, et mélanger les deux fait que pino ignore le destination. */ transport: app.inProduction ? { targets: [targets.file({ destination: 1 })] } : undefined, }, }, }) export default loggerConfig /** * Inferring types for the list of loggers you have configured * in your application. */ declare module '@adonisjs/core/types' { export interface LoggersList extends InferLoggers {} }