diff --git a/src/Stats.cc b/src/Stats.cc index 27b433c9ee..f418e9cccc 100644 --- a/src/Stats.cc +++ b/src/Stats.cc @@ -224,7 +224,7 @@ void ProfileLogger::Log() i != thread_stats.end(); ++i ) { threading::MsgThread::Stats s = i->second; - file->Write(fmt("%0.6f %-15s in=%" PRIu64 " out=%" PRIu64 " pending=%" PRIu64 "/%" PRIu64 "\n", + file->Write(fmt("%0.6f %-25s in=%" PRIu64 " out=%" PRIu64 " pending=%" PRIu64 "/%" PRIu64 "\n", network_time, i->first.c_str(), s.sent_in, s.sent_out, diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 63d4c60a5c..6d53ea363f 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -480,6 +480,8 @@ WriterBackend* Manager::CreateBackend(WriterFrontend* frontend, bro_int_t type) WriterBackend* backend = (*ld->factory)(frontend); assert(backend); + + frontend->ty_name = ld->name; return backend; } diff --git a/src/logging/WriterBackend.cc b/src/logging/WriterBackend.cc index fe3a6ef560..4d2e497b14 100644 --- a/src/logging/WriterBackend.cc +++ b/src/logging/WriterBackend.cc @@ -55,13 +55,15 @@ public: using namespace logging; -WriterBackend::WriterBackend(WriterFrontend* arg_frontend, const string& name) : MsgThread(name) +WriterBackend::WriterBackend(WriterFrontend* arg_frontend) : MsgThread() { path = ""; num_fields = 0; fields = 0; buffering = true; frontend = arg_frontend; + + SetName(frontend->Name()); } WriterBackend::~WriterBackend() @@ -107,6 +109,8 @@ bool WriterBackend::Init(string arg_path, int arg_num_fields, const Field* const num_fields = arg_num_fields; fields = arg_fields; + SetName(frontend->Name()); + if ( ! DoInit(arg_path, arg_num_fields, arg_fields) ) { DisableFrontend(); diff --git a/src/logging/WriterBackend.h b/src/logging/WriterBackend.h index 21dcd41ff7..33271e43f9 100644 --- a/src/logging/WriterBackend.h +++ b/src/logging/WriterBackend.h @@ -34,7 +34,7 @@ public: * @param name A descriptive name for writer's type (e.g., \c Ascii). * */ - WriterBackend(WriterFrontend* frontend, const string& name); + WriterBackend(WriterFrontend* frontend); /** * Destructor. diff --git a/src/logging/WriterFrontend.cc b/src/logging/WriterFrontend.cc index 79c180b749..79278870f9 100644 --- a/src/logging/WriterFrontend.cc +++ b/src/logging/WriterFrontend.cc @@ -99,6 +99,7 @@ WriterFrontend::WriterFrontend(bro_int_t type) buf = true; write_buffer = 0; write_buffer_pos = 0; + ty_name = ""; backend = log_mgr->CreateBackend(this, type); assert(backend); @@ -109,6 +110,14 @@ WriterFrontend::~WriterFrontend() { } +string WriterFrontend::Name() const + { + if ( path.size() ) + return ty_name; + + return ty_name + "/" + path; + } + void WriterFrontend::Stop() { FlushWriteBuffer(); diff --git a/src/logging/WriterFrontend.h b/src/logging/WriterFrontend.h index 6f1bb4ea1b..e0bc590dfc 100644 --- a/src/logging/WriterFrontend.h +++ b/src/logging/WriterFrontend.h @@ -30,6 +30,9 @@ public: * frontend will internally instantiate a WriterBackend of the * corresponding type. * + * name: A descriptive name for the backend wroter type (e.g., \c + * Ascii). + * * Frontends must only be instantiated by the main thread. */ WriterFrontend(bro_int_t type); @@ -171,6 +174,14 @@ public: */ int NumFields() const { return num_fields; } + /** + * Returns a descriptive name for the writer, including the type of + * the backend and the path used. + * + * This method is safe to call from any thread. + */ + string Name() const; + /** * Returns the log fields as passed into the constructor. */ @@ -184,6 +195,7 @@ protected: bool initialized; // True if initialized. bool buf; // True if buffering is enabled (default). + string ty_name; // Name of the backend type. Set by the manager. string path; // The log path. int num_fields; // The number of log fields. const Field* const* fields; // The log fields. diff --git a/src/logging/writers/Ascii.cc b/src/logging/writers/Ascii.cc index 0e522dde1d..7cc8459e68 100644 --- a/src/logging/writers/Ascii.cc +++ b/src/logging/writers/Ascii.cc @@ -10,7 +10,7 @@ using namespace logging; using namespace writer; -Ascii::Ascii(WriterFrontend* frontend) : WriterBackend(frontend, "Ascii") +Ascii::Ascii(WriterFrontend* frontend) : WriterBackend(frontend) { file = 0; diff --git a/src/logging/writers/None.h b/src/logging/writers/None.h index 19dc685ecb..6a62161f49 100644 --- a/src/logging/writers/None.h +++ b/src/logging/writers/None.h @@ -11,7 +11,7 @@ namespace logging { namespace writer { class None : public WriterBackend { public: - None(WriterFrontend* frontend) : WriterBackend(frontend, "None") {} + None(WriterFrontend* frontend) : WriterBackend(frontend) {} ~None() {}; static WriterBackend* Instantiate(WriterFrontend* frontend) diff --git a/src/threading/BasicThread.cc b/src/threading/BasicThread.cc index 73dc562b31..4d51c3c4e4 100644 --- a/src/threading/BasicThread.cc +++ b/src/threading/BasicThread.cc @@ -9,7 +9,7 @@ using namespace threading; uint64_t BasicThread::thread_counter = 0; -BasicThread::BasicThread(const string& arg_name) +BasicThread::BasicThread() { started = false; terminating = false; @@ -18,7 +18,7 @@ BasicThread::BasicThread(const string& arg_name) buf = 0; buf_len = 1024; - name = Fmt("%s@%d", arg_name.c_str(), ++thread_counter); + name = Fmt("thread-%d", ++thread_counter); thread_mgr->AddThread(this); } @@ -27,6 +27,27 @@ BasicThread::~BasicThread() { } +void BasicThread::SetName(const string& arg_name) + { + // Slight race condition here with reader threads, but shouldn't matter. + name = arg_name; + } + +void BasicThread::SetOSName(const string& name) + { +#ifdef LINUX + pthread_setname_np(pthread_self(), name.c_str()); +#endif + +#ifdef __APPLE__ + pthread_setname_np(name.c_str()); +#endif + +#ifdef FREEBSD + pthread_set_name_np(pthread_self(), name, name.c_str()); +#endif + } + const char* BasicThread::Fmt(const char* format, ...) { if ( ! buf ) diff --git a/src/threading/BasicThread.h b/src/threading/BasicThread.h index aeafc61c52..6d2f739620 100644 --- a/src/threading/BasicThread.h +++ b/src/threading/BasicThread.h @@ -34,16 +34,31 @@ public: * @param name A descriptive name for thread the thread. This may * show up in messages to the user. */ - BasicThread(const string& name); // Managed by manager, must not delete otherwise. + BasicThread(); /** - * Returns a descriptive name for the thread. This is the name passed - * into the constructor. + * Returns a descriptive name for the thread. If not set via + * SetName(). If not set, a default name is choosen automatically. * * This method is safe to call from any thread. */ const string& Name() const { return name; } + /** + * Sets a descriptive name for the thread. This should be a string + * that's useful in output presented to the user and uniquely + * identifies the thread. + * + * This method must be called only from the thread itself. + */ + void SetName(const string& name); + + /** + * Set the name shown by the OS as the thread's description. Not + * supported on all OSs. + */ + void SetOSName(const string& name); + /** * Starts the thread. Calling this methods will spawn a new OS thread * executing Run(). Note that one can't restart a thread after a diff --git a/src/threading/MsgThread.cc b/src/threading/MsgThread.cc index 1bda8943da..f41b20ddf9 100644 --- a/src/threading/MsgThread.cc +++ b/src/threading/MsgThread.cc @@ -127,7 +127,7 @@ bool ReporterMessage::Process() return true; } -MsgThread::MsgThread(const string& name) : BasicThread(name) +MsgThread::MsgThread() : BasicThread() { cnt_sent_in = cnt_sent_out = 0; thread_mgr->AddMsgThread(this); @@ -142,6 +142,12 @@ void MsgThread::OnStop() void MsgThread::Heartbeat() { SendIn(new HeartbeatMessage(this, network_time, current_time())); + + string name = Fmt("%s (%d/%d)", name.c_str(), + cnt_sent_in - queue_in.Size(), + cnt_sent_out - queue_out.Size()); + + SetOSName(name.c_str()); } void MsgThread::Info(const char* msg) diff --git a/src/threading/MsgThread.h b/src/threading/MsgThread.h index ec249e90ad..459ac6c603 100644 --- a/src/threading/MsgThread.h +++ b/src/threading/MsgThread.h @@ -34,10 +34,8 @@ public: * threading::Manager. * * Only Bro's main thread may instantiate a new thread. - * - * @param name A descriptive name. This is passed on to BasicThread(). */ - MsgThread(const string& name); + MsgThread(); /** * Sends a message to the child thread. The message will be proceesed