Log Correlation Overview
What is Log Correlation?
Log Correlation links logs across services:
1. Same request across multiple services
2. Same user across different operations
3. Same order across different systems
4. Same error across different components
Benefits:
├── Trace request through system
├── Identify bottlenecks
├── Debug distributed issues
├── Understand user journeys
└── Find root cause faster
Correlation ID
// Generate correlation ID
class CorrelationId
{
public function generate()
{
return uniqid('req_', true);
}
public function propagate($request)
{
// Get from header or generate new
$correlationId = $request->getHeader('X-Correlation-ID') ?: $this->generate();
// Store in request
$request->setCorrelationId($correlationId);
// Pass to downstream services
$this->propagateToDownstream($correlationId);
return $correlationId;
}
}
Log Format
{
"timestamp": "2025-01-15T14:15:00.000Z",
"level": "error",
"correlation_id": "req_67890abcdef",
"service": "checkout",
"message": "Payment gateway timeout",
"context": {
"order_id": 12345,
"customer_id": 678,
"payment_method": "stripe",
"amount": 99.99
},
"trace_id": "abc123def456",
"span_id": "789ghi012"
}
Correlation ID Implementation
Middleware for Correlation
// PSR-15 Middleware
class CorrelationMiddleware
{
public function process($request, $handler)
{
// Get or generate correlation ID
$correlationId = $request->getHeader('X-Correlation-ID');
if (!$correlationId) {
$correlationId = $this->generateId();
}
// Add to request attributes
$request = $request->withAttribute('correlation_id', $correlationId);
// Add to response headers
$response = $handler->handle($request);
$response = $response->withHeader('X-Correlation-ID', $correlationId);
// Log with correlation ID
$this->logger->info('Request processed', [
'correlation_id' => $correlationId,
'method' => $request->getMethod(),
'uri' => $request->getUri()->getPath()
]);
return $response;
}
}
Propagate Across Services
// HTTP client with correlation
class HttpClient
{
public function request($method, $url, $options)
{
// Add correlation ID to headers
$correlationId = $this->getCorrelationId();
$options['headers'] = array_merge(
$options['headers'] ?? [],
['X-Correlation-ID' => $correlationId]
);
return $this->client->request($method, $url, $options);
}
}
// Message queue with correlation
class MessageProducer
{
public function send($queue, $message)
{
$message['correlation_id'] = $this->getCorrelationId();
$this->queue->sendMessage($queue, json_encode($message));
}
}
Database Correlation
// Add correlation ID to database logs
class DatabaseLogger
{
public function log($query, $params)
{
$correlationId = $this->getCorrelationId();
$this->db->insert('query_log', [
'correlation_id' => $correlationId,
'query' => $query,
'params' => json_encode($params),
'created_at' => date('Y-m-d H:i:s')
]);
}
}
Log Aggregation
Centralized Logging
// ELK Stack configuration
$elasticsearchConfig = [
'hosts' => ['elasticsearch:9200'],
'index' => 'magento-logs-' . date('Y.m.d'),
'type' => '_doc'
];
// Fluentd configuration
$fluentdConfig = [
'sources' => [
['type' => 'tail', 'path' => '/var/log/magento/*.log']
],
'filters' => [
['type' => 'parser', 'format' => 'json']
],
'outputs' => [
['type' => 'elasticsearch', 'host' => 'elasticsearch']
]
];
Log Search
// Search logs by correlation ID
class LogSearch
{
public function searchByCorrelationId($correlationId)
{
$query = [
'query' => [
'term' => ['correlation_id' => $correlationId]
],
'sort' => [['timestamp' => 'asc']]
];
return $this->elasticsearch->search($query);
}
public function searchByTimeRange($startTime, $endTime)
{
$query = [
'query' => [
'range' => [
'timestamp' => [
'gte' => $startTime,
'lte' => $endTime
]
]
]
];
return $this->elasticsearch->search($query);
}
public function searchByService($service)
{
$query = [
'query' => [
'term' => ['service' => $service]
]
];
return $this->elasticsearch->search($query);
}
}
Log Analysis
// Analyze logs for patterns
class LogAnalyzer
{
public function analyze($logs)
{
$analysis = [
'total' => count($logs),
'errors' => 0,
'warnings' => 0,
'services' => [],
'correlation_ids' => []
];
foreach ($logs as $log) {
// Count by level
if ($log['level'] === 'error') {
$analysis['errors']++;
}
if ($log['level'] === 'warning') {
$analysis['warnings']++;
}
// Count by service
$service = $log['service'];
if (!isset($analysis['services'][$service])) {
$analysis['services'][$service] = 0;
}
$analysis['services'][$service]++;
// Collect correlation IDs
if (isset($log['correlation_id'])) {
$analysis['correlation_ids'][] = $log['correlation_id'];
}
}
$analysis['correlation_ids'] = array_unique($analysis['correlation_ids']);
return $analysis;
}
}
Distributed Debugging
Trace Request Flow
// Trace request through services
class RequestTracer
{
public function trace($correlationId)
{
$trace = [];
// Get logs from all services
$services = ['gateway', 'checkout', 'payment', 'order', 'notification'];
foreach ($services as $service) {
$logs = $this->getLogs($service, $correlationId);
foreach ($logs as $log) {
$trace[] = [
'service' => $service,
'timestamp' => $log['timestamp'],
'event' => $log['message'],
'duration' => $log['duration'] ?? null
];
}
}
// Sort by timestamp
usort($trace, function($a, $b) {
return $a['timestamp'] - $b['timestamp'];
});
return $trace;
}
}
Identify Bottlenecks
// Find slow services
class BottleneckFinder
{
public function find($trace)
{
$serviceTimes = [];
foreach ($trace as $entry) {
$service = $entry['service'];
$duration = $entry['duration'] ?? 0;
if (!isset($serviceTimes[$service])) {
$serviceTimes[$service] = 0;
}
$serviceTimes[$service] += $duration;
}
// Sort by duration
arsort($serviceTimes);
// Return top bottleneck
return key($serviceTimes);
}
}
Debugging Tools
// Distributed debugging
class DistributedDebugger
{
public function debug($correlationId)
{
$debugInfo = [
'correlation_id' => $correlationId,
'services' => [],
'errors' => [],
'slow_operations' => []
];
// Collect from each service
$services = $this->getServices();
foreach ($services as $service) {
$info = $service->getDebugInfo($correlationId);
$debugInfo['services'][$service->getName()] = $info;
// Collect errors
if (!empty($info['errors'])) {
$debugInfo['errors'] = array_merge(
$debugInfo['errors'],
$info['errors']
);
}
// Collect slow operations
if (!empty($info['slow_operations'])) {
$debugInfo['slow_operations'] = array_merge(
$debugInfo['slow_operations'],
$info['slow_operations']
);
}
}
return $debugInfo;
}
}
Practice Problems
0 / 1 solved
Log Correlation Implementation
Implement correlation IDs across 5 microservices for request tracing.
Solution
// Implementation:
// 1. Gateway: Generate correlation ID
// 2. Middleware: Add to request/response headers
// 3. Services: Log with correlation ID
// 4. Queue: Add to message metadata
// 5. Database: Store in query logs
// 6. Aggregation: ELK stack
// 7. Search: By correlation ID Quiz
1. What is a correlation ID?
2. How is correlation ID propagated?
3. What is log aggregation?
4. Why is log correlation important?
Flashcards
Question
Correlation ID purpose?
Click to reveal answer
Answer
Trace request across multiple services
Question
How to propagate correlation ID?
Click to reveal answer
Answer
HTTP headers and message queue metadata
Question
Log aggregation?
Click to reveal answer
Answer
Collect logs from multiple services centrally
Question
Distributed debugging?
Click to reveal answer
Answer
Trace request flow, identify bottlenecks
Question
Log correlation benefit?
Click to reveal answer
Answer
Debug distributed systems, find root cause faster
Revision Notes
Key Takeaways
- 1. Correlation ID: Unique identifier across services
- 2. Propagation: HTTP headers, message queue metadata
- 3. Aggregation: Central log collection
- 4. Debugging: Trace flow, identify bottlenecks
- 5. Benefit: Debug distributed systems faster
Interview Tips
- • Explain correlation ID implementation
- • Discuss log aggregation architecture
- • Know distributed debugging techniques
- • Understand log analysis methods
Cheat Sheet
Log Correlation
- Correlation ID: Unique across services
- Propagate: HTTP headers, MQ metadata
- Aggregate: Central log collection
- Debug: Trace flow, find bottlenecks
- Benefit: Faster root cause analysis