DotNetDupe 4.0.6
C++17/20 Implementation of the .NET Base Class Library (BCL)
Loading...
Searching...
No Matches
LoggerBase.cpp
Go to the documentation of this file.
1#include "pch.h"
6#include <chrono>
7#include <iomanip>
8#include <sstream>
9
10namespace DotNetDupe {
11 namespace Extensions {
12 namespace Logging {
13
15 : m_categoryName(categoryName), m_config(config) {
17 }
18
19 bool LoggerBase::IsEnabled(LogLevel logLevel) const {
21 return logLevel >= m_config.MinLevel && logLevel != LogLevel::None;
22 }
23
24 void LoggerBase::Log(LogLevel logLevel, const DotNetDupe::System::String& message) {
26 if (!IsEnabled(logLevel)) return;
27
30 Log(logLevel, message, emptyProps);
31 }
32
35 auto now = std::chrono::system_clock::now();
36 auto time = std::chrono::system_clock::to_time_t(now);
37 struct tm buf;
38#if defined(_WIN32)
39 gmtime_s(&buf, &time);
40#else
41 gmtime_r(&time, &buf);
42#endif
44 std::string sFmt = formatFmt.IsEmpty() ? "%Y-%m-%d %H:%M:%S" : formatFmt.GetRawString();
45 char timeStr[255] = { 0 };
46 size_t written = std::strftime(timeStr, sizeof(timeStr), sFmt.c_str(), &buf);
47 if (written > 0) {
48 return DotNetDupe::System::String(timeStr);
49 }
50 return DotNetDupe::System::String("time_error");
51 }
52
53 const char* LoggerBase::LogLevelToString(LogLevel level) const {
55 switch (level) {
56 case LogLevel::Trace: return "Trace";
57 case LogLevel::Debug: return "Debug";
58 case LogLevel::Information: return "Information";
59 case LogLevel::Warning: return "Warning";
60 case LogLevel::Error: return "Error";
61 case LogLevel::Critical: return "Critical";
62 default: return "None";
63 }
64 }
65
66 static void ReplaceToken(std::string& str, const std::string& from, const char* to) {
68 size_t pos = 0;
69 std::string sTo = to ? to : "";
70 while ((pos = str.find(from, pos)) != std::string::npos) {
71 str.replace(pos, from.length(), sTo);
72 pos += sTo.length();
73 }
74 }
75
78 auto keys = properties.GetKeys();
79 for (int iIdx = 0; iIdx < keys.GetLength(); ++iIdx) {
80 DotNetDupe::System::String key = keys[iIdx];
81 std::string placeholder = "{" + std::string(key.GetRawString()) + "}";
82 if (str.find(placeholder) != std::string::npos) {
84 properties.TryGetValue(key, val);
85 ReplaceToken(str, placeholder, val.GetRawString());
86 usedKeys.push_back(key.GetRawString());
87 }
88 }
89 }
90
93 if (properties.GetCount() == 0) return "";
94 std::stringstream ss;
95 auto keys = properties.GetKeys();
96 bool bFirst = true;
97
99 for (int iIdx = 0; iIdx < keys.GetLength(); ++iIdx) {
100 std::string k = keys[iIdx].GetRawString();
101 if (std::find(usedKeys.begin(), usedKeys.end(), k) != usedKeys.end()) continue;
102 if (!bFirst) ss << ", ";
104 properties.TryGetValue(keys[iIdx], val);
105 ss << k << ": " << val.GetRawString();
106 bFirst = false;
107 }
108 return ss.str();
109 }
110
113 std::string res = fmt.GetRawString();
114 ReplaceToken(res, "{Timestamp}", timestamp.GetRawString());
115 ReplaceToken(res, "{Level}", level.GetRawString());
116 ReplaceToken(res, "{Category}", category.GetRawString());
117 ReplaceToken(res, "{Message}", message.GetRawString());
118 ReplaceToken(res, "{Properties}", properties.GetRawString());
119 ReplaceToken(res, "{ProcessId}", processId.GetRawString());
120 ReplaceToken(res, "{ThreadId}", threadId.GetRawString());
121 return DotNetDupe::System::String(res.c_str());
122 }
123
126 if (properties.GetCount() == 0) return;
128 auto keys = properties.GetKeys();
129
131 for (int iIdx = 0; iIdx < keys.GetLength(); ++iIdx) {
133 properties.TryGetValue(keys[iIdx], val);
135 }
136 logObj.SetProperty("properties", propsObj);
137 }
138
140 using namespace DotNetDupe::System::Text::Json;
143 logObj.SetProperty("timestamp", JsonElement(timestamp));
144 logObj.SetProperty("level", JsonElement(DotNetDupe::System::String(level)));
145 logObj.SetProperty("category", JsonElement(category));
146 logObj.SetProperty("processId", JsonElement(static_cast<double>(procId)));
147 logObj.SetProperty("threadId", JsonElement(static_cast<double>(threadId)));
148 logObj.SetProperty("message", JsonElement(message));
149
151 AddJsonLogProperties(logObj, properties);
152 return logObj.ToString();
153 }
154
159 const char* levelStr = LogLevelToString(logLevel);
162
165 return BuildJsonLog(timestamp, levelStr, m_categoryName, procId, threadId, message, properties);
166 }
167
169 std::vector<std::string> usedKeys;
170 std::string sWorkingFmt = m_config.PlainTextFormat.GetRawString();
171 ReplaceDynamicPropertyTokens(sWorkingFmt, properties, usedKeys);
172 std::string propsStr = SerializeUnusedPropertiesText(properties, usedKeys);
173 std::string sProcId = std::to_string(procId);
174 std::string sThreadId = std::to_string(threadId);
175 return FormatLogLine(DotNetDupe::System::String(sWorkingFmt.c_str()), timestamp, DotNetDupe::System::String(levelStr), m_categoryName, message, DotNetDupe::System::String(propsStr.c_str()), DotNetDupe::System::String(sProcId.c_str()), DotNetDupe::System::String(sThreadId.c_str()));
176 }
177
178 }
179 }
180}
Represents a specific JSON value within a JsonDocument.
Provides access to local and remote processes and enables you to start and stop local system processe...
Creates and controls a thread, sets its priority, and gets its status mirroring .NET System....
DotNetDupe::System::String m_categoryName
Definition LoggerBase.h:18
DotNetDupe::System::String FormatLogLine(const DotNetDupe::System::String &fmt, const DotNetDupe::System::String &timestamp, const DotNetDupe::System::String &level, const DotNetDupe::System::String &category, const DotNetDupe::System::String &message, const DotNetDupe::System::String &properties, const DotNetDupe::System::String &processId, const DotNetDupe::System::String &threadId) const
Formats a single log line according to configuration template.
void Log(LogLevel logLevel, const DotNetDupe::System::String &message) override
Writes a log entry without extra structured properties.
const char * LogLevelToString(LogLevel level) const
Converts a LogLevel enumeration to its uppercase string name.
bool IsEnabled(LogLevel logLevel) const override
Checks whether logging is enabled for the specified log level.
DotNetDupe::System::String GetFormattedTimestamp(const DotNetDupe::System::String &formatFmt) const
Generates a formatted timestamp string using strftime syntax.
DotNetDupe::System::String BuildLogMessage(LogLevel logLevel, const DotNetDupe::System::String &message, const DotNetDupe::System::Collections::Generic::Dictionary< DotNetDupe::System::String, DotNetDupe::System::String > &properties) const
Builds the final log message string applying plain text or JSON serialization.
LoggerBase(const DotNetDupe::System::String &categoryName, const LoggerConfiguration &config)
Initializes a new LoggerBase instance with category name and configuration.
Represents a collection of keys and values.
Definition Dictionary.h:66
bool TryGetValue(const TKey &key, TValue &value) const
Definition Dictionary.h:285
static int GetCurrentProcessId()
Gets the process identifier of the calling process.
Definition Process.cpp:282
Represents text as a sequence of UTF-8 code units with culture-invariant operations.
Definition String.h:74
const char * GetRawString() const
Definition String.cpp:230
Represents a specific JSON value within a JsonDocument or object hierarchy.
Definition JsonElement.h:39
String ToString() const
Serializes the element into a JSON string representation.
void SetProperty(const String &sPropertyName, const JsonElement &objValue)
Sets or replaces a property on the current JSON object.
static int GetCurrentThreadId()
Returns an integer identifier for the current managed thread.
Definition Thread.cpp:148
LogLevel
Defines logging severity levels.
Definition ILogger.h:15
@ Warning
Logs that highlight an abnormal or unexpected event.
Definition ILogger.h:23
@ Critical
Logs that describe an unrecoverable application or system crash.
Definition ILogger.h:27
@ None
Not used for writing log messages. Specifies that a logging category should not write any messages.
Definition ILogger.h:29
@ Error
Logs that highlight when the current flow of execution is stopped due to a failure.
Definition ILogger.h:25
@ Debug
Logs that are used for interactive investigation during development.
Definition ILogger.h:19
@ Information
Logs that track the general flow of the application.
Definition ILogger.h:21
@ Trace
Logs that contain the most detailed messages.
Definition ILogger.h:17
static void AddJsonLogProperties(DotNetDupe::System::Text::Json::JsonElement &logObj, const DotNetDupe::System::Collections::Generic::Dictionary< DotNetDupe::System::String, DotNetDupe::System::String > &properties)
static std::string SerializeUnusedPropertiesText(const DotNetDupe::System::Collections::Generic::Dictionary< DotNetDupe::System::String, DotNetDupe::System::String > &properties, const std::vector< std::string > &usedKeys)
static void ReplaceDynamicPropertyTokens(std::string &str, const DotNetDupe::System::Collections::Generic::Dictionary< DotNetDupe::System::String, DotNetDupe::System::String > &properties, std::vector< std::string > &usedKeys)
static void ReplaceToken(std::string &str, const std::string &from, const char *to)
static DotNetDupe::System::String BuildJsonLog(const DotNetDupe::System::String &timestamp, const char *level, const DotNetDupe::System::String &category, int procId, unsigned long threadId, const DotNetDupe::System::String &message, const DotNetDupe::System::Collections::Generic::Dictionary< DotNetDupe::System::String, DotNetDupe::System::String > &properties)
Encapsulates logging system configuration options.
DotNetDupe::System::String TimestampFormat
Timestamp formatting template using strftime syntax (e.g. "%Y-%m-%d %H:%M:%S").
bool IsJsonFormat
Specifies whether to serialize log messages as structured JSON objects.
DotNetDupe::System::String PlainTextFormat
Plain text formatting template (e.g. "{Timestamp} [{Level}] [{Category}] {Message}...
LogLevel MinLevel
Minimum log level required for a message to be recorded.