#include <sstream>
#include <queue>
#include <algorithm>
+#include <cstdarg>
#include "appid_session.h"
#include "appid_cpu_profile_table.h"
+#include "control/control.h"
using namespace snort;
+
#define TABLE_HEADER(num_rows) "AppId Performance Statistics (top %d appids)\n===================================================================================================================================================\n", num_rows
static const char* columns = " AppId App Name Usecs Pkts AvgUsecs/Pkt Sessions AvgUsecs/Sess MaxPkts/Sess MaxUsecs/Sess %%/Total\n";
static const char* partition = "---------------------------------------------------------------------------------------------------------------------------------------------------\n";
return numStr;
}
+static void print_log(ControlConn* ctrlcon, AppidCPUProfilerOutputType output_type, int level, const char* format, ...)
+{
+ static std::vector<char> buffer(STD_BUF);
+
+ va_list args;
+ va_start(args, format);
+
+ int response_len = std::vsnprintf(buffer.data(), buffer.size(), format, args);
+
+ va_end(args);
+
+ if (response_len < 0 || static_cast<size_t>(response_len) >= buffer.size())
+ return;
+
+ switch (output_type)
+ {
+ case OUTPUT_CONSOLE:
+ LogRespond(ctrlcon, "%s", buffer.data());
+ break;
+ case OUPUT_LOGFILE:
+ appid_log(nullptr, level, "%s", buffer.data());
+ break;
+ default:
+ break;
+ }
+}
+
// Comparator for priority queue based on avg_processing_time/session
struct CompareByAvgProcessingTime {
bool operator()(const std::pair<AppId, AppidCPUProfilerStats>& a, const std::pair<AppId, AppidCPUProfilerStats>& b) const {
}
};
-AppidCpuTableDisplayStatus AppidCPUProfilingManager::display_appid_cpu_profiler_table(AppId appid, OdpContext& odp_ctxt)
+AppidCpuTableDisplayStatus AppidCPUProfilingManager::display_appid_cpu_profiler_table(AppId appid, OdpContext& odp_ctxt, ControlConn* ctrlcon)
{
+ AppidCPUProfilerOutputType output_type = OUPUT_LOGFILE;
+
if (odp_ctxt.is_appid_cpu_profiler_running())
return DISPLAY_ERROR_APPID_PROFILER_RUNNING;
else if (appid_cpu_profiling_table.empty())
return DISPLAY_ERROR_TABLE_EMPTY;
+ if (ctrlcon)
+ output_type = OUTPUT_CONSOLE;
+
auto bucket = appid_cpu_profiling_table.find(appid);
if (bucket != appid_cpu_profiling_table.end())
{
- appid_log(nullptr, TRACE_INFO_LEVEL, TABLE_HEADER(1));
- appid_log(nullptr, TRACE_INFO_LEVEL, columns);
- appid_log(nullptr, TRACE_INFO_LEVEL, partition);
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL, TABLE_HEADER(1));
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL, columns);
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL, partition);
- appid_log(nullptr, TRACE_INFO_LEVEL, " %5d %-15.15s %14.14s %10.10s %15.14s %11.11s %16.14s %15.14s %15.14s %10.2f\n",
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL, " %5d %-15.15s %14.14s %10.10s %15.14s %11.11s %16.14s %15.14s %15.14s %10.2f\n",
appid, bucket->second.app_name.c_str(), FormatWithCommas(bucket->second.processing_time).c_str(), FormatWithCommas(bucket->second.processed_packets).c_str(),
FormatWithCommas(bucket->second.processing_time/bucket->second.processed_packets).c_str(), FormatWithCommas(bucket->second.per_appid_sessions).c_str(),
FormatWithCommas(bucket->second.processing_time/bucket->second.per_appid_sessions).c_str(), FormatWithCommas(bucket->second.max_processed_pkts_per_session).c_str(),
- FormatWithCommas(bucket->second.max_processing_time_per_session).c_str(), (static_cast<float>(bucket->second.processing_time)/total_processing_time)*100);
+ FormatWithCommas(bucket->second.max_processing_time_per_session).c_str(), static_cast<float>(bucket->second.processing_time)/static_cast<float>(total_processing_time)*100);
}
else
{
- appid_log(nullptr, TRACE_INFO_LEVEL,"Appid %d not found in the table\n", appid);
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL,"Appid %d not found in the table\n", appid);
}
return DISPLAY_SUCCESS;
}
-AppidCpuTableDisplayStatus AppidCPUProfilingManager::display_appid_cpu_profiler_table(OdpContext& odp_ctxt, uint32_t display_rows_limit, bool override_running_flag)
+AppidCpuTableDisplayStatus AppidCPUProfilingManager::display_appid_cpu_profiler_table(OdpContext& odp_ctxt, uint32_t display_rows_limit, bool override_running_flag, ControlConn* ctrlcon)
{
+ AppidCPUProfilerOutputType output_type = OUPUT_LOGFILE;
+
if (odp_ctxt.is_appid_cpu_profiler_running() and !override_running_flag)
return DISPLAY_ERROR_APPID_PROFILER_RUNNING;
else if (appid_cpu_profiling_table.empty())
for (const auto& entry : appid_cpu_profiling_table)
sorted_appid_cpu_profiler_table.push(entry);
+ if (ctrlcon)
+ output_type = OUTPUT_CONSOLE;
+
display_rows_limit = static_cast<uint32_t>(std::min({static_cast<size_t>(display_rows_limit), sorted_appid_cpu_profiler_table.size(), static_cast<size_t>(APPID_CPU_PROFILER_MAX_DISPLAY_ROWS)}));
- appid_log(nullptr, TRACE_INFO_LEVEL, TABLE_HEADER(display_rows_limit));
- appid_log(nullptr, TRACE_INFO_LEVEL, columns);
- appid_log(nullptr, TRACE_INFO_LEVEL, partition);
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL, TABLE_HEADER(display_rows_limit));
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL, columns);
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL, partition);
uint32_t rows_displayed = 0;
if (!entry.second.processed_packets or !entry.second.per_appid_sessions)
continue;
- appid_log(nullptr, TRACE_INFO_LEVEL, " %5d %-15.15s %14.14s %10.10s %15.14s %11.11s %16.14s %15.14s %15.14s %10.2f\n",
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL, " %5d %-15.15s %14.14s %10.10s %15.14s %11.11s %16.14s %15.14s %15.14s %10.2f\n",
entry.first, entry.second.app_name.c_str(), FormatWithCommas(entry.second.processing_time).c_str(), FormatWithCommas(entry.second.processed_packets).c_str(),
FormatWithCommas(entry.second.processing_time/entry.second.processed_packets).c_str(), FormatWithCommas(entry.second.per_appid_sessions).c_str(),
FormatWithCommas(entry.second.processing_time/entry.second.per_appid_sessions).c_str(), FormatWithCommas(entry.second.max_processed_pkts_per_session).c_str(),
- FormatWithCommas(entry.second.max_processing_time_per_session).c_str(), (static_cast<float>(entry.second.processing_time)/total_processing_time)*100);
+ FormatWithCommas(entry.second.max_processing_time_per_session).c_str(), static_cast<float>(entry.second.processing_time)/static_cast<float>(total_processing_time)*100);
rows_displayed += 1;
}
- appid_log(nullptr, TRACE_INFO_LEVEL, partition);
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL, partition);
- appid_log(nullptr, TRACE_INFO_LEVEL, "Totals(all_sessions) : %15.15s %10.10s %15.14s %10.10s %15.15s %15.14s %16.15s %9d\n",
+ print_log(ctrlcon, output_type, TRACE_INFO_LEVEL, "Totals(all_sessions) : %15.15s %10.10s %15.14s %10.10s %15.15s %15.14s %16.15s %9d\n",
FormatWithCommas(total_processing_time).c_str(), FormatWithCommas(total_processed_packets).c_str(), FormatWithCommas(total_processing_time/total_processed_packets).c_str(),
FormatWithCommas(total_per_appid_sessions).c_str(), FormatWithCommas(total_processing_time/total_per_appid_sessions).c_str(),
FormatWithCommas(max_processed_pkts_per_session).c_str(), FormatWithCommas(max_processing_time_per_session).c_str(), 100);