diff --git a/userspace/falco/configuration.cpp b/userspace/falco/configuration.cpp index 1c328597..45d4222b 100644 --- a/userspace/falco/configuration.cpp +++ b/userspace/falco/configuration.cpp @@ -69,10 +69,7 @@ falco_configuration::falco_configuration(): m_metrics_interval(5000), m_metrics_stats_rule_enabled(false), m_metrics_output_file(""), - m_metrics_resource_utilization_enabled(true), - m_metrics_state_counters_enabled(true), - m_metrics_kernel_event_counters_enabled(true), - m_metrics_libbpf_stats_enabled(true), + m_metrics_flags((PPM_SCAP_STATS_KERNEL_COUNTERS | PPM_SCAP_STATS_LIBBPF_STATS | PPM_SCAP_STATS_RESOURCE_UTILIZATION | PPM_SCAP_STATS_STATE_COUNTERS)), m_metrics_convert_memory_to_mb(true), m_metrics_include_empty_values(false) { @@ -454,10 +451,29 @@ void falco_configuration::load_yaml(const std::string& config_name, const yaml_h m_metrics_interval = falco::utils::parse_prometheus_interval(m_metrics_interval_str); m_metrics_stats_rule_enabled = config.get_scalar("metrics.output_rule", false); m_metrics_output_file = config.get_scalar("metrics.output_file", ""); - m_metrics_resource_utilization_enabled = config.get_scalar("metrics.resource_utilization_enabled", true); - m_metrics_state_counters_enabled = config.get_scalar("metrics.state_counters_enabled", true); - m_metrics_kernel_event_counters_enabled = config.get_scalar("metrics.kernel_event_counters_enabled", true); - m_metrics_libbpf_stats_enabled = config.get_scalar("metrics.libbpf_stats_enabled", true); + + m_metrics_flags = 0; + if (config.get_scalar("metrics.resource_utilization_enabled", true)) + { + m_metrics_flags |= PPM_SCAP_STATS_RESOURCE_UTILIZATION; + + } + if (config.get_scalar("metrics.state_counters_enabled", true)) + { + m_metrics_flags |= PPM_SCAP_STATS_STATE_COUNTERS; + + } + if (config.get_scalar("metrics.kernel_event_counters_enabled", true)) + { + m_metrics_flags |= PPM_SCAP_STATS_KERNEL_COUNTERS; + + } + if (config.get_scalar("metrics.libbpf_stats_enabled", true)) + { + m_metrics_flags |= PPM_SCAP_STATS_LIBBPF_STATS; + + } + m_metrics_convert_memory_to_mb = config.get_scalar("metrics.convert_memory_to_mb", true); m_metrics_include_empty_values = config.get_scalar("metrics.include_empty_values", false); diff --git a/userspace/falco/configuration.h b/userspace/falco/configuration.h index 49749fcc..4b29aaed 100644 --- a/userspace/falco/configuration.h +++ b/userspace/falco/configuration.h @@ -158,10 +158,7 @@ public: uint64_t m_metrics_interval; bool m_metrics_stats_rule_enabled; std::string m_metrics_output_file; - bool m_metrics_resource_utilization_enabled; - bool m_metrics_state_counters_enabled; - bool m_metrics_kernel_event_counters_enabled; - bool m_metrics_libbpf_stats_enabled; + uint32_t m_metrics_flags; bool m_metrics_convert_memory_to_mb; bool m_metrics_include_empty_values; std::vector m_plugins; diff --git a/userspace/falco/stats_writer.cpp b/userspace/falco/stats_writer.cpp index 80678713..2be9f1ba 100644 --- a/userspace/falco/stats_writer.cpp +++ b/userspace/falco/stats_writer.cpp @@ -15,9 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -#ifndef _WIN32 #include -#endif #include #include #include @@ -35,11 +33,7 @@ limitations under the License. // overflows here. Threads calling stats_writer::handle() will just // check that this value changed since their last observation. static std::atomic s_timer((stats_writer::ticker_t) 0); -#if !defined(__APPLE__) && !defined(_WIN32) static timer_t s_timerid; -#else -static uint16_t s_timerid; -#endif // note: Workaround for older GLIBC versions (< 2.35), where calling timer_delete() // with an invalid timer ID not returned by timer_create() causes a segfault because of // a bug in GLIBC (https://sourceware.org/bugzilla/show_bug.cgi?id=28257). @@ -52,37 +46,6 @@ static void timer_handler(int signum) s_timer.fetch_add(1, std::memory_order_relaxed); } -#if defined(_WIN32) -bool stats_writer::init_ticker(uint32_t interval_msec, std::string &err) -{ - return true; -} -#endif - -#if defined(__APPLE__) -bool stats_writer::init_ticker(uint32_t interval_msec, std::string &err) -{ - struct sigaction handler = {}; - - memset (&handler, 0, sizeof(handler)); - handler.sa_handler = &timer_handler; - if (sigaction(SIGALRM, &handler, NULL) == -1) - { - err = std::string("Could not set up signal handler for periodic timer: ") + strerror(errno); - return false; - } - - struct sigevent sev = {}; - /* Create the timer */ - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIGALRM; - sev.sigev_value.sival_ptr = &s_timerid; - - return true; -} -#endif - -#if defined(EMSCRIPTEN) bool stats_writer::init_ticker(uint32_t interval_msec, std::string &err) { struct itimerspec timer = {}; @@ -95,40 +58,13 @@ bool stats_writer::init_ticker(uint32_t interval_msec, std::string &err) err = std::string("Could not set up signal handler for periodic timer: ") + strerror(errno); return false; } - - struct sigevent sev = {}; - /* Create the timer */ - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIGALRM; - sev.sigev_value.sival_ptr = &s_timerid; - - timer.it_value.tv_sec = interval_msec / 1000; - timer.it_value.tv_nsec = (interval_msec % 1000) * 1000 * 1000; - timer.it_interval = timer.it_value; - - return true; -} -#endif - -#if defined(__linux__) -bool stats_writer::init_ticker(uint32_t interval_msec, std::string &err) -{ - struct itimerspec timer = {}; - struct sigaction handler = {}; - - memset (&handler, 0, sizeof(handler)); - handler.sa_handler = &timer_handler; - if (sigaction(SIGALRM, &handler, NULL) == -1) - { - err = std::string("Could not set up signal handler for periodic timer: ") + strerror(errno); - return false; - } - + struct sigevent sev = {}; /* Create the timer */ sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGALRM; sev.sigev_value.sival_ptr = &s_timerid; +#ifndef __EMSCRIPTEN__ // delete any previously set timer if (s_timerid_exists) { @@ -147,19 +83,20 @@ bool stats_writer::init_ticker(uint32_t interval_msec, std::string &err) } s_timerid_exists = true; +#endif timer.it_value.tv_sec = interval_msec / 1000; timer.it_value.tv_nsec = (interval_msec % 1000) * 1000 * 1000; timer.it_interval = timer.it_value; +#ifndef __EMSCRIPTEN__ if (timer_settime(s_timerid, 0, &timer, NULL) == -1) { err = std::string("Could not set up periodic timer: ") + strerror(errno); return false; } - +#endif return true; } -#endif stats_writer::ticker_t stats_writer::get_ticker() { @@ -214,7 +151,7 @@ stats_writer::~stats_writer() m_file_output.close(); } // delete timerID and reset timer -#ifdef __linux__ +#ifndef __EMSCRIPTEN__ if (s_timerid_exists) { timer_delete(s_timerid); @@ -295,7 +232,7 @@ void stats_writer::worker() noexcept } catch(const std::exception &e) { - falco_logger::log(falco_logger::level::ERR, "stats_writer (worker): " + std::string(e.what()) + "\n"); + falco_logger::log(LOG_ERR, "stats_writer (worker): " + std::string(e.what()) + "\n"); } } } @@ -356,26 +293,15 @@ void stats_writer::collector::get_metrics_output_fields_additional( double stats_snapshot_time_delta_sec, const std::string& src) { const scap_agent_info* agent_info = inspector->get_agent_info(); + const scap_machine_info* machine_info = inspector->get_machine_info(); #if !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__) uint32_t nstats = 0; int32_t rc = 0; - uint32_t flags = 0; - - if (m_writer->m_config->m_metrics_resource_utilization_enabled) - { - /* Resource utilization, CPU and memory usage etc. */ - flags |= PPM_SCAP_STATS_RESOURCE_UTILIZATION; - } - - if (m_writer->m_config->m_metrics_state_counters_enabled) - { - /* Counters related to sinsp state (threadtable including fds per thread as well as container cache) */ - flags |= PPM_SCAP_STATS_STATE_COUNTERS; - } + uint32_t flags = m_writer->m_config->m_metrics_flags; auto buffer = inspector->get_sinsp_stats_v2_buffer(); - sinsp_stats_v2 sinsp_stats_v2 = inspector->get_sinsp_stats_v2(); + auto sinsp_stats_v2 = inspector->get_sinsp_stats_v2(); sinsp_thread_manager* thread_manager = inspector->m_thread_manager; const scap_stats_v2* sinsp_stats_v2_snapshot = libsinsp::stats::get_sinsp_stats_v2(flags, agent_info, thread_manager, sinsp_stats_v2, buffer, &nstats, &rc); @@ -450,18 +376,17 @@ void stats_writer::collector::get_metrics_output_fields_additional( /* Kernel side stats counters and libbpf stats if applicable. */ nstats = 0; rc = 0; - flags = 0; + if (!(inspector->check_current_engine(BPF_ENGINE) || inspector->check_current_engine(MODERN_BPF_ENGINE))) + { + flags &= ~PPM_SCAP_STATS_LIBBPF_STATS; + } + if (!(machine_info->flags & PPM_BPF_STATS_ENABLED)) + { + flags &= ~PPM_SCAP_STATS_LIBBPF_STATS; + } - if (m_writer->m_config->m_metrics_kernel_event_counters_enabled) - { - flags |= PPM_SCAP_STATS_KERNEL_COUNTERS; - } - if (m_writer->m_config->m_metrics_libbpf_stats_enabled && (inspector->check_current_engine(BPF_ENGINE) || inspector->check_current_engine(MODERN_BPF_ENGINE))) - { - flags |= PPM_SCAP_STATS_LIBBPF_STATS; - } - const scap_stats_v2* stats_v2_snapshot = inspector->get_capture_stats_v2(flags, &nstats, &rc); - if (stats_v2_snapshot && nstats > 0 && rc == 0) + const scap_stats_v2* scap_stats_v2_snapshot = inspector->get_capture_stats_v2(flags, &nstats, &rc); + if (scap_stats_v2_snapshot && nstats > 0 && rc == 0) { /* Cache n_evts and n_drops to derive n_drops_perc. */ uint64_t n_evts = 0; @@ -470,21 +395,21 @@ void stats_writer::collector::get_metrics_output_fields_additional( uint64_t n_drops_delta = 0; for(uint32_t stat = 0; stat < nstats; stat++) { - if (stats_v2_snapshot[stat].name[0] == '\0') + if (scap_stats_v2_snapshot[stat].name[0] == '\0') { break; } // todo: as we expand scap_stats_v2 prefix may be pushed to scap or we may need to expand // functionality here for example if we add userspace syscall counters that should be prefixed w/ `falco.` char metric_name[STATS_NAME_MAX] = "scap."; - strlcat(metric_name, stats_v2_snapshot[stat].name, sizeof(metric_name)); - switch(stats_v2_snapshot[stat].type) + strlcat(metric_name, scap_stats_v2_snapshot[stat].name, sizeof(metric_name)); + switch(scap_stats_v2_snapshot[stat].type) { case STATS_VALUE_TYPE_U64: /* Always send high level n_evts related fields, even if zero. */ - if (strncmp(stats_v2_snapshot[stat].name, "n_evts", 7) == 0) // exact not prefix match here + if (strncmp(scap_stats_v2_snapshot[stat].name, "n_evts", 7) == 0) // exact not prefix match here { - n_evts = stats_v2_snapshot[stat].value.u64; + n_evts = scap_stats_v2_snapshot[stat].value.u64; output_fields[metric_name] = n_evts; output_fields["scap.n_evts_prev"] = m_last_n_evts; n_evts_delta = n_evts - m_last_n_evts; @@ -500,9 +425,9 @@ void stats_writer::collector::get_metrics_output_fields_additional( m_last_n_evts = n_evts; } /* Always send high level n_drops related fields, even if zero. */ - else if (strncmp(stats_v2_snapshot[stat].name, "n_drops", 8) == 0) // exact not prefix match here + else if (strncmp(scap_stats_v2_snapshot[stat].name, "n_drops", 8) == 0) // exact not prefix match here { - n_drops = stats_v2_snapshot[stat].value.u64; + n_drops = scap_stats_v2_snapshot[stat].value.u64; output_fields[metric_name] = n_drops; output_fields["scap.n_drops_prev"] = m_last_n_drops; n_drops_delta = n_drops - m_last_n_drops; @@ -517,11 +442,11 @@ void stats_writer::collector::get_metrics_output_fields_additional( } m_last_n_drops = n_drops; } - if (stats_v2_snapshot[stat].value.u64 == 0 && !m_writer->m_config->m_metrics_include_empty_values) + if (scap_stats_v2_snapshot[stat].value.u64 == 0 && !m_writer->m_config->m_metrics_include_empty_values) { break; } - output_fields[metric_name] = stats_v2_snapshot[stat].value.u64; + output_fields[metric_name] = scap_stats_v2_snapshot[stat].value.u64; break; default: break;