@loglito/loglito
v0.1.32
Published
JavaScript/TypeScript client library for Loglito logging service
Maintainers
Readme
@loglito/loglito
The official JavaScript/TypeScript client library for Loglito, a powerful logging and observability platform designed for solo developers.
Features
- 🚀 High Performance - Intelligent buffering with configurable flush intervals
- 🔄 Auto-Retry - Built-in retry logic with exponential backoff
- 📝 Multiple Calling Patterns - Flexible API supporting various usage styles
- 🧪 TypeScript Support - Full TypeScript definitions included
- 🌐 Universal - Works in Node.js and modern browsers
- 📦 Batch Logging - Send multiple logs in a single request
- ⚡ Immediate Mode - Option for real-time logging without buffering
- 🛡️ Error Handling - Comprehensive error types for different scenarios
- 🔍 Trace Functionality - Group related logs with trace IDs for better debugging
Installation
npm install @loglito/loglitoyarn add @loglito/loglitoQuick Start
import { Loglito } from '@loglito/loglito';
// Initialize the client with your API key
const loglito = new Loglito({
apiKey: 'your-api-key-here',
project: 'my_awesome_project' // Optional: project name added as __project_name to all logs
});
// Simple logging
await loglito.log('Hello world!');
// Level, message, and data
await loglito.log('info', 'User subscribed', {
user_id: 123,
plan: 'premium'
});
// NEW: Convenient shortcut methods for different log levels
await loglito.info('User logged in', { user_id: 2132 });
await loglito.debug('API response', { status: 200, endpoint: '/users' });
await loglito.warning('Rate limit approaching', { current_usage: 85, limit: 100 });
await loglito.error('Database connection failed', { error: 'timeout', retries: 3 });
// Traditional structured logging
await loglito.log({
message: 'User logged in',
data: {
username: 'john',
ip_address: '192.168.1.1'
}
});
// Log with specific level
await loglito.log('warning', 'Low disk space', {
disk_usage: '85%',
server: 'web-01'
});
// Trace functionality - group related logs
loglito.setTrace('request-123');
await loglito.info('Request started', { endpoint: '/api/users' });
await loglito.debug('Database query executed', { time: 23.5 });
await loglito.info('Request completed', { status: 200 });
loglito.clearTrace(); // Clear trace for next operationShortcut Methods
For convenience, the client provides shortcut methods for common log levels:
import { Loglito } from '@loglito/loglito';
const loglito = new Loglito({ apiKey: 'your-api-key' });
// Info level logging
await loglito.info('User logged in', { user_id: 2132 });
// Debug level logging
await loglito.debug('SQL query executed', {
query: 'SELECT * FROM users WHERE id = ?',
params: [123],
execution_time: 0.045
});
// Warning level logging
await loglito.warning('Rate limit approaching', {
current_usage: 85,
limit: 100,
user_id: 456
});
// Error level logging
await loglito.error('Payment processing failed', {
error: 'card_declined',
order_id: 'ORD-789',
amount: 99.99
});
// The data parameter is optional
await loglito.info('Application started');
await loglito.debug('Cache miss');Configuration
Basic Configuration
import { Loglito } from '@loglito/loglito';
const loglito = new Loglito({
apiKey: 'your-api-key',
baseUrl: 'https://api.loglito.io', // Custom API endpoint
timeout: 30000, // Request timeout in milliseconds
retries: 3, // Number of retry attempts
verifySsl: true // SSL certificate verification
});Performance Configuration (Buffering)
The client uses intelligent buffering for optimal performance:
const loglito = new Loglito({
apiKey: 'your-api-key',
bufferSize: 100, // Flush after 100 logs
flushInterval: 2000, // Flush every 2 seconds
immediateMode: false // Use buffering (default)
});
// For real-time logging (no buffering)
const loglitoImmediate = new Loglito({
apiKey: 'your-api-key',
immediateMode: true
});Project Parameter
You can set a project name that will be automatically added as __project_name to all log entries:
// Project parameter - adds __project_name to all logs
const loglito = new Loglito({
apiKey: 'your-api-key',
project: 'my_awesome_project'
});
await loglito.log('User login');
// Results in: {"__message": "User login", "__project_name": "my_awesome_project", ...}Default Data
You can also configure default data that will be automatically included in all log entries:
// Set default data that will be included in ALL logs
const loglito = new Loglito({
apiKey: 'your-api-key',
project: 'my_awesome_project', // Project ID
data: {
version: '1.0.2',
environment: 'production',
service: 'user-authentication'
}
});
// All logs will now include the default data
await loglito.log('User login');
// Results in: {"__message": "User login", "project": "nextsearch", "version": "1.0.2", ...}
await loglito.log('info', 'Payment processed', { amount: 99.99 });
// Results in: {"__level": "info", "__message": "Payment processed", "amount": 99.99, "project": "nextsearch", ...}
// Specific log data can override default data
await loglito.log('warning', 'Test environment issue', { environment: 'testing' });
// The "environment" field will be "testing" instead of "production"
// Works with all log methods
await loglito.info('User action', { action: 'file_upload' });
// Includes both the default data AND the specific action dataEnvironment Variables
You can also configure the client using environment variables:
const loglito = new Loglito({
apiKey: process.env.LOGLITO_API_KEY!,
baseUrl: process.env.LOGLITO_BASE_URL || 'https://loglito.io'
});Usage Examples
Multiple Calling Patterns
The log() method supports several flexible calling patterns:
const loglito = new Loglito({ apiKey: 'your-api-key' });
// 1. Simple string message
await loglito.log('Application started');
// 2. Level, message, and data object (RECOMMENDED)
await loglito.log('info', 'User subscribed', {
user_id: 123,
plan: 'premium'
});
// 3. Level, message, and multiple data objects
await loglito.log('info', 'User action',
{ user_id: 123 },
{ action: 'file_upload' },
{ file_size: 1024 }
);
// 4. Object-style arguments
await loglito.log({
level: 'info',
message: 'User authentication successful',
data: { user_id: 123 }
});
// 5. Mixed approach with additional properties
await loglito.log('error', 'Payment failed',
{ order_id: '12345', amount: 99.99 },
{ retry_count: 3, processor: 'stripe' }
);API Payload Format
All logs are sent to the API in a consistent batch format:
{
"logs": [
{
"log": {
"__date": "2024-01-15T10:30:00.123Z",
"__message": "User subscribed",
"__level": "info",
"user_id": 123,
"plan": "premium"
}
}
]
}Structured Logging
// E-commerce example
await loglito.log('info', 'Order placed', {
order_id: 'ORD-12345',
customer_id: 'CUST-789',
total_amount: 99.99,
items: [
{ product: 'Widget A', quantity: 2, price: 29.99 },
{ product: 'Widget B', quantity: 1, price: 39.99 }
],
payment_method: 'credit_card',
shipping_address: {
city: 'New York',
state: 'NY',
zip: '10001'
}
});
// Error logging with context
await loglito.log('error', 'Database connection failed', {
error_type: 'ConnectionTimeout',
database: 'postgres',
host: 'db.example.com',
retry_count: 3,
port: 5432
});
// Debug logging for performance monitoring
await loglito.log('debug', 'API response time', {
endpoint: '/api/users',
method: 'GET',
response_time: 0.245,
status_code: 200,
user_id: 123
});Batch Logging
For high-volume applications, use batch logging to send multiple logs in a single request:
const logs = [
{
message: 'User login',
level: 'info' as const,
data: { user_id: 123, ip: '192.168.1.1' }
},
{
message: 'Page view',
level: 'debug' as const,
data: { page: '/dashboard', user_id: 123 }
},
{
message: 'API call',
level: 'info' as const,
data: { endpoint: '/api/users', method: 'GET', status: 200 }
}
];
await loglito.logBatch(logs);Trace Functionality
Use trace IDs to group related log entries together, making it easier to follow request flows or batch operations:
const loglito = new Loglito({ apiKey: 'your-api-key' });
// Request tracing example
loglito.setTrace('request-abc123');
await loglito.info('Request started', { endpoint: '/api/users', method: 'GET' });
await loglito.debug('Database query executed', {
query: 'SELECT * FROM users WHERE active = ?',
execution_time: 23.5
});
await loglito.debug('Cache lookup performed', {
cache_key: 'users_active',
cache_hit: true
});
await loglito.info('Request completed', {
status_code: 200,
response_time: 45.2
});
// Clear trace for next request
loglito.clearTrace();
// Batch processing example
loglito.setTrace('batch-xyz789');
const batchLogs = [
{ message: 'Batch job started', level: 'info', data: { job_type: 'user_export' } },
{ message: 'Processing chunk 1', level: 'debug', data: { records: 100 } },
{ message: 'Processing chunk 2', level: 'debug', data: { records: 100 } },
{ message: 'Batch job completed', level: 'info', data: { total_records: 200 } }
];
await loglito.logBatch(batchLogs);
// Multiple operations with different traces
loglito.setTrace('email-operation-456');
await loglito.info('Email sending started');
await loglito.info('Email sent successfully');
loglito.setTrace('file-operation-789');
await loglito.info('File processing started');
await loglito.info('File processed successfully');
// Operations without trace
loglito.clearTrace();
await loglito.info('Background cleanup completed');All logs sent while a trace ID is set will automatically include __trace_id in the log data, making it easy to filter and group related logs in your Loglito dashboard.
Using async/await and Promises
// Using async/await
try {
const success = await loglito.log('info', 'User action', { user_id: 123 });
if (success) {
console.log('Log sent successfully');
}
} catch (error) {
console.error('Failed to send log:', error);
}
// Using Promises
loglito.log('info', 'Background task', { task_id: 'bg-001' })
.then(success => {
if (success) {
console.log('Log queued successfully');
}
})
.catch(error => {
console.error('Failed to queue log:', error);
});Manual Flushing
// Queue some logs
await loglito.log('info', 'Event 1');
await loglito.log('info', 'Event 2');
await loglito.log('info', 'Event 3');
// Manually flush all queued logs
const flushed = await loglito.flush(5000); // 5 second timeout
if (flushed) {
console.log('All logs flushed successfully');
}API Reference
Loglito Class
Constructor
new Loglito(config: LoglitoConfig)LoglitoConfig Properties:
apiKey(string): Your Loglito API key (required)baseUrl(string, optional): Base URL for the Loglito APItimeout(number, optional): Request timeout in millisecondsretries(number, optional): Number of retry attempts for failed requestsverifySsl(boolean, optional): Whether to verify SSL certificatesbufferSize(number, optional): Maximum logs to buffer before forcing flushflushInterval(number, optional): Time in milliseconds between automatic flushesimmediateMode(boolean, optional): Send logs immediately without buffering
Methods
log(...args): Promise<boolean>
Send a single log entry to Loglito.
Calling Patterns:
log(message: string)log(level: LogLevel, message: string)log(level: LogLevel, message: string, data: object)log(level: LogLevel, message: string, ...dataObjects: object[])log(options: { level?, message?, data?, [key]: any })
Returns: Promise<boolean> - True if successful, False otherwise
logBatch(logs: LogEntry[]): Promise<boolean>
Send multiple log entries in a single request.
Parameters:
logs(LogEntry[]): Array of log objects
Returns: Promise<boolean> - True if successful, False otherwise
flush(timeoutMs?: number): Promise<boolean>
Manually flush all queued logs.
Parameters:
timeoutMs(number, optional): Maximum time to wait for flush completion
Returns: Promise<boolean> - True if flush completed successfully
testConnection(): Promise<boolean>
Test the connection to Loglito by sending a test log.
Returns: Promise<boolean> - True if connection is successful
close(): Promise<void>
Close the client and flush any remaining logs.
Returns: Promise<void>
info(message: string, data?: Record<string, any>): Promise<boolean>
Send an info level log entry.
Parameters:
message(string): Log messagedata(object, optional): Additional structured data
Returns: Promise<boolean> - True if successful, False otherwise
debug(message: string, data?: Record<string, any>): Promise<boolean>
Send a debug level log entry.
Parameters:
message(string): Log messagedata(object, optional): Additional structured data
Returns: Promise<boolean> - True if successful, False otherwise
warning(message: string, data?: Record<string, any>): Promise<boolean>
Send a warning level log entry.
Parameters:
message(string): Log messagedata(object, optional): Additional structured data
Returns: Promise<boolean> - True if successful, False otherwise
error(message: string, data?: Record<string, any>): Promise<boolean>
Send an error level log entry.
Parameters:
message(string): Log messagedata(object, optional): Additional structured data
Returns: Promise<boolean> - True if successful, False otherwise
setTrace(traceId: string): void
Set a trace ID that will be automatically added to all subsequent log entries.
Parameters:
traceId(string): The trace ID to set. This will be added as__trace_idto all logs.
Returns: void
clearTrace(): void
Clear the current trace ID.
After calling this method, subsequent log entries will not include the trace ID.
Returns: void
Types
// Log levels
type LogLevel = 'debug' | 'info' | 'warning' | 'error' | 'critical';
// Log entry for batch operations
interface LogEntry {
message?: string;
level?: LogLevel;
data?: Record<string, any>;
[key: string]: any;
}
// Configuration interface
interface LoglitoConfig {
apiKey: string;
baseUrl?: string;
timeout?: number;
retries?: number;
verifySsl?: boolean;
bufferSize?: number;
flushInterval?: number;
immediateMode?: boolean;
}Error Handling
The client provides specific exception types for different error scenarios:
import {
Loglito,
LoglitoError,
LoglitoAuthenticationError,
LoglitoConnectionError,
LoglitoServerError
} from '@loglito/loglito';
try {
const loglito = new Loglito({ apiKey: 'invalid-key' });
await loglito.log('info', 'Test message', { test: true });
} catch (error) {
if (error instanceof LoglitoAuthenticationError) {
console.error('Invalid API key');
} else if (error instanceof LoglitoConnectionError) {
console.error('Connection failed');
} else if (error instanceof LoglitoServerError) {
console.error('Server error:', error.statusCode);
} else if (error instanceof LoglitoError) {
console.error('General Loglito error');
}
}Integration Examples
Express.js Application
import express from 'express';
import { Loglito } from '@loglito/loglito';
const app = express();
const loglito = new Loglito({ apiKey: 'your-api-key' });
app.get('/user/:id', async (req, res) => {
await loglito.log('info', 'User profile accessed', {
user_id: parseInt(req.params.id),
endpoint: '/user',
method: 'GET',
ip: req.ip
});
// ... your application logic ...
});Next.js Application
// pages/api/users.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { Loglito } from '@loglito/loglito';
const loglito = new Loglito({
apiKey: process.env.LOGLITO_API_KEY!
});
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
await loglito.log('info', 'API endpoint called', {
method: req.method,
url: req.url,
user_agent: req.headers['user-agent']
});
// ... your API logic ...
}React Application
// hooks/useLogging.ts
import { useEffect } from 'react';
import { Loglito } from '@loglito/loglito';
const loglito = new Loglito({
apiKey: process.env.REACT_APP_LOGLITO_API_KEY!
});
export function useLogging() {
useEffect(() => {
loglito.log('info', 'Application loaded', {
user_agent: navigator.userAgent,
timestamp: Date.now()
});
return () => {
loglito.close();
};
}, []);
return loglito;
}
// In your component
function App() {
const loglito = useLogging();
const handleUserAction = async (action: string) => {
await loglito.log('info', 'User action', { action });
};
// ... rest of component
}Browser Usage
<!DOCTYPE html>
<html>
<head>
<title>Loglito Browser Example</title>
</head>
<body>
<script type="module">
import { Loglito } from 'https://unpkg.com/@loglito/loglito@latest/dist/index.esm.js';
const loglito = new Loglito({
apiKey: 'your-api-key'
});
// Log page view
await loglito.log('info', 'Page viewed', {
page: window.location.pathname,
referrer: document.referrer,
user_agent: navigator.userAgent
});
// Clean up on page unload
window.addEventListener('beforeunload', () => {
loglito.close();
});
</script>
</body>
</html>Development
Building
npm run buildTesting
npm testTesting Published Package
To test the published package from npm:
npm run test:publishedThis script will:
- Install
@loglito/loglitofrom npm in a temporary directory - Test all major functionality
- Clean up afterwards
Type Checking
npm run type-checkLinting
npm run lint