Examples
Real-world usage patterns for @nextrush/log.
Table of Contents
- Enterprise Setup (500+ Files)
- Express.js API
- Next.js Application
- Microservice
- CLI Application
- Worker/Background Jobs
- Browser Application
- React Application
Enterprise Setup (500+ Files)
For large applications, set up centralized logging configuration.
1. Create Logger Configuration
typescript
// src/lib/logger.ts
import {
configure,
configureFromEnv,
createLogger,
addGlobalTransport,
enableNamespaces,
} from '@nextrush/log';
/**
* Initialize logging for the entire application.
* Call once at app startup.
*/
export function initializeLogging() {
// Read from environment variables
configureFromEnv((name) => process.env[name]);
// Or configure explicitly
configure({
enabled: process.env.NODE_ENV !== 'test',
minLevel: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
env: process.env.NODE_ENV as 'development' | 'production',
});
// In production, only log from important modules
if (process.env.NODE_ENV === 'production') {
enableNamespaces(['api:*', 'auth:*', 'payments:*', 'critical:*']);
}
// Send errors to monitoring service
addGlobalTransport((entry) => {
if (entry.level === 'error' || entry.level === 'fatal') {
sendToErrorTracking(entry);
}
});
}
// Re-export for use across the app
export { createLogger };
// Pre-configured loggers for common modules
export const apiLog = createLogger('api');
export const authLog = createLogger('auth');
export const dbLog = createLogger('db');2. Initialize at App Start
typescript
// src/index.ts
import { initializeLogging } from './lib/logger';
initializeLogging();
// ... rest of your app3. Use in Any File
typescript
// src/features/users/service.ts
import { createLogger } from '@/lib/logger';
const log = createLogger('api:users');
export async function createUser(data: UserData) {
log.info('Creating user', { email: data.email });
// ...
}4. Feature-Based Logger Organization
src/
├── lib/
│ └── logger.ts # Central config
├── features/
│ ├── users/
│ │ ├── logger.ts # const log = createLogger('users')
│ │ ├── service.ts # import { log } from './logger'
│ │ └── routes.ts
│ ├── orders/
│ │ ├── logger.ts
│ │ └── service.ts
│ └── payments/
│ ├── logger.ts
│ └── service.ts5. Debug Mode in Production
typescript
// Add to window for debugging
if (typeof window !== 'undefined') {
(window as any).__debug = {
enableLogs: () => {
import('@nextrush/log').then(({ enableLogging, setGlobalLevel }) => {
enableLogging();
setGlobalLevel('debug');
console.log('✅ Logging enabled');
});
},
disableLogs: () => {
import('@nextrush/log').then(({ disableLogging }) => {
disableLogging();
console.log('❌ Logging disabled');
});
},
showConfig: () => {
import('@nextrush/log').then(({ getGlobalConfig }) => {
console.log(getGlobalConfig());
});
},
};
}
// Usage in browser console:
// __debug.enableLogs()
// __debug.disableLogs()
// __debug.showConfig()Express.js API
Setup
typescript
// src/logger.ts
import { createLogger } from '@nextrush/log';
export const log = createLogger('API', {
metadata: {
service: 'user-api',
version: process.env.npm_package_version,
},
});Request Logging Middleware
typescript
// src/middleware/logger.ts
import { log } from '../logger';
export function requestLogger(req, res, next) {
const correlationId = req.headers['x-request-id'] || crypto.randomUUID();
const requestLog = log.withCorrelationId(correlationId);
req.log = requestLog;
res.setHeader('x-correlation-id', correlationId);
const timer = requestLog.time();
res.on('finish', () => {
timer.end('Request completed', {
method: req.method,
path: req.path,
status: res.statusCode,
});
});
next();
}Route Handlers
typescript
// src/routes/users.ts
import express from 'express';
const router = express.Router();
router.get('/:id', async (req, res) => {
const { log } = req;
const { id } = req.params;
log.info('Fetching user', { userId: id });
try {
const user = await db.users.findById(id);
if (!user) {
log.warn('User not found', { userId: id });
return res.status(404).json({ error: 'Not found' });
}
log.debug('User found', { userId: id });
res.json(user);
} catch (error) {
log.error('Failed to fetch user', { userId: id }, error);
res.status(500).json({ error: 'Internal error' });
}
});
export default router;Error Handler
typescript
// src/middleware/error.ts
import { log } from '../logger';
export function errorHandler(error, req, res, next) {
const requestLog = req.log || log;
requestLog.error('Unhandled error', {
method: req.method,
path: req.path,
}, error);
res.status(500).json({ error: 'Internal server error' });
}Next.js Application
Shared Logger
typescript
// lib/logger.ts
import { createLogger } from '@nextrush/log';
export const log = createLogger('MyApp', {
metadata: { version: process.env.NEXT_PUBLIC_VERSION },
});Server Actions
typescript
// app/actions.ts
'use server';
import { log } from '@/lib/logger';
import { headers } from 'next/headers';
export async function createPost(formData: FormData) {
const headersList = await headers();
const requestId = headersList.get('x-request-id') || crypto.randomUUID();
const actionLog = log.withCorrelationId(requestId);
actionLog.info('Creating post');
try {
const title = formData.get('title');
const post = await db.posts.create({ title });
actionLog.info('Post created', { postId: post.id });
return { success: true, post };
} catch (error) {
actionLog.error('Failed to create post', error);
return { success: false, error: 'Failed to create post' };
}
}API Routes
typescript
// app/api/users/route.ts
import { log } from '@/lib/logger';
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const correlationId = request.headers.get('x-request-id') || crypto.randomUUID();
const routeLog = log.withCorrelationId(correlationId);
routeLog.info('Fetching users');
try {
const users = await db.users.findMany();
routeLog.debug('Users fetched', { count: users.length });
return NextResponse.json(users, {
headers: { 'x-correlation-id': correlationId },
});
} catch (error) {
routeLog.error('Failed to fetch users', error);
return NextResponse.json({ error: 'Internal error' }, { status: 500 });
}
}Middleware
typescript
// middleware.ts
import { log } from '@/lib/logger';
import { NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
const correlationId = request.headers.get('x-request-id') || crypto.randomUUID();
log.info('Request', {
method: request.method,
path: request.nextUrl.pathname,
correlationId,
});
const response = NextResponse.next();
response.headers.set('x-correlation-id', correlationId);
return response;
}Microservice
Logger with Service Context
typescript
// src/logger.ts
import { createLogger, createBatchTransport } from '@nextrush/log';
const log = createLogger('OrderService', {
metadata: {
service: 'order-service',
version: process.env.VERSION,
instance: process.env.HOSTNAME,
region: process.env.AWS_REGION,
},
});
// Send logs to centralized logging
const { transport, flush } = createBatchTransport(
async (entries) => {
await fetch(process.env.LOG_COLLECTOR_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(entries),
});
},
{ batchSize: 100, flushInterval: 1000 }
);
log.addTransport(transport);
// Graceful shutdown
process.on('SIGTERM', async () => {
log.info('Shutting down');
await flush();
process.exit(0);
});
export { log };Event Handling
typescript
// src/handlers/order-created.ts
import { log } from '../logger';
export async function handleOrderCreated(event: OrderCreatedEvent) {
const handlerLog = log
.withCorrelationId(event.correlationId)
.withMetadata({ orderId: event.orderId });
handlerLog.info('Processing order');
const timer = handlerLog.time('order-processing');
try {
await validateOrder(event.order);
handlerLog.debug('Order validated');
await reserveInventory(event.order);
handlerLog.debug('Inventory reserved');
await processPayment(event.order);
handlerLog.debug('Payment processed');
timer.end('Order processed successfully');
} catch (error) {
timer.end('Order processing failed');
handlerLog.error('Failed to process order', error);
throw error;
}
}CLI Application
Setup with Verbosity Levels
typescript
// src/cli.ts
import { createLogger } from '@nextrush/log';
import { program } from 'commander';
function createCliLogger(verbose: boolean) {
return createLogger('CLI', {
minLevel: verbose ? 'debug' : 'info',
pretty: true,
});
}
program
.option('-v, --verbose', 'Enable verbose output')
.action(async (options) => {
const log = createCliLogger(options.verbose);
log.info('Starting build');
log.debug('Build configuration', { options });
try {
const timer = log.time('build');
await runBuild();
timer.end('Build completed');
} catch (error) {
log.error('Build failed', error);
process.exit(1);
}
});
program.parse();Worker/Background Jobs
Job Processing Logger
typescript
// src/worker.ts
import { createLogger } from '@nextrush/log';
const workerLog = createLogger('Worker', {
metadata: { workerId: process.env.WORKER_ID },
});
export async function processJob(job: Job) {
const jobLog = workerLog.withMetadata({
jobId: job.id,
jobType: job.type,
attempt: job.attemptNumber,
});
jobLog.info('Job started');
const timer = jobLog.time();
try {
switch (job.type) {
case 'email':
await sendEmail(job.data);
break;
case 'report':
await generateReport(job.data);
break;
default:
throw new Error(`Unknown job type: ${job.type}`);
}
timer.end('Job completed');
} catch (error) {
timer.end('Job failed');
jobLog.error('Job execution failed', error);
throw error;
}
}Queue Event Logging
typescript
// src/queue.ts
import { log } from './logger';
queue.on('completed', (job, result) => {
log.info('Job completed', { jobId: job.id, jobType: job.type });
});
queue.on('failed', (job, error) => {
log.error('Job failed', { jobId: job.id, jobType: job.type }, error);
});
queue.on('stalled', (job) => {
log.warn('Job stalled', { jobId: job.id, jobType: job.type });
});Browser Application
Setup
typescript
// src/logger.ts
import { createLogger, createBatchTransport } from '@nextrush/log';
const log = createLogger('App', {
minLevel: import.meta.env.PROD ? 'warn' : 'debug',
});
// Send errors to backend in production
if (import.meta.env.PROD) {
const { transport } = createBatchTransport(
async (entries) => {
const errors = entries.filter(e => e.level === 'error' || e.level === 'fatal');
if (errors.length === 0) return;
await fetch('/api/client-logs', {
method: 'POST',
body: JSON.stringify(errors),
});
},
{ batchSize: 5, flushInterval: 10000 }
);
log.addTransport(transport);
}
export { log };Usage
typescript
// src/api.ts
import { log } from './logger';
export async function fetchUser(id: string) {
const apiLog = log.child('API');
apiLog.debug('Fetching user', { userId: id });
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
apiLog.error('API error', { status: response.status, userId: id });
throw new Error(`HTTP ${response.status}`);
}
return response.json();
} catch (error) {
apiLog.error('Failed to fetch user', { userId: id }, error);
throw error;
}
}React Application
Provider Setup
tsx
// src/App.tsx
import { LogProvider, LogErrorBoundary } from '@nextrush/log/react';
export default function App() {
return (
<LogProvider
context="MyApp"
options={{ minLevel: import.meta.env.PROD ? 'warn' : 'debug' }}
>
<LogErrorBoundary fallback={<ErrorPage />}>
<Router />
</LogErrorBoundary>
</LogProvider>
);
}Component Logging
tsx
// src/components/UserProfile.tsx
import { useLogger } from '@nextrush/log/react';
import { useEffect, useState } from 'react';
export function UserProfile({ userId }) {
const log = useLogger('UserProfile');
const [user, setUser] = useState(null);
useEffect(() => {
log.debug('Loading user', { userId });
fetchUser(userId)
.then((data) => {
log.debug('User loaded', { userId });
setUser(data);
})
.catch((error) => {
log.error('Failed to load user', { userId }, error);
});
}, [userId, log]);
return user ? <div>{user.name}</div> : <div>Loading...</div>;
}Custom Hook with Logging
tsx
// src/hooks/useApi.ts
import { useLogger } from '@nextrush/log/react';
import { useState, useCallback } from 'react';
export function useApi<T>(endpoint: string) {
const log = useLogger('useApi');
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const execute = useCallback(async () => {
setLoading(true);
setError(null);
log.debug('Fetching', { endpoint });
try {
const response = await fetch(endpoint);
const result = await response.json();
log.debug('Fetch complete', { endpoint });
setData(result);
return result;
} catch (err) {
log.error('Fetch failed', { endpoint }, err);
setError(err as Error);
throw err;
} finally {
setLoading(false);
}
}, [endpoint, log]);
return { data, loading, error, execute };
}