diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index a4f5779af4..eebabff558 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -22,10 +22,10 @@ jobs: - name: Download latest master report uses: dawidd6/action-download-artifact@v6 with: - search_artifacts: true branch: master event: push name: perf_report + workflow: pages.yml - name: Diff from master - perf unit tests run: | @@ -132,4 +132,4 @@ jobs: tail -n 6 heaptrack_scap_diff.txt | grep "total memory leaked" | awk -F': ' '{print $2 }' | tr '.' ',' | numfmt --from=iec | awk '{if (substr($1,RSTART+RLENGTH)+0 > 0) print }' &> heaptrack_scap_diff_above_thresh.txt if [ -s heaptrack_scap_diff_above_thresh.txt ]; then exit 2 - fi \ No newline at end of file + fi diff --git a/userspace/libsinsp/container.cpp b/userspace/libsinsp/container.cpp index bee446b386..1ea31a1a78 100644 --- a/userspace/libsinsp/container.cpp +++ b/userspace/libsinsp/container.cpp @@ -50,6 +50,14 @@ sinsp_container_manager::sinsp_container_manager(sinsp* inspector, bool static_c m_static_image(static_image), m_container_engine_mask(~0ULL) { + if (m_inspector != nullptr) + { + m_sinsp_stats_v2 = m_inspector->get_sinsp_stats_v2(); + } + else + { + m_sinsp_stats_v2 = nullptr; + } } bool sinsp_container_manager::remove_inactive_containers() @@ -83,22 +91,22 @@ bool sinsp_container_manager::remove_inactive_containers() }); auto containers = m_containers.lock(); - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_missing_container_images = 0; + m_sinsp_stats_v2->m_n_missing_container_images = 0; // Will include pod sanboxes, but that's ok - m_inspector->get_sinsp_stats_v2()->m_n_containers = containers->size(); + m_sinsp_stats_v2->m_n_containers = containers->size(); } for(auto it = containers->begin(); it != containers->end();) { sinsp_container_info::ptr_t container = it->second; - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2) { auto container_info = container.get(); if (!container_info || (container_info && !container_info->m_is_pod_sandbox && container_info->m_image.empty())) { // Only count missing container images and exclude sandboxes - m_inspector->get_sinsp_stats_v2()->m_n_missing_container_images++; + m_sinsp_stats_v2->m_n_missing_container_images++; } } if(containers_in_use.find(it->first) == containers_in_use.end()) diff --git a/userspace/libsinsp/container.h b/userspace/libsinsp/container.h index 2bc3fb2344..1301acc79b 100644 --- a/userspace/libsinsp/container.h +++ b/userspace/libsinsp/container.h @@ -242,6 +242,7 @@ class sinsp_container_manager : std::map> m_container_engine_by_type; sinsp* m_inspector; + std::shared_ptr m_sinsp_stats_v2; libsinsp::Mutex>> m_containers; std::unordered_map> m_lookups; std::list m_new_callbacks; diff --git a/userspace/libsinsp/fdinfo.cpp b/userspace/libsinsp/fdinfo.cpp index af127b4164..b96a7e6762 100644 --- a/userspace/libsinsp/fdinfo.cpp +++ b/userspace/libsinsp/fdinfo.cpp @@ -298,6 +298,14 @@ sinsp_fdtable::sinsp_fdtable(sinsp* inspector) { m_tid = 0; m_inspector = inspector; + if (m_inspector != nullptr) + { + m_sinsp_stats_v2 = m_inspector->get_sinsp_stats_v2(); + } + else + { + m_sinsp_stats_v2 = nullptr; + } reset_cache(); } @@ -308,9 +316,9 @@ inline std::shared_ptr sinsp_fdtable::find_ref(int64_t fd) // if(m_last_accessed_fd != -1 && fd == m_last_accessed_fd) { - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2) { - m_inspector->get_sinsp_stats_v2()->m_n_cached_fd_lookups++; + m_sinsp_stats_v2->m_n_cached_fd_lookups++; } return m_last_accessed_fdinfo; } @@ -322,17 +330,17 @@ inline std::shared_ptr sinsp_fdtable::find_ref(int64_t fd) if(fdit == m_table.end()) { - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2) { - m_inspector->get_sinsp_stats_v2()->m_n_failed_fd_lookups++; + m_sinsp_stats_v2->m_n_failed_fd_lookups++; } - return NULL; + return nullptr; } else { - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_noncached_fd_lookups++; + m_sinsp_stats_v2->m_n_noncached_fd_lookups++; } m_last_accessed_fd = fd; @@ -369,9 +377,9 @@ inline std::shared_ptr sinsp_fdtable::add_ref(int64_t fd, std::uni // No entry in the table, this is the normal case // m_last_accessed_fd = -1; - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_added_fds++; + m_sinsp_stats_v2->m_n_added_fds++; } return m_table.emplace(fd, std::move(fdinfo)).first->second; @@ -440,19 +448,19 @@ bool sinsp_fdtable::erase(int64_t fd) // call that created this fd. The assertion will detect it, while in release mode we just // keep going. // - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_failed_fd_lookups++; + m_sinsp_stats_v2->m_n_failed_fd_lookups++; } return false; } else { m_table.erase(fdit); - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_noncached_fd_lookups++; - m_inspector->get_sinsp_stats_v2()->m_n_removed_fds++; + m_sinsp_stats_v2->m_n_noncached_fd_lookups++; + m_sinsp_stats_v2->m_n_removed_fds++; } return true; } diff --git a/userspace/libsinsp/fdinfo.h b/userspace/libsinsp/fdinfo.h index 7890916420..b3c42e52e5 100644 --- a/userspace/libsinsp/fdinfo.h +++ b/userspace/libsinsp/fdinfo.h @@ -438,6 +438,9 @@ class SINSP_PUBLIC sinsp_fdinfo : public libsinsp::state::table_entry /*@}*/ +// Forward declare sinsp_stats_v2 to avoid including metrics_collector.h here. +struct sinsp_stats_v2; + /////////////////////////////////////////////////////////////////////////////// // fd info table /////////////////////////////////////////////////////////////////////////////// @@ -547,6 +550,7 @@ class sinsp_fdtable : public libsinsp::state::table private: sinsp* m_inspector; std::unordered_map> m_table; + std::shared_ptr m_sinsp_stats_v2; // // Simple fd cache diff --git a/userspace/libsinsp/metrics_collector.cpp b/userspace/libsinsp/metrics_collector.cpp index a3fdff1b4c..a9a5beff24 100644 --- a/userspace/libsinsp/metrics_collector.cpp +++ b/userspace/libsinsp/metrics_collector.cpp @@ -449,6 +449,13 @@ uint64_t libs_metrics_collector::get_container_memory_used() const return memory_used; } +// Small helper to be used by sinsp_stats_v2_collectors as +// empty lambda return value. +static metrics_v2 null_metric() +{ + return metrics_v2{}; +} + void libs_metrics_collector::snapshot() { m_metrics.clear(); @@ -485,7 +492,6 @@ void libs_metrics_collector::snapshot() // METRICS_V2_STATE_COUNTERS related uint64_t n_fds = 0; uint64_t n_threads = 0; - std::shared_ptr sinsp_stats_v2 = m_inspector->get_sinsp_stats_v2(); const std::function sinsp_stats_v2_collectors[] = { [SINSP_RESOURCE_UTILIZATION_CPU_PERC] = [this,&cpu_usage_perc]() { @@ -576,151 +582,176 @@ void libs_metrics_collector::snapshot() METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT, n_fds); }, - [SINSP_STATS_V2_NONCACHED_FD_LOOKUPS] = [this,&sinsp_stats_v2]() { - return new_metric("n_noncached_fd_lookups", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_noncached_fd_lookups); + [SINSP_STATS_V2_NONCACHED_FD_LOOKUPS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_noncached_fd_lookups", METRICS_V2_STATE_COUNTERS, + METRIC_VALUE_TYPE_U64, METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_noncached_fd_lookups); + } + return null_metric(); }, - [SINSP_STATS_V2_CACHED_FD_LOOKUPS] = [this,&sinsp_stats_v2]() { - return new_metric("n_cached_fd_lookups", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_cached_fd_lookups); + [SINSP_STATS_V2_CACHED_FD_LOOKUPS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_cached_fd_lookups", METRICS_V2_STATE_COUNTERS, + METRIC_VALUE_TYPE_U64, METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_cached_fd_lookups); + } + return null_metric(); }, - [SINSP_STATS_V2_FAILED_FD_LOOKUPS] = [this,&sinsp_stats_v2]() { - return new_metric("n_failed_fd_lookups", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_failed_fd_lookups); + [SINSP_STATS_V2_FAILED_FD_LOOKUPS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_failed_fd_lookups", METRICS_V2_STATE_COUNTERS, + METRIC_VALUE_TYPE_U64, METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_failed_fd_lookups); + } + return null_metric(); }, - [SINSP_STATS_V2_ADDED_FDS] = [this,&sinsp_stats_v2]() { - return new_metric("n_added_fds", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_added_fds); + [SINSP_STATS_V2_ADDED_FDS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_added_fds", METRICS_V2_STATE_COUNTERS, METRIC_VALUE_TYPE_U64, + METRIC_VALUE_UNIT_COUNT, METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_added_fds); + } + return null_metric(); }, - [SINSP_STATS_V2_REMOVED_FDS] = [this,&sinsp_stats_v2]() { - return new_metric("n_removed_fds", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_removed_fds); + [SINSP_STATS_V2_REMOVED_FDS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_removed_fds", METRICS_V2_STATE_COUNTERS, METRIC_VALUE_TYPE_U64, + METRIC_VALUE_UNIT_COUNT, METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_removed_fds); + } + return null_metric(); }, - [SINSP_STATS_V2_STORED_EVTS] = [this,&sinsp_stats_v2]() { - return new_metric("n_stored_evts", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_stored_evts); + [SINSP_STATS_V2_STORED_EVTS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_stored_evts", METRICS_V2_STATE_COUNTERS, METRIC_VALUE_TYPE_U64, + METRIC_VALUE_UNIT_COUNT, METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_stored_evts); + } + return null_metric(); }, - [SINSP_STATS_V2_STORE_EVTS_DROPS] = [this,&sinsp_stats_v2]() { - return new_metric("n_store_evts_drops", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_store_evts_drops); + [SINSP_STATS_V2_STORE_EVTS_DROPS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_store_evts_drops", METRICS_V2_STATE_COUNTERS, + METRIC_VALUE_TYPE_U64, METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_store_evts_drops); + } + return null_metric(); }, - [SINSP_STATS_V2_RETRIEVED_EVTS] = [this,&sinsp_stats_v2]() { - return new_metric("n_retrieved_evts", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_retrieved_evts); + [SINSP_STATS_V2_RETRIEVED_EVTS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_retrieved_evts", METRICS_V2_STATE_COUNTERS, METRIC_VALUE_TYPE_U64, + METRIC_VALUE_UNIT_COUNT, METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_retrieved_evts); + } + return null_metric(); }, - [SINSP_STATS_V2_RETRIEVE_EVTS_DROPS] = [this,&sinsp_stats_v2]() { - return new_metric("n_retrieve_evts_drops", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_retrieve_evts_drops); + [SINSP_STATS_V2_RETRIEVE_EVTS_DROPS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_retrieve_evts_drops", METRICS_V2_STATE_COUNTERS, + METRIC_VALUE_TYPE_U64, METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_retrieve_evts_drops); + } + return null_metric(); }, - [SINSP_STATS_V2_NONCACHED_THREAD_LOOKUPS] = [this,&sinsp_stats_v2]() { - return new_metric("n_noncached_thread_lookups", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_noncached_thread_lookups); + [SINSP_STATS_V2_NONCACHED_THREAD_LOOKUPS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_noncached_thread_lookups", METRICS_V2_STATE_COUNTERS, + METRIC_VALUE_TYPE_U64, METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_noncached_thread_lookups); + } + return null_metric(); }, - [SINSP_STATS_V2_CACHED_THREAD_LOOKUPS] = [this,&sinsp_stats_v2]() { - return new_metric("n_cached_thread_lookups", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_cached_thread_lookups); + [SINSP_STATS_V2_CACHED_THREAD_LOOKUPS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_cached_thread_lookups", METRICS_V2_STATE_COUNTERS, + METRIC_VALUE_TYPE_U64, METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_cached_thread_lookups); + } + return null_metric(); }, - [SINSP_STATS_V2_FAILED_THREAD_LOOKUPS] = [this,&sinsp_stats_v2]() { - return new_metric("n_failed_thread_lookups", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_failed_thread_lookups); + [SINSP_STATS_V2_FAILED_THREAD_LOOKUPS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_failed_thread_lookups", METRICS_V2_STATE_COUNTERS, + METRIC_VALUE_TYPE_U64, METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_failed_thread_lookups); + } + return null_metric(); }, - [SINSP_STATS_V2_ADDED_THREADS] = [this,&sinsp_stats_v2]() { - return new_metric("n_added_threads", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_added_threads); + [SINSP_STATS_V2_ADDED_THREADS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_added_threads", METRICS_V2_STATE_COUNTERS, METRIC_VALUE_TYPE_U64, + METRIC_VALUE_UNIT_COUNT, METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_added_threads); + } + return null_metric(); }, - [SINSP_STATS_V2_REMOVED_THREADS] = [this,&sinsp_stats_v2]() { - return new_metric("n_removed_threads", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U64, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_removed_threads); + [SINSP_STATS_V2_REMOVED_THREADS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_removed_threads", METRICS_V2_STATE_COUNTERS, METRIC_VALUE_TYPE_U64, + METRIC_VALUE_UNIT_COUNT, METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_removed_threads); + } + return null_metric(); }, - [SINSP_STATS_V2_N_DROPS_FULL_THREADTABLE] = [this,&sinsp_stats_v2]() { - return new_metric("n_drops_full_threadtable", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U32, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_MONOTONIC, - sinsp_stats_v2->m_n_drops_full_threadtable); + [SINSP_STATS_V2_N_DROPS_FULL_THREADTABLE] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_drops_full_threadtable", METRICS_V2_STATE_COUNTERS, + METRIC_VALUE_TYPE_U32, METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_MONOTONIC, + m_sinsp_stats_v2->m_n_drops_full_threadtable); + } + return null_metric(); }, - [SINSP_STATS_V2_N_MISSING_CONTAINER_IMAGES] = [this,&sinsp_stats_v2]() { - return new_metric("n_missing_container_images", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U32, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT, - sinsp_stats_v2->m_n_missing_container_images); + [SINSP_STATS_V2_N_MISSING_CONTAINER_IMAGES] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_missing_container_images", METRICS_V2_STATE_COUNTERS, + METRIC_VALUE_TYPE_U32, METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT, + m_sinsp_stats_v2->m_n_missing_container_images); + } + return null_metric(); }, - [SINSP_STATS_V2_N_CONTAINERS] = [this,&sinsp_stats_v2]() { - return new_metric("n_containers", - METRICS_V2_STATE_COUNTERS, - METRIC_VALUE_TYPE_U32, - METRIC_VALUE_UNIT_COUNT, - METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT, - sinsp_stats_v2->m_n_containers); + [SINSP_STATS_V2_N_CONTAINERS] = [this]() { + if (m_sinsp_stats_v2) + { + return new_metric("n_containers", METRICS_V2_STATE_COUNTERS, METRIC_VALUE_TYPE_U32, + METRIC_VALUE_UNIT_COUNT, + METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT, + m_sinsp_stats_v2->m_n_containers); + } + return null_metric(); }, }; - static_assert(sizeof(sinsp_stats_v2_collectors) / sizeof(sinsp_stats_v2_collectors[0]) == SINSP_MAX_STATS_V2, "sinsp_stats_v2_resource_utilization_names array size does not match expected size"); - /* * libsinsp metrics */ - if((m_metrics_flags & METRICS_V2_RESOURCE_UTILIZATION)) { const scap_agent_info* agent_info = m_inspector->get_agent_info(); @@ -730,43 +761,48 @@ void libs_metrics_collector::snapshot() // Resource utilization of the agent itself for (int i = SINSP_RESOURCE_UTILIZATION_CPU_PERC; i <= SINSP_RESOURCE_UTILIZATION_HOST_FDS; i++) { - m_metrics.emplace_back(sinsp_stats_v2_collectors[i]()); + auto metric = sinsp_stats_v2_collectors[i](); + if (metric.name[0] != '\0') + { + // Check that metric is actually initialized, + // ie: it is not referencing m_sinsp_stats_v2 + // when sinsp stats are not enabled. + m_metrics.emplace_back(metric); + } } } if((m_metrics_flags & METRICS_V2_STATE_COUNTERS)) { - if (!sinsp_stats_v2) + auto thread_manager = m_inspector->m_thread_manager.get(); + if (thread_manager) { - m_inspector->set_sinsp_stats_v2_enabled(); - sinsp_stats_v2 = m_inspector->get_sinsp_stats_v2(); - } - - if (sinsp_stats_v2) - { - auto thread_manager = m_inspector->m_thread_manager.get(); - if (thread_manager) + n_threads = thread_manager->get_thread_count(); + threadinfo_map_t* threadtable = thread_manager->get_threads(); + if (threadtable) { - n_threads = thread_manager->get_thread_count(); - threadinfo_map_t* threadtable = thread_manager->get_threads(); - if (threadtable) + threadtable->loop([&n_fds] (sinsp_threadinfo& tinfo) { - threadtable->loop([&n_fds] (sinsp_threadinfo& tinfo) + sinsp_fdtable* fdtable = tinfo.get_fd_table(); + if (fdtable != nullptr) { - sinsp_fdtable* fdtable = tinfo.get_fd_table(); - if (fdtable != nullptr) - { - n_fds += fdtable->size(); - } - return true; - }); - } + n_fds += fdtable->size(); + } + return true; + }); } + } - // Resource utilization of the agent itself - for (int i = SINSP_STATS_V2_N_THREADS; i < SINSP_MAX_STATS_V2; i++) + // Resource utilization of the agent itself + for (int i = SINSP_STATS_V2_N_THREADS; i < SINSP_MAX_STATS_V2; i++) + { + auto metric = sinsp_stats_v2_collectors[i](); + if (metric.name[0] != '\0') { - m_metrics.emplace_back(sinsp_stats_v2_collectors[i]()); + // Check that metric is actually initialized, + // ie: it is not referencing m_sinsp_stats_v2 + // when sinsp stats are not enabled. + m_metrics.emplace_back(metric); } } } @@ -774,7 +810,6 @@ void libs_metrics_collector::snapshot() /* * plugins metrics */ - if(m_metrics_flags & METRICS_V2_PLUGINS) { for (auto& p : m_inspector->get_plugin_manager()->plugins()) @@ -799,6 +834,14 @@ libs_metrics_collector::libs_metrics_collector(sinsp* inspector, uint32_t flags) m_inspector(inspector), m_metrics_flags(flags) { + if (m_inspector != nullptr) + { + m_sinsp_stats_v2 = m_inspector->get_sinsp_stats_v2(); + } + else + { + m_sinsp_stats_v2 = nullptr; + } } } // namespace libs::metrics diff --git a/userspace/libsinsp/metrics_collector.h b/userspace/libsinsp/metrics_collector.h index 147ac0aeef..4f80e947f6 100644 --- a/userspace/libsinsp/metrics_collector.h +++ b/userspace/libsinsp/metrics_collector.h @@ -271,6 +271,7 @@ class libs_metrics_collector private: sinsp* m_inspector; + std::shared_ptr m_sinsp_stats_v2; uint32_t m_metrics_flags = METRICS_V2_KERNEL_COUNTERS | METRICS_V2_LIBBPF_STATS | METRICS_V2_RESOURCE_UTILIZATION | METRICS_V2_STATE_COUNTERS | METRICS_V2_PLUGINS; std::vector m_metrics; diff --git a/userspace/libsinsp/parsers.cpp b/userspace/libsinsp/parsers.cpp index 76c80d649b..514956cb8c 100644 --- a/userspace/libsinsp/parsers.cpp +++ b/userspace/libsinsp/parsers.cpp @@ -51,7 +51,14 @@ sinsp_parser::sinsp_parser(sinsp *inspector) : m_tmp_evt(m_inspector), m_syscall_event_source_idx(sinsp_no_event_source_idx) { - + if (m_inspector != nullptr) + { + m_sinsp_stats_v2 = m_inspector->get_sinsp_stats_v2(); + } + else + { + m_sinsp_stats_v2 = nullptr; + } } sinsp_parser::~sinsp_parser() @@ -678,9 +685,9 @@ bool sinsp_parser::reset(sinsp_evt *evt) etype == PPME_SYSCALL_VFORK_20_X || etype == PPME_SYSCALL_CLONE3_X) { - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_failed_thread_lookups--; + m_sinsp_stats_v2->m_n_failed_thread_lookups--; } } return false; @@ -829,9 +836,9 @@ void sinsp_parser::store_event(sinsp_evt *evt) // we won't be able to parse the corresponding exit event and we'll have // to drop the information it carries. // - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_store_evts_drops++; + m_sinsp_stats_v2->m_n_store_evts_drops++; } return; } @@ -865,9 +872,9 @@ void sinsp_parser::store_event(sinsp_evt *evt) memcpy(tinfo->get_last_event_data(), evt->get_scap_evt(), elen); tinfo->set_lastevent_cpuid(evt->get_cpuid()); - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_stored_evts++; + m_sinsp_stats_v2->m_n_stored_evts++; } } @@ -890,9 +897,9 @@ bool sinsp_parser::retrieve_enter_event(sinsp_evt *enter_evt, sinsp_evt *exit_ev // This happen especially at the beginning of trace files, where events // can be truncated // - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_retrieve_evts_drops++; + m_sinsp_stats_v2->m_n_retrieve_evts_drops++; } return false; } @@ -913,9 +920,9 @@ bool sinsp_parser::retrieve_enter_event(sinsp_evt *enter_evt, sinsp_evt *exit_ev && enter_evt->get_type() == PPME_SYSCALL_EXECVEAT_E) { - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_retrieved_evts++; + m_sinsp_stats_v2->m_n_retrieved_evts++; } return true; } @@ -928,15 +935,15 @@ bool sinsp_parser::retrieve_enter_event(sinsp_evt *enter_evt, sinsp_evt *exit_ev { //ASSERT(false); exit_evt->get_tinfo()->set_lastevent_data_validity(false); - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_retrieve_evts_drops++; + m_sinsp_stats_v2->m_n_retrieve_evts_drops++; } return false; } - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_retrieved_evts++; + m_sinsp_stats_v2->m_n_retrieved_evts++; } return true; @@ -3615,15 +3622,15 @@ void sinsp_parser::parse_close_exit(sinsp_evt *evt) // It is normal when a close fails that the fd lookup failed, so we revert the // increment of m_n_failed_fd_lookups (for the enter event too if there's one). // - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_failed_fd_lookups--; + m_sinsp_stats_v2->m_n_failed_fd_lookups--; } if(evt->get_tinfo() && evt->get_tinfo()->is_lastevent_data_valid()) { - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_failed_fd_lookups--; + m_sinsp_stats_v2->m_n_failed_fd_lookups--; } } } diff --git a/userspace/libsinsp/parsers.h b/userspace/libsinsp/parsers.h index 066c0b302c..51ad9c9fb7 100644 --- a/userspace/libsinsp/parsers.h +++ b/userspace/libsinsp/parsers.h @@ -147,6 +147,8 @@ class sinsp_parser // sinsp* m_inspector; + std::shared_ptr m_sinsp_stats_v2; + // // Temporary storage to avoid memory allocation // diff --git a/userspace/libsinsp/sinsp.cpp b/userspace/libsinsp/sinsp.cpp index 59068466a5..51c6a211cc 100644 --- a/userspace/libsinsp/sinsp.cpp +++ b/userspace/libsinsp/sinsp.cpp @@ -64,8 +64,9 @@ int32_t on_new_entry_from_proc(void* context, char* error, int64_t tid, scap_thr /////////////////////////////////////////////////////////////////////////////// std::atomic sinsp::instance_count{0}; -sinsp::sinsp(bool static_container, const std::string &static_id, const std::string &static_name, const std::string &static_image) : +sinsp::sinsp(bool static_container, const std::string &static_id, const std::string &static_name, const std::string &static_image, bool with_metrics) : m_external_event_processor(), + m_sinsp_stats_v2(with_metrics ? std::make_shared() : nullptr), m_evt(this), m_lastevent_ts(0), m_host_root(scap_get_host_root()), @@ -80,6 +81,7 @@ sinsp::sinsp(bool static_container, const std::string &static_id, const std::str // used by container_manager curl_global_init(CURL_GLOBAL_DEFAULT); #endif + m_h = NULL; m_parser = NULL; m_is_dumping = false; @@ -104,7 +106,6 @@ sinsp::sinsp(bool static_container, const std::string &static_id, const std::str m_next_flush_time_ns = 0; m_last_procrequest_tod = 0; m_get_procs_cpu_from_driver = false; - m_flush_memory_dump = false; m_next_stats_print_time_ns = 0; m_large_envs_enabled = false; m_increased_snaplen_port_range = DEFAULT_INCREASE_SNAPLEN_PORT_RANGE; @@ -1967,31 +1968,6 @@ void sinsp::set_proc_scan_log_interval_ms(uint64_t val) m_proc_scan_log_interval_ms = val; } -void sinsp::set_sinsp_stats_v2_enabled() -{ - if (m_sinsp_stats_v2 == nullptr) - { - m_sinsp_stats_v2 = std::make_unique(); - m_sinsp_stats_v2->m_n_noncached_fd_lookups = 0; - m_sinsp_stats_v2->m_n_cached_fd_lookups = 0; - m_sinsp_stats_v2->m_n_failed_fd_lookups = 0; - m_sinsp_stats_v2->m_n_added_fds = 0; - m_sinsp_stats_v2->m_n_removed_fds = 0; - m_sinsp_stats_v2->m_n_stored_evts = 0; - m_sinsp_stats_v2->m_n_store_evts_drops = 0; - m_sinsp_stats_v2->m_n_retrieved_evts = 0; - m_sinsp_stats_v2->m_n_retrieve_evts_drops = 0; - m_sinsp_stats_v2->m_n_noncached_thread_lookups = 0; - m_sinsp_stats_v2->m_n_cached_thread_lookups = 0; - m_sinsp_stats_v2->m_n_failed_thread_lookups = 0; - m_sinsp_stats_v2->m_n_added_threads = 0; - m_sinsp_stats_v2->m_n_removed_threads = 0; - m_sinsp_stats_v2->m_n_drops_full_threadtable = 0; - m_sinsp_stats_v2->m_n_missing_container_images = 0; - m_sinsp_stats_v2->m_n_containers= 0; - } -} - /////////////////////////////////////////////////////////////////////////////// // Note: this is defined here so we can inline it in sinso::next /////////////////////////////////////////////////////////////////////////////// diff --git a/userspace/libsinsp/sinsp.h b/userspace/libsinsp/sinsp.h index 6e53c199db..de9c394f31 100644 --- a/userspace/libsinsp/sinsp.h +++ b/userspace/libsinsp/sinsp.h @@ -161,7 +161,8 @@ class SINSP_PUBLIC sinsp : public capture_stats_source sinsp(bool static_container = false, const std::string &static_id = "", const std::string &static_name = "", - const std::string &static_image = ""); + const std::string &static_image = "", + bool with_metrics = false); virtual ~sinsp() override; @@ -438,11 +439,6 @@ class SINSP_PUBLIC sinsp : public capture_stats_source */ void set_proc_scan_log_interval_ms(uint64_t val); - /*! - * \brief enabling sinsp state counters on the hot path via initializing the respective smart pointer. - */ - void set_sinsp_stats_v2_enabled(); - /*! \brief Returns a new instance of a filtercheck supporting fields for a generic event source (e.g. evt.num, evt.time, evt.pluginname...) @@ -700,7 +696,7 @@ class SINSP_PUBLIC sinsp : public capture_stats_source /*! \brief Returns true if truncated environments should be loaded from /proc */ - inline bool large_envs_enabled() + inline bool large_envs_enabled() const { return (is_live() || is_syscall_plugin()) && m_large_envs_enabled; } @@ -1158,6 +1154,7 @@ class SINSP_PUBLIC sinsp : public capture_stats_source return left == static_cast(-1) || left <= right; } + std::shared_ptr m_sinsp_stats_v2; scap_t* m_h; struct scap_platform* m_platform {}; char m_platform_lasterr[SCAP_LASTERR_SIZE]; @@ -1188,9 +1185,7 @@ class SINSP_PUBLIC sinsp : public capture_stats_source bool m_is_dumping; const scap_machine_info* m_machine_info; const scap_agent_info* m_agent_info; - std::shared_ptr m_sinsp_stats_v2; uint32_t m_num_cpus; - bool m_flush_memory_dump; bool m_large_envs_enabled; sinsp_network_interfaces m_network_interfaces {}; diff --git a/userspace/libsinsp/test/sinsp_metrics.ut.cpp b/userspace/libsinsp/test/sinsp_metrics.ut.cpp index f3bc8c08fc..23f60d8db9 100644 --- a/userspace/libsinsp/test/sinsp_metrics.ut.cpp +++ b/userspace/libsinsp/test/sinsp_metrics.ut.cpp @@ -23,9 +23,6 @@ limitations under the License. TEST_F(sinsp_with_test_input, sinsp_libs_metrics_collector_prometheus) { - m_inspector.set_sinsp_stats_v2_enabled(); - // Extra call to verify that we don't fail - m_inspector.set_sinsp_stats_v2_enabled(); DEFAULT_TREE auto evt = generate_random_event(p2_t1_tid); ASSERT_EQ(get_field_as_string(evt, "proc.nthreads"), "3"); @@ -249,9 +246,6 @@ testns_falco_host_boot_timestamp_nanoseconds{raw_name="host_boot_ts"} 1708753667 TEST_F(sinsp_with_test_input, sinsp_libs_metrics_collector_output_rule) { - m_inspector.set_sinsp_stats_v2_enabled(); - // Extra call to verify that we don't fail - m_inspector.set_sinsp_stats_v2_enabled(); DEFAULT_TREE auto evt = generate_random_event(p2_t1_tid); ASSERT_EQ(get_field_as_string(evt, "proc.nthreads"), "3"); @@ -317,7 +311,7 @@ TEST_F(sinsp_with_test_input, sinsp_libs_metrics_collector_output_rule) if (std::find(metrics_names_values_gt.begin(), metrics_names_values_gt.end(), metric.name) != metrics_names_values_gt.end()) { ASSERT_GT(metric.value.u64, 0); - // Just making sure we don't get a high value due to an unitialized variables + // Just making sure we don't get a high value due to an uninitialized variables ASSERT_LT(metric.value.u64, 106721347371); success_values_cnt++; } diff --git a/userspace/libsinsp/test/sinsp_with_test_input.h b/userspace/libsinsp/test/sinsp_with_test_input.h index fc569f0bcb..9057ffb76d 100644 --- a/userspace/libsinsp/test/sinsp_with_test_input.h +++ b/userspace/libsinsp/test/sinsp_with_test_input.h @@ -40,7 +40,7 @@ class sinsp_with_test_input : public ::testing::Test sinsp_with_test_input(); ~sinsp_with_test_input(); - sinsp m_inspector; + sinsp m_inspector = sinsp(false, "", "", "", true); void open_inspector(sinsp_mode_t mode = SINSP_MODE_TEST); diff --git a/userspace/libsinsp/threadinfo.cpp b/userspace/libsinsp/threadinfo.cpp index 0ec2972b57..a856098d77 100644 --- a/userspace/libsinsp/threadinfo.cpp +++ b/userspace/libsinsp/threadinfo.cpp @@ -1388,6 +1388,14 @@ sinsp_thread_manager::sinsp_thread_manager(sinsp* inspector) m_fdtable_dyn_fields(std::make_shared()) { m_inspector = inspector; + if (m_inspector != nullptr) + { + m_sinsp_stats_v2 = m_inspector->get_sinsp_stats_v2(); + } + else + { + m_sinsp_stats_v2 = nullptr; + } clear(); } @@ -1493,15 +1501,15 @@ std::shared_ptr sinsp_thread_manager::add_thread(std::unique_p && threadinfo->m_pid != m_inspector->m_self_pid ) { - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { // rate limit messages to avoid spamming the logs - if (m_inspector->get_sinsp_stats_v2()->m_n_drops_full_threadtable % m_max_thread_table_size == 0) + if (m_sinsp_stats_v2->m_n_drops_full_threadtable % m_max_thread_table_size == 0) { libsinsp_logger()->format(sinsp_logger::SEV_INFO, "Thread table full, dropping tid %lu (pid %lu, comm \"%s\")", threadinfo->m_tid, threadinfo->m_pid, threadinfo->m_comm.c_str()); } - m_inspector->get_sinsp_stats_v2()->m_n_drops_full_threadtable++; + m_sinsp_stats_v2->m_n_drops_full_threadtable++; } return nullptr; } @@ -1526,9 +1534,9 @@ std::shared_ptr sinsp_thread_manager::add_thread(std::unique_p tinfo_shared_ptr->compute_program_hash(); m_threadtable.put(tinfo_shared_ptr); - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_added_threads++; + m_sinsp_stats_v2->m_n_added_threads++; } return tinfo_shared_ptr; @@ -1674,9 +1682,9 @@ void sinsp_thread_manager::remove_thread(int64_t tid) if(thread_to_remove == nullptr) { // Extra m_inspector nullptr check - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_failed_thread_lookups++; + m_sinsp_stats_v2->m_n_failed_thread_lookups++; } return; } @@ -1796,9 +1804,9 @@ void sinsp_thread_manager::remove_thread(int64_t tid) * the cache just to be sure. */ m_last_tid = -1; - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_removed_threads++; + m_sinsp_stats_v2->m_n_removed_threads++; } } @@ -2140,9 +2148,9 @@ threadinfo_map_t::ptr_t sinsp_thread_manager::find_thread(int64_t tid, bool look thr = m_last_tinfo.lock(); if (thr) { - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_cached_thread_lookups++; + m_sinsp_stats_v2->m_n_cached_thread_lookups++; } // This allows us to avoid performing an actual timestamp lookup // for something that may not need to be precise @@ -2158,9 +2166,9 @@ threadinfo_map_t::ptr_t sinsp_thread_manager::find_thread(int64_t tid, bool look if(thr) { - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_noncached_thread_lookups++; + m_sinsp_stats_v2->m_n_noncached_thread_lookups++; } if(!lookup_only) { @@ -2173,9 +2181,9 @@ threadinfo_map_t::ptr_t sinsp_thread_manager::find_thread(int64_t tid, bool look } else { - if (m_inspector != nullptr && m_inspector->get_sinsp_stats_v2()) + if (m_sinsp_stats_v2 != nullptr) { - m_inspector->get_sinsp_stats_v2()->m_n_failed_thread_lookups++; + m_sinsp_stats_v2->m_n_failed_thread_lookups++; } return NULL; } diff --git a/userspace/libsinsp/threadinfo.h b/userspace/libsinsp/threadinfo.h index 47fd5d46a1..ec428de4da 100644 --- a/userspace/libsinsp/threadinfo.h +++ b/userspace/libsinsp/threadinfo.h @@ -1016,6 +1016,8 @@ class SINSP_PUBLIC sinsp_thread_manager: public libsinsp::state::table void free_dump_fdinfos(std::vector* fdinfos_to_free); sinsp* m_inspector; + std::shared_ptr m_sinsp_stats_v2; + /* the key is the pid of the group, and the value is a shared pointer to the thread_group_info */ std::unordered_map> m_thread_groups; threadinfo_map_t m_threadtable;