Causal Linking
Satori allows you to link related events to trace cause-and-effect relationships, making it easy to understand event chains and debug complex flows.
Basic Causal Linking
Use the cause option to link an event to a previous event:
logger.info('User clicked submit');
// Link to the previous event
logger.info('Form validation started', {
cause: logger.lastEventId
});
logger.info('API request sent', {
cause: logger.lastEventId
});
Event Chains
Build chains of related events:
// Start of chain
logger.info('Order placed', { tags: ['order'] });
const orderId = logger.lastEventId;
// Payment processing (caused by order)
logger.info('Payment initiated', { cause: orderId });
const paymentId = logger.lastEventId;
// Parallel effects from payment
logger.info('Inventory updated', { cause: paymentId });
logger.info('Email sent', { cause: paymentId });
logger.info('Analytics tracked', { cause: paymentId });
The Causal Graph
Satori maintains a causal graph for querying relationships:
import { CausalGraph } from '@nisoku/satori-log';
const graph = new CausalGraph();
// Add events with causes
graph.addEvent('evt_1', 'auth');
graph.addEvent('evt_2', 'auth', ['evt_1']); // evt_1 caused evt_2
graph.addEvent('evt_3', 'auth', ['evt_2']);
graph.addEvent('evt_4', 'auth', ['evt_2']); // evt_2 caused both evt_3 and evt_4
// Query relationships
graph.getCauses('evt_3'); // ['evt_2']
graph.getEffects('evt_2'); // ['evt_3', 'evt_4']
graph.getCausalChain('evt_1'); // ['evt_1', 'evt_2', 'evt_3', 'evt_4']
// Check if events are related
graph.areCausallyRelated('evt_1', 'evt_4'); // true
Real-World Example: Request Tracing
const apiLogger = satori.createLogger('api');
async function handleRequest(req, res) {
// Log request start
apiLogger.info('Request received', {
tags: ['request'],
state: { method: req.method, path: req.path }
});
const requestId = apiLogger.lastEventId;
// Authentication (caused by request)
apiLogger.info('Authenticating user', { cause: requestId });
const user = await authenticate(req);
apiLogger.info('User authenticated', {
cause: apiLogger.lastEventId,
state: { userId: user.id }
});
// Business logic (caused by authentication)
const authId = apiLogger.lastEventId;
apiLogger.info('Processing business logic', { cause: authId });
const result = await processRequest(req, user);
// Response (caused by processing)
apiLogger.info('Sending response', {
cause: apiLogger.lastEventId,
state: { status: 200 }
});
res.json(result);
}
Querying Causal Chains
Find all events in a causal chain:
const chain = graph.getCausalChain('evt_1');
// Returns: ['evt_1', 'evt_2', 'evt_3', 'evt_4']
// Filter to find root causes of errors
const errorEvent = events.find(e => e.level === 'error');
const rootCause = graph.getCauses(errorEvent.id)[0];
Automatic Causal Linking
Satori can automatically link events within the same scope:
const logger = satori.createLogger('auth');
// These are automatically linked within the scope
logger.info('Login started');
logger.info('Credentials validated'); // Auto-linked to previous
logger.info('Session created'); // Auto-linked to previous
Pruning Old Events
Keep the causal graph manageable:
// Remove events older than 5 minutes
graph.prune(5 * 60 * 1000);
Visualizing Causal Relationships
Export the graph for visualization:
const events = satori.getEvents();
const graph = buildCausalGraph(events);
// Export as DOT format for Graphviz
const dot = exportToDot(graph);
console.log(dot);
Next Steps
- Filtering Events: Query events by various criteria
- Advanced Features: Circuit breakers, persistence
- Examples: More real-world patterns