From 6e6713fb231dc9cf41bddef56e84cbf9f9419b8d Mon Sep 17 00:00:00 2001 From: Johannes Fleck Date: Fri, 30 Oct 2026 13:21:18 +0100 Subject: [PATCH 1/2] fix: resolve pino-pretty transport path for vite dev Since pino 10.4.0 the transport caller is detected via util.getCallSites(), which returns an empty script name for modules evaluated by Vite's SSR module runner. pino then cannot resolve 'pino-pretty' and `npm run dev` fails with "unable to determine transport target". Resolve the target to an absolute path ourselves. knip now sees pino-pretty as used, so drop it from ignoreDependencies. --- knip.json | 2 -- src/lib/server/logging/logger.ts | 7 ++++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/knip.json b/knip.json index 0bbb15ea..54b3bee5 100644 --- a/knip.json +++ b/knip.json @@ -2,8 +2,6 @@ "$schema": "https://unpkg.com/knip@6/schema.json", "entry": ["drizzle.config.ts", "src/lib/editor/grammar/patch-generated.mjs"], "ignoreDependencies": [ - // Loaded dynamically by pino via a string transport target, not a static import. - "pino-pretty", // Invoked as a standalone CLI in docker/Dockerfile, not referenced from source. "@cyclonedx/cyclonedx-npm" ], diff --git a/src/lib/server/logging/logger.ts b/src/lib/server/logging/logger.ts index 28cbdada..b5c9a97d 100644 --- a/src/lib/server/logging/logger.ts +++ b/src/lib/server/logging/logger.ts @@ -1,3 +1,4 @@ +import { createRequire } from 'node:module'; import pino from 'pino'; import { redactionPaths, redactionCensor } from './redaction.js'; import type { LoggingConfig } from './types.js'; @@ -8,6 +9,7 @@ import type { LoggingConfig } from './types.js'; // This is safe because the file lives under $lib/server/ which SvelteKit // already prevents from being imported client-side. const dev = process.env.NODE_ENV !== 'production'; +const require = createRequire(import.meta.url); function resolveConfig(): LoggingConfig { const level = process.env.LOG_LEVEL ?? (dev ? 'trace' : 'info'); @@ -37,7 +39,10 @@ function createLogger(): pino.Logger { const targets: pino.TransportTargetOptions[] = []; if (config.pretty) { - targets.push({ target: 'pino-pretty', level: config.level }); + // Resolve to an absolute path: since pino 10.4.0 the caller is detected via + // util.getCallSites(), which returns an empty script name for modules + // evaluated by Vite's SSR module runner, so pino cannot resolve 'pino-pretty'. + targets.push({ target: require.resolve('pino-pretty'), level: config.level }); } else { targets.push({ target: 'pino/file', level: config.level }); } From 23f295107004eb6de85b6247f465eccde14b28ac Mon Sep 17 00:00:00 2001 From: Johannes Fleck Date: Fri, 30 Oct 2026 13:21:24 +0100 Subject: [PATCH 2/2] fix: avoid pino multistream warning with a single log target A per-target `level` makes pino route logs through multistream, which since pino 10.4.0 warns about our custom `formatters.level` (PINO_TRANSPORT_MULTI_TARGETS_LEVEL_FORMATTER). A single target needs no level as the logger already filters. Keep it for multiple targets (LOG_JSON_FILE), where multistream would otherwise default targets to 'info' and drop debug logs. --- src/lib/server/logging/logger.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/lib/server/logging/logger.ts b/src/lib/server/logging/logger.ts index b5c9a97d..e18ff4b8 100644 --- a/src/lib/server/logging/logger.ts +++ b/src/lib/server/logging/logger.ts @@ -42,19 +42,26 @@ function createLogger(): pino.Logger { // Resolve to an absolute path: since pino 10.4.0 the caller is detected via // util.getCallSites(), which returns an empty script name for modules // evaluated by Vite's SSR module runner, so pino cannot resolve 'pino-pretty'. - targets.push({ target: require.resolve('pino-pretty'), level: config.level }); + targets.push({ target: require.resolve('pino-pretty') }); } else { - targets.push({ target: 'pino/file', level: config.level }); + targets.push({ target: 'pino/file' }); } if (config.jsonLogFile) { targets.push({ target: 'pino/file', - options: { destination: config.jsonLogFile, mkdir: true }, - level: config.level + options: { destination: config.jsonLogFile, mkdir: true } }); } + // A per-target `level` routes logs through pino's multistream, which warns about + // the custom `formatters.level` above (PINO_TRANSPORT_MULTI_TARGETS_LEVEL_FORMATTER). + // A single target needs no level as the logger already filters; multiple targets + // do, as multistream defaults targets without one to 'info'. + if (targets.length > 1) { + for (const target of targets) target.level = config.level; + } + return pino(options, pino.transport({ targets })); }