config/logger.ts: en dev, on duplique les logs vers apps/api/storage/logs/app.log via un `multistream` pino (pretty stdout + JSON file en parallèle). Plus fiable que `transport.targets` qui tourne dans un worker thread et fail silencieusement quand le path n'est pas accessible. Logs ciblés sur le pipeline relance pour debug rapide : - relance_scheduler : tâche créée + delaySec + queueJobId - send_relance_job : pick-up / skip / envoi / OK / KO - mail_dispatcher : driver actif (smtp/resend) + send OK / err .gitignore : storage/uploads + storage/logs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
101 lines
2.8 KiB
TypeScript
101 lines
2.8 KiB
TypeScript
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<typeof loggerConfig> {}
|
|
}
|