Node.js SDK
The Node.js SDK provides server-side logging for Node.js applications. Built on top of logstyx-js-core, it adds automatic device information collection, optional error capture, and automatic HTTP request logging for production environments.
Installation
npm install github:devatlogstyx/logstyx-js-node#releaseRequirements
Node.js version 18 or higher is required.
Quick Start
Manual Logging (Traditional)
const logstyx = require('logstyx-js-node')({
projectId: 'YOUR_PROJECT_ID',
apiKey: 'YOUR_API_KEY'
});
// Log events manually
logstyx.info({ message: 'User logged in', userId: 123 });
logstyx.error({ message: 'Payment failed', error: err.message });Auto-Instrumentation (Zero-Code Logging)
Automatically log all HTTP requests without manual logstyx.info() calls:
const logstyx = require('logstyx-js-node')({
projectId: 'YOUR_PROJECT_ID',
apiKey: 'YOUR_API_KEY',
autoInstrument: true // 🔥 Enable automatic logging
});
const express = require('express');
const app = express();
app.get('/api/orders', (req, res) => {
res.json({ orders: [] });
// ✅ Automatically logged: method, path, status, duration
});
app.listen(3000);No manual logging needed! All requests are automatically captured.
Configuration Options
Required Options
projectId (string)
Your Logstyx project identifier from the dashboard.
projectId: 'proj_abc123xyz'apiKey (string)
Your project's API key for HMAC signature authentication. Get this from your project settings.
apiKey: 'your_api_key_here'Keep API Keys Secret
Never commit API keys to version control or expose them in client-side code. Use environment variables:
apiKey: process.env.LOGSTYX_API_KEYOptional Options
endpoint (string)
The Logstyx API endpoint, should point to your self-hosted instance.
Default: https://api.logstyx.com/v1/logs
endpoint: 'https://logs.yourcompany.com/api/v1/logs'captureUncaught (boolean)
Enable automatic capture of uncaught exceptions. When enabled, uncaught errors are logged as critical before the process exits.
Default: false
captureUncaught: truecaptureUnhandledRejections (boolean)
Enable automatic capture of unhandled promise rejections. When enabled, unhandled rejections are logged as critical.
Default: false
captureUnhandledRejections: trueautoInstrument (boolean)
Enable automatic HTTP request logging. When enabled, all HTTP requests are automatically logged with method, path, status, duration, and more.
Default: false
autoInstrument: trueignorePaths (string[])
Array of paths to ignore when auto-instrumentation is enabled. Useful for health checks and metrics endpoints.
Default: ['/health', '/metrics']
ignorePaths: ['/health', '/metrics', '/favicon.ico']slowRequestThreshold (number)
Duration in milliseconds. Requests exceeding this threshold will be logged as WARNING instead of INFO.
Default: 1000 (1 second)
slowRequestThreshold: 2000 // 2 secondsredactFields (string[])
Array of field names to redact from request/response bodies and headers. Field values are replaced with [REDACTED].
Default: ['password', 'token', 'authorization', 'secret', 'apiKey', 'creditCard', 'ssn']
redactFields: ['password', 'token', 'authorization', 'secret', 'apiKey']contextHook (function)
Function that receives the Express/Fastify request object and returns additional context to include in every auto-logged request.
Default: null
contextHook: (req) => ({
tenantId: req.headers['x-tenant-id'],
environment: process.env.NODE_ENV,
version: process.env.APP_VERSION
})buildRequestPayload (function)
Custom function to build the request payload. Receives the request object and should return an object with the data you want to log.
Default: Built-in payload builder
buildRequestPayload: (req) => ({
method: req.method,
path: req.path,
ip: req.ip,
userId: req.user?.id
})Manual Logging
Perfect for logging custom business events, database operations, or any application-specific events.
Basic Usage
const logstyx = require('logstyx-js-node')({
projectId: 'YOUR_PROJECT_ID',
apiKey: 'YOUR_API_KEY',
endpoint: 'https://api.logstyx.com/v1/logs',
captureUncaught: true,
captureUnhandledRejections: true
});
// Send logs at different levels
logstyx.info({ message: 'This is an info log!' });
logstyx.warning({ message: 'This is a warning log!' });
logstyx.error({ message: 'This is an error log!' });
logstyx.critical({ message: 'System failure!' });Setting Context
Add persistent context that will be included in all subsequent logs:
// Add persistent context
logstyx.setContext({
userId: 123,
environment: 'production'
});
// All subsequent logs will include this context
logstyx.info({ message: 'User action' });
// Includes userId and environment
// Clear context when needed
logstyx.clearContext(['userId']); // Remove specific keys
logstyx.clearContext(); // Clear all contextAuto-Instrumentation
Automatically capture HTTP requests, responses, errors, and performance metrics without writing manual logging code.
Supported Frameworks
- ✅ Express - Fully supported
- ✅ Fastify - Fully supported
- 📜 Koa, Hapi, NestJS - Coming soon
Setup Method 1: Regular Setup
Important: Load Order Matters
Require logstyx-js-node BEFORE requiring Express/Fastify. The SDK needs to patch the framework modules before they are loaded.
// ✅ CORRECT: Logstyx first
const logstyx = require('logstyx-js-node')({
projectId: 'YOUR_PROJECT_ID',
apiKey: 'YOUR_API_KEY',
autoInstrument: true,
// Optional: Configure what to capture
ignorePaths: ['/health', '/metrics'],
// Ignore all successful GET requests to reduce noise
shouldIgnore: (req,res) => req.method === 'GET' && res.statusCode <=400 && !res.isSlow,
slowRequestThreshold: 1000,
redactFields: ['password', 'token', 'creditCard'],
// Add custom context to all auto-logged requests
contextHook: (req) => ({
tenantId: req.headers['x-tenant-id'],
orgId: req.user?.organizationId
})
});
// Then require your framework
const express = require('express');
const app = express();
app.get('/api/users', (req, res) => {
res.json({ users: [] }); // Auto-logged!
});
app.listen(3000);// ❌ WRONG: Framework loaded first won't work
const express = require('express'); // Already cached!
const logstyx = require('logstyx-js-node')({ autoInstrument: true });Setup Method 2: Using --require Flag (Recommended)
Use Node.js --require flag to ensure auto-instrumentation works regardless of require order:
node --require logstyx-js-node/register app.jspackage.json:
{
"scripts": {
"start": "node --require logstyx-js-node/register app.js",
"dev": "nodemon --require logstyx-js-node/register app.js"
}
}app.js (any order now works!):
const express = require('express');
const app = express();
// Configure logstyx anywhere
const logstyx = require('logstyx-js-node')({
projectId: 'YOUR_PROJECT_ID',
apiKey: 'YOUR_API_KEY',
autoInstrument: true
});
app.get('/api/orders', (req, res) => {
res.json({ orders: [] }); // Auto-logged!
});
app.listen(3000);What Gets Logged Automatically?
Auto-instrumentation logs requests at different levels based on status and performance:
- INFO: Successful requests (status 2xx)
- WARNING: Slow requests (duration >
slowRequestThreshold) - ERROR: Client errors (status 4xx)
- CRITICAL: Server errors (status 5xx)
Each log includes:
- HTTP method, path, URL
- Status code and response time
- IP address and user agent
- Request/response body (with field redaction)
- Headers (with field redaction)
- Query parameters and route params
- User context (if available via
req.user,req.session, etc.) - Custom context (via
contextHook)
Filtering Log Noise
To avoid hitting your log limits with high-traffic but low-value requests (like successful GETs for static data), use the shouldIgnore option:
const logstyx = require('logstyx-js-node')({
autoInstrument: true,
// This will NOT log: GET /api/data (200 OK)
// This WILL log: GET /api/data (500 Error)
// This WILL log: POST /api/data (200 OK)
shouldIgnore: (req,res) => req.method === 'GET' && res.statusCode <=400,
});Example auto-logged payload:
{
title: "GET /api/orders",
message: "Request completed successfully",
method: "GET",
url: "/api/orders",
path: "/api/orders",
ip: "192.168.1.1",
userAgent: "Mozilla/5.0...",
requestId: "abc-123",
user: { id: 456, email: "user@example.com" },
session: { id: "sess_xyz" },
query: { page: 1 },
params: {},
body: { /* request body with redacted fields */ },
response: { /* response body with redacted fields */ },
responseTime: 45,
statusCode: 200,
isSlow: false,
// Custom fields from contextHook
tenantId: "tenant_123",
environment: "production"
}Combining Auto + Manual Logging
You can use both auto-instrumentation and manual logging together for comprehensive coverage:
const logstyx = require('logstyx-js-node')({
projectId: 'YOUR_PROJECT_ID',
apiKey: 'YOUR_API_KEY',
autoInstrument: true,
// Add tenant context to all auto-logs
contextHook: (req) => ({
tenantId: req.headers['x-tenant-id']
})
});
const express = require('express');
const app = express();
app.post('/api/orders', async (req, res) => {
// HTTP request/response is auto-logged with tenantId
// Add custom business logic logs
logstyx.info({
title: 'Order processing started',
orderId: req.body.orderId
});
try {
const order = await processOrder(req.body);
res.json(order); // Auto-logged as INFO
} catch (error) {
// Custom error log with additional context
logstyx.error({
title: 'Order processing failed',
orderId: req.body.orderId,
error: error.message
});
throw error; // Also auto-logged as CRITICAL
}
});
app.listen(3000);Advanced: Custom Context Hook
The contextHook allows you to inject custom data into every auto-logged request:
const logstyx = require('logstyx-js-node')({
projectId: 'YOUR_PROJECT_ID',
apiKey: 'YOUR_API_KEY',
autoInstrument: true,
contextHook: (req) => {
return {
// Multi-tenant support
tenantId: req.headers['x-tenant-id'],
orgId: req.user?.organizationId,
// Environment info
environment: process.env.NODE_ENV,
version: process.env.APP_VERSION,
// Feature flags
features: req.user?.enabledFeatures || [],
// Request tracing
traceId: req.headers['x-trace-id'],
// Custom business context
subscription: req.user?.subscription?.tier
};
}
});All auto-logged requests will now include these custom fields alongside the standard request information.
Advanced: Custom Payload Builder
Override the entire request payload structure:
const logstyx = require('logstyx-js-node')({
projectId: 'YOUR_PROJECT_ID',
apiKey: 'YOUR_API_KEY',
autoInstrument: true,
buildRequestPayload: (req) => {
// Custom payload structure
return {
// Basic request info
method: req.method,
endpoint: req.path,
// Custom user detection
userId: req.user?.id || req.headers['x-user-id'],
// Custom session handling
sessionId: req.cookies?.sessionId,
// Include only specific headers
correlationId: req.headers['x-correlation-id'],
// Business-specific fields
storeId: req.headers['x-store-id'],
region: req.headers['x-region']
};
}
});Automatic Device Information
The Node.js SDK automatically collects and includes device information with every log:
{
type: "node",
origin: null,
os: "Linux", // os.type()
platform: "linux", // os.platform()
browser: null,
screen: null
}This information is automatically added to every log payload, helping you identify which server or environment generated the log.
Error Capture
Uncaught Exceptions
When captureUncaught is enabled, the SDK automatically captures and logs uncaught exceptions:
const logstyx = require('logstyx-js-node')({
projectId: 'proj_xyz',
apiKey: 'key_abc',
captureUncaught: true
});
// This error will be automatically logged as critical
throw new Error('Unexpected server error');
// Logged as:
// logstyx.critical({
// title: 'Error',
// message: 'Unexpected server error',
// stack: '...'
// });Process Exit
After logging an uncaught exception, the process will still exit. The SDK logs the error but doesn't prevent the default Node.js behavior.
Unhandled Promise Rejections
When captureUnhandledRejections is enabled, unhandled promise rejections are automatically logged:
const logstyx = require('logstyx-js-node')({
projectId: 'proj_xyz',
apiKey: 'key_abc',
captureUnhandledRejections: true
});
// This rejection will be automatically logged as critical
Promise.reject(new Error('Unhandled async error'));
// Logged as:
// logstyx.critical({
// title: 'Error',
// message: 'Unhandled async error',
// stack: '...'
// });Manual Error Logging
You can still manually log errors with additional context:
try {
await riskyOperation();
} catch (error) {
logstyx.error({
message: 'Operation failed',
operation: 'riskyOperation',
error: error.message,
stack: error.stack,
userId: currentUser.id
});
}API Methods
logstyx.info(data)
Log informational messages:
logstyx.info({
message: 'User authenticated',
userId: '12345',
method: 'oauth2'
});logstyx.warning(data)
Log warnings:
logstyx.warning({
message: 'High memory usage',
usage: process.memoryUsage().heapUsed,
threshold: 1024 * 1024 * 500
});logstyx.error(data)
Log errors:
logstyx.error({
message: 'Database query failed',
query: 'SELECT * FROM users',
error: err.message
});logstyx.critical(data)
Log critical issues:
logstyx.critical({
message: 'Payment processor unavailable',
service: 'stripe',
impact: 'All transactions blocked'
});logstyx.send(level, data)
Send a log with a custom level:
logstyx.send('INFO', { message: 'Custom log' });logstyx.setContext(context)
Set persistent context for all subsequent logs:
logstyx.setContext({
environment: process.env.NODE_ENV,
hostname: require('os').hostname(),
version: require('./package.json').version
});logstyx.clearContext(keys?)
Clear context:
// Clear specific keys
logstyx.clearContext(['requestId']);
// Clear all context
logstyx.clearContext();Complete Examples
Express with Auto-Instrumentation
const logstyx = require('logstyx-js-node')({
projectId: process.env.LOGSTYX_PROJECT_ID,
apiKey: process.env.LOGSTYX_API_KEY,
endpoint: 'https://logs.company.com/api/v1/logs',
autoInstrument: true,
ignorePaths: ['/health', '/metrics'],
slowRequestThreshold: 1000,
redactFields: ['password', 'token', 'creditCard'],
captureUncaught: true,
captureUnhandledRejections: true,
contextHook: (req) => ({
tenantId: req.headers['x-tenant-id'],
environment: process.env.NODE_ENV
})
});
const express = require('express');
const app = express();
app.use(express.json());
// Set application context
logstyx.setContext({
service: 'api-server',
version: '1.0.0'
});
// All requests are automatically logged
app.get('/api/users', async (req, res) => {
try {
const users = await fetchUsers();
res.json(users);
} catch (error) {
// Additional custom error log
logstyx.error({
message: 'Failed to fetch users',
error: error.message
});
res.status(500).json({ error: 'Failed to fetch users' });
}
});
app.post('/api/orders', async (req, res) => {
// Business logic logging
logstyx.info({
title: 'Order processing started',
orderId: req.body.orderId
});
try {
const order = await processOrder(req.body);
res.json(order);
} catch (error) {
logstyx.error({
title: 'Order processing failed',
orderId: req.body.orderId,
error: error.message
});
throw error;
}
});
app.listen(3000, () => {
logstyx.info({
message: 'Server started',
port: 3000
});
});Manual Logging Only
const logstyx = require('logstyx-js-node')({
projectId: process.env.LOGSTYX_PROJECT_ID,
apiKey: process.env.LOGSTYX_API_KEY,
endpoint: 'https://logs.company.com/api/v1/logs',
captureUncaught: true,
captureUnhandledRejections: true
});
const express = require('express');
const app = express();
// Set application context
logstyx.setContext({
environment: process.env.NODE_ENV,
service: 'api-server',
version: '1.0.0'
});
// Manual request logging middleware
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
logstyx.info({
message: 'HTTP request',
method: req.method,
path: req.path,
statusCode: res.statusCode,
duration: Date.now() - start
});
});
next();
});
// Error handling middleware
app.use((err, req, res, next) => {
logstyx.error({
message: 'Request error',
error: err.message,
stack: err.stack,
method: req.method,
path: req.path
});
res.status(500).json({ error: 'Internal server error' });
});
app.listen(3000, () => {
logstyx.info({
message: 'Server started',
port: 3000
});
});Best Practices
Use Environment Variables
Store credentials in environment variables:
// .env file
LOGSTYX_PROJECT_ID=proj_abc123
LOGSTYX_API_KEY=key_xyz789
LOGSTYX_ENDPOINT=https://logs.company.com/api/v1/logs
NODE_ENV=production
// app.js
require('dotenv').config();
const logstyx = require('logstyx-js-node')({
projectId: process.env.LOGSTYX_PROJECT_ID,
apiKey: process.env.LOGSTYX_API_KEY,
endpoint: process.env.LOGSTYX_ENDPOINT
});Enable Auto-Instrumentation in Production
Use auto-instrumentation to capture all HTTP traffic automatically:
const logstyx = require('logstyx-js-node')({
projectId: process.env.LOGSTYX_PROJECT_ID,
apiKey: process.env.LOGSTYX_API_KEY,
autoInstrument: process.env.NODE_ENV === 'production',
captureUncaught: process.env.NODE_ENV === 'production',
captureUnhandledRejections: process.env.NODE_ENV === 'production'
});Set Application Context
Provide context that helps identify logs:
logstyx.setContext({
environment: process.env.NODE_ENV,
hostname: require('os').hostname(),
service: 'payment-api',
version: require('./package.json').version,
region: process.env.AWS_REGION
});Structure Your Logs
Use consistent structure for better searchability:
// ❌ Avoid
logstyx.info('User john@example.com logged in');
// ✅ Better
logstyx.info({
message: 'User logged in',
email: 'john@example.com',
timestamp: Date.now()
});Log Performance Metrics
Track performance of operations:
async function processPayment(order) {
const start = Date.now();
try {
const result = await stripe.charge(order);
logstyx.info({
message: 'Payment processed',
orderId: order.id,
amount: order.amount,
duration: Date.now() - start,
success: true
});
return result;
} catch (error) {
logstyx.error({
message: 'Payment failed',
orderId: order.id,
amount: order.amount,
duration: Date.now() - start,
error: error.message
});
throw error;
}
}Avoid Logging Sensitive Data
Never log passwords, tokens, or PII. Use the redactFields option:
const logstyx = require('logstyx-js-node')({
projectId: 'YOUR_PROJECT_ID',
apiKey: 'YOUR_API_KEY',
autoInstrument: true,
redactFields: [
'password',
'token',
'authorization',
'secret',
'apiKey',
'creditCard',
'ssn',
'socialSecurity'
]
});// ❌ Dangerous
logstyx.info({
user: {
email: user.email,
password: user.password, // Never log passwords!
creditCard: user.card // Never log credit cards!
}
});
// ✅ Safe
logstyx.info({
message: 'User updated',
userId: user.id,
email: user.email,
action: 'profile_update'
});Use Appropriate Log Levels
Choose the right level for each log:
info: Normal operations, state changes, important eventswarning: Potential issues, deprecated features, high resource usageerror: Failures that were handled, retryable errorscritical: System failures, unhandled errors, service outages
// Info: Normal operation
logstyx.info({ message: 'Cache refreshed', entries: 1000 });
// Warning: Concerning but not broken
logstyx.warning({
message: 'Response time high',
duration: 2000,
threshold: 1000
});
// Error: Something failed but was handled
logstyx.error({
message: 'Email delivery failed',
recipient: 'user@example.com',
retry: true
});
// Critical: System-level failure
logstyx.critical({
message: 'Database connection lost',
database: 'production-db',
impact: 'All writes blocked'
});Troubleshooting
Auto-instrumentation not working?
Check load order:
- Make sure
logstyx-js-nodeis required BEFORE Express/Fastify - Or use
--require logstyx-js-node/registerflag
node --require logstyx-js-node/register app.jsLogs not appearing?
- Verify
projectIdandapiKeyare correct - Check network connectivity to the endpoint
- Look for console errors
- Ensure the path isn't in
ignorePaths
Too many logs?
- Add paths to ignore:
ignorePaths: ['/health', '/metrics', '/favicon.ico', '/static/*']- Filter by Method/Status: Use the shouldIgnore hook to silence successful GET requests while maintaining visibility on errors
// Silence successful & fast GETs only
shouldIgnore: (req,res) => req.method === 'GET' && res.statusCode <=400 && !res.isSlow,Sensitive data in logs?
Add fields to redact:
redactFields: ['password', 'ssn', 'creditCard', 'apiKey', 'token']