Package Exports
- @padfoot044/pepper-log
Readme
🌶️ PepperLog v3.0.2
Comprehensive OpenTelemetry observability with structured logging and distributed tracing for JavaScript/TypeScript frameworks. Now supports OTLP traces AND logs with automatic correlation.
✨ What's New in v3.0.0
- 📝 Structured Logging: Real logs sent to
/v1/logsendpoint (not just traces!) - 🔗 Trace-Log Correlation: Automatic correlation with trace/span IDs
- 🎯 Proper Separation: Traces appear in "Traces", Logs in "Logs" sections
- ⚡ Enhanced Performance: Batched exports for both traces and logs
- 🌐 Full OTLP Support: Complete OpenTelemetry Logs Protocol implementation
- 🧠 Smart Configuration: Auto-detects logs endpoint from traces endpoint
✨ Features
- 🚀 Universal Compatibility: Works in both browser and Node.js environments
- 🎯 Auto-Detection: Automatically detects frameworks (Angular, React, Vue, Next.js, Express, etc.)
- 🔌 Multiple Backends: SigNoz, Grafana, Datadog, Jaeger, New Relic, and more
- 🌐 Zero Browser Conflicts: Browser-optimized with no Node.js dependencies
- 📊 Complete Telemetry: Tracing, structured logging, and metrics in one package
- 🛡️ Error-Safe: Graceful degradation - your app continues even if telemetry fails
- 📝 TypeScript Support: Full TypeScript definitions included
🚀 Quick Start
Installation
npm install @padfoot044/pepper-logBasic Usage - Enhanced with Logging
import { PepperLog, LogLevel } from '@padfoot044/pepper-log';
// v3.0.0: Configure both traces AND logs
const logger = new PepperLog({
serviceName: 'my-awesome-app',
backend: 'signoz', // or 'grafana', 'jaeger', etc.
config: {
endpoint: 'http://localhost:4318/v1/traces', // Traces endpoint
logsEndpoint: 'http://localhost:4318/v1/logs', // Logs endpoint (NEW!)
},
features: {
tracing: true,
logging: true, // Enable structured logging
metrics: true,
autoInstrumentation: true
},
// Enhanced logging configuration
logging: {
enabled: true,
level: LogLevel.INFO,
enableCorrelation: true, // Auto-correlate logs with traces
consoleOutput: true
}
});
await logger.initialize();
// STRUCTURED LOGGING (NEW!) - Goes to "Logs" section
logger.info('User logged in', {
userId: '12345',
method: 'oauth',
duration: 150
});
logger.error('Payment failed', new Error('Insufficient funds'), {
userId: '12345',
amount: 99.99,
paymentMethod: 'credit_card'
});
// TRACING (Existing) - Goes to "Traces" section
await logger.traceFunction('process-payment', async () => {
// These logs are automatically correlated with the trace!
logger.info('Payment processing started', { amount: 99.99 });
// Your business logic here
await processPayment();
logger.info('Payment completed successfully');
return { success: true };
}, {
userId: '12345',
paymentAmount: 99.99
});What's Different in v3.0.0?
Before (v1.x) - Tracing Only:
// Everything went to "Traces" section
logger.info('message'); // Created a span, not a log
logger.error('error'); // Created a span, not a logNow (v3.0.0) - Proper Separation:
// Structured Logging → "Logs" section
logger.info('User action', { userId: '123' }); // Real log entry
logger.error('Error occurred', error, { context: 'payment' }); // Real log entry
// Tracing → "Traces" section
logger.traceFunction('operation', async () => { // Real span
logger.info('Step completed'); // Correlated log with trace ID!
});🎯 Framework Integration
Angular
import { Injectable } from '@angular/core';
import { PepperLog } from '@padfoot044/pepper-log';
@Injectable({ providedIn: 'root' })
export class TelemetryService {
private pepperLog = new PepperLog({
serviceName: 'angular-app',
backend: 'grafana'
});
async initialize() {
await this.pepperLog.initialize();
}
async traceUserAction(action: string, data?: any) {
return this.pepperLog.traceFunction(`user-${action}`, async () => {
// Your business logic
return { action, data, timestamp: Date.now() };
});
}
}React
import React, { useEffect } from 'react';
import { PepperLog } from '@padfoot044/pepper-log';
const telemetry = new PepperLog({
serviceName: 'react-app',
backend: 'signoz'
});
function App() {
useEffect(() => {
telemetry.initialize();
}, []);
const handleClick = async () => {
await telemetry.traceFunction('button-click', async () => {
console.log('Button clicked!');
});
};
return <button onClick={handleClick}>Click me</button>;
}Installation
npm install @padfoot044/pepper-log
# or
yarn add pepper-log
# or
pnpm add pepper-logBasic Usage
import { PepperLog } from '@padfoot044/pepper-log';
// Initialize with minimal configuration
const logger = new PepperLog({
serviceName: 'my-awesome-app',
backend: 'signoz',
config: {
endpoint: 'http://localhost:4318/v1/traces'
}
});
// Auto-detects framework and initializes everything
await logger.initialize();
// That's it! Your app is now instrumented 🎉Environment Variables (Alternative)
You can also configure PepperLog using environment variables:
PEPPER_LOG_SERVICE_NAME=my-app
PEPPER_LOG_BACKEND=signoz
PEPPER_LOG_ENDPOINT=http://localhost:4318/v1/tracesimport { PepperLog } from '@padfoot044/pepper-log';
// Uses environment variables
const logger = new PepperLog({
serviceName: process.env.PEPPER_LOG_SERVICE_NAME!,
backend: process.env.PEPPER_LOG_BACKEND as any,
config: {
endpoint: process.env.PEPPER_LOG_ENDPOINT
}
});
await logger.initialize();🎯 Supported Frameworks
PepperLog automatically detects and provides optimized instrumentation for:
| Framework | Auto-Detection | Custom Instrumentation |
|---|---|---|
| React | ✅ | Component lifecycle, route changes |
| Angular | ✅ | HTTP interceptors, route events |
| Vue.js | ✅ | Component lifecycle, Vue Router |
| Next.js | ✅ | Page transitions, API routes, SSR |
| Express | ✅ | Middleware, route handlers |
| Fastify | ✅ | Hooks, request lifecycle |
| Koa | ✅ | Middleware, context |
🔌 Supported Backends
SigNoz (Recommended for self-hosting)
const logger = new PepperLog({
serviceName: 'my-app',
backend: 'signoz',
config: {
endpoint: 'http://localhost:4318/v1/traces'
}
});Datadog
const logger = new PepperLog({
serviceName: 'my-app',
backend: 'datadog',
config: {
apiKey: process.env.DATADOG_API_KEY,
endpoint: 'https://trace.agent.datadoghq.com/v0.4/traces'
}
});Jaeger
const logger = new PepperLog({
serviceName: 'my-app',
backend: 'jaeger',
config: {
endpoint: 'http://localhost:14268/api/traces'
}
});New Relic
const logger = new PepperLog({
serviceName: 'my-app',
backend: 'newrelic',
config: {
apiKey: process.env.NEW_RELIC_LICENSE_KEY,
endpoint: 'https://otlp.nr-data.net/v1/traces'
}
});Grafana Cloud
const logger = new PepperLog({
serviceName: 'my-app',
backend: 'grafana',
config: {
apiKey: process.env.GRAFANA_CLOUD_API_KEY,
endpoint: 'https://tempo.grafana.net:443/v1/traces'
}
});Custom Backend
const logger = new PepperLog({
serviceName: 'my-app',
backend: 'custom',
config: {
endpoint: 'https://your-custom-otlp-endpoint.com/v1/traces',
headers: {
'Authorization': 'Bearer your-token'
}
}
});📖 Advanced Usage
Manual Instrumentation
// Create custom spans
const span = logger.createSpan('user.login', {
attributes: {
'user.id': '12345',
'user.email': 'user@example.com'
}
});
// Add attributes to current span
logger.addAttributes({
'custom.attribute': 'value',
'request.id': requestId
});
span.end();Function Tracing
// Automatically trace any function
const result = await logger.traceFunction(
'database.query',
async () => {
return await db.query('SELECT * FROM users');
},
{
'db.operation': 'select',
'db.table': 'users'
}
);Custom Metrics
// Create counters
const requestCounter = logger.createCounter(
'http.requests.total',
'Total number of HTTP requests'
);
// Create histograms
const responseTime = logger.createHistogram(
'http.request.duration',
'HTTP request duration in milliseconds'
);
// Use metrics
requestCounter.add(1, { method: 'GET', route: '/api/users' });
responseTime.record(150, { method: 'POST', route: '/api/auth' });Framework-Specific Features
React
// Automatically instruments:
// - Component render cycles
// - React Router navigation
// - State changes (with React DevTools)
const logger = new PepperLog({
serviceName: 'my-react-app',
backend: 'signoz',
config: { endpoint: 'http://localhost:4318/v1/traces' }
});Angular
// Automatically instruments:
// - HTTP client requests
// - Router events
// - Component lifecycle
const logger = new PepperLog({
serviceName: 'my-angular-app',
backend: 'signoz',
config: { endpoint: 'http://localhost:4318/v1/traces' }
});Express
// Automatically instruments:
// - All middleware
// - Route handlers
// - Database queries
// - HTTP client requests
const logger = new PepperLog({
serviceName: 'my-express-api',
backend: 'signoz',
config: { endpoint: 'http://localhost:4318/v1/traces' }
});⚙️ Configuration Options
interface PepperLogConfig {
/** Service name for tracing */
serviceName: string;
/** Backend service provider */
backend: 'signoz' | 'datadog' | 'jaeger' | 'newrelic' | 'grafana' | 'azure' | 'aws-xray' | 'custom';
/** Backend-specific configuration */
config: {
endpoint?: string;
apiKey?: string;
headers?: Record<string, string>;
batchConfig?: {
maxExportBatchSize?: number;
exportTimeoutMillis?: number;
scheduledDelayMillis?: number;
};
};
/** Optional framework override (auto-detected if not provided) */
framework?: 'react' | 'angular' | 'vue' | 'express' | 'nextjs' | 'fastify' | 'koa' | 'auto';
/** Enable/disable specific features */
features?: {
tracing?: boolean; // Default: true
metrics?: boolean; // Default: true
logging?: boolean; // Default: true
autoInstrumentation?: boolean; // Default: true
};
/** Environment (auto-detected if not provided) */
environment?: string;
/** Custom attributes added to all traces */
globalAttributes?: Record<string, string | number | boolean>;
}🔍 Auto-Detection
PepperLog uses multiple strategies to auto-detect your framework:
- Package.json Analysis: Scans dependencies for framework packages
- Runtime Detection: Checks for framework-specific global objects
- File Structure: Looks for framework-specific config files and folders
- Environment Variables: Checks for framework-specific environment variables
Detection Priority
- Next.js (highest priority - extends React)
- Angular
- React
- Vue.js
- Express/Fastify/Koa (Node.js frameworks)
📊 What Gets Instrumented
Automatic Instrumentation
- ✅ HTTP Requests: Incoming and outgoing HTTP calls
- ✅ Database Queries: PostgreSQL, MySQL, MongoDB, Redis
- ✅ File System: File read/write operations (configurable)
- ✅ DNS Lookups: DNS resolution timing
- ✅ Process Metrics: CPU, memory usage
Framework-Specific
React
- Component render cycles
- Route changes (React Router)
- State management operations
- Error boundaries
Angular
- HTTP interceptor traces
- Router navigation events
- Component lifecycle
- Service injections
Vue.js
- Component lifecycle hooks
- Vue Router navigation
- Vuex state changes
- Computed property evaluation
Express/Node.js
- Middleware execution
- Route handler performance
- Database connection pooling
- External API calls
🐛 Debugging
Enable debug mode to see what's happening:
const logger = new PepperLog({
serviceName: 'my-app',
backend: 'signoz',
config: {
endpoint: 'http://localhost:4318/v1/traces'
},
environment: 'development' // Enables debug logging
});
// Check what was detected
const framework = logger.getDetectedFramework();
console.log('Detected framework:', framework);
const config = logger.getConfig();
console.log('Final config:', config);🔧 Troubleshooting
Common Issues
Q: Framework not detected correctly
// Override auto-detection
const logger = new PepperLog({
framework: 'react', // Force specific framework
serviceName: 'my-app',
backend: 'signoz',
config: { endpoint: 'http://localhost:4318/v1/traces' }
});Q: Too much or too little instrumentation
const logger = new PepperLog({
serviceName: 'my-app',
backend: 'signoz',
config: { endpoint: 'http://localhost:4318/v1/traces' },
features: {
autoInstrumentation: false, // Disable auto-instrumentation
tracing: true, // Keep manual tracing
metrics: false // Disable metrics
}
});Q: Backend connection issues
// Test with a simple backend first
const logger = new PepperLog({
serviceName: 'my-app',
backend: 'jaeger',
config: {
endpoint: 'http://localhost:14268/api/traces'
}
});🤝 Contributing
We welcome contributions! See our Contributing Guide for details.
📄 License
MIT License - see LICENSE file for details.
🙏 Acknowledgments
- Built on top of OpenTelemetry
- Inspired by the need for easier observability in JavaScript applications
- Special thanks to the SigNoz, Jaeger, and OpenTelemetry communities
Made with ❤️ and 🌶️ by the PepperLog team