zeek/src/DebugLogger.cc
2024-11-22 10:06:59 +01:00

189 lines
5.3 KiB
C++

#ifdef DEBUG
#include "zeek/DebugLogger.h"
#include <unistd.h>
#include <cstdlib>
#include "zeek/RunState.h"
#include "zeek/plugin/Plugin.h"
zeek::detail::DebugLogger zeek::detail::debug_logger;
zeek::detail::DebugLogger& debug_logger = zeek::detail::debug_logger;
namespace zeek::detail {
// Same order here as in DebugStream.
DebugLogger::Stream DebugLogger::streams[NUM_DBGS] =
{{"serial", 0, false}, {"rules", 0, false}, {"string", 0, false}, {"notifiers", 0, false},
{"main-loop", 0, false}, {"dpd", 0, false}, {"packet_analysis", 0, false}, {"file_analysis", 0, false},
{"tm", 0, false}, {"logging", 0, false}, {"input", 0, false}, {"threading", 0, false},
{"plugins", 0, false}, {"zeekygen", 0, false}, {"pktio", 0, false}, {"broker", 0, false},
{"scripts", 0, false}, {"supervisor", 0, false}, {"hashkey", 0, false}, {"spicy", 0, false},
{"cluster", 0, false}};
DebugLogger::DebugLogger() {
verbose = false;
file = nullptr;
}
DebugLogger::~DebugLogger() {
if ( file && file != stderr )
fclose(file);
}
void DebugLogger::OpenDebugLog(const char* filename) {
if ( filename ) {
filename = util::detail::log_file_name(filename);
file = fopen(filename, "w");
if ( ! file ) {
// The reporter may not be initialized here yet.
if ( reporter )
reporter->FatalError("can't open '%s' for debugging output", filename);
else {
fprintf(stderr, "can't open '%s' for debugging output\n", filename);
exit(1);
}
}
util::detail::setvbuf(file, NULL, _IOLBF, 0);
}
else
file = stderr;
}
void DebugLogger::ShowStreamsHelp() {
fprintf(stderr, "\n");
fprintf(stderr, "Enable debug output into debug.log with -B <streams>.\n");
fprintf(stderr, "<streams> is a comma-separated list of streams to enable.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Available streams:\n");
for ( int i = 0; i < NUM_DBGS; ++i )
fprintf(stderr, " %s\n", streams[i].prefix);
fprintf(stderr, "\n");
fprintf(stderr,
" plugin-<plugin-name> (replace '::' in name with '-'; e.g., '-B "
"plugin-Zeek-Netmap')\n");
fprintf(stderr, "\n");
fprintf(stderr, "Pseudo streams\n");
fprintf(stderr, " verbose Increase verbosity.\n");
fprintf(stderr, " all Enable all streams at maximum verbosity.\n");
fprintf(stderr, "\n");
}
void DebugLogger::EnableStreams(const char* s) {
char* brkt;
char* tmp = util::copy_string(s);
char* tok = strtok(tmp, ",");
while ( tok ) {
if ( strcasecmp("all", tok) == 0 ) {
for ( int i = 0; i < NUM_DBGS; ++i ) {
streams[i].enabled = true;
enabled_streams.insert(streams[i].prefix);
}
verbose = true;
goto next;
}
if ( strcasecmp("verbose", tok) == 0 ) {
verbose = true;
goto next;
}
if ( strcasecmp("help", tok) == 0 ) {
ShowStreamsHelp();
exit(0);
}
if ( util::starts_with(tok, "plugin-") ) {
// Cannot verify this at this time, plugins may not
// have been loaded.
enabled_streams.insert(tok);
goto next;
}
int i;
for ( i = 0; i < NUM_DBGS; ++i ) {
if ( strcasecmp(streams[i].prefix, tok) == 0 ) {
streams[i].enabled = true;
enabled_streams.insert(tok);
goto next;
}
}
reporter->FatalError("unknown debug stream '%s', try -B help.\n", tok);
next:
tok = strtok(0, ",");
}
delete[] tmp;
}
bool DebugLogger::CheckStreams(const std::set<std::string>& plugin_names) {
bool ok = true;
std::set<std::string> available_plugin_streams;
for ( const auto& p : plugin_names )
available_plugin_streams.insert(PluginStreamName(p));
for ( const auto& stream : enabled_streams ) {
if ( ! util::starts_with(stream, "plugin-") )
continue;
if ( available_plugin_streams.count(stream) == 0 ) {
reporter->Error("No plugin debug stream '%s' found", stream.c_str());
ok = false;
}
}
return ok;
}
void DebugLogger::Log(DebugStream stream, const char* fmt, ...) {
Stream* g = &streams[int(stream)];
if ( ! g->enabled )
return;
fprintf(file, "%17.06f/%17.06f [%s] ", run_state::network_time, util::current_time(true), g->prefix);
for ( int i = g->indent; i > 0; --i )
fputs(" ", file);
va_list ap;
va_start(ap, fmt);
vfprintf(file, fmt, ap);
va_end(ap);
fputc('\n', file);
fflush(file);
}
void DebugLogger::Log(const plugin::Plugin& plugin, const char* fmt, ...) {
std::string tok = PluginStreamName(plugin.Name());
if ( enabled_streams.find(tok) == enabled_streams.end() )
return;
fprintf(file, "%17.06f/%17.06f [plugin %s] ", run_state::network_time, util::current_time(true),
plugin.Name().c_str());
va_list ap;
va_start(ap, fmt);
vfprintf(file, fmt, ap);
va_end(ap);
fputc('\n', file);
fflush(file);
}
} // namespace zeek::detail
#endif