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.
This commit is contained in:
2026-04-30 19:30:15 +02:00
parent e2b3bc421c
commit 477fabfef8
2 changed files with 33 additions and 2 deletions
+20
View File
@@ -134,6 +134,19 @@ export function createTeltonikaAdapter(options: TeltonikaAdapterOptions): Adapte
'malformed frame; dropping connection',
);
}
} else if (
err instanceof Error &&
'code' in err &&
// Routine on cellular: NAT timeouts, carrier RST, half-closed pipes.
// Surface as info (one-liner, no stack) so warns mean something.
['ETIMEDOUT', 'ECONNRESET', 'EPIPE', 'ENOTCONN'].includes(
(err as NodeJS.ErrnoException).code as string,
)
) {
sessionLogger.info(
{ code: (err as NodeJS.ErrnoException).code },
'session ended (transport error)',
);
} else {
sessionLogger.warn({ err }, 'unexpected error reading frame; dropping connection');
}
@@ -204,6 +217,13 @@ export function createTeltonikaAdapter(options: TeltonikaAdapterOptions): Adapte
result: 'ok',
});
// Pilot-stage visibility into per-frame ingest. Downgrade to debug
// once task 1.10 wires up prom-client and frames_total is scrapeable.
sessionLogger.info(
{ codec: codecLabel, records: result.recordCount },
'frame ingested',
);
// ACK: 4-byte big-endian record count
const ack = Buffer.alloc(4);
ack.writeUInt32BE(result.recordCount, 0);