Skip to content

Commit 956d0c0

Browse files
committed
refactor(metrics): improve d_instantiate dispatch metric tracking
Add new metrics to the d_instantiate hook that allow for tracking individual event types dispatched. This is helpful to identify if one of these types are being lost by comparing the `Added` label from the originating hook (like path_mkdir or path_symlink) with the corresponding `Added<hook>` label. In order for `d_instantiate` to have its own type some trait + iterator gymnastics were necessary. The summary for this is: * A new `KernelMetric` trait is created which describes how metrics coming from the kernel should be accumulated and encoded using a `KernelMetricLabel` helper type. * The trait is implemented for `metrics_by_hook_t` and `metrics_d_instantiate_t`. * The metrics module know how to translate from `KernelMetricLabel` to `LabelValues`, so it does the same `accumulate` process it used to do and then uses the iterator produced by `encode` to add metrics dynamically.
1 parent cfc8a73 commit 956d0c0

6 files changed

Lines changed: 89 additions & 14 deletions

File tree

fact-ebpf/src/bpf/main.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ int BPF_PROG(trace_d_instantiate, struct dentry* dentry, struct inode* inode) {
336336
if (m == NULL) {
337337
return 0;
338338
}
339-
struct submit_event_args_t args = {.metrics = &m->d_instantiate};
339+
struct submit_event_args_t args = {.metrics = &m->d_instantiate.base};
340340

341341
args.metrics->total++;
342342

@@ -364,6 +364,7 @@ int BPF_PROG(trace_d_instantiate, struct dentry* dentry, struct inode* inode) {
364364
args.metrics->error++;
365365
}
366366

367+
m->d_instantiate.added_mkdir++;
367368
submit_mkdir_event(&args);
368369
break;
369370
case FILE_ACTIVITY_SYMLINK:
@@ -375,7 +376,10 @@ int BPF_PROG(trace_d_instantiate, struct dentry* dentry, struct inode* inode) {
375376
}
376377

377378
if (args.monitored != NOT_MONITORED) {
379+
m->d_instantiate.added_symlink++;
378380
submit_symlink_event(&args, d_inst_ctx->symlink_target);
381+
} else {
382+
args.metrics->ignored++;
379383
}
380384
break;
381385
default:

fact-ebpf/src/bpf/types.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,20 @@ struct metrics_by_hook_t {
179179
unsigned long long ringbuffer_full;
180180
};
181181

182+
struct metrics_d_instantiate_t {
183+
struct metrics_by_hook_t base;
184+
unsigned long long added_mkdir;
185+
unsigned long long added_symlink;
186+
};
187+
182188
struct metrics_t {
183189
struct metrics_by_hook_t file_open;
184190
struct metrics_by_hook_t path_unlink;
185191
struct metrics_by_hook_t path_chmod;
186192
struct metrics_by_hook_t path_chown;
187193
struct metrics_by_hook_t path_rename;
188194
struct metrics_by_hook_t path_mkdir;
189-
struct metrics_by_hook_t d_instantiate;
195+
struct metrics_d_instantiate_t d_instantiate;
190196
struct metrics_by_hook_t path_rmdir;
191197
struct metrics_by_hook_t inode_setxattr;
192198
struct metrics_by_hook_t inode_removexattr;

fact-ebpf/src/lib.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,25 @@ impl<'de> Deserialize<'de> for monitored_t {
201201
}
202202
}
203203

204-
impl metrics_by_hook_t {
204+
pub enum KernelMetricLabel {
205+
Total,
206+
Added,
207+
Dropped,
208+
Ignored,
209+
Error,
210+
RingbufferFull,
211+
212+
// d_instantiate specific metrics
213+
AddedMkDir,
214+
AddedSymlink,
215+
}
216+
217+
pub trait KernelMetric {
218+
fn accumulate(self, other: &Self) -> Self;
219+
fn encode(&self) -> impl Iterator<Item = (KernelMetricLabel, u64)>;
220+
}
221+
222+
impl KernelMetric for metrics_by_hook_t {
205223
fn accumulate(mut self, other: &metrics_by_hook_t) -> metrics_by_hook_t {
206224
self.total += other.total;
207225
self.added += other.added;
@@ -210,6 +228,35 @@ impl metrics_by_hook_t {
210228
self.ringbuffer_full += other.ringbuffer_full;
211229
self
212230
}
231+
232+
fn encode(&self) -> impl Iterator<Item = (KernelMetricLabel, u64)> {
233+
use KernelMetricLabel::*;
234+
[
235+
(Total, self.total),
236+
(Added, self.added),
237+
(Error, self.error),
238+
(Ignored, self.ignored),
239+
(RingbufferFull, self.ringbuffer_full),
240+
]
241+
.into_iter()
242+
}
243+
}
244+
245+
impl KernelMetric for metrics_d_instantiate_t {
246+
fn accumulate(mut self, other: &metrics_d_instantiate_t) -> metrics_d_instantiate_t {
247+
self.base = self.base.accumulate(&other.base);
248+
self.added_mkdir += other.added_mkdir;
249+
self.added_symlink += other.added_symlink;
250+
self
251+
}
252+
253+
fn encode(&self) -> impl Iterator<Item = (KernelMetricLabel, u64)> {
254+
use KernelMetricLabel::*;
255+
self.base.encode().chain([
256+
(AddedSymlink, self.added_symlink),
257+
(AddedMkDir, self.added_mkdir),
258+
])
259+
}
213260
}
214261

215262
macro_rules! impl_metrics_t {

fact/src/config/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,10 @@ pub struct FactCli {
869869
/// This is an advanced configuration parameter, it can be used to
870870
/// increase the amount of in-flight events that use the
871871
/// d_instantiate LSM hook for resolving inode numbers.
872+
///
873+
/// Whether this value needs to be tweaked can be determined with
874+
/// the metrics exposed for the d_instantiate hook and the ones for
875+
/// the originating hooks.
872876
#[arg(
873877
long = "d-inst-size",
874878
env = "FACT_D_INSTANTIATE_CTX_SIZE",

fact/src/metrics/kernel_metrics.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use aya::maps::{MapData, PerCpuArray};
22
use prometheus_client::registry::Registry;
33

4-
use fact_ebpf::{metrics_by_hook_t, metrics_t};
4+
use fact_ebpf::{KernelMetric, metrics_t};
55

66
use crate::metrics::MetricEvents;
77

8-
use super::{EventCounter, LabelValues};
8+
use super::EventCounter;
99

1010
macro_rules! define_kernel_metrics {
1111
($($hook:ident),+ $(,)?) => {
@@ -46,17 +46,11 @@ macro_rules! define_kernel_metrics {
4646
Ok(())
4747
}
4848

49-
fn refresh_labels(ec: &EventCounter, m: &metrics_by_hook_t) {
49+
fn refresh_labels(ec: &EventCounter, m: &impl KernelMetric) {
5050
ec.counter.clear();
51-
for (label, value) in [
52-
(LabelValues::Total, m.total),
53-
(LabelValues::Added, m.added),
54-
(LabelValues::Error, m.error),
55-
(LabelValues::Ignored, m.ignored),
56-
(LabelValues::RingbufferFull, m.ringbuffer_full),
57-
] {
51+
for (label, value) in m.encode() {
5852
ec.counter
59-
.get_or_create(&MetricEvents { label })
53+
.get_or_create(&MetricEvents{ label: label.into() })
6054
.inc_by(value);
6155
}
6256
}

fact/src/metrics/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use prometheus_client::{
66

77
use host_scanner::HostScannerMetrics;
88

9+
use fact_ebpf::KernelMetricLabel;
910
pub mod exporter;
1011
pub mod host_scanner;
1112
pub mod kernel_metrics;
@@ -18,6 +19,25 @@ enum LabelValues {
1819
Ignored,
1920
Error,
2021
RingbufferFull,
22+
23+
// d_instantiate specific metrics
24+
AddedMkDir,
25+
AddedSymlink,
26+
}
27+
28+
impl From<KernelMetricLabel> for LabelValues {
29+
fn from(value: KernelMetricLabel) -> Self {
30+
match value {
31+
KernelMetricLabel::Total => LabelValues::Total,
32+
KernelMetricLabel::Added => LabelValues::Added,
33+
KernelMetricLabel::Dropped => LabelValues::Dropped,
34+
KernelMetricLabel::Ignored => LabelValues::Ignored,
35+
KernelMetricLabel::Error => LabelValues::Error,
36+
KernelMetricLabel::RingbufferFull => LabelValues::RingbufferFull,
37+
KernelMetricLabel::AddedMkDir => LabelValues::AddedMkDir,
38+
KernelMetricLabel::AddedSymlink => LabelValues::AddedSymlink,
39+
}
40+
}
2141
}
2242

2343
#[derive(Clone, Hash, Eq, Debug, PartialEq, EncodeLabelSet)]

0 commit comments

Comments
 (0)