@hiprax/logger
v0.6.0
Published
Fully typed Winston-based logger with rotation, timezone support, and Express middleware
Maintainers
Readme
@hiprax/logger
Fully typed, production-grade logging toolkit for Node.js applications. Built on top of Winston with first-class TypeScript support, rotating file transports, timezone mirroring, and an HTTP middleware that outperforms traditional solutions.
Features
- ✅ Multi-target logging (console, per-module files, shared files, custom transports). Console output stays enabled but omits timestamps so only files capture the full timeline.
- ✅ Daily rotation with independent retention rules
- ✅ Guaranteed UTC timestamps plus optional verified IANA timezones
- ✅ Automatic log directory creation (including nested module scopes)
- ✅ Batteries-included Express middleware with structured payloads
- ✅ Zero-config ESM & CommonJS builds, rich IntelliSense docs
- ✅ Comprehensive Jest suite with 100% coverage
Installation
npm install @hiprax/loggerThe package ships with precompiled dual builds. No transpilation is required in consuming projects.
Quick Start
import { createLogger } from "@hiprax/logger";
const securityLogger = createLogger({
moduleName: "security/failedLogins",
extraTimezones: ["Europe/London"],
});
securityLogger.warn(`Failed login attempt\nEmail: ${email}\nIP: ${req.realIp}`);CommonJS usage is equally simple:
const { createLogger } = require("@hiprax/logger");API
createLogger(options?: LoggerOptions)
| Option | Type | Default | Description |
| ---------------------- | --------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------- |
| moduleName | string | 'global' | Label used in log lines and for module-specific files. Supports nested scopes (security/failedLogins). |
| logDirectory | string | <process.cwd()>/logs | Target directory (auto-created). |
| level | LogLevel | 'info' | Default level for all transports. |
| consoleLevel | LogLevel | level | Console-specific level. |
| includeConsole | boolean | true | Enables console logging. Console lines omit timestamps; files keep the full multi-timezone output. |
| includeFile | boolean | true | Enables module-specific rotating file logging. |
| includeGlobalFile | boolean | true | Enables shared rotating file logging. |
| globalModuleName | string | 'all-logs' | Label for the shared log file. |
| extraTimezones | string \| string[] | [] | Additional IANA zones to render beside UTC. Validity is enforced. |
| rotation | RotationStrategy | 20 MB / 14 days / daily | Rotation config for the module file. |
| globalRotation | RotationStrategy | rotation | Override rotation for the shared file. |
| additionalTransports | winston.transport[] | [] | Appends custom transports (e.g., HTTP, Kafka). |
RotationStrategy
interface RotationStrategy {
maxSize?: string; // e.g., '20m', '200k'
maxFiles?: string; // e.g., '14d', '30'
datePattern?: string; // default: 'YYYY-MM-DD'
zippedArchive?: boolean;
}Request Logging Middleware
import express from "express";
import { createRequestLogger } from "@hiprax/logger";
const app = express();
app.use(express.json());
app.use(
createRequestLogger({
includeRequestBody: true,
includeRequestHeaders: ["authorization"],
includeResponseHeaders: true,
maskBodyKeys: ["password", "token"],
enrich: (req) => ({ tenantId: req.headers["x-tenant-id"] }),
}),
);When includeHttpContext is enabled, the middleware attaches rich structured metadata via info.http while emitting a concise human-readable message. It relies on plain Node events (finish/close) and does not depend on on-finished, keeping the surface secure and modern.
| Option | Type | Default | Description |
| ------------------------ | --------------------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------- |
| logger | winston.Logger | Scoped http logger | Provide your own logger or reuse the scoped one. |
| level | LogLevel \| (status: number) => LogLevel | Auto (info/warn/error) | Override severity per response. |
| label | string | 'http' | Included in the auto-generated logger name (http/<label>). |
| messageBuilder | (entry) => string | "METHOD URL status latency (event)" | Customize the final message string. |
| skip | (req, res) => boolean | false | Allowlist/denylist support. |
| enrich | (req, res, durationMs) => Record<string, unknown> | undefined | Inject extra context (e.g., tenant, user). |
| includeRequestHeaders | boolean \| string[] | false | Toggle or limit header emission. |
| includeResponseHeaders | boolean \| string[] | false | Same as above for responses. |
| includeRequestBody | boolean | false | Logs parsed body (with redaction). |
| maskBodyKeys | string[] | [] | Keys replaced with [REDACTED]. Applies deeply, including arrays. |
| maxBodyLength | number | 3000 | Caps serialized body size to prevent log floods. |
| includeHttpContext | boolean | false | Adds the structured payload under info.http. |
| loggingEnabled | boolean | true | Hard enable/disable switch. |
| loggingMode | RequestLoggingMode | 'always' | Env-aware control. Supports 'dev-only', 'prod-only', 'test-only', or custom rules. |
Environment-aware request logging
- Use
loggingMode: 'dev-only'to automatically log whenNODE_ENV,APP_ENV, orENVequalsdev,development, orlocal(case-insensitive). - Use
loggingMode: 'prod-only'to emit logs exclusively when the env matchesprod,production, orlive. - Use
loggingMode: 'test-only'to limit logging totest,testing,qa, orstaging. - Provide a custom configuration, e.g.:
loggingMode: { sources: ["DEPLOYMENT_STAGE"], allow: ["staging", "qa"], fallback: false } - Pair
loggingEnabledwith boolean expressions (loggingEnabled: process.env.FEATURE_LOGS === "on") for one-line toggles. - Keep log output lightweight unless needed by turning
includeHttpContexton only when you want the structured payload.
Timezone Handling
- UTC is always logged.
- Additional zones must be valid IANA identifiers (
moment-timezonevalidation). Invalid entries throwInvalidTimezoneError. - Provide a single string or an array:
extraTimezones: ['Europe/London', 'America/New_York'].
Custom Transports
import { PassThrough } from "node:stream";
import winston from "winston";
const capture = new PassThrough();
const logger = createLogger({
moduleName: "audit",
includeConsole: false,
includeFile: false,
includeGlobalFile: false,
additionalTransports: [new winston.transports.Stream({ stream: capture })],
});Scripts
| Command | Description |
| --------------- | ------------------------------------------------------ |
| npm run build | Generates dual ESM/CJS bundles plus type declarations. |
| npm test | Runs Jest with 100% coverage enforcement. |
Testing & Coverage
npm testts-jestcompiles TypeScript on the fly.- Coverage thresholds are locked at 100% global branches/functions/lines/statements.
Security Notes
- All filesystem interactions are sandboxed to the configured log directory.
- Timezones are validated against the Moment timezone database before use.
- Sensitive request payload fields can be masked recursively via
maskBodyKeys.
Contributing
- Clone the repo and install dependencies.
- Run
npm testto ensure the suite passes before submitting changes. - Follow the existing TypeScript, linting, and documentation patterns.
📄 License
MIT License - see LICENSE file for details.
