@sailboat-computer/event-bus
Version:
Standardized event bus for sailboat computer v3 with resilience features and offline capabilities
232 lines (198 loc) • 6.82 kB
text/typescript
/**
* Monitoring and alerting example
*
* This example demonstrates how to use the monitoring and alerting features of the event bus.
*/
import { createEventBus, EventPriority, EventCategory, AlertType, Alert } from '../src';
// Define a simple event type
interface TestEvent {
id: string;
value: number;
timestamp: string;
}
// Create an alert handler that logs alerts
function createAlertHandler() {
return (alert: Alert) => {
const statusText = alert.resolved ? 'RESOLVED' : 'ACTIVE';
const severityText = alert.severity.toUpperCase();
console.log(`[${statusText}] [${severityText}] ${alert.message}`);
if (alert.details) {
console.log(' Details:', JSON.stringify(alert.details, null, 2));
}
};
}
// Create a handler that will fail for certain events
function createFailingHandler() {
return (event: any) => {
const testEvent = event.data as TestEvent;
console.log(`Processing event: ${testEvent.id} = ${testEvent.value}`);
// Simulate a failure for events with value > 50
if (testEvent.value > 50) {
throw new Error(`Failed to process event with value ${testEvent.value}`);
}
console.log(`Successfully processed event: ${testEvent.id}`);
};
}
async function runExample() {
console.log('Starting monitoring example...');
// Create event bus with monitoring enabled
const eventBus = createEventBus({
adapter: {
type: 'memory',
config: {
serviceName: 'monitoring-example',
simulateLatency: true,
latencyRange: [50, 200] // Simulate high latency to trigger processing time alerts
}
},
offlineBuffer: {
maxSize: 100,
priorityRetention: true
},
metrics: {
enabled: true,
detailedTimings: true
},
deadLetterQueue: {
enabled: true,
maxSize: 100,
maxAttempts: 3
},
monitoring: {
enabled: true,
alertThresholds: {
failedPublishesThreshold: 5, // 5%
deadLetterQueueSizeThreshold: 2,
reconnectionAttemptsThreshold: 3,
processingTimeThreshold: 100 // 100ms
},
checkInterval: 1000 // Check every second for demo purposes
}
});
// Initialize event bus
await eventBus.initialize({
adapter: {
type: 'memory',
config: {
serviceName: 'monitoring-example',
simulateLatency: true,
latencyRange: [50, 200]
}
},
offlineBuffer: {
maxSize: 100,
priorityRetention: true
},
metrics: {
enabled: true,
detailedTimings: true
},
deadLetterQueue: {
enabled: true,
maxSize: 100,
maxAttempts: 3
},
monitoring: {
enabled: true,
alertThresholds: {
failedPublishesThreshold: 5,
deadLetterQueueSizeThreshold: 2,
reconnectionAttemptsThreshold: 3,
processingTimeThreshold: 100
},
checkInterval: 1000
}
});
console.log('Event bus initialized with monitoring enabled');
// Register alert handler
const handlerId = eventBus.registerAlertHandler(createAlertHandler());
console.log(`Registered alert handler with ID: ${handlerId}`);
// Subscribe to events with a handler that will fail for some events
await eventBus.subscribe<TestEvent>('test.event.v1', createFailingHandler());
console.log('Subscribed to test.event.v1 events');
// Publish some events
const events = [
{ id: 'event-1', value: 25, timestamp: new Date().toISOString() },
{ id: 'event-2', value: 75, timestamp: new Date().toISOString() }, // Will fail
{ id: 'event-3', value: 30, timestamp: new Date().toISOString() },
{ id: 'event-4', value: 90, timestamp: new Date().toISOString() }, // Will fail
{ id: 'event-5', value: 40, timestamp: new Date().toISOString() }
];
// Publish each event
for (const event of events) {
try {
console.log(`Publishing event: ${event.id} = ${event.value}`);
await eventBus.publish<TestEvent>(
'test.event.v1',
event,
{
priority: EventPriority.NORMAL,
category: EventCategory.DATA,
tags: ['test', `value-${event.value}`]
}
);
console.log(`Published event: ${event.id}`);
} catch (error) {
console.error(`Failed to publish event: ${error.message}`);
}
// Wait a bit between events
await new Promise(resolve => setTimeout(resolve, 200));
}
// Wait for events to be processed and alerts to be generated
console.log('\nWaiting for alerts to be generated...');
await new Promise(resolve => setTimeout(resolve, 2000));
// Get active alerts
console.log('\nActive alerts:');
const activeAlerts = eventBus.getActiveAlerts();
if (activeAlerts.length === 0) {
console.log('No active alerts');
} else {
for (const alert of activeAlerts) {
console.log(`- [${alert.severity}] ${alert.message}`);
}
}
// Get alert history
console.log('\nAlert history:');
const alertHistory = eventBus.getAlertHistory();
if (alertHistory.length === 0) {
console.log('No alert history');
} else {
for (const alert of alertHistory) {
const statusText = alert.resolved ? 'RESOLVED' : 'ACTIVE';
console.log(`- [${statusText}] [${alert.severity}] ${alert.message}`);
}
}
// Get metrics
const metrics = eventBus.getMetrics();
console.log('\nEvent Bus Metrics:');
console.log(`- Published events: ${metrics.publishedEvents}`);
console.log(`- Failed publishes: ${metrics.failedPublishes}`);
console.log(`- Processed events: ${metrics.processedEvents}`);
console.log(`- Dead letter queue size: ${(metrics as any).deadLetterQueueSize}`);
console.log(`- Dead letter queue events: ${(metrics as any).deadLetterQueueEvents}`);
console.log(`- Average processing time: ${(metrics as any).averageProcessingTime.toFixed(2)}ms`);
// Filter alerts by type
console.log('\nProcessing time alerts:');
const processingTimeAlerts = eventBus.getAlertHistory(undefined, AlertType.PROCESSING_TIME);
if (processingTimeAlerts.length === 0) {
console.log('No processing time alerts');
} else {
for (const alert of processingTimeAlerts) {
console.log(`- [${alert.severity}] ${alert.message}`);
}
}
// Clear alert history
console.log('\nClearing alert history...');
eventBus.clearAlertHistory();
// Verify alert history is cleared
const remainingAlerts = eventBus.getAlertHistory();
console.log(`Alert history size after clearing: ${remainingAlerts.length}`);
// Close the event bus
await eventBus.close();
console.log('\nMonitoring example completed');
}
// Run the example
runExample().catch(error => {
console.error('Example failed:', error);
process.exit(1);
});