mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
206 lines
5.1 KiB
C++
206 lines
5.1 KiB
C++
/*
|
|
Copyright (C) 2013 Birunthan Mohanathas
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "StdAfx.h"
|
|
#include "Logger.h"
|
|
#include "DialogAbout.h"
|
|
#include "Litestep.h"
|
|
#include "Rainmeter.h"
|
|
#include "Section.h"
|
|
#include "MeterWindow.h"
|
|
#include "System.h"
|
|
#include "resource.h"
|
|
|
|
namespace {
|
|
|
|
const size_t MAX_LOG_ENTIRES = 20;
|
|
|
|
} // namespace
|
|
|
|
Logger::Logger() :
|
|
m_LoggerCallback (nullptr)
|
|
{
|
|
System::InitializeCriticalSection(&m_CsLog);
|
|
System::InitializeCriticalSection(&m_CsLogDelay);
|
|
}
|
|
|
|
Logger::~Logger()
|
|
{
|
|
DeleteCriticalSection(&m_CsLog);
|
|
DeleteCriticalSection(&m_CsLogDelay);
|
|
}
|
|
|
|
Logger& Logger::GetInstance()
|
|
{
|
|
static Logger s_Logger;
|
|
return s_Logger;
|
|
}
|
|
|
|
void Logger::LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, const WCHAR* msg)
|
|
{
|
|
WCHAR timestampSz[128];
|
|
size_t len = _snwprintf_s(
|
|
timestampSz,
|
|
_TRUNCATE,
|
|
L"%02llu:%02llu:%02llu.%03llu",
|
|
timestamp / (1000 * 60 * 60),
|
|
(timestamp / (1000 * 60)) % 60,
|
|
(timestamp / 1000) % 60,
|
|
timestamp % 1000);
|
|
|
|
// Store up to MAX_LOG_ENTIRES entries.
|
|
Entry entry = {level, std::wstring(timestampSz, len), source, msg};
|
|
m_Entries.push_back(entry);
|
|
if (m_Entries.size() > MAX_LOG_ENTIRES)
|
|
{
|
|
m_Entries.pop_front();
|
|
}
|
|
|
|
// Call callback function
|
|
if (m_LoggerCallback != nullptr)
|
|
(*m_LoggerCallback)(entry.level, entry.timestamp.c_str(), source, msg);
|
|
|
|
#ifdef _DEBUG
|
|
|
|
const WCHAR* levelSz =
|
|
(entry.level == Level::Error) ? L"ERRO" :
|
|
(entry.level == Level::Warning) ? L"WARN" :
|
|
(entry.level == Level::Notice) ? L"NOTE" :
|
|
L"DBUG";
|
|
|
|
std::wstring message = levelSz;
|
|
message += L" (";
|
|
message.append(entry.timestamp);
|
|
message += L") ";
|
|
message += entry.source;
|
|
message += L": ";
|
|
message += entry.message;
|
|
message += L'\n';
|
|
|
|
OutputDebugStringW (message.c_str ());
|
|
|
|
#endif
|
|
}
|
|
|
|
void Logger::Log(Level level, const WCHAR* source, const WCHAR* msg)
|
|
{
|
|
struct DelayedEntry
|
|
{
|
|
Level level;
|
|
ULONGLONG elapsed;
|
|
std::wstring message;
|
|
};
|
|
static std::list<DelayedEntry> s_DelayedEntries;
|
|
|
|
static ULONGLONG s_StartTime = System::GetTickCount64();
|
|
ULONGLONG elapsed = System::GetTickCount64() - s_StartTime;
|
|
|
|
if (TryEnterCriticalSection(&m_CsLog))
|
|
{
|
|
// Log queued messages first.
|
|
EnterCriticalSection(&m_CsLogDelay);
|
|
|
|
while (!s_DelayedEntries.empty())
|
|
{
|
|
DelayedEntry& entry = s_DelayedEntries.front();
|
|
LogInternal(entry.level, entry.elapsed, source, entry.message.c_str());
|
|
|
|
s_DelayedEntries.erase(s_DelayedEntries.begin());
|
|
}
|
|
|
|
LeaveCriticalSection(&m_CsLogDelay);
|
|
|
|
// Log the actual message.
|
|
LogInternal(level, elapsed, source, msg);
|
|
|
|
LeaveCriticalSection(&m_CsLog);
|
|
}
|
|
else
|
|
{
|
|
// Queue message.
|
|
EnterCriticalSection(&m_CsLogDelay);
|
|
|
|
DelayedEntry entry = {level, elapsed, msg};
|
|
s_DelayedEntries.push_back(entry);
|
|
|
|
LeaveCriticalSection(&m_CsLogDelay);
|
|
}
|
|
}
|
|
|
|
void Logger::LogVF(Level level, const WCHAR* source, const WCHAR* format, va_list args)
|
|
{
|
|
WCHAR* buffer = new WCHAR[1024];
|
|
|
|
_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(RmNullCRTInvalidParameterHandler);
|
|
_CrtSetReportMode(_CRT_ASSERT, 0);
|
|
|
|
errno = 0;
|
|
_vsnwprintf_s(buffer, 1024, _TRUNCATE, format, args);
|
|
if (errno != 0)
|
|
{
|
|
level = Level::Error;
|
|
_snwprintf_s(buffer, 1024, _TRUNCATE, L"Internal error: %s", format);
|
|
}
|
|
|
|
_set_invalid_parameter_handler(oldHandler);
|
|
|
|
Log(level, source, buffer);
|
|
delete [] buffer;
|
|
}
|
|
|
|
std::wstring GetSectionSourceString(Section* section)
|
|
{
|
|
std::wstring source;
|
|
if (section)
|
|
{
|
|
MeterWindow* meterWindow = section->GetMeterWindow();
|
|
if (meterWindow)
|
|
{
|
|
source = meterWindow->GetSkinPath();
|
|
source += L" - ";
|
|
}
|
|
|
|
source += L'[';
|
|
source += section->GetOriginalName();
|
|
source += L']';
|
|
}
|
|
return source;
|
|
}
|
|
|
|
void Logger::LogSection(Logger::Level level, Section* section, const WCHAR* message)
|
|
{
|
|
const std::wstring source = GetSectionSourceString(section);
|
|
GetLogger().Log(level, source.c_str(), message);
|
|
}
|
|
|
|
void Logger::LogSectionVF(Logger::Level level, Section* section, const WCHAR* format, va_list args)
|
|
{
|
|
const std::wstring source = GetSectionSourceString(section);
|
|
GetLogger().LogVF(level, source.c_str(), format, args);
|
|
}
|
|
|
|
void Logger::LogMeterWindowVF(Logger::Level level, MeterWindow* meterWindow, const WCHAR* format, va_list args)
|
|
{
|
|
std::wstring source;
|
|
if (meterWindow)
|
|
{
|
|
source = meterWindow->GetSkinPath();
|
|
}
|
|
GetLogger().LogVF(level, source.c_str(), format, args);
|
|
}
|