winamp/Src/Plugins/DSP/sc_serv3/nmrCommon/services/logger.cpp
2024-09-24 14:54:57 +02:00

967 lines
25 KiB
C++

#include "logger.h"
#include <stdio.h>
#include <algorithm>
#include "stl/functors.h"
#include "file/fileUtils.h"
#include "stl/stringUtils.h"
#include "macros.h"
#include "../../global.h"
#ifndef _WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#endif
#ifdef _WIN32
#define __F__ __FUNCTION__
#else
#define __F__ string(__PRETTY_FUNCTION__) +
#endif
using namespace std;
using namespace uniString;
using namespace stringUtil;
////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// LOGGER ELEMENTS ///////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef _WIN32
//////////// Win32 File Logger
inline uniFile::filenameType AOL_logger::fileLogger_element::make_backup_log(const uniFile::filenameType &filename,int which) throw()
{
return fileUtil::stripSuffix(filename) + "_" +
tobs<uniFile::filenameType>(which) + "."
+ fileUtil::getSuffix(filename);
}
uniFile::filenameType AOL_logger::fileLogger_element::make_archive_log() throw()
{
SYSTEMTIME sysTime = {0};
::GetLocalTime(&sysTime);
wchar_t d[100] = {0}, t[100] = {0};
::GetDateFormatW(LOCALE_SYSTEM_DEFAULT,0,&sysTime,_T("yyyy'_'MM'_'dd"),d,99);
::GetTimeFormatW(LOCALE_SYSTEM_DEFAULT,0,&sysTime,_T("HH'_'mm'_'ss"),t,99);
return tos((const wchar_t *)d) + "_" + tos((const wchar_t *)t);
}
void AOL_logger::fileLogger_element::rotate() throw()
{
m_lastRolloverTime = ::time(NULL);
if (m_file == INVALID_HANDLE_VALUE || m_first == false)
{
return;
}
// close the log
forgetHandleInvalid(m_file);
// rotate
for (int x = m_numFileBackups; x > 0; --x)
{
uniFile::filenameType dest = make_backup_log(m_fileName,x);
// archive the log file about to be removed into a gz file
if (m_numFileBackups > 0 && x == m_numFileBackups && m_archiveFileBackups)
{
uniFile::filenameType archive = dest;
utf8::size_type pos = archive.rfind(utf8("_"+tos(m_numFileBackups)));
if ((pos != utf8::npos) && (uniFile::fileSize(dest) > 0))
{
archive = (dest.substr(0,pos) + utf8("_log_" + make_archive_log() + ".gz"));
HANDLE m_archive = ::CreateFileW(archive.toWString().c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_archive != INVALID_HANDLE_VALUE)
{
DWORD written(0);
utf8 out;
z_stream m_stream = {0};
if (uniFile::fileSize(dest) > 0)
{
FILE* m_logFile = uniFile::fopen(dest,"rb");
if (m_logFile != NULL)
{
bool started = false;
while (!feof(m_logFile))
{
std::vector<uniString::utf8::value_type> m_logFileBuffer;
const size_t BUFSIZE(1024*16);
m_logFileBuffer.clear();
m_logFileBuffer.resize(BUFSIZE + 1);
size_t amt = fread(&(m_logFileBuffer[0]), 1, BUFSIZE, m_logFile);
if (amt > 0)
{
out = utf8(&(m_logFileBuffer[0]), amt);
if (started == false)
{
compressDataStart(out, &m_stream);
started = true;
}
else
{
compressDataCont(out, &m_stream);
}
::WriteFile(m_archive, out.c_str(), (DWORD)out.size(), &written, NULL);
}
}
compressDataFinish(out, &m_stream);
::WriteFile(m_archive, out.c_str(), (DWORD)out.size(), &written, NULL);
compressDataEnd(&m_stream);
::fclose(m_logFile);
forgetHandleInvalid(m_archive);
// no need to keep any 0-byte files
// this is just incase of weirdness
if (!uniFile::fileSize(archive))
{
uniFile::unlink(archive);
}
}
else
{
forgetHandleInvalid(m_archive);
uniFile::unlink(archive);
}
}
}
}
}
::DeleteFileW(dest.toWString().c_str());
::MoveFileW(
((x-1) ? make_backup_log(m_fileName,(x-1)).toWString().c_str()
: m_fileName.toWString().c_str()),
dest.toWString().c_str());
}
// open new log
m_file = ::CreateFileW(m_fileName.toWString().c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
AOL_logger::fileLogger_element::fileLogger_element(const uniFile::filenameType &filename, const uniFile::filenameType &defaultFilename,
bool &useDefaultPath, int backups, bool archive, int rolloverInterval, size_t SID) throw(exception)
: m_fileName(filename), m_file(INVALID_HANDLE_VALUE), m_lastRolloverTime(0), m_rolloverInterval(rolloverInterval), m_numFileBackups(backups),
m_archiveFileBackups(archive), m_first(false), m_SID(SID)
{
// this will fill in the default log path as required
wchar_t s_defaultFileName[MAX_PATH] = {0};
ExpandEnvironmentStringsW(defaultFilename.toWString().c_str(), s_defaultFileName, MAX_PATH);
utf8 m_defaultFilename(utf32(s_defaultFileName).toUtf8());
useDefaultPath = false;
m_file = ::CreateFileW(m_fileName.toWString().c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_file == INVALID_HANDLE_VALUE)
{
m_file = ::CreateFileW(m_defaultFilename.toWString().c_str(),GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_file == INVALID_HANDLE_VALUE)
{
uniFile::filenameType fallbackFilename("%temp%\\sc_serv_" + tos(getpid()) + ".log");
wchar_t s_fallbackFileName[MAX_PATH] = {0};
ExpandEnvironmentStringsW(fallbackFilename.toWString().c_str(), s_fallbackFileName, MAX_PATH);
utf8 m_fallbackFilename(utf32(s_fallbackFileName).toUtf8());
m_file = ::CreateFileW(m_fallbackFilename.toWString().c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_file == INVALID_HANDLE_VALUE)
{
throw runtime_error("Logger could not open the log file \"" + m_fileName.hideAsString() + "\" for writing [" + errMessage().hideAsString() + "]. Check the directory exists and another instance is not already running.");
}
else
{
m_fileName = m_fallbackFilename;
}
}
else
{
m_fileName = m_defaultFilename;
}
}
::SetFilePointer(m_file,0,0,FILE_END); // seek to end
if (m_fileName == m_defaultFilename)
{
useDefaultPath = true;
}
gOptions.setOption(utf8("reallogfile"), m_fileName);
// using this to prevent rotating empty log files on startup
m_first = fileUtil::fileExists(m_fileName.hideAsString());
if (m_first && !uniFile::fileSize(m_fileName))
{
m_first = false;
}
rotate();
}
AOL_logger::fileLogger_element::~fileLogger_element() throw()
{
forgetHandleInvalid(m_file);
}
void AOL_logger::fileLogger_element::log(message &m) throw(exception)
{
time_t t = ::time(NULL);
if (t < m_lastRolloverTime || (((t - m_lastRolloverTime) > m_rolloverInterval) && m_rolloverInterval))
{
rotate();
rotatew3cFiles("w3c");
}
if (m.m_alreadyLogged)
return;
if (m_SID != m.m_streamID && m_SID)
{
return;
}
m.m_alreadyLogged = true;
m_first = true;
utf8 ss = m.getTimestamp() + "\t" + m.typeAsStr();
const utf8 &msg = m.getMsg();
if (msg[0] != '[')
{
const char *section = m.fromSection();
if (section)
{
bool wrap = (section[0] == '[') ? false : true;
size_t ID = m.getID();
if (wrap)
{
ss += "\t[";
ss += section;
if (ID > 0)
{
ss += " sid=";
ss += tos(ID);
}
ss += "] ";
}
else
{
ss += "\t";
ss += section;
// if (ID > 0)
// ss += " ID present ";
}
}
else
ss += "\t";
}
else
ss += "\t";
const map<utf8,utf8> *fields = m.getFields();
if (fields)
{
for (map<utf8,utf8>::const_iterator i = fields->begin(); i != fields->end(); ++i)
{
if (!(*i).first.empty())
{
if (!(*i).second.empty())
{
ss += "\t" + (*i).second;
}
else
{
return;
}
}
}
}
ss += msg;
ss += eol();
if (m_file == INVALID_HANDLE_VALUE)
{
throw runtime_error(__F__ " Error writing to log file " + m_fileName.hideAsString());
}
DWORD written(0);
if ((!::WriteFile(m_file, ss.c_str(), (DWORD)ss.size(), &written, NULL)) || (written != ss.size()))
{
throw runtime_error(__F__ " Error writing to log file " + m_fileName.hideAsString());
}
}
#else
/////////// Unix File Logger
uniFile::filenameType AOL_logger::fileLogger_element::make_backup_log(const uniFile::filenameType &filename,int which) throw()
{
return fileUtil::stripSuffix(filename) + "_" + tos(which) + "." + fileUtil::getSuffix(filename);
}
uniFile::filenameType AOL_logger::fileLogger_element::make_archive_log() throw()
{
char buf[256] = {0};
struct tm ttm;
time_t ttt;
::time(&ttt);
::strftime(buf, 255, "%Y_%m_%d_%H_%M_%S", ::localtime_r(&ttt, &ttm));
return buf;
}
void AOL_logger::fileLogger_element::rotate() throw()
{
m_lastRolloverTime = ::time(NULL);
if ((m_file == -1) || (m_first == false))
{
return;
}
// close the log
::close(m_file);
m_file = -1;
// rotate
for (int x = m_numFileBackups; x > 0; --x)
{
uniFile::filenameType dest = make_backup_log(m_fileName,x);
// archive the log file about to be removed into a gz file
if (m_numFileBackups > 0 && x == m_numFileBackups && m_archiveFileBackups)
{
uniFile::filenameType archive = dest;
utf8::size_type pos = archive.rfind(utf8("_"+tos(m_numFileBackups)));
if ((pos != utf8::npos) && (uniFile::fileSize(dest) > 0))
{
archive = (dest.substr(0,pos) + utf8("_log_" + make_archive_log() + ".gz"));
int m_archive = ::open(archive.hideAsString().c_str(),O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (m_archive != -1)
{
utf8 out;
z_stream m_stream = {0};
if (uniFile::fileSize(dest) > 0)
{
FILE* m_logFile = uniFile::fopen(dest,"rb");
if (m_logFile != NULL)
{
bool started = false;
while (!feof(m_logFile))
{
std::vector<uniString::utf8::value_type> m_logFileBuffer;
const size_t BUFSIZE(1024*16);
m_logFileBuffer.clear();
m_logFileBuffer.resize(BUFSIZE + 1);
size_t amt = fread(&(m_logFileBuffer[0]), 1, BUFSIZE, m_logFile);
if (amt > 0)
{
out = utf8(&(m_logFileBuffer[0]), amt);
if (started == false)
{
compressDataStart(out, &m_stream);
started = true;
}
else
{
compressDataCont(out, &m_stream);
}
::write(m_archive,out.c_str(),out.size());
}
}
compressDataFinish(out, &m_stream);
::write(m_archive,out.c_str(),out.size());
compressDataEnd(&m_stream);
::fclose(m_logFile);
::close(m_archive);
// no need to keep any 0-byte files
// this is just incase of weirdness
if (!uniFile::fileSize(archive))
{
uniFile::unlink(archive);
}
}
else
{
::close(m_archive);
uniFile::unlink(archive);
}
}
}
}
}
::remove(dest.hideAsString().c_str());
::rename(
((x-1) ? make_backup_log(m_fileName,(x-1)).hideAsString().c_str()
: m_fileName.hideAsString().c_str()),
dest.hideAsString().c_str());
}
// open new log
m_file = ::open(m_fileName.hideAsString().c_str(),O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
}
AOL_logger::fileLogger_element::fileLogger_element(const uniFile::filenameType &filename,
const uniFile::filenameType &defaultFilename,
bool &useDefaultPath, int backups,
bool archive, int rolloverInterval, size_t SID) throw(exception):
m_fileName(filename), m_file(-1), m_lastRolloverTime(0),
m_rolloverInterval(rolloverInterval), m_numFileBackups(backups),
m_archiveFileBackups(archive), m_first(false), m_SID(SID)
{
umask(0);
useDefaultPath = false;
m_file = ::open(filename.hideAsString().c_str(),O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (m_file == -1)
{
if (SID == 0)
m_file = ::open (defaultFilename.hideAsString().c_str(),O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (m_file == -1)
{
uniFile::filenameType fallbackFilename("/tmp/sc_serv_" + tos(getpid()) + ".log");
m_file = ::open(fallbackFilename.hideAsString().c_str(),O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (m_file == -1)
{
throw runtime_error("Logger could not open the log file \"" + m_fileName.hideAsString() + "\" for writing [" + errMessage().hideAsString() + "]. Check the directory exists and another instance is not already running.");
}
else
{
m_fileName = fallbackFilename;
}
}
else
{
m_fileName = defaultFilename;
}
}
if (m_fileName == defaultFilename)
{
useDefaultPath = true;
}
gOptions.setOption(utf8("reallogfile"), m_fileName);
// using this to prevent rotating empty log files on startup
m_first = fileUtil::fileExists(m_fileName.hideAsString());
if (m_first && !uniFile::fileSize(m_fileName))
{
m_first = false;
}
rotate();
}
AOL_logger::fileLogger_element::~fileLogger_element() throw()
{
if (m_file != -1)
::close(m_file);
m_file = -1;
}
void AOL_logger::fileLogger_element::log(message &m) throw(exception)
{
time_t t = ::time(NULL);
if (t < m_lastRolloverTime || (((t - m_lastRolloverTime) > m_rolloverInterval) && m_rolloverInterval))
{
rotate();
rotatew3cFiles("w3c");
}
if (m.m_alreadyLogged)
return;
if (m_SID != m.m_streamID && m_SID)
{
return;
}
m.m_alreadyLogged = true;
m_first = true;
utf8 ss = m.getTimestamp() + "\t" + m.typeAsStr();
const utf8 &msg = m.getMsg();
if (msg[0] != '[')
{
const char *section = m.fromSection();
if (section)
{
bool wrap = (section[0] == '[') ? false : true;
size_t ID = m.getID();
if (wrap)
{
ss += "\t[";
ss += section;
if (ID > 0)
{
ss += " sid=";
ss += tos(ID);
}
ss += "] ";
}
else
{
ss += "\t";
ss += section;
// if (ID > 0)
// ss += " ID present ";
}
}
else
ss += "\t";
}
else
ss += "\t";
const map<utf8,utf8> *fields = m.getFields();
if (fields)
{
for (map<utf8,utf8>::const_iterator i = fields->begin(); i != fields->end(); ++i)
{
if (!(*i).first.empty())
{
if (!(*i).second.empty())
{
ss += "\t" + (*i).second;
}
else
{
return;
}
}
}
ss += " ";
}
ss += msg;
ss += eol();
if (m_file == -1)
{
throw runtime_error(__F__ " Error writing to log file " + m_fileName.hideAsString());
}
if (::write(m_file,ss.c_str(),ss.size()) == -1)
{
throw runtime_error(__F__ " Error writing to log file " + m_fileName.hideAsString());
}
}
#endif
#ifdef _WIN32
//////// Win32 console logger
AOL_logger::consoleLogger_element::consoleLogger_element() throw(exception) : m_stdoutConsole(NULL), m_stderrConsole(NULL)
{
::AllocConsole();
::SetConsoleOutputCP(65001); // utf-8
::SetConsoleCP(CP_UTF8);//65001);
m_stdoutConsole = ::GetStdHandle(STD_OUTPUT_HANDLE);
m_stderrConsole = ::GetStdHandle(STD_ERROR_HANDLE);
if ((!m_stdoutConsole) || (!m_stderrConsole))
{
throw runtime_error("Logger could not open console");
}
}
AOL_logger::consoleLogger_element::~consoleLogger_element() throw()
{
if (m_stdoutConsole != NULL)
{
::FreeConsole();
m_stdoutConsole = NULL;
m_stderrConsole = NULL;
}
}
void AOL_logger::consoleLogger_element::log(message &m) throw(exception)
{
static const DWORD maxLogLine=2048;
utf8 ss = m.getTimestamp() + "\t" + m.typeAsStr();
const utf8 &msg = m.getMsg();
if (msg[0] != '[')
{
const char *section = m.fromSection();
if (section)
{
bool wrap = (section[0] == '[') ? false : true;
size_t ID = m.getID();
if (wrap)
{
ss += "\t[";
ss += section;
if (ID > 0)
{
ss += " sid=";
ss += tos(ID);
}
ss += "] ";
}
else
{
ss += "\t";
ss += section;
// if (ID > 0)
// ss += " ID present ";
}
}
else
ss += "\t";
}
else
ss += "\t";
const map<utf8,utf8> *fields = m.getFields();
if (fields)
{
for (map<utf8,utf8>::const_iterator i = fields->begin(); i != fields->end(); ++i)
{
if (!(*i).first.empty())
{
if (!(*i).second.empty())
{
ss += "\t" + (*i).second;
}
else
{
return;
}
}
}
}
ss += m.getMsg();
ss += eol();
HANDLE h = (m.getType() == AOL_logger::message::BM_ERROR ? m_stderrConsole : m_stdoutConsole);
if (h != INVALID_HANDLE_VALUE)
{
// see if we need to colour the output - only used for errors and warnings
AOL_logger::message::message_t type = m.getType();
bool painted = false;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo = {0};
WORD wOldColorAttrs = 0;
if (type != AOL_logger::message::BM_INFO && GetConsoleScreenBufferInfo(h, &csbiInfo))
{
wOldColorAttrs = csbiInfo.wAttributes;
// red for error, yellow for warnings, green for debug, blue for update
if (type == AOL_logger::message::BM_ERROR)
{
painted = true;
SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
}
else if (type == AOL_logger::message::BM_WARNING)
{
painted = true;
SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}
else if (type == AOL_logger::message::BM_DEBUG)
{
painted = true;
SetConsoleTextAttribute(h, FOREGROUND_GREEN);
}
else if (type == AOL_logger::message::BM_UPDATE)
{
painted = true;
SetConsoleTextAttribute(h, FOREGROUND_BLUE);
}
}
// utf8 sometimes returns a size that does not match input
DWORD written(0);
DWORD amtToWrite = (DWORD)ss.size();
bool truncated = false;
if (amtToWrite > maxLogLine)
{
amtToWrite = maxLogLine;
truncated = true;
}
if (truncated)
{
utf8 truncateMsg = m.getTimestamp() + "\t" + ((char)message::BM_WARNING) + "\t[MAIN] Next line is truncated" + eol();
::WriteFile(h,truncateMsg.c_str(),(DWORD)truncateMsg.size(),&written,NULL);
written = 0;
}
if (::WriteFile(h,ss.c_str(),amtToWrite,&written,NULL))
{
if (truncated)
{
// eol
written = 0;
::WriteFile(h,eol().c_str(),(DWORD)eol().size(),&written,NULL);
}
}
// revert the colouring if we needed to change it
if (painted)
{
SetConsoleTextAttribute(h, wOldColorAttrs);
}
}
}
#else
/////// Unix console logger
AOL_logger::consoleLogger_element::consoleLogger_element() throw(exception) :
m_stdoutConsole(STDOUT_FILENO), m_stderrConsole(STDERR_FILENO)
{
if ((m_stdoutConsole == -1) || (m_stderrConsole == -1))
{
throw runtime_error("Logger could not open console");
}
}
AOL_logger::consoleLogger_element::~consoleLogger_element() throw()
{
m_stdoutConsole = m_stderrConsole = -1;
}
void AOL_logger::consoleLogger_element::log(message &m) throw(exception)
{
utf8 sc = "";
// see if we need to colour the output - only used for errors, warnings and debugs
AOL_logger::message::message_t type = m.getType();
if (type != AOL_logger::message::BM_INFO)
{
// red for error, yellow for warnings, green for debug, blue for update
if (type == AOL_logger::message::BM_ERROR)
{
sc = "\033[01;31m";
}
else if (type == AOL_logger::message::BM_WARNING)
{
sc = "\033[01;33m";
}
else if (type == AOL_logger::message::BM_DEBUG)
{
sc = "\033[0;32m";
}
else if (type == AOL_logger::message::BM_UPDATE)
{
sc = "\033[0;34m";
}
}
utf8 ss = sc + m.getTimestamp() + "\t" + m.typeAsStr();
const utf8 &msg = m.getMsg();
if (msg[0] != '[')
{
const char *section = m.fromSection();
if (section)
{
bool wrap = (section[0] == '[') ? false : true;
size_t ID = m.getID();
if (wrap)
{
ss += "\t[";
ss += section;
if (ID > 0)
{
ss += " sid=";
ss += tos(ID);
}
ss += "] ";
}
else
{
ss += "\t";
ss += section;
// if (ID > 0)
// ss += " ID present ";
}
}
else
ss += "\t";
}
else
ss += "\t";
const map<utf8,utf8> *fields = m.getFields();
if (fields)
{
for (map<utf8,utf8>::const_iterator i = fields->begin(); i != fields->end(); ++i)
{
if (!(*i).first.empty())
{
if (!(*i).second.empty())
{
ss += "\t" + (*i).second;
}
else
{
return;
}
}
}
}
ss += m.getMsg();
ss += eol() + (!sc.empty() ? "\033[0m" : "");
int console = (m.getType() == AOL_logger::message::BM_ERROR ? m_stderrConsole : m_stdoutConsole);
if (console != -1)
{
::write(console,ss.c_str(),ss.size());
}
}
#endif
#ifdef _WIN32
// Win32 system logger
void AOL_logger::systemLogger_element::registerEventLog(const utf8 &log_object_name,
const uniFile::filenameType &fullExePath) throw()
{
HKEY key = NULL;
DWORD disposition = 0;
wstring regEntry = L"System\\CurrentControlSet\\Services\\EventLog\\Application\\";
regEntry += log_object_name.toWString();
LONG err = ::RegCreateKeyExW(HKEY_LOCAL_MACHINE, regEntry.c_str(), 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, &disposition);
if (err == ERROR_SUCCESS)
{
DWORD ts = 1;
wstring widePath = fullExePath.toWString();
::RegSetValueExW(key,L"EventMessageFile",0,REG_SZ,(const BYTE *)widePath.c_str(),(DWORD)((fullExePath.size() + 1) * 2));
::RegSetValueExW(key,L"TypesSupported",0,REG_DWORD,(const BYTE *)&ts,sizeof(ts));
::RegCloseKey(key);
}
}
AOL_logger::systemLogger_element::systemLogger_element(const utf8 &log_object_name,
const uniFile::filenameType &fullExePath,
const utf8 &loggerConfigString) throw(exception)
: m_systemLog(NULL), m_loggerConfigString(loggerConfigString)
{
registerEventLog(log_object_name,fullExePath);
m_systemLog = ::RegisterEventSourceW(NULL, // uses local computer
log_object_name.toWString().c_str()); // source name
if (m_systemLog == NULL)
{
throw runtime_error("Could not register the event source for the system logs.");
}
}
AOL_logger::systemLogger_element::~systemLogger_element() throw()
{
if (m_systemLog != NULL)
{
::DeregisterEventSource(m_systemLog);
m_systemLog = NULL;
}
}
static WORD charToLogType(char c) throw()
{
if (c == 'E')
{
return EVENTLOG_ERROR_TYPE;
}
if (c == 'W')
{
return EVENTLOG_WARNING_TYPE;
}
if (c == 'I')
{
return EVENTLOG_INFORMATION_TYPE;
}
return 0;
}
static WORD messageTypeToLogType(AOL_logger::message::message_t t, const utf8 &configString) throw()
{
if (configString.size() < 5)
{
return EVENTLOG_ERROR_TYPE;
}
switch (t)
{
case AOL_logger::message::BM_INFO:
{
return charToLogType(configString[3]);
}
case AOL_logger::message::BM_WARNING:
{
return charToLogType(configString[2]);
}
case AOL_logger::message::BM_ERROR:
{
return charToLogType(configString[0]);
}
case AOL_logger::message::BM_DEBUG:
{
return charToLogType(configString[4]);
}
}
return 0;
}
void AOL_logger::systemLogger_element::log(message &m) throw(exception)
{
if (m_systemLog == NULL)
{
throw runtime_error(__F__ " Error writing to system log");
}
const map<utf8,utf8> *fields = m.getFields();
utf8 ss;
if (fields)
{
for (map<utf8,utf8>::const_iterator i = fields->begin(); i != fields->end(); ++i)
{
if (!(*i).first.empty())
{
if (!(*i).second.empty())
{
ss += (!ss.empty() ? "\t" : "") + (*i).second;
}
else
{
return;
}
}
}
}
ss += m.getMsg();
if (!ss.empty())
{
utf32 u32(stripWhitespace(ss));
utf16 u16(u32.toUtf16(true));
const wchar_t *s = (const wchar_t *)u16.c_str();
WORD et = messageTypeToLogType(m.getType(), m_loggerConfigString);
if (et)
{
::ReportEventW(m_systemLog, // event log handle
et, // event type
0, // category 0
((DWORD)0xC0000001L), // event identifier
NULL, // no user security identifier
1, // one substitution string
0, // no data
&s, // pointer to string array
NULL);
}
}
}
#endif