Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 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
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
46 changes: 23 additions & 23 deletions core/common/src/buffer_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub const TASK_COMM_LEN: usize = 16; // linux/sched.h
#[cfg(feature = "monitoring-structs")]
#[repr(C, packed)]
#[derive(Clone, Copy, Zeroable)]
pub struct NetworkMetrics {
pub struct PacketLossMetrics {
pub tgid: u32,
pub comm: [u8; TASK_COMM_LEN],
pub ts_us: u64,
Expand All @@ -108,7 +108,7 @@ pub struct NetworkMetrics {
pub sk_drops: i32, // Offset 136
}
#[cfg(feature = "monitoring-structs")]
unsafe impl aya::Pod for NetworkMetrics {}
unsafe impl aya::Pod for PacketLossMetrics {}

#[cfg(feature = "monitoring-structs")]
#[repr(C, packed)]
Expand Down Expand Up @@ -208,7 +208,7 @@ pub enum BufferType {
#[cfg(feature = "network-structs")]
VethLog,
#[cfg(feature = "monitoring-structs")]
NetworkMetrics,
PacketLossMetrics,
#[cfg(feature = "monitoring-structs")]
TimeStampMetrics,
#[cfg(feature = "monitoring-structs")]
Expand Down Expand Up @@ -436,7 +436,7 @@ impl BufferType {
///
/// Counterpart to [`read_network_buffer`] for the `time_stamp_events` map.

pub async fn read_network_metrics(
pub async fn read_packet_loss_metrics(
buffers: &mut [BytesMut],
tot_events: i32,
offset: i32,
Expand All @@ -445,7 +445,7 @@ impl BufferType {
) {
for i in offset..tot_events {
let vec_bytes = &buffers[i as usize];
if vec_bytes.len() < std::mem::size_of::<NetworkMetrics>() {
if vec_bytes.len() < std::mem::size_of::<PacketLossMetrics>() {
error!(
"Corrupted Network Metrics data. Raw data: {}. Readed {} bytes expected {} bytes",
vec_bytes
Expand All @@ -454,28 +454,28 @@ impl BufferType {
.collect::<Vec<_>>()
.join(" "),
vec_bytes.len(),
std::mem::size_of::<NetworkMetrics>()
std::mem::size_of::<PacketLossMetrics>()
);
continue;
}
if vec_bytes.len() >= std::mem::size_of::<NetworkMetrics>() {
let net_metrics: NetworkMetrics =
if vec_bytes.len() >= std::mem::size_of::<PacketLossMetrics>() {
let packet_loss: PacketLossMetrics =
unsafe { std::ptr::read_unaligned(vec_bytes.as_ptr() as *const _) };

match exporter {
"otlp" => metrics.record_network_metrics(&net_metrics),
"otlp" => metrics.record_packet_loss_metrics(&packet_loss),
_ => continue, // skip
}
let tgid = net_metrics.tgid;
let comm = String::from_utf8_lossy(&net_metrics.comm);
let ts_us = net_metrics.ts_us;
let sk_drop_count = net_metrics.sk_drops;
let sk_err = net_metrics.sk_err;
let sk_err_soft = net_metrics.sk_err_soft;
let sk_backlog_len = net_metrics.sk_backlog_len;
let sk_write_memory_queued = net_metrics.sk_write_memory_queued;
let sk_ack_backlog = net_metrics.sk_ack_backlog;
let sk_receive_buffer_size = net_metrics.sk_receive_buffer_size;
let tgid = packet_loss.tgid;
let comm = String::from_utf8_lossy(&packet_loss.comm);
let ts_us = packet_loss.ts_us;
let sk_drop_count = packet_loss.sk_drops;
let sk_err = packet_loss.sk_err;
let sk_err_soft = packet_loss.sk_err_soft;
let sk_backlog_len = packet_loss.sk_backlog_len;
let sk_write_memory_queued = packet_loss.sk_write_memory_queued;
let sk_ack_backlog = packet_loss.sk_ack_backlog;
let sk_receive_buffer_size = packet_loss.sk_receive_buffer_size;

info!(
"tgid: {}, comm: {}, ts_us: {}, sk_drops: {}, sk_err: {}, sk_err_soft: {}, sk_backlog_len: {}, sk_write_memory_queued: {}, sk_ack_backlog: {}, sk_receive_buffer_size: {}",
Expand Down Expand Up @@ -811,15 +811,15 @@ pub async fn read_perf_buffer<T: std::borrow::BorrowMut<aya::maps::MapData>>(
.await
}
#[cfg(feature = "monitoring-structs")]
BufferType::NetworkMetrics => {
BufferType::read_network_metrics(
BufferType::PacketLossMetrics => {
BufferType::read_packet_loss_metrics(
&mut buffers,
tot_events,
offset,
"otlp",
metrics
.clone()
.expect("Metrics required for NetworkMetrics"),
.expect("Metrics required for PacketLossMetrics"),
)
.await
}
Expand Down Expand Up @@ -939,7 +939,7 @@ impl BufferSize {
#[cfg(feature = "network-structs")]
BufferSize::TcpEvents => std::mem::size_of::<TcpPacketRegistry>(),
#[cfg(feature = "monitoring-structs")]
BufferSize::NetworkMetricsEvents => std::mem::size_of::<NetworkMetrics>(),
BufferSize::NetworkMetricsEvents => std::mem::size_of::<PacketLossMetrics>(),
#[cfg(feature = "monitoring-structs")]
BufferSize::TimeMetricsEvents => std::mem::size_of::<TimeStampMetrics>(),
#[cfg(feature = "monitoring-structs")]
Expand Down
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;
118 changes: 61 additions & 57 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 @@ -61,94 +58,99 @@ pub struct Metrics {
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")
.build();

// delta microseconds
let delta_us = meter
.u64_histogram("delta_us")
.with_description("Distribution of delta_us values from timestamp events")
.i64_gauge(Semantic::SocketErrorsCount.title())
.with_description(Semantic::SocketErrorsCount.description())
.with_unit("1")
.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();

// 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();

// 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,
Expand All @@ -159,17 +161,17 @@ impl Metrics {
}
}

/// 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.
/// - `tgid` – task group ID.
/// - `comm` – 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 = &[
Expand All @@ -178,19 +180,18 @@ impl Metrics {
];

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`]).
/// [`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();
Expand All @@ -200,8 +201,7 @@ impl Metrics {
];

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,6 +231,7 @@ 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);
}
Expand All @@ -247,6 +248,7 @@ impl Metrics {
KeyValue::new("command", command),
];

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

Expand All @@ -262,6 +264,7 @@ impl Metrics {
KeyValue::new("command", command),
];

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

Expand All @@ -272,6 +275,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