See every request. Capture every error. Understand your application.
Cipher Logger is a lightweight, production-ready HTTP logging library for Node.js. It captures every request in Express and Next.js applications. You decide exactly which fields appear in each log — required fields are always recorded, optional fields are opt-in.
- Features
- Installation
- Quick Start
- Configuration
- Express
- Next.js
- Log Schema
- API Reference
- Architecture
- Local Development
- Contributing
- License
- TypeScript-first — full type coverage across the entire API
- Configurable fields — fine-grained control over optional log fields
- Express middleware — records real
statusanddurationafter the response finishes - Next.js middleware — drop-in support for
middleware.ts - Zero heavy dependencies — only
expressornextas optional peer dependencies - Node.js 18+ compatible
npm install cipher-logger
# or
pnpm add cipher-logger
# or
yarn add cipher-loggerInstall the framework you use:
# Express
npm install express
# Next.js
npm install nextimport { createCipherLogger } from "cipher-logger";
const cipher = createCipherLogger({
fields: {
ip: true,
userAgent: true,
query: true,
},
level: "info",
});import { createCipherLogger } from "cipher-logger";
const cipher = createCipherLogger({
// Optional fields — default: false (disabled)
fields: {
ip: true,
userAgent: true,
referer: false,
protocol: true,
host: true,
query: true,
requestId: true,
metadata: false,
},
// Log level: debug | info | warn | error
level: "info",
// Optional prefix in console output
prefix: "api",
});| Option | Type | Default | Description |
|---|---|---|---|
fields |
Partial<Record<OptionalRequestField, boolean>> |
all false |
Optional log fields to include |
level |
"debug" | "info" | "warn" | "error" |
"debug" |
Minimum log level |
prefix |
string |
— | Prefix in console output |
import express from "express";
import { createCipherLogger } from "cipher-logger";
const app = express();
const cipher = createCipherLogger({
fields: {
ip: true,
userAgent: true,
query: true,
requestId: true,
},
level: "info",
prefix: "express",
});
// Mount before your routes
app.use(cipher.express());
app.get("/users", (req, res) => {
res.json({ users: [] });
});
app.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});[2026-09-01T20:00:00.000Z] [INFO] [express] HTTP Request {
id: 'a1b2c3d4-...',
type: 'http',
timestamp: '2026-09-01T20:00:00.000Z',
method: 'GET',
path: '/users?page=1',
status: 200,
duration: 12,
ip: '::1',
userAgent: 'Mozilla/5.0 ...',
query: { page: '1' }
}
In Express,
statusanddurationare recorded afterres.finishand reflect the actual response.
Create middleware.ts at the project root (or src/middleware.ts):
import { createCipherLogger } from "cipher-logger";
import type { NextRequest } from "next/server";
const cipher = createCipherLogger({
fields: {
ip: true,
userAgent: true,
host: true,
query: true,
},
level: "info",
});
export function middleware(request: NextRequest) {
return cipher.next()(request);
}
export const config = {
matcher: [
/*
* Match all routes except static files and images
*/
"/((?!_next/static|_next/image|favicon.ico).*)",
],
};Or more concisely:
import { createCipherLogger } from "cipher-logger";
const cipher = createCipherLogger({
fields: { ip: true, userAgent: true },
});
export default cipher.next();
export const config = {
matcher: ["/api/:path*", "/dashboard/:path*"],
};Note: Next.js middleware runs before the route handler, so
statusanddurationreflect the middleware execution, not the final route response. Route handler wrappers for more accurate logging are planned for future releases.
Always included in every HTTP log:
| Field | Type | Description |
|---|---|---|
id |
string |
Unique identifier (UUID) |
type |
"http" |
Log type |
timestamp |
string |
ISO 8601 timestamp |
method |
string |
HTTP method |
path |
string |
Request path |
status |
number |
HTTP status code |
duration |
number |
Duration in milliseconds |
Enabled via the fields config:
| Field | Type | Description |
|---|---|---|
ip |
string |
Client IP address |
userAgent |
string |
User-Agent header |
referer |
string |
Referer header |
protocol |
string |
Protocol (http / https) |
host |
string |
Host header |
query |
Record<string, string> |
Query string parameters |
requestId |
string |
From x-request-id header |
metadata |
Record<string, unknown> |
Custom metadata |
Creates a Cipher Logger instance.
const cipher = createCipherLogger(config);Methods:
| Method | Description |
|---|---|
cipher.logRequest(input) |
Manually log an HTTP request |
cipher.express() |
Returns Express middleware |
cipher.next() |
Returns Next.js middleware |
Base logging class (independent of HTTP):
import { Logger } from "cipher-logger";
const logger = new Logger({ level: "info", prefix: "app" });
logger.info("Server started");
logger.warn("Deprecated API used", { route: "/old" });
logger.error("Unhandled error", { err: "..." });
logger.debug("Debug info");import type {
CipherLogger,
CipherLoggerConfig,
RequestLog,
RequestLogInput,
OptionalRequestField,
LogLevel,
LoggerOptions,
ExpressMiddleware,
NextMiddleware,
} from "cipher-logger";cipher-logger/
├── src/
│ ├── core/ # Core — field config & log building
│ │ ├── logger.ts
│ │ ├── types.ts
│ │ ├── build-request-log.ts
│ │ └── create-cipher-logger.ts
│ ├── express/ # Express adapter
│ │ └── middleware.ts
│ ├── next/ # Next.js adapter
│ │ └── middleware.ts
│ └── index.ts # Public entry point
┌─────────────────────────────────────────┐
│ Core │
│ fields config → buildRequestLog │
└──────────────────┬──────────────────────┘
│
┌─────────┴─────────┐
▼ ▼
┌───────────┐ ┌───────────┐
│ Express │ │ Next.js │
│ middleware│ │ middleware│
└───────────┘ └───────────┘
git clone https://github.com/cipherunits/CipherLogger.git
cd CipherLogger
pnpm install
pnpm run buildContributions are welcome and appreciated.
- Check Issues first
- If no existing issue matches, open a new one with a clear description
- Fork the repository
- Create a branch:
git checkout -b feature/my-feature - Commit your changes:
git commit -m "feat: add something useful" - Push the branch:
git push origin feature/my-feature - Open a Pull Request
- Use Conventional Commits for commit messages
- Run
pnpm run buildbefore submitting a PR - Keep changes focused and scoped
- Update the README for any API changes
- GitHub Issues: cipherunits/CipherLogger/issues
- Organization: CipherUnits
MIT © Cipher Unit
Built by Cipher Unit