Skip to content

Commit

Permalink
refactor(userspae/libsinsp): api methods for controlling automatic ro…
Browse files Browse the repository at this point in the history
…utines

Signed-off-by: Jason Dellaluce <[email protected]>
  • Loading branch information
jasondellaluce authored and poiana committed Jan 22, 2024
1 parent 9d2ff1e commit e2734c7
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 48 deletions.
4 changes: 2 additions & 2 deletions userspace/libsinsp/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ bool sinsp_container_manager::remove_inactive_containers()

if(m_last_flush_time_ns == 0)
{
m_last_flush_time_ns = m_inspector->m_lastevent_ts - m_inspector->m_inactive_container_scan_time_ns + 30 * ONE_SECOND_IN_NS;
m_last_flush_time_ns = m_inspector->m_lastevent_ts - m_inspector->m_containers_purging_scan_time_ns + 30 * ONE_SECOND_IN_NS;
}

if(m_inspector->m_lastevent_ts >
m_last_flush_time_ns + m_inspector->m_inactive_container_scan_time_ns)
m_last_flush_time_ns + m_inspector->m_containers_purging_scan_time_ns)
{
res = true;

Expand Down
44 changes: 16 additions & 28 deletions userspace/libsinsp/sinsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ sinsp::sinsp(bool static_container, const std::string &static_id, const std::str
m_parser = new sinsp_parser(this);
m_thread_manager = new sinsp_thread_manager(this);
m_max_fdtable_size = MAX_FD_TABLE_SIZE;
m_inactive_container_scan_time_ns = DEFAULT_INACTIVE_CONTAINER_SCAN_TIME_S * ONE_SECOND_IN_NS;
m_deleted_users_groups_scan_time_ns = DEFAULT_DELETED_USERS_GROUPS_SCAN_TIME_S * ONE_SECOND_IN_NS;
m_containers_purging_scan_time_ns = DEFAULT_INACTIVE_CONTAINER_SCAN_TIME_S * ONE_SECOND_IN_NS;
m_usergroups_purging_scan_time_ns = DEFAULT_DELETED_USERS_GROUPS_SCAN_TIME_S * ONE_SECOND_IN_NS;
m_filter = NULL;
m_fds_to_remove = new std::vector<int64_t>;
m_machine_info = NULL;
Expand Down Expand Up @@ -1297,7 +1297,7 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
evt->m_evtnum = m_nevts;
m_lastevent_ts = ts;

if(m_automatic_threadtable_purging)
if (m_auto_threads_purging)
{
//
// Delayed removal of threads from the thread table, so that
Expand All @@ -1315,9 +1315,7 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
}
}

#ifndef HAS_ANALYZER

if(is_debug_enabled() && is_live())
if (m_auto_stats_print && is_debug_enabled() && is_live())
{
if(ts > m_next_stats_print_time_ns)
{
Expand All @@ -1330,18 +1328,15 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
}
}

//
// Run the periodic connection, thread and users/groups table cleanup
//
if(!is_offline())
if (m_auto_containers_purging && !is_offline())
{
m_container_manager.remove_inactive_containers();
}

#if !defined(CYGWING_AGENT) && !defined(MINIMAL_BUILD) && !defined(__EMSCRIPTEN__)
if (m_auto_usergroups_purging && !is_offline())
{
m_usergroup_manager.clear_host_users_groups();
#endif // !defined(CYGWING_AGENT) && !defined(MINIMAL_BUILD)
}
#endif // HAS_ANALYZER

//
// Delayed removal of the fd, so that
Expand Down Expand Up @@ -1662,7 +1657,10 @@ void sinsp::stop_capture()
}

/* Print scap stats */
print_capture_stats(sinsp_logger::SEV_DEBUG);
if (m_auto_stats_print)
{
print_capture_stats(sinsp_logger::SEV_DEBUG);
}

/* Print the number of threads and fds in our tables */
uint64_t thread_cnt = 0;
Expand Down Expand Up @@ -2042,16 +2040,6 @@ bool sinsp::remove_inactive_threads()
return m_thread_manager->remove_inactive_threads();
}

void sinsp::disable_automatic_threadtable_purging()
{
m_automatic_threadtable_purging = false;
}

void sinsp::set_thread_purge_interval_s(uint32_t val)
{
m_inactive_thread_scan_time_ns = (uint64_t)val * ONE_SECOND_IN_NS;
}

void sinsp::set_thread_timeout_s(uint32_t val)
{
m_thread_timeout_ns = (uint64_t)val * ONE_SECOND_IN_NS;
Expand Down Expand Up @@ -2105,20 +2093,20 @@ bool sinsp_thread_manager::remove_inactive_threads()
// Set the first table scan for 30 seconds in, so that we can spot bugs in the logic without having
// to wait for tens of minutes
//
if(m_inspector->m_inactive_thread_scan_time_ns > 30 * ONE_SECOND_IN_NS)
if(m_inspector->m_threads_purging_scan_time_ns > 30 * ONE_SECOND_IN_NS)
{
m_last_flush_time_ns =
(m_inspector->m_lastevent_ts - m_inspector->m_inactive_thread_scan_time_ns + 30 * ONE_SECOND_IN_NS);
(m_inspector->m_lastevent_ts - m_inspector->m_threads_purging_scan_time_ns + 30 * ONE_SECOND_IN_NS);
}
else
{
m_last_flush_time_ns =
(m_inspector->m_lastevent_ts - m_inspector->m_inactive_thread_scan_time_ns);
(m_inspector->m_lastevent_ts - m_inspector->m_threads_purging_scan_time_ns);
}
}

if(m_inspector->m_lastevent_ts >
m_last_flush_time_ns + m_inspector->m_inactive_thread_scan_time_ns)
m_last_flush_time_ns + m_inspector->m_threads_purging_scan_time_ns)
{
std::unordered_set<int64_t> to_delete;

Expand Down
81 changes: 69 additions & 12 deletions userspace/libsinsp/sinsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,18 +383,72 @@ class SINSP_PUBLIC sinsp : public capture_stats_source
void set_min_log_severity(sinsp_logger::severity sev);

/*!
* \brief set whether the library will automatically purge the threadtable
* at specific times. If not, client is responsible for thread lifetime
* management. If invoked, then the purge interval and thread timeout change
* defaults, but have no observable effect.
* \brief Enables or disables an automatic routine that periodically purges
* thread infos from the internal state. If disabled, the client is
* responsible of manually-handling the lifetime of threads.
* When the routine is run, then the purge interval and thread timeout
* change defaults, but with no observable effect.
*/
void disable_automatic_threadtable_purging();
void set_auto_threads_purging(bool enabled)
{
m_auto_threads_purging = enabled;
}

/*!
* \brief Sets the interval (in seconds) at which the automatic threads
* purging routine runs (if enabled).
*/
inline void set_auto_threads_purging_interval_s(uint32_t val)
{
m_threads_purging_scan_time_ns = (uint64_t)val * ONE_SECOND_IN_NS;
}

/*!
* \brief sets the interval at which the thread purge code runs. This does
* not run every event as it's mildly expensive if there are lots of threads
* \brief Enables or disables an automatic routine that periodically purges
* thread infos from the internal state. If disabled, the client is
* responsible of manually-handling the lifetime of containers.
*/
void set_thread_purge_interval_s(uint32_t val);
void set_auto_containers_purging(bool enabled)
{
m_auto_containers_purging = enabled;
}

/*!
* \brief Sets the interval (in seconds) at which the automatic containers
* purging routine runs (if enabled).
*/
inline void set_auto_containers_purging_interval_s(uint32_t val)
{
m_containers_purging_scan_time_ns = (uint64_t)val * ONE_SECOND_IN_NS;
}

/*!
* \brief Enables or disables an automatic routine that periodically purges
* users and groups infos from the internal state. If disabled, the client
* is responsible of manually-handling the lifetime of users and groups.
*/
void set_auto_usergroups_purging(bool enabled)
{
m_auto_usergroups_purging = enabled;
}

/*!
* \brief Sets the interval (in seconds) at which the automatic
* users and groups purging routine runs (if enabled).
*/
inline void set_auto_usergroups_purging_interval_s(uint32_t val)
{
m_usergroups_purging_scan_time_ns = (uint64_t)val * ONE_SECOND_IN_NS;
}

/*!
* \brief Enables or disables an automatic routine that periodically logs
* the current capture stats.
*/
inline void set_auto_stats_print(bool enabled)
{
m_auto_stats_print = enabled;
}

/*!
* \brief sets the amount of time after which a thread which has seen no events
Expand Down Expand Up @@ -1081,19 +1135,21 @@ VISIBILITY_PRIVATE
// Some thread table limits
//
uint32_t m_max_fdtable_size;
bool m_automatic_threadtable_purging = true;
bool m_auto_threads_purging = true;
uint64_t m_thread_timeout_ns = (uint64_t)1800 * ONE_SECOND_IN_NS;
uint64_t m_inactive_thread_scan_time_ns = (uint64_t)1200 * ONE_SECOND_IN_NS;
uint64_t m_threads_purging_scan_time_ns = (uint64_t)1200 * ONE_SECOND_IN_NS;

//
// Container limits
//
uint64_t m_inactive_container_scan_time_ns;
bool m_auto_containers_purging = true;
uint64_t m_containers_purging_scan_time_ns;

//
// Users/groups limits
//
uint64_t m_deleted_users_groups_scan_time_ns;
bool m_auto_usergroups_purging = true;
uint64_t m_usergroups_purging_scan_time_ns;

//
// How to render the data buffers
Expand Down Expand Up @@ -1185,6 +1241,7 @@ VISIBILITY_PRIVATE
//
// End of second housekeeping
//
bool m_auto_stats_print = true;
uint64_t m_next_stats_print_time_ns;

static unsigned int m_num_possible_cpus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ TEST_F(sinsp_with_test_input, container_manager_cache_threadtable_lifecycle)
ASSERT_EQ(test_container_id, container_info_check->m_id);

// Arbitrary time travel to invoke removal / flush logic remove_inactive_containers
m_inspector.m_inactive_container_scan_time_ns = 0;
m_inspector.m_containers_purging_scan_time_ns = 0;
m_inspector.m_container_manager.m_last_flush_time_ns = 1;
m_inspector.m_container_manager.remove_inactive_containers();
const sinsp_container_info::ptr_t container_info_check_not_removed = m_inspector.m_container_manager.get_container(test_container_id);
Expand All @@ -52,7 +52,7 @@ TEST_F(sinsp_with_test_input, container_manager_cache_threadtable_lifecycle)
// Mock remove test_container1 container from threadtable
tinfo = m_inspector.get_thread_ref(p4_t1_tid, false, true).get();
tinfo->m_container_id = "";
m_inspector.m_inactive_container_scan_time_ns = 0;
m_inspector.m_containers_purging_scan_time_ns = 0;
m_inspector.m_container_manager.m_last_flush_time_ns = 1;
m_inspector.m_container_manager.remove_inactive_containers();

Expand Down
2 changes: 1 addition & 1 deletion userspace/libsinsp/test/sinsp_with_test_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ class sinsp_with_test_input : public ::testing::Test {
{
/* We need to set these 2 variables to enable the remove_inactive_logic */
m_inspector.m_thread_manager->m_last_flush_time_ns = 1;
m_inspector.m_inactive_thread_scan_time_ns = 2;
m_inspector.m_threads_purging_scan_time_ns = 2;

m_inspector.m_lastevent_ts = m_lastevent_ts;
m_inspector.m_thread_timeout_ns = thread_timeout;
Expand Down
4 changes: 2 additions & 2 deletions userspace/libsinsp/user.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,11 @@ bool sinsp_usergroup_manager::clear_host_users_groups()

if(m_last_flush_time_ns == 0)
{
m_last_flush_time_ns = m_inspector->m_lastevent_ts - m_inspector->m_deleted_users_groups_scan_time_ns + 60 * ONE_SECOND_IN_NS;
m_last_flush_time_ns = m_inspector->m_lastevent_ts - m_inspector->m_usergroups_purging_scan_time_ns + 60 * ONE_SECOND_IN_NS;
}

if(m_inspector->m_lastevent_ts >
m_last_flush_time_ns + m_inspector->m_deleted_users_groups_scan_time_ns)
m_last_flush_time_ns + m_inspector->m_usergroups_purging_scan_time_ns)
{
res = true;

Expand Down
2 changes: 1 addition & 1 deletion userspace/libsinsp/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ namespace libsinsp { namespace procfs_utils { class ns_helper; }}
* * on PPME_{USER,GROUP}_ADDED, the new user/group is stored in the m_{user,group}_list<container_id>, if not present.
*
* * Host users and groups lists are cleared once every DEFAULT_DELETED_USERS_GROUPS_SCAN_TIME_S (1 min by default),
* see sinsp::m_deleted_users_groups_scan_time_ns.
* see sinsp::m_usergroups_purging_scan_time_ns.
* Then, the users and groups will be refreshed as explained above, every time a threadinfo is created.
* This is needed to fetch deleted users/groups, or overwritten ones.
* Note: PPME_USER_DELETED_E is never sent for host users; we miss
Expand Down

0 comments on commit e2734c7

Please sign in to comment.