diff --git a/src/EventHandler.cc b/src/EventHandler.cc index 154bc7615f..e15234d750 100644 --- a/src/EventHandler.cc +++ b/src/EventHandler.cc @@ -9,6 +9,7 @@ #include "zeek/Var.h" #include "zeek/broker/Data.h" #include "zeek/broker/Manager.h" +#include "zeek/telemetry/Manager.h" namespace zeek { @@ -53,7 +54,16 @@ void EventHandler::SetFunc(FuncPtr f) void EventHandler::Call(Args* vl, bool no_remote) { - call_count++; + if ( ! call_count ) + { + static auto eh_invocations_family = telemetry_mgr->CounterFamily( + "zeek", "event-handler-invocations", {"name"}, + "Number of times the given event handler was called", "1", true); + + call_count = eh_invocations_family.GetOrAdd({{"name", name}}); + } + + call_count->Inc(); if ( new_event ) NewEvent(vl); diff --git a/src/EventHandler.h b/src/EventHandler.h index e7c9458971..258682adfc 100644 --- a/src/EventHandler.h +++ b/src/EventHandler.h @@ -2,12 +2,14 @@ #pragma once +#include #include #include #include "zeek/Type.h" #include "zeek/ZeekArgs.h" #include "zeek/ZeekList.h" +#include "zeek/telemetry/Counter.h" namespace zeek { @@ -55,7 +57,7 @@ public: } bool GenerateAlways() const { return generate_always; } - uint64_t CallCount() const { return call_count; } + uint64_t CallCount() const { return call_count ? call_count->Value() : 0; } private: void NewEvent(zeek::Args* vl); // Raise new_event() meta event. @@ -67,7 +69,9 @@ private: bool enabled; bool error_handler; // this handler reports error messages. bool generate_always; - uint64_t call_count = 0; + + // Initialize this lazy, so we don't expose metrics for 0 values. + std::optional call_count; std::unordered_set auto_publish; }; diff --git a/testing/btest/Baseline/scripts.base.frameworks.telemetry.event-handler-invocations/out b/testing/btest/Baseline/scripts.base.frameworks.telemetry.event-handler-invocations/out new file mode 100644 index 0000000000..bc1ab6859b --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.telemetry.event-handler-invocations/out @@ -0,0 +1,4 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +zeek, event-handler-invocations, [zeek_init], 1 +zeek, event-handler-invocations, [connection_state_remove], 500 +zeek, event-handler-invocations, [zeek_done], 1 diff --git a/testing/btest/scripts/base/frameworks/telemetry/event-handler-invocations.zeek b/testing/btest/scripts/base/frameworks/telemetry/event-handler-invocations.zeek new file mode 100644 index 0000000000..e1a52792f5 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/telemetry/event-handler-invocations.zeek @@ -0,0 +1,21 @@ +# @TEST-DOC: Query for zeek event-handler-invocations metrics counting number of times handlers were called. + +# Note compilable to C++ due to globals being initialized to a record that +# has an opaque type as a field. +# @TEST-REQUIRES: test "${ZEEK_USE_CPP}" != "1" +# @TEST-EXEC: zcat <$TRACES/echo-connections.pcap.gz | zeek -b -Cr - %INPUT > out +# @TEST-EXEC: btest-diff out +# @TEST-EXEC-FAIL: test -f reporter.log + +@load base/frameworks/telemetry + + +event zeek_done() &priority=-100 + { + local ms = Telemetry::collect_metrics("zeek", "event-handler-invocations"); + for ( _, m in ms ) + { + if ( /zeek_.*|connection_.*/ in cat(m$labels)) + print m$opts$prefix, m$opts$name, m$labels, m$count_value; + } + }