Package Exports
- @hemantwasthere/monitoring-sdk
- @hemantwasthere/monitoring-sdk/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@hemantwasthere/monitoring-sdk) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@hemantwasthere/monitoring-sdk
A comprehensive monitoring SDK for Node.js applications that provides seamless integration with Prometheus, Loki, and Grafana for metrics collection, logging, and observability.
Features
- 🚀 Easy Integration: Drop-in SDK for NestJS, Express, and pure Node.js applications
- 📊 Prometheus Metrics: Automatic HTTP request metrics, custom counters, gauges, and histograms
- 📝 Centralized Logging: Structured logging with Loki integration using Winston
- ⏱️ Cron Job Monitoring: Built-in decorators for monitoring scheduled tasks
- 🏷️ Consistent Labeling: Standardized labels across all metrics and logs
- 🔧 Global Configuration: Set common settings once and use across multiple services
- 🎯 Technology Agnostic: Works with different Node.js frameworks
Installation
npm install @hemantwasthere/monitoring-sdk
Quick Start
There are three ways to initialize the monitoring SDK, from simplest to most customized:
Method 1: Zero Configuration (Simplest)
Just set environment variables and use initializeWithDefaults()
:
# Set these environment variables
export LOKI_URL=http://your-monitoring-server:3100
export NODE_ENV=production
export CLUSTER_NAME=prod-cluster
export AWS_REGION=us-east-1
import { MonitoringSDK } from '@hemantwasthere/monitoring-sdk';
// Auto-configures from environment variables
const monitoring = MonitoringSDK.initializeWithDefaults({
projectName: 'my-project',
serviceName: 'user-service',
technology: 'nestjs'
});
Method 2: Global Configuration (Recommended)
Set up global configuration once at your application startup:
import { MonitoringSDK } from '@hemantwasthere/monitoring-sdk';
// Set global configuration once
MonitoringSDK.setGlobalConfig({
lokiHost: 'http://your-monitoring-server:3100',
environment: process.env.NODE_ENV || 'development',
logLevel: 'info',
customLabels: {
region: 'us-east-1',
cluster: 'prod-cluster'
}
});
// Now initialize each service without repeating common configuration
const monitoring = MonitoringSDK.initialize({
projectName: 'my-project',
serviceName: 'user-service',
technology: 'nestjs'
});
Method 3: Full Configuration (Most Control)
Configure everything explicitly for each service:
const monitoring = MonitoringSDK.initialize({
projectName: 'my-project',
serviceName: 'user-service',
technology: 'nestjs',
lokiHost: 'http://your-monitoring-server:3100',
environment: 'production',
logLevel: 'info',
customLabels: { region: 'us-east-1' }
});
Summary:
- Method 1: Perfect for microservices with consistent environment setup
- Method 2: Best for applications where you want explicit control over global config
- Method 3: Use when each service needs different configuration
Framework Integration
NestJS
import { MonitoringSDK, MonitoringInterceptor } from '@hemantwasthere/monitoring-sdk';
import { APP_INTERCEPTOR } from '@nestjs/core';
// In your main.ts
MonitoringSDK.setGlobalConfig({
lokiHost: 'http://monitoring-server:3100',
environment: process.env.NODE_ENV,
});
const monitoring = MonitoringSDK.initialize({
projectName: 'ecommerce',
serviceName: 'user-service',
technology: 'nestjs'
});
// In your AppModule
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: MonitoringInterceptor,
},
],
})
export class AppModule {}
// Add metrics endpoint
app.getHttpAdapter().get('/metrics', async (req, res) => {
const metrics = await monitoring.getMetrics().getMetrics();
res.setHeader('Content-Type', monitoring.getMetrics().getRegistry().contentType);
res.send(metrics);
});
// Add health endpoint
app.getHttpAdapter().get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
Express
import { MonitoringSDK, expressMetricsMiddleware, MonitoringController } from '@hemantwasthere/monitoring-sdk';
MonitoringSDK.setGlobalConfig({
lokiHost: 'http://monitoring-server:3100',
environment: process.env.NODE_ENV,
});
const monitoring = MonitoringSDK.initialize({
projectName: 'my-project',
serviceName: 'payment-service',
technology: 'express'
});
const app = express();
// Add metrics middleware
app.use(expressMetricsMiddleware());
// Add monitoring endpoints
const controller = new MonitoringController();
app.get('/metrics', (req, res) => controller.getMetrics(req, res));
app.get('/health', (req, res) => controller.getHealth(req, res));
Cron Job Monitoring
import { CronMonitor } from '@hemantwasthere/monitoring-sdk';
class DataProcessingService {
@CronMonitor.monitor('daily-report-generation')
async generateDailyReports() {
// Your cron job logic here
// Metrics will be automatically collected:
// - Execution duration
// - Success/failure counts
// - Error details if job fails
}
@CronMonitor.monitor('cleanup-old-data', { timeout: 30000 })
async cleanupOldData() {
// Job with custom timeout
}
}
Custom Metrics
const monitoring = MonitoringSDK.getInstance();
const metrics = monitoring.getMetrics();
// Counter
const orderCounter = metrics.createCounter('orders_total', 'Total orders processed', ['status', 'payment_method']);
orderCounter.inc({ status: 'completed', payment_method: 'credit_card' });
// Gauge
const activeUsers = metrics.createGauge('active_users', 'Number of active users');
activeUsers.set(150);
// Histogram
const responseTime = metrics.createHistogram('api_response_time', 'API response time', ['endpoint']);
responseTime.observe({ endpoint: '/api/users' }, 0.25);
Logging
const monitoring = MonitoringSDK.getInstance();
const logger = monitoring.getLogger();
logger.info('User logged in', {
userId: '12345',
correlationId: 'abc-123'
});
logger.error('Database connection failed', {
error: 'Connection timeout',
database: 'users-db'
});
Configuration Options
Global Configuration
interface GlobalMonitoringConfig {
lokiHost: string; // Loki server URL
environment?: string; // Environment name (dev, prod, etc.)
logLevel?: string; // Log level (info, debug, error)
customLabels?: Record<string, string>; // Labels added to all metrics/logs
}
Service Configuration
interface MonitoringConfig {
projectName: string; // Project/application name
serviceName: string; // Service name within the project
technology: string; // Technology stack (nestjs, express, nodejs)
environment?: string; // Override global environment
lokiHost?: string; // Override global Loki host
metricsPath?: string; // Custom metrics endpoint path
logLevel?: string; // Override global log level
enableDefaultMetrics?: boolean; // Enable Node.js default metrics
prefixDefaultMetrics?: boolean; // Prefix default metrics with project_service_
customLabels?: Record<string, string>; // Additional service-specific labels
}
Production Deployment
1. Docker Compose (Monitoring Stack)
Deploy the centralized monitoring stack:
# Clone the monitoring setup
git clone https://github.com/unwrap-labs/monitoring-setup.git
cd monitoring-setup/centralized-stack
# Start the monitoring stack
docker-compose up -d
This provides:
- Prometheus (metrics): http://localhost:9090
- Grafana (dashboards): http://localhost:3000
- Loki (logs): http://localhost:3100
- AlertManager (alerts): http://localhost:9093
2. Application Configuration
// Production configuration
MonitoringSDK.setGlobalConfig({
lokiHost: process.env.LOKI_URL || 'http://monitoring-cluster:3100',
environment: 'production',
logLevel: 'info',
customLabels: {
cluster: process.env.CLUSTER_NAME,
region: process.env.AWS_REGION,
version: process.env.APP_VERSION
}
});
3. Environment Variables
# .env
LOKI_URL=http://your-monitoring-cluster:3100
NODE_ENV=production
LOG_LEVEL=info
CLUSTER_NAME=prod-cluster
AWS_REGION=us-east-1
APP_VERSION=1.2.3
Collected Metrics
HTTP Metrics
http_request_duration_milliseconds
- Request response timeshttp_requests_total
- Total request count by method, route, status
Cron Job Metrics
cron_job_duration_seconds
- Job execution timecron_job_executions_total
- Total job executionscron_job_failures_total
- Failed job count
System Metrics (when enabled)
- Node.js process metrics (memory, CPU, GC)
- Event loop lag
- Heap usage
Best Practices
- Set Global Config Once: Use
setGlobalConfig()
at application startup - Consistent Naming: Use kebab-case for project and service names
- Meaningful Labels: Add relevant labels to metrics for better filtering
- Error Handling: Always handle monitoring errors gracefully
- Resource Cleanup: Monitoring shouldn't impact application performance
Troubleshooting
Common Issues
- Loki Connection Failed: Ensure Loki host is accessible and port 3100 is open
- Metrics Not Appearing: Check if
/metrics
endpoint is properly exposed - High Memory Usage: Reduce metric cardinality by limiting label values
Debug Mode
MonitoringSDK.setGlobalConfig({
logLevel: 'debug',
// ... other config
});
Contributing
We welcome contributions! Please see our Contributing Guide for details.
License
MIT - see LICENSE file for details.