Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 22 additions & 0 deletions userspace/falco/app/actions/process_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ struct live_context {
std::unique_ptr<source_sync_context> sync;
};

// Batch size used to publish the per-source event count into the global
// state.num_evts counter (see #3584). Must be a power of two so the
// hot-path predicate compiles to a single AND.
static constexpr uint64_t NUM_EVTS_PUBLISH_BATCH = 1024;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are relying on NUM_EVTS_PUBLUSH_BATCH being a power of two, I would add a static check

Suggested change
static constexpr uint64_t NUM_EVTS_PUBLISH_BATCH = 1024;
static constexpr uint64_t NUM_EVTS_PUBLISH_BATCH = 1024;
static_assert((NUM_EVTS_PUBLISH_BATCH & (NUM_EVTS_PUBLISH_BATCH -1)) == 0);


//
// Event processing loop
//
Expand Down Expand Up @@ -386,6 +391,17 @@ static falco::app::run_result do_inspect(
}

num_evts++;
// Publish to the global Prometheus counter in batches so the
// per-event hot path stays free of `lock`-prefixed atomic ops.
// One fetch_add every 1024 events bounds the per-event amortised
// cost to a few cycles on x86 even at multi-MHz event rates,
// while keeping the counter visible to /metrics within the same
// order of magnitude as a typical Prometheus scrape interval.
// The residual (num_evts & 1023) is flushed by the caller once
// the loop exits. See issue #3584.
if((num_evts & (NUM_EVTS_PUBLISH_BATCH - 1)) == 0) {
s.num_evts.fetch_add(NUM_EVTS_PUBLISH_BATCH, std::memory_order_relaxed);
}
}

return run_result::ok();
Expand Down Expand Up @@ -419,6 +435,12 @@ static void process_inspector_events(
uint64_t(s.options.duration_to_tot * ONE_SECOND_IN_NS),
num_evts);

// Flush any unpublished tail (events processed since the last
// NUM_EVTS_PUBLISH_BATCH boundary inside do_inspect). See #3584.
if(uint64_t residual = num_evts & (NUM_EVTS_PUBLISH_BATCH - 1)) {
s.num_evts.fetch_add(residual, std::memory_order_relaxed);
}

duration = ((double)clock()) / CLOCKS_PER_SEC - duration;

inspector->get_capture_stats(&cstats);
Expand Down
7 changes: 7 additions & 0 deletions userspace/falco/app/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ struct state {
falco::app::options options;
std::atomic<bool> restart = false;

// Cumulative count of userspace events processed by Falco across every
// loaded event source. Maintained by the per-source event loop in
// process_events.cpp and read by the Prometheus output sink so the
// `falco.num_evts` value already exposed via stats_writer is also
// available on /metrics. See issue #3584.
std::atomic<uint64_t> num_evts = 0;

std::shared_ptr<falco_configuration> config;
std::shared_ptr<falco_outputs> outputs;
std::shared_ptr<falco_engine> engine;
Expand Down
15 changes: 15 additions & 0 deletions userspace/falco/falco_metrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,21 @@ std::string falco_metrics::falco_to_text_prometheus(
state.outputs->get_outputs_queue_num_drops()));
}

// # HELP falcosecurity_falco_num_evts_total https://falco.org/docs/metrics/
// # TYPE falcosecurity_falco_num_evts_total counter
// falcosecurity_falco_num_evts_total 12345
//
// Exposes the same `num_evts` counter that the JSON / text stats sinks
// already emit via stats_writer; aggregated across every event source.
// See issue #3584.
additional_wrapper_metrics.emplace_back(libs::metrics::libsinsp_metrics::new_metric(
"num_evts",
METRICS_V2_MISC,
METRIC_VALUE_TYPE_U64,
METRIC_VALUE_UNIT_COUNT,
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
state.num_evts.load(std::memory_order_relaxed)));

// # HELP falcosecurity_falco_reload_timestamp_nanoseconds https://falco.org/docs/metrics/
// # TYPE falcosecurity_falco_reload_timestamp_nanoseconds gauge
// falcosecurity_falco_reload_timestamp_nanoseconds 1748338536592811359
Expand Down