Files
tcp-ingestion/src/observability/logger.ts
T
julian 477fabfef8 Sharpen pilot logging: ISO timestamps, level labels, transport-error classification, per-frame info
- Emit ISO-8601 timestamps and string level labels (info/warn/...) so
  Portainer's log viewer renders seconds and human-readable levels.
- Classify ETIMEDOUT/ECONNRESET/EPIPE/ENOTCONN as info one-liners
  rather than warns with stack traces. These are routine on cellular.
- Add an info "frame ingested" line per accepted AVL frame so device
  activity is visible at info level until task 1.10 wires up prom-client.
2026-04-30 19:30:24 +02:00

54 lines
1.5 KiB
TypeScript

import pino from 'pino';
import type { Logger } from 'pino';
export type { Logger };
/**
* Builds the root pino logger. Called once at startup with the config values.
*
* In development, pino-pretty is used for human-readable output (lazy import
* so it is never bundled in production paths). In test/production, raw JSON is
* emitted — fast and parseable by log aggregators.
*/
export function createLogger(options: {
level: string;
nodeEnv: string;
instanceId: string;
}): Logger {
const { level, nodeEnv, instanceId } = options;
const base = {
service: 'tcp-ingestion',
instance_id: instanceId,
};
// Emit `"level":"info"` instead of pino's default `"level":30` so log
// viewers (Portainer, etc.) show a human-readable label rather than the
// numeric level.
const formatters = {
level: (label: string) => ({ level: label }),
};
if (nodeEnv === 'development') {
return pino({
level,
base,
timestamp: pino.stdTimeFunctions.isoTime,
formatters,
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'SYS:standard',
ignore: 'pid,hostname',
},
},
});
}
// Production and test: plain JSON — fast, no extra deps.
// ISO-8601 string timestamps (vs default epoch-ms) survive downstream
// log renderers (Portainer, Docker --timestamps) without losing seconds.
return pino({ level, base, timestamp: pino.stdTimeFunctions.isoTime, formatters });
}