-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathLogger.cpp
More file actions
111 lines (97 loc) · 3.63 KB
/
Copy pathLogger.cpp
File metadata and controls
111 lines (97 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "Logger.h"
#include <iostream>
#include <ShlObj.h>
std::ofstream Logger::logFile;
std::mutex Logger::logMutex;
std::unordered_map<std::string, std::chrono::steady_clock::time_point> Logger::lastLogTimes;
void Logger::Init() {
char desktopPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_DESKTOP, NULL, 0, desktopPath))) {
std::string logFilePath = std::string(desktopPath) + "\\MapleCLogs.txt";
logFile.open(logFilePath, std::ios::app);
if (!logFile.is_open()) {
std::cerr << "Failed to open log file: " << logFilePath << std::endl;
} else {
Log("Log file opened successfully: " + logFilePath, LogLevel::Info);
}
} else {
std::cerr << "Failed to get desktop path" << std::endl;
}
}
void Logger::Log(const std::string& message, LogLevel level) {
std::lock_guard<std::mutex> lock(logMutex);
if (!ShouldLog(message)) {
return;
}
std::string levelStr;
switch (level) {
case LogLevel::Debug: levelStr = "[DEBUG]"; break;
case LogLevel::Info: levelStr = "[INFO]"; break;
case LogLevel::Warning: levelStr = "[WARNING]"; break;
case LogLevel::Error: levelStr = "[ERROR]"; break;
case LogLevel::Critical: levelStr = "[CRITICAL]"; break;
}
std::string timeStr = GetTimeStamp();
std::string fullMessage = timeStr + " " + levelStr + " " + message;
// Log to file
if (logFile.is_open()) {
logFile << fullMessage << std::endl;
logFile.flush();
}
// Log to console
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
WORD color;
switch (level) {
case LogLevel::Debug: color = 8; break; // Gray
case LogLevel::Info: color = 7; break; // White
case LogLevel::Warning: color = 14; break; // Yellow
case LogLevel::Error: color = 12; break; // Red
case LogLevel::Critical: color = 79; break; // White on Red
default: color = 7; break; // White
}
SetConsoleTextAttribute(hConsole, color);
std::cout << fullMessage << std::endl;
SetConsoleTextAttribute(hConsole, 7); // Reset to default color
}
void Logger::LogLastError(const std::string& context) {
DWORD error = GetLastError();
LPSTR errorMessage = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&errorMessage, 0, NULL);
std::string errorStr(errorMessage, size);
LocalFree(errorMessage);
Log(context + ": " + errorStr, LogLevel::Error);
}
void Logger::Close() {
if (logFile.is_open()) {
logFile.close();
}
}
std::string Logger::GetTimeStamp() {
auto now = std::chrono::system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(now);
std::tm timeInfo;
localtime_s(&timeInfo, &in_time_t);
std::stringstream ss;
ss << std::put_time(&timeInfo, "[%Y-%m-%d %H:%M:%S]");
return ss.str();
}
std::string Logger::GetHexStr(HRESULT hr) {
std::stringstream ss;
ss << std::hex << std::showbase << hr;
return ss.str();
}
std::string Logger::GetHexStr(UINT64 value) {
std::stringstream ss;
ss << std::hex << std::uppercase << value;
return ss.str();
}
bool Logger::ShouldLog(const std::string& message) {
auto now = std::chrono::steady_clock::now();
auto& lastTime = lastLogTimes[message];
if (now - lastTime < std::chrono::milliseconds(100)) {
return false;
}
lastTime = now;
return true;
}