Browse Source

write to log through the separate thread

pull/718/head
orignal 8 years ago
parent
commit
d91691c344
  1. 3
      Daemon.cpp
  2. 96
      Log.cpp
  3. 20
      Log.h
  4. 3
      api.cpp

3
Daemon.cpp

@ -113,7 +113,7 @@ namespace i2p
} else { } else {
// use stdout -- default // use stdout -- default
} }
i2p::log::Logger().Ready(); i2p::log::Logger().Start();
LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
LogPrint(eLogDebug, "FS: main config file: ", config); LogPrint(eLogDebug, "FS: main config file: ", config);
@ -351,6 +351,7 @@ namespace i2p
} }
#endif #endif
i2p::crypto::TerminateCrypto (); i2p::crypto::TerminateCrypto ();
i2p::log::Logger().Stop();
return true; return true;
} }

96
Log.cpp

@ -58,13 +58,29 @@ namespace log {
Log::Log(): Log::Log():
m_Destination(eLogStdout), m_MinLevel(eLogInfo), m_Destination(eLogStdout), m_MinLevel(eLogInfo),
m_LogStream (nullptr), m_Logfile(""), m_IsReady(false), m_HasColors(true) m_LogStream (nullptr), m_Logfile(""), m_HasColors(true),
m_IsRunning (false), m_Thread (nullptr)
{ {
} }
Log::~Log () Log::~Log ()
{ {
switch (m_Destination) { delete m_Thread;
}
void Log::Start ()
{
if (!m_IsRunning)
{
m_IsRunning = true;
m_Thread = new std::thread (std::bind (&Log::Run, this));
}
}
void Log::Stop ()
{
switch (m_Destination)
{
#ifndef _WIN32 #ifndef _WIN32
case eLogSyslog : case eLogSyslog :
closelog(); closelog();
@ -78,7 +94,14 @@ namespace log {
/* do nothing */ /* do nothing */
break; break;
} }
Process(); m_IsRunning = false;
m_Queue.WakeUp ();
if (m_Thread)
{
m_Thread->join ();
delete m_Thread;
m_Thread = nullptr;
}
} }
void Log::SetLogLevel (const std::string& level) { void Log::SetLogLevel (const std::string& level) {
@ -106,45 +129,52 @@ namespace log {
* Unfortunately, with current startup process with late fork() this * Unfortunately, with current startup process with late fork() this
* will give us nothing but pain. Maybe later. See in NetDb as example. * will give us nothing but pain. Maybe later. See in NetDb as example.
*/ */
void Log::Process() { void Log::Process(std::shared_ptr<LogMsg> msg)
std::unique_lock<std::mutex> l(m_OutputLock); {
if (!msg) return;
std::hash<std::thread::id> hasher; std::hash<std::thread::id> hasher;
unsigned short short_tid; unsigned short short_tid;
while (1) { short_tid = (short) (hasher(msg->tid) % 1000);
auto msg = m_Queue.GetNextWithTimeout (1); switch (m_Destination) {
if (!msg)
break;
short_tid = (short) (hasher(msg->tid) % 1000);
switch (m_Destination) {
#ifndef _WIN32 #ifndef _WIN32
case eLogSyslog: case eLogSyslog:
syslog(GetSyslogPrio(msg->level), "[%03u] %s", short_tid, msg->text.c_str()); syslog(GetSyslogPrio(msg->level), "[%03u] %s", short_tid, msg->text.c_str());
break; break;
#endif #endif
case eLogFile: case eLogFile:
case eLogStream: case eLogStream:
if (m_LogStream) if (m_LogStream)
*m_LogStream << TimeAsString(msg->timestamp) *m_LogStream << TimeAsString(msg->timestamp)
<< "@" << short_tid
<< "/" << g_LogLevelStr[msg->level]
<< " - " << msg->text << std::endl;
break;
case eLogStdout:
default:
std::cout << TimeAsString(msg->timestamp)
<< "@" << short_tid << "@" << short_tid
<< "/" << LogMsgColors[msg->level] << g_LogLevelStr[msg->level] << LogMsgColors[eNumLogLevels] << "/" << g_LogLevelStr[msg->level]
<< " - " << msg->text << std::endl; << " - " << msg->text << std::endl;
break; break;
} // switch case eLogStdout:
} // while default:
std::cout << TimeAsString(msg->timestamp)
<< "@" << short_tid
<< "/" << LogMsgColors[msg->level] << g_LogLevelStr[msg->level] << LogMsgColors[eNumLogLevels]
<< " - " << msg->text << std::endl;
break;
} // switch
} }
void Log::Append(std::shared_ptr<i2p::log::LogMsg> & msg) { void Log::Run ()
{
while (m_IsRunning)
{
std::shared_ptr<LogMsg> msg;
while (msg = m_Queue.Get ())
Process (msg);
if (m_LogStream) m_LogStream->flush();
if (m_IsRunning)
m_Queue.Wait ();
}
}
void Log::Append(std::shared_ptr<i2p::log::LogMsg> & msg)
{
m_Queue.Put(msg); m_Queue.Put(msg);
if (!m_IsReady)
return;
Process();
} }
void Log::SendTo (const std::string& path) void Log::SendTo (const std::string& path)

20
Log.h

@ -16,6 +16,7 @@
#include <sstream> #include <sstream>
#include <chrono> #include <chrono>
#include <memory> #include <memory>
#include <thread>
#include "Queue.h" #include "Queue.h"
#ifndef _WIN32 #ifndef _WIN32
@ -56,9 +57,9 @@ namespace log {
std::time_t m_LastTimestamp; std::time_t m_LastTimestamp;
char m_LastDateTime[64]; char m_LastDateTime[64];
i2p::util::Queue<std::shared_ptr<LogMsg> > m_Queue; i2p::util::Queue<std::shared_ptr<LogMsg> > m_Queue;
volatile bool m_IsReady;
bool m_HasColors; bool m_HasColors;
mutable std::mutex m_OutputLock; volatile bool m_IsRunning;
std::thread * m_Thread;
private: private:
@ -66,10 +67,8 @@ namespace log {
Log (const Log &); Log (const Log &);
const Log& operator=(const Log&); const Log& operator=(const Log&);
/** void Run ();
* @brief process stored messages in queue void Process (std::shared_ptr<LogMsg> msg);
*/
void Process ();
/** /**
* @brief Makes formatted string from unix timestamp * @brief Makes formatted string from unix timestamp
@ -87,6 +86,9 @@ namespace log {
LogType GetLogType () { return m_Destination; }; LogType GetLogType () { return m_Destination; };
LogLevel GetLogLevel () { return m_MinLevel; }; LogLevel GetLogLevel () { return m_MinLevel; };
void Start ();
void Stop ();
/** /**
* @brief Sets minimal allowed level for log messages * @brief Sets minimal allowed level for log messages
* @param level String with wanted minimal msg level * @param level String with wanted minimal msg level
@ -120,12 +122,6 @@ namespace log {
*/ */
void Append(std::shared_ptr<i2p::log::LogMsg> &); void Append(std::shared_ptr<i2p::log::LogMsg> &);
/** @brief Allow log output */
void Ready() { m_IsReady = true; }
/** @brief Flushes the output log stream */
void Flush();
/** @brief Reopen log file */ /** @brief Reopen log file */
void Reopen(); void Reopen();
}; };

3
api.cpp

@ -47,7 +47,7 @@ namespace api
i2p::log::Logger().SendTo (logStream); i2p::log::Logger().SendTo (logStream);
else else
i2p::log::Logger().SendTo (i2p::fs::DataDirPath (i2p::fs::GetAppName () + ".log")); i2p::log::Logger().SendTo (i2p::fs::DataDirPath (i2p::fs::GetAppName () + ".log"));
i2p::log::Logger().Ready(); i2p::log::Logger().Start ();
LogPrint(eLogInfo, "API: starting NetDB"); LogPrint(eLogInfo, "API: starting NetDB");
i2p::data::netdb.Start(); i2p::data::netdb.Start();
LogPrint(eLogInfo, "API: starting Transports"); LogPrint(eLogInfo, "API: starting Transports");
@ -65,6 +65,7 @@ namespace api
i2p::transport::transports.Stop(); i2p::transport::transports.Stop();
LogPrint(eLogInfo, "API: stopping NetDB"); LogPrint(eLogInfo, "API: stopping NetDB");
i2p::data::netdb.Stop(); i2p::data::netdb.Stop();
i2p::log::Logger().Stop ();
} }
void RunPeerTest () void RunPeerTest ()

Loading…
Cancel
Save