Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6b294ab
[#186]: added trace_cpu_frequency and trace_cpu_idle tracepoints in m…
LorenzoTettamanti Jun 14, 2026
936b5d8
[#186]: added cpu frequency tracer user space functions to read the d…
LorenzoTettamanti Jun 14, 2026
f240ff9
[#186]: updated metrics.yaml kubernetes manifest. Added tracefs path …
LorenzoTettamanti Jun 14, 2026
9802b0d
(feat): added memory tracing in kernel space using sys_enter_mmap tr…
LorenzoTettamanti Jun 20, 2026
ce341e5
(feat: #186): added cpu_bytes_alloc_events_total, cpy_bytes_alloc mem…
LorenzoTettamanti Jun 20, 2026
12ae5b5
(feat : #186): added userspace consumer for memory allocation events.…
LorenzoTettamanti Jun 20, 2026
fc158c8
(feat: #186) : Added scheduler tracing metrics (sched_stat_wait,sched…
LorenzoTettamanti Jun 21, 2026
84ca27f
(feat: #186) : added userspace consumer for scheduler metrics
LorenzoTettamanti Jun 21, 2026
c8141f4
(example): added grafana dashboard example
LorenzoTettamanti Jun 22, 2026
85b2884
[#186]: Added cpu idle metrics in kernel space
LorenzoTettamanti Jun 22, 2026
86c88ef
[#186]: added userspace consumer for the cpu idle events
LorenzoTettamanti Jun 22, 2026
f244487
(example): Added docker example(only metrics). improved dashboard tem…
LorenzoTettamanti Jul 3, 2026
46cdb15
[#186]: fixed typo in cpu.rs
LorenzoTettamanti Jul 3, 2026
845c5c4
(chores): updated metrics image
LorenzoTettamanti Jul 3, 2026
fabdc00
(fix): fixed grafana version
LorenzoTettamanti Jul 10, 2026
7dda5d6
(refactor): refactored network tracing using a network.rs module
LorenzoTettamanti Jul 11, 2026
46f33b8
(refactor): changed NetworkMetrics data structure name to PacketLossM…
LorenzoTettamanti Jul 11, 2026
02222ae
(fix): fixed subtle bug occurring. changed way to return pid and tgid…
LorenzoTettamanti Jul 11, 2026
0d30ead
(refactor): updated consumer userspace API with the latest kernel sp…
LorenzoTettamanti Jul 11, 2026
47708df
(refactor): updated metrics/main.rs with the latest metrics_tracer ch…
LorenzoTettamanti Jul 11, 2026
dfe2d33
(metrics): updated metrics semantics to better represent the metrics …
LorenzoTettamanti Jul 11, 2026
6c84220
Merge branch '0.1.5' into metrics-patch
LorenzoTettamanti Jul 11, 2026
09dea56
(fix): fixed typo in build-local-metrics
LorenzoTettamanti Jul 12, 2026
b91f832
(fix): fixed typos introduced during the merge
LorenzoTettamanti Jul 12, 2026
97ddf52
[#201]: added semantic.rs
LorenzoTettamanti Jul 13, 2026
bb373a6
(cleaning): removed deprecated code. Fixed uppercase enum variant wit…
LorenzoTettamanti Jul 15, 2026
353d991
[#186]: Histogram<u64> distributions for sched_stat_wait and sched_st…
LorenzoTettamanti Jul 16, 2026
f56d53c
[#119]: moved read packet functions to dedicated consumer.rs module
LorenzoTettamanti Jul 20, 2026
9f9aa59
(#150): added service_discovery.rs module in the core library
LorenzoTettamanti Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
802 changes: 47 additions & 755 deletions core/common/src/buffer_type.rs

Large diffs are not rendered by default.

779 changes: 779 additions & 0 deletions core/common/src/consumer.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions core/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ pub mod map_handlers;
pub mod otel_metrics;
#[cfg(feature = "program-handlers")]
pub mod program_handlers;
mod semantic;
160 changes: 95 additions & 65 deletions core/common/src/otel_metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
//! telemetry by process.

use crate::buffer_type::{
CpuFrequency, CpuIdle, MemAlloc, NetworkMetrics, SchedStatRuntime, SchedStatWait,
CpuFrequency, CpuIdle, MemAlloc, PacketLossMetrics, SchedStatRuntime, SchedStatWait,
TimeStampMetrics,
};
use crate::semantic::Semantic;
use opentelemetry::KeyValue;
use opentelemetry::metrics::{Counter, Gauge, Histogram, Meter};
pub struct Metrics {
Expand All @@ -23,7 +24,7 @@ pub struct Metrics {

/// Total number of network-related events produced by the `net_metrics`
/// eBPF map.
pub packets_total: Counter<u64>,
pub socket_events_total: Counter<u64>,

/// Observed socket drop count (`sk_drops`) from the kernel sock struct.
pub sk_drops: Gauge<i64>,
Expand All @@ -33,11 +34,7 @@ pub struct Metrics {

/// Histogram of `delta_us` values supplied by the `time_stamp_events`
/// perf buffer.
pub delta_us: Histogram<u64>,

/// Histogram of `ts_us` values seen in both `net_metrics` and
/// `time_stamp_events`.
pub ts_us: Histogram<u64>,
pub tcp_latency_us: Histogram<u64>,

/// Cpu bytes alloc total events
pub cpu_bytes_alloc_events_total: Counter<u64>,
Expand All @@ -54,154 +51,179 @@ pub struct Metrics {
/// Observed scheduler wait time in nanoseconds (sched_stat_wait).
pub sched_stat_wait: Gauge<i64>,

/// Distribution of scheduler wait times in nanoseconds (sched_stat_wait).
pub sched_stat_wait_distribution: Histogram<u64>,

/// Observed scheduler runtime in nanoseconds (sched_stat_runtime).
pub sched_stat_runtime: Gauge<i64>,

/// Distribution of scheduler runtimes in nanoseconds (sched_stat_runtime).
pub sched_stat_runtime_distribution: Histogram<u64>,

/// Current CPU idle C-state per cpu_id, updated only on state change.
pub cpu_idle_state: Gauge<i64>,
}

// TODO: add identity metrics with TC classifier packet counts
// TODO: introduce a metric called total_tcp_packets total_udp_packets
impl Metrics {
/// Initialise all instruments backed by the supplied [`Meter`].
pub fn new(meter: &Meter) -> Self {
// total events
let events_total = meter
.u64_counter("events_total")
.with_description("Total number of eBPF events processed")
.u64_counter(Semantic::TotalEvents.title())
.with_description(Semantic::TotalEvents.description())
.with_unit("1")
.build();

// total packets
let packets_total = meter
.u64_counter("packets_total")
.with_description("Total number of network events processed")
// total socket events
let socket_events_total = meter
.u64_counter(Semantic::SocketTotalEvents.title())
.with_description(Semantic::SocketTotalEvents.description())
.with_unit("1")
.build();

// socket drops
let sk_drops = meter
.i64_gauge("sk_drops")
.with_description("Socket drop count per event")
.i64_gauge(Semantic::SocketDrops.title())
.with_description(Semantic::SocketDrops.description())
.with_unit("1")
.build();

// socket errors
let sk_err = meter
.i64_gauge("sk_err")
.with_description("Socket error count per event")
.i64_gauge(Semantic::SocketErrorsCount.title())
.with_description(Semantic::SocketErrorsCount.description())
.with_unit("1")
.build();

// delta microseconds
let delta_us = meter
.u64_histogram("delta_us")
.with_description("Distribution of delta_us values from timestamp events")
.build();

// timestamp microseconds grouped
let ts_us = meter
.u64_histogram("ts_us")
.with_description("Distribution of timestamp values from eBPF events")
// tcp latency microseconds
let tcp_latency_us = meter
.u64_histogram(Semantic::Latency.title())
.with_description(Semantic::Latency.description())
.with_unit("us")
.build();

// cpu bytes alloc total events
let cpu_bytes_alloc_events_total = meter
.u64_counter("bytes_alloc_events_total")
.with_description("Total bytes_alloc events occuring in the CPU")
.u64_counter(Semantic::PerCpuTotalEvents.title())
.with_description(Semantic::PerCpuTotalEvents.description())
.with_unit("1")
.build();

// cpu bytes allocation
let cpu_bytes_alloc = meter
.i64_gauge("cpu_bytes_alloc")
.with_description("Cpu bytes allocation per event")
.i64_gauge(Semantic::PerCpuBytesAllocated.title())
.with_description(Semantic::PerCpuBytesAllocated.description())
.with_unit("bytes")
.build();

// memory allocation (mmap) events total
let mem_alloc_events_total = meter
.u64_counter("mem_alloc_events_total")
.with_description("Total number of memory allocation (mmap) events processed")
.u64_counter(Semantic::TotalMemoryAllocationEvents.title())
.with_description(Semantic::TotalMemoryAllocationEvents.description())
.with_unit("1")
.build();

// bytes requested via mmap syscalls
let enter_mem_alloc = meter
.i64_gauge("enter_mem_alloc")
.with_description("Bytes requested via mmap syscalls")
.i64_gauge(Semantic::RequestedMemoryBytes.title())
.with_description(Semantic::RequestedMemoryBytes.description())
.with_unit("bytes")
.build();

// scheduler wait time in nanoseconds
let sched_stat_wait = meter
.i64_gauge("sched_stat_wait")
.with_description("Scheduler wait time in nanoseconds from sched_stat_wait")
.i64_gauge(Semantic::SchedulerWaitTime.title())
.with_description(Semantic::SchedulerWaitTime.description())
.with_unit("ns")
.build();

// distribution of scheduler wait times
let sched_stat_wait_distribution = meter
.u64_histogram(Semantic::SchedulerWaitTimeDistribution.title())
.with_description(Semantic::SchedulerWaitTimeDistribution.description())
.with_unit("ns")
.build();

// scheduler runtime in nanoseconds
let sched_stat_runtime = meter
.i64_gauge("sched_stat_runtime")
.with_description("Scheduler runtime in nanoseconds from sched_stat_runtime")
.i64_gauge(Semantic::SchedulerRuntime.title())
.with_description(Semantic::SchedulerRuntime.description())
.with_unit("ns")
.build();

// distribution of scheduler runtimes
let sched_stat_runtime_distribution = meter
.u64_histogram(Semantic::SchedulerRuntimeDistribution.title())
.with_description(Semantic::SchedulerRuntimeDistribution.description())
.with_unit("ns")
.build();

// current CPU idle C-state per cpu_id
let cpu_idle_state = meter
.i64_gauge("cpu_idle_state")
.with_description("Current CPU idle C-state per cpu_id, updated only on state change")
.i64_gauge(Semantic::CpuIdleState.title())
.with_description(Semantic::CpuIdleState.description())
.build();

Self {
events_total,
packets_total,
socket_events_total,
sk_drops,
sk_err,
delta_us,
ts_us,
tcp_latency_us,
cpu_bytes_alloc,
cpu_bytes_alloc_events_total,
mem_alloc_events_total,
enter_mem_alloc,
sched_stat_wait,
sched_stat_wait_distribution,
sched_stat_runtime,
sched_stat_runtime_distribution,
cpu_idle_state,
}
}

/// Record a single [`NetworkMetrics`] event.
/// Record a single [`PacketLossMetrics`] event.
///
/// Increments `events_total` and `packets_total`, records `sk_drops` and
/// `sk_err` as gauges, and observes `ts_us` in the timestamp histogram.
/// Increments `events_total` and `socket_events_total`, records `sk_drops`
/// and `sk_err` as gauges.
///
/// Every observation carries:
///
/// -`tgid` – task group ID.
/// - `comm` – command name (null-terminated bytes converted to a UTF-8
/// - `tgid` – task group ID.
/// - `command` – command name (null-terminated bytes converted to a UTF-8
/// string and trimmed).
pub fn record_network_metrics(&self, m: &NetworkMetrics) {
pub fn record_packet_loss_metrics(&self, m: &PacketLossMetrics) {
let comm = String::from_utf8_lossy(&m.comm);
let comm_trimmed = comm.trim_end_matches('\0').to_string();
let attrs = &[
KeyValue::new("tgid", m.tgid as i64),
KeyValue::new("comm", comm_trimmed),
KeyValue::new("command", comm_trimmed),
];

self.events_total.add(1, attrs);
self.packets_total.add(1, attrs);
self.socket_events_total.add(1, attrs);
self.sk_drops.record(m.sk_drops as i64, attrs);
self.sk_err.record(m.sk_err as i64, attrs);
self.ts_us.record(m.ts_us, attrs);
}

/// Record a single [`TimeStampMetrics`] event.
///
/// Increments `events_total`, and records `delta_us` and `ts_us` in their
/// respective histograms.
/// Increments `events_total`, and records `delta_us` in the latency
/// histogram.
///
/// Every observation carries `tgid` and `comm` (see
/// [`record_network_metrics`]).
/// Every observation carries `tgid` and `command` (see
/// [`record_packet_loss_metrics`]).
pub fn record_timestamp_metrics(&self, m: &TimeStampMetrics) {
let comm = String::from_utf8_lossy(&m.comm);
let comm_trimmed = comm.trim_end_matches('\0').to_string();
let attrs = &[
KeyValue::new("tgid", m.tgid as i64),
KeyValue::new("comm", comm_trimmed),
KeyValue::new("command", comm_trimmed),
];

self.events_total.add(1, attrs);
self.delta_us.record(m.delta_us, attrs);
self.ts_us.record(m.ts_us, attrs);
self.tcp_latency_us.record(m.delta_us, attrs);
}

pub fn record_cpu_bytes_alloc(&self, m: &CpuFrequency) {
Expand Down Expand Up @@ -231,14 +253,16 @@ impl Metrics {
KeyValue::new("command", command),
];

self.events_total.add(1, attrs);
self.mem_alloc_events_total.add(1, attrs);
self.enter_mem_alloc.record(m.length as i64, attrs);
}

/// Record a single [`SchedStatWait`] event.
///
/// Records `delay` in the `sched_stat_wait` gauge. No shared or dedicated
/// counter is incremented, as requested.
/// Increments `events_total`, records `delay` in the `sched_stat_wait`
/// gauge, and observes `delay` in the `sched_stat_wait_distribution`
/// histogram.
pub fn record_sched_stat_wait(&self, m: &SchedStatWait) {
let comm = String::from_utf8_lossy(&m.command);
let command = comm.trim_end_matches('\0').to_string();
Expand All @@ -247,13 +271,16 @@ impl Metrics {
KeyValue::new("command", command),
];

self.events_total.add(1, attrs);
self.sched_stat_wait.record(m.delay as i64, attrs);
self.sched_stat_wait_distribution.record(m.delay, attrs);
}

/// Record a single [`SchedStatRuntime`] event.
///
/// Records `runtime` in the `sched_stat_runtime` gauge. No shared or
/// dedicated counter is incremented, as requested.
/// Increments `events_total`, records `runtime` in the `sched_stat_runtime`
/// gauge, and observes `runtime` in the `sched_stat_runtime_distribution`
/// histogram.
pub fn record_sched_stat_runtime(&self, m: &SchedStatRuntime) {
let comm = String::from_utf8_lossy(&m.command);
let command = comm.trim_end_matches('\0').to_string();
Expand All @@ -262,7 +289,9 @@ impl Metrics {
KeyValue::new("command", command),
];

self.events_total.add(1, attrs);
self.sched_stat_runtime.record(m.runtime as i64, attrs);
self.sched_stat_runtime_distribution.record(m.runtime, attrs);
}

/// Record a single [`CpuIdle`] event.
Expand All @@ -272,6 +301,7 @@ impl Metrics {
pub fn record_cpu_idle(&self, m: &CpuIdle) {
let attrs = &[KeyValue::new("cpu_id", m.cpu_id as i64)];

self.events_total.add(1, attrs);
self.cpu_idle_state.record(m.state as i64, attrs);
}
}
Loading