Course contentsShow
← Linux
Lesson 1736 of 1,81914. Observability and Performance TroubleshootingFree lesson

Correlating Logs, Metrics, and Traces

Unify kernel performance telemetry with application logs using correlation IDs.

In this lesson, you will learn how to bridge the gap between low-level kernel performance telemetry and high-level application behavior by propagating correlation IDs across the user-kernel boundary.

The Observability Gap

In high-performance environments, we often encounter a "correlation gap." Your metrics might show a spike in CPU usage or kernel wait times, and your logs might show a timeout error, but linking these two events requires a shared piece of context. By injecting a unique Correlation ID into the kernel’s execution path, we can tie specific request flows to the underlying Linux kernel activity.

Unifying Telemetry with Correlation IDs

The strategy is to propagate a request ID (often a Trace ID from your distributed tracing header) into a thread-local variable or a task-specific metadata field that eBPF programs can access.

When your application initiates a system call, it marks the current thread with the active Correlation ID. An eBPF program, triggered by a tracepoint or kprobe, can then capture this ID alongside kernel telemetry like scheduler latency or disk I/O wait.

Consider a simple eBPF probe capturing disk latency:

SEC("kprobe/blk_account_io_done")
int BPF_KPROBE(trace_io_done) {
    u64 pid = bpf_get_current_pid_tgid();
    u32 tid = pid; 
    // Retrieve the Correlation ID stored by the app in a BPF map
    u64 *corr_id = bpf_map_lookup_elem(&active_requests, &tid);
    
    if (corr_id) {
        // Output the latency event tagged with the Correlation ID
        bpf_printk("Request %llu I/O latency: %llu ns", *corr_id, latency);
    }
    return 0;
}

By standardizing this approach, your log aggregator receives a log line containing the correlation_id, your time-series database receives a metric labeled with that ID, and your tracing backend receives the corresponding span. When an anomaly occurs, you no longer search for "slow requests"; you query your telemetry store for a specific correlation_id to see the complete lifecycle from the application logic down to the kernel’s thread scheduling decisions.

Key Takeaway: By injecting Correlation IDs into task metadata, you unify disparate signals, allowing you to reconstruct a request’s journey across both application threads and kernel subsystems.