pinqloq
v1.2.1
Published
Structured logging and log shipping SDK for Express — captures HTTP request/response logs and manual application events, and ships them to the Pinqloq log management platform.
Maintainers
Readme
Pinqloq (Node.js / Express)
Pinqloq is a structured logging and log shipping SDK for centralized application logs. It
captures HTTP request/response logs through Express middleware and sends manual application
events to the Pinqloq log management platform using in-memory buffering, batching, and HTTPS
delivery. This is the Node.js counterpart of the .NET pinqloq SDK —
same platform, same wire protocol, idiomatic API on each side.
Features
- Automatic Express request/response logging
- Correlation id read from the caller's header, falling back to a generated request id
- Name-based redaction of sensitive fields, headers, and whole endpoints
- Manual structured application events
- Buffered and batched HTTPS delivery
- Graceful shutdown flush
Requirements
- Node.js 18 or later
- Express 4 or 5
- A Pinqloq project and secret key
Installation
npm install pinqloqQuick Start
Store your secret key in an environment variable or a secret manager. Do not hardcode production credentials.
import express from "express";
import { createPinqloq } from "pinqloq";
const pinqloqClient = createPinqloq({
secretKey: process.env.PINQLOQ_SECRET_KEY!,
apiLogsCollectionName: "myapp_api_logs"
});
const app = express();
app.use(express.json());
// Mount AFTER body-parsing middleware so req.body is populated when the log is captured.
app.use(
pinqloqClient.requestLogging({
excludePaths: ["/health"]
})
);
app.listen(3000);
process.on("SIGTERM", async () => {
await pinqloqClient.shutdown();
process.exit(0);
});The middleware captures the HTTP method, path, and status code as searchable metadata. The
request body, response body, request headers, and response headers go to the log detail as
InputJson, OutputJson, RequestHeaders, and ResponseHeaders. Bodies are truncated at 32 KB.
Manual Logging
Use pinqloqClient.enqueue to send structured application events:
pinqloqClient.enqueue({
event: "order.created",
deviceIdentifier: order.customerId,
logLevel: PinqloqLogLevel.Information,
logSourceType: PinqloqLogSourceType.Backend,
metadata: { orderId: order.id }
});event is required on every entry.
deviceIdentifier is optional and has no global fallback: set it per entry, and an entry that
leaves it unset is stored without one.
pinqloqClient.logger still returns the same PinqloqLogger — useful when you want to pass just
the logging capability into a function without handing it the whole client (request logging,
shutdown, and all).
Add Request Metadata
By default the middleware reads the optional deviceIdentifier from the device-identifier
request header. Override how it is resolved with resolveDeviceIdentifier. The override wins; if
it returns undefined/blank, the middleware falls back to the device-identifier header. If
neither resolves a value, the log is stored without a deviceIdentifier.
app.use(
pinqloqClient.requestLogging({
excludePaths: ["/health"],
resolveDeviceIdentifier: (req) => req.user?.id,
resolveAppVersionName: (req) => req.header("x-app-version"),
metadata: {
userId: (req) => req.user?.id
}
})
);Use metadata for searchable values such as user and tenant IDs. Use detail for additional
drill-down information. The event key (the panel title) defaults to "{method} {path}" and can
be overridden via metadata.event.
Correlation ID
Every log carries a correlationId that ties together the records of a single request or flow.
The request-logging middleware fills it with no configuration: the caller's correlation-id
request header when present, otherwise a generated id.
pinqloqClient.enqueue({
event: "order.created",
deviceIdentifier: order.customerId,
correlationId: currentCorrelationId
});Redacting Sensitive Values
Request and response bodies and headers may contain credentials, tokens, or personal information. Unlike the .NET SDK's attribute-based redaction (which relies on C# reflection over typed DTOs — not available at runtime in TypeScript/Express), this SDK redacts by name:
redactFields— case-insensitive field/header names masked with*****REDACTED*****wherever they appear in a captured body or header, at any nesting depth.redactPaths— path prefixes (matched the same way asexcludePaths) where every value inInputJson,OutputJson,RequestHeaders, andResponseHeadersis masked, keeping the JSON structure and header names intact — the equivalent of the .NET SDK's[PinqloqRedactEndpoint].
app.use(
pinqloqClient.requestLogging({
redactFields: ["ssnLastFour"],
redactPaths: ["/payment"]
})
);A built-in, unconditional floor of common credential names (password, token, Authorization,
card numbers, ...) is always masked, even with no configuration — see
src/redaction/plan.ts for the full list.
Security and Reliability
Logs are buffered in memory and sent in batches. Buffered logs may be lost if the process is
terminated without a graceful shutdown — call pinqloqClient.shutdown() on SIGTERM/SIGINT.
Delivery failures are reported through onFailed callbacks and, even without callbacks, as
throttled console.error/console.warn output — never silently discarded, but also never
blocking. If your secret key is authorized for more than one collection, set
apiLogsCollectionName (or a per-entry collectionName); otherwise the batch is rejected.
Documentation
- .NET SDK — the reference implementation for this platform's wire protocol and feature set.
- Ruby SDK, Go SDK — the other implementations.
- Full documentation
License
MIT
