Logging
Comprehensive guide to structured logging in ocpp-ws-io
Logging
ocpp-ws-io includes a structured logging system powered by voltlog-io. It provides real-time traffic inspection, performance monitoring, and integration with external logging services.
Overview
Logging in ocpp-ws-io is designed to be:
- Zero-Config: Works out of the box with sensible defaults.
- Structured: All logs are JSON-formatted for easy parsing and ingestion.
- OCPP-Aware: Special handling for OCPP messages, including direction and metadata.
- Extensible: Use built-in transports or bring your own logger (Pino, Winston, etc.).
Quick Start
Enable logging when initializing your client or server:
import { OCPPClient } from "ocpp-ws-io";
const client = new OCPPClient({
identity: "CP-001",
endpoint: "ws://localhost:3000",
logging: {
enabled: true, // Default: true
prettify: true, // 🌈 Enable colors & icons for development
exchangeLog: true, // ⚡ Log every OCPP message (Call/Result/Error)
},
});Configuration
The logging option accepts a LoggingConfig object:
| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable or disable all logging. |
logging (root) | boolean | undefined | Can be set directly to false to completely disable logging with a safe NOOP fallback. |
level | string | 'info' | Minimum log level (trace, debug, info, warn, error, fatal). |
prettify | boolean | false | Use prettyTransport for human-readable output (colors, icons). |
exchangeLog | boolean | false | Log all OCPP messages with direction (IN/OUT) and metadata. |
logger | LoggerLike | undefined | Custom logger instance (e.g., Pino) to replace the default logger. |
handler | function | undefined | Custom voltlog-io transport function (entry) => void | Promise<void> |
showMetadata | boolean | true | Show trailing metadata object in logs. |
showSourceMeta | boolean | true | Show source context (component, identity). |
prettifySource | boolean | false | Compact source tag [OCPPServer/CP-1]. |
prettifyMetadata | boolean | false | Format metadata as key=value pairs. |
Levels
| Level | Value | Usage |
|---|---|---|
fatal | 60 | System is unusable. |
error | 50 | Error conditions (connection failures, validation errors). |
warn | 40 | Warning conditions (retries, unexpected messages). |
info | 30 | Normal operational messages (connect/disconnect, startup). |
debug | 20 | Detailed internal state (protocol negotiation, raw payloads). |
trace | 10 | Very detailed step-by-step tracing. |
Exchange Logging (Middleware)
The exchangeLog feature is now powered by the internal Logging Middleware. It logs every WebSocket message sent or received.
Output Format
When prettify: true is also enabled, you get styled output distinguishing outbound calls, inbound calls, and asynchronous results:
// Outbound RPC Call (from Station to CSMS)
⚡ CP-101 → BootNotification [OUT]
// Inbound RPC Call (from CSMS to Station)
✅ CP-101 ← GetConfiguration [IN]
// Asynchronous RPC Result / Error returned
🔥 CP-101 ← BootNotification [RES] { latencyMs: 45 }When prettify: false (production), logs are structured JSON:
{
"level": 30,
"msg": "BootNotification",
"direction": "OUT",
"messageId": "12345",
"payload": { ... }
}Voltlog Integration
This library uses voltlog-io under the hood. You can import logging utilities directly from ocpp-ws-io/logger:
import { createLogger, consoleTransport } from "ocpp-ws-io/logger";
const logger = createLogger({
name: "MyCSMS",
transports: [consoleTransport()],
});
logger.info("System started");Using a Custom Logger Instance
If you already use Pino, Winston, or another logger, you can pass it to ocpp-ws-io. The logger must satisfy the LoggerLike interface (methods: debug, info, warn, error, child).
Example with Pino:
import pino from "pino";
import { OCPPServer } from "ocpp-ws-io";
const myLogger = pino();
const server = new OCPPServer({
logging: {
logger: myLogger, // ocpp-ws-io will use this instance
},
});Using a Custom Transport Handler
If you prefer to let ocpp-ws-io handle the logger initialization (and middleware enrichment) but want to siphon the formatted log items to an external observability platform (like Datadog, Sentry, an external file, or a custom UI), you can provide a custom handler callback.
This handler will receive the fully resolved LogEntry directly from the internal voltlog-io pipeline!
const server = new OCPPServer({
logging: {
enabled: true,
handler: async (entry) => {
// example: Send log to a remote ingest API
await fetch("https://logs.example.com/ingest", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(entry),
});
},
},
});Browser Client
The BrowserOCPPClient also supports logging, configured the same way.
import { BrowserOCPPClient } from "ocpp-ws-io/browser";
const client = new BrowserOCPPClient({
endpoint: "wss://csms.example.com",
identity: "Simulator-1",
logging: {
level: "debug",
exchangeLog: true,
},
});Note: In the browser,
prettifyuses browser console styling (CSS) instead of terminal colors.