SockIt
|
#include <Logger.h>
Static Public Member Functions | |
static void | error (string msg, int port=NO_PORT, string host="local") |
static void | info (string msg, int port=NO_PORT, string host="local") |
static void | warn (string msg, int port=NO_PORT, string host="local") |
static const bool | is_enabled () |
static void | shutdown () |
Static Public Attributes | |
static const int | NO_PORT = 0 |
Private Member Functions | |
Logger () | |
Static Private Member Functions | |
static void | queue (string host, int port, string msg, string cat) |
static string | get_date () |
static string | get_timestamp () |
static string | get_log_base_path () |
static void | initialize () |
static void | log_writer_run () |
static void | handle_write_request (string dir, string line) |
static void | formatter_run () |
static void | handle_format_request (string host, int port, string msg, string cat) |
Static Private Attributes | |
static const int | SLEEP_TIME_MS = 50 |
static bool | initialized = false |
static bool | enabled = true |
static boost::mutex | log_writer_mtx |
static boost::mutex | formatter_mtx |
static boost::mutex | shutdown_mtx |
static boost::condition_variable | shutdown_cvar |
static boost::condition_variable | formatter_cvar |
static boost::condition_variable | log_writer_cvar |
static std::queue< pair< pair < string, int >, pair< string, string > > > | raw_requests |
static std::queue< pair < string, string > > | write_requests |
static string | pid |
static boost::thread | frm_t |
static boost::thread | lw_t |
Do not instantiate or inherit from this class.
An asynchronous logger. Call by using Logger::info("msg");
or equivalent method. Designed to have the main thread do as little work as possible.
Internally, there are two background threads. One formats a log request into a file directory and a log entry. The other actually writes this into the log. Hopefully, one thread can be in a system call (to get the current date or time) and the other can be doing I/O.
Sadly, a bug in firebreath+boost prevents both background threads from sleeping and just periodically checking that there's work. The bug makes the sleeping thread hang indefinitely (until interrupted). Since the bug affects waiting/timed waiting on a condition variable, (which is how boost implements sleep), the main thread has to signal the formatter thread just in case the bug happened. The formatter thread then signals the log writing thread when there's work.
Logs are placed in /sockit/YYYY-MM-DD/REMOTEHOST/PROCESSID/sockit-traffic.log.
Note: Logger::shutdown() should only be called once, when the plugin is shutting down. After this is called, no more logging will take place.
static void Logger::error | ( | string | msg, |
int | port = NO_PORT , |
||
string | host = "local" |
||
) | [inline, static] |
Log that there is an error, along with a message.
host | Either a client's remote host or the localhost for servers |
port | Either the remote host's port (for a client) or the server's local port |
msg | The message to log |
Definition at line 71 of file Logger.h.
References is_enabled(), and queue().
Referenced by TcpServer::accept_handler(), TcpClient::connect_handler(), TcpServer::init(), TcpClient::init(), UdpClient::init_socket(), UdpServer::initialize(), Udp::receive_handler(), Tcp::receive_handler(), UdpClient::resolve_handler(), TcpClient::resolve_handler(), NetworkThread::run(), UdpEvent::send(), UdpClient::send(), TcpEvent::send(), TcpClient::send(), Udp::send_handler(), Tcp::send_handler(), Tcp::set_tcp_keepalive(), UdpServer::shutdown(), TcpServer::shutdown(), TcpClient::shutdown(), socket_deallocate(), UdpServer::start_listening(), TcpServer::start_listening(), TcpClient::TcpClient(), TcpEvent::TcpEvent(), UdpClient::UdpClient(), and UdpEvent::UdpEvent().
{ if (Logger::is_enabled()) Logger::queue(host, port, msg, "ERROR : "); }
void Logger::formatter_run | ( | ) | [static, private] |
Only the formatter thread should be here. Run until logging is disabled and handle formatting requests.
Definition at line 130 of file Logger.cpp.
References enabled, formatter_cvar, formatter_mtx, handle_format_request(), raw_requests, and SLEEP_TIME_MS.
Referenced by initialize().
{ // needed for sleeping on a boost cvar boost::unique_lock<boost::mutex> fmt_lock(formatter_mtx); // continue as long as logging is enabled and there are still raw requests to process while(true) { while (!raw_requests.empty()) { // handle one request pair<pair<string, int> , pair<string, string> > p = raw_requests.front(); raw_requests.pop(); fmt_lock.unlock(); handle_format_request(p.first.first, p.first.second, p.second.first, p.second.second); fmt_lock.lock(); } if(enabled || !raw_requests.empty()) { // Sigh. There's a bug with firebreath + boost::this_thread::sleep/boost::condition_variable.timed_wait // where the sleeping thread hangs forever. So this is a compromise/work around. // don't hold the lock across the gettime system call fmt_lock.unlock(); boost::system_time sleep_time = boost::get_system_time() + boost::posix_time::milliseconds(SLEEP_TIME_MS); fmt_lock.lock(); // wake up periodically to check for work. formatter_cvar.timed_wait(fmt_lock, sleep_time); } else { fmt_lock.unlock(); break; } } }
string Logger::get_date | ( | ) | [static, private] |
Helper for building the directory path. Gets the current date (local time) in YYYY-MM-DD format.
Definition at line 65 of file Logger.cpp.
Referenced by handle_format_request().
{
boost::gregorian::date d(boost::gregorian::day_clock::local_day());
return boost::gregorian::to_iso_extended_string(d);
}
string Logger::get_log_base_path | ( | ) | [static, private] |
Helper for building the directory path. Gets the base log path.
Definition at line 79 of file Logger.cpp.
References PROFILE_BUF_LEN.
Referenced by handle_format_request().
{ #if defined (__UNIX__) || defined (__OSX__) string path(getenv("HOME")); #else #define PROFILE_BUF_LEN 250 char profilepath[PROFILE_BUF_LEN]; ExpandEnvironmentStringsA("%USERPROFILE%", profilepath, PROFILE_BUF_LEN); string path(profilepath); #endif path.append("/sockit"); return path; }
string Logger::get_timestamp | ( | ) | [static, private] |
Helper for building the directory path. Gets the current timestamp (local time) in HH:MM:SS format
Definition at line 72 of file Logger.cpp.
Referenced by handle_format_request().
{
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
return boost::posix_time::to_simple_string(now);
}
void Logger::handle_format_request | ( | string | host, |
int | port, | ||
string | msg, | ||
string | cat | ||
) | [static, private] |
Only the formatter thread should be here. Handles a format request.
Definition at line 170 of file Logger.cpp.
References get_date(), get_log_base_path(), get_timestamp(), log_writer_cvar, log_writer_mtx, NO_PORT, pid, and write_requests.
Referenced by formatter_run().
{ // used to build the log path string host_str = (host == "local" ? "localhost" : host); string port_str = (port == NO_PORT ? "" : boost::lexical_cast<string>(port)); string day = get_date(); string time = get_timestamp(); // figure out the path for this message string log_path(get_log_base_path() + "/" + day + "/" + host_str + "/" + pid); string entry(cat + "[" + time + "] " + "[" + host_str + (port == NO_PORT ? "] " : "] [" + port_str + "] ") + msg); // log request item pair<string, string> item(log_path, entry); // add item to log write queue log_writer_mtx.lock(); write_requests.push(item); // awaken log writing thread - it has work log_writer_mtx.unlock(); log_writer_cvar.notify_one(); }
void Logger::handle_write_request | ( | string | dir, |
string | line | ||
) | [static, private] |
Only the log writing thread should be in this function. Handles a log write request.
Definition at line 238 of file Logger.cpp.
Referenced by log_writer_run().
{ namespace fs = boost::filesystem; if (!fs::exists(dir)) { try { fs::create_directories(dir); } catch (fs::filesystem_error &err) { // hope someone is listening.. std::cout << "Error: could not create directory " << dir << std::endl; return; } } string fileName(dir + "/sockit-traffic.log"); line.append("\n"); FILE *fp = fopen(fileName.c_str(), "a"); if(fp) { fwrite(line.c_str(), line.size(), 1, fp); fclose(fp); } else { std::cout << "Error: could not open file " << fileName << std::endl; } }
static void Logger::info | ( | string | msg, |
int | port = NO_PORT , |
||
string | host = "local" |
||
) | [inline, static] |
Write low-priority information to the log.
host | Either a client's remote host or the localhost for servers |
port | Either the remote host's port (for a client) or the server's local port |
msg | The message to log |
Definition at line 84 of file Logger.h.
References is_enabled(), and queue().
Referenced by TcpServer::accept_handler(), TcpClient::connect_handler(), NetworkThread::create_tcp_client(), NetworkThread::create_tcp_server(), NetworkThread::create_udp_client(), NetworkThread::create_udp_server(), TcpClient::init(), UdpClient::init_socket(), UdpServer::listen(), Udp::log_options(), Tcp::log_options(), NetworkThread::NetworkThread(), Udp::receive_handler(), Tcp::receive_handler(), UdpClient::resolve_handler(), TcpClient::resolve_handler(), UdpClient::send(), Udp::send_handler(), Tcp::send_handler(), UdpServer::start_listening(), and TcpServer::start_listening().
{ if (Logger::is_enabled()) Logger::queue(host, port, msg, "INFO : "); }
void Logger::initialize | ( | ) | [static, private] |
Initialize the background logging thread. Should only be called once.
Definition at line 56 of file Logger.cpp.
References formatter_run(), frm_t, initialized, log_writer_run(), and lw_t.
Referenced by queue().
{ initialized = true; frm_t = boost::thread(&Logger::formatter_run); lw_t = boost::thread(&Logger::log_writer_run); }
static const bool Logger::is_enabled | ( | ) | [inline, static] |
void Logger::log_writer_run | ( | ) | [static, private] |
Only the log writing thread should be in this function. Run until logging is disabled and handle log writing requests.
Definition at line 197 of file Logger.cpp.
References enabled, handle_write_request(), log_writer_cvar, log_writer_mtx, raw_requests, shutdown_cvar, SLEEP_TIME_MS, and write_requests.
Referenced by initialize().
{ // Needed to sleep on a boost cvar boost::unique_lock<boost::mutex> lw_lock(log_writer_mtx); // continue as long as logging is enabled and there are either // raw requests to process or log writing requests to process while(true) { while (!write_requests.empty()) { // handle one request pair<string, string> p = write_requests.front(); write_requests.pop(); log_writer_mtx.unlock(); handle_write_request(p.first, p.second); log_writer_mtx.lock(); } if(enabled || !raw_requests.empty() || !write_requests.empty()) { // don't hold the lock across a system call lw_lock.unlock(); boost::system_time sleep_time = boost::get_system_time() + boost::posix_time::milliseconds(SLEEP_TIME_MS); lw_lock.lock(); // wait until there's work log_writer_cvar.timed_wait(lw_lock, sleep_time); } else { lw_lock.unlock(); break; } } // notify the main thread to wake up shutdown_cvar.notify_all(); }
void Logger::queue | ( | string | host, |
int | port, | ||
string | msg, | ||
string | cat | ||
) | [static, private] |
Definition at line 112 of file Logger.cpp.
References formatter_cvar, formatter_mtx, initialize(), initialized, and raw_requests.
Referenced by error(), info(), and warn().
{ pair<string, int> item1(host, port); pair<string, string> item2(msg, cat); pair<pair<string, int> , pair<string, string> > item(item1, item2); formatter_mtx.lock(); if (!Logger::initialized) Logger::initialize(); raw_requests.push(item); formatter_cvar.notify_one(); formatter_mtx.unlock(); }
void Logger::shutdown | ( | ) | [static] |
Dangerous. Disables logging and forces the remaining logging requests to finish. Should only be called when the plugin is shutting down.
Definition at line 98 of file Logger.cpp.
References enabled, initialized, shutdown_cvar, and shutdown_mtx.
{ // disable any more log requests and disable the background threads from sleeping enabled = false; if(initialized) { // wait until the log writing queue is done boost::unique_lock<boost::mutex> lock(shutdown_mtx); shutdown_cvar.wait(lock); } }
static void Logger::warn | ( | string | msg, |
int | port = NO_PORT , |
||
string | host = "local" |
||
) | [inline, static] |
Log that there is an warning, along with a message.
host | Either a client's remote host or the localhost for servers |
port | Either the remote host's port (for a client) or the server's local port |
msg | The message to log |
Definition at line 97 of file Logger.h.
References is_enabled(), and queue().
Referenced by TcpServer::accept_handler(), TcpServer::close(), TcpClient::close(), TcpClient::connect_handler(), UdpServer::listen(), UdpClient::listen(), Tcp::receive_handler(), TcpClient::resolve_handler(), Tcp::send_handler(), and NetworkThread::~NetworkThread().
{ if (Logger::is_enabled()) Logger::queue(host, port, msg, "WARN : "); }
bool Logger::enabled = true [static, private] |
Enabled?
Definition at line 160 of file Logger.h.
Referenced by formatter_run(), is_enabled(), log_writer_run(), and shutdown().
boost::condition_variable Logger::formatter_cvar [static, private] |
The formatter thread sleeps on this.
Definition at line 175 of file Logger.h.
Referenced by formatter_run(), and queue().
boost::mutex Logger::formatter_mtx [static, private] |
Mutex for the formatter queue
Definition at line 166 of file Logger.h.
Referenced by formatter_run(), and queue().
boost::thread Logger::frm_t [static, private] |
bool Logger::initialized = false [static, private] |
Initialized?
Definition at line 157 of file Logger.h.
Referenced by initialize(), queue(), and shutdown().
boost::condition_variable Logger::log_writer_cvar [static, private] |
The log writer thread sleeps on this.
Definition at line 178 of file Logger.h.
Referenced by handle_format_request(), and log_writer_run().
boost::mutex Logger::log_writer_mtx [static, private] |
Mutex for the log writer queue
Definition at line 163 of file Logger.h.
Referenced by handle_format_request(), and log_writer_run().
boost::thread Logger::lw_t [static, private] |
const int Logger::NO_PORT = 0 [static] |
no port is given
Definition at line 117 of file Logger.h.
Referenced by NetworkThread::create_tcp_client(), NetworkThread::create_tcp_server(), NetworkThread::create_udp_client(), NetworkThread::create_udp_server(), handle_format_request(), NetworkThread::NetworkThread(), NetworkThread::run(), and NetworkThread::~NetworkThread().
string Logger::pid [static, private] |
std::queue< pair< pair< string, int >, pair< string, string > > > Logger::raw_requests [static, private] |
Queue for the raw requests
Definition at line 181 of file Logger.h.
Referenced by formatter_run(), log_writer_run(), and queue().
boost::condition_variable Logger::shutdown_cvar [static, private] |
Cvar for shutting down (main thread uses this)
Definition at line 172 of file Logger.h.
Referenced by log_writer_run(), and shutdown().
boost::mutex Logger::shutdown_mtx [static, private] |
const int Logger::SLEEP_TIME_MS = 50 [static, private] |
The formatter thread polls for work; this sets its sleep time.
Definition at line 127 of file Logger.h.
Referenced by formatter_run(), and log_writer_run().
std::queue< pair< string, string > > Logger::write_requests [static, private] |
Queue for the write requests
Definition at line 184 of file Logger.h.
Referenced by handle_format_request(), and log_writer_run().