Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
analysis.cppm
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
24export module kcenon.logger:analysis;
25
26// Standard library imports
27import <chrono>;
28import <memory>;
29import <string>;
30import <unordered_map>;
31import <vector>;
32
33// Import core partition for types
34import :core;
35
36export namespace kcenon::logger::analysis {
37
44 common::interfaces::log_level level;
45 std::string message;
46 std::chrono::system_clock::time_point timestamp;
47 std::string source_file;
48 int source_line;
49 std::string function_name;
50};
51
58 size_t total_entries = 0;
59 std::unordered_map<common::interfaces::log_level, size_t> level_counts;
60 std::chrono::system_clock::time_point earliest_timestamp;
61 std::chrono::system_clock::time_point latest_timestamp;
62 std::vector<std::string> most_frequent_messages;
63 std::unordered_map<std::string, size_t> error_patterns;
64};
65
76private:
77 std::vector<analyzed_log_entry> entries_;
79 bool stats_dirty_ = true;
80
81public:
86 void add_entry(const analyzed_log_entry& entry) {
87 entries_.push_back(entry);
88 stats_dirty_ = true;
89 }
90
95 void add_entries(const std::vector<analyzed_log_entry>& entries) {
96 entries_.insert(entries_.end(), entries.begin(), entries.end());
97 stats_dirty_ = true;
98 }
99
103 void clear() {
104 entries_.clear();
106 stats_dirty_ = true;
107 }
108
114 if (stats_dirty_) {
115 update_stats();
116 stats_dirty_ = false;
117 }
118 return cached_stats_;
119 }
120
126 std::vector<analyzed_log_entry> filter_by_level(common::interfaces::log_level level) const {
127 std::vector<analyzed_log_entry> filtered;
128 for (const auto& entry : entries_) {
129 if (entry.level == level) {
130 filtered.push_back(entry);
131 }
132 }
133 return filtered;
134 }
135
142 std::vector<analyzed_log_entry> filter_by_time_range(
143 const std::chrono::system_clock::time_point& start,
144 const std::chrono::system_clock::time_point& end) const {
145
146 std::vector<analyzed_log_entry> filtered;
147 for (const auto& entry : entries_) {
148 if (entry.timestamp >= start && entry.timestamp <= end) {
149 filtered.push_back(entry);
150 }
151 }
152 return filtered;
153 }
154
160 std::vector<analyzed_log_entry> search_messages(const std::string& search_text) const {
161 std::vector<analyzed_log_entry> results;
162 for (const auto& entry : entries_) {
163 if (entry.message.find(search_text) != std::string::npos) {
164 results.push_back(entry);
165 }
166 }
167 return results;
168 }
169
175 double get_error_rate(const std::chrono::minutes& window = std::chrono::minutes(60)) const {
176 auto now = std::chrono::system_clock::now();
177 auto start_time = now - window;
178
179 size_t total_in_window = 0;
180 size_t errors_in_window = 0;
181
182 for (const auto& entry : entries_) {
183 if (entry.timestamp >= start_time) {
184 total_in_window++;
185 if (entry.level == common::interfaces::log_level::error ||
186 entry.level == common::interfaces::log_level::critical) {
187 errors_in_window++;
188 }
189 }
190 }
191
192 return total_in_window > 0 ?
193 static_cast<double>(errors_in_window) / static_cast<double>(total_in_window) : 0.0;
194 }
195
201 const auto& stats = get_stats();
202
203 std::string report = "=== Log Analysis Summary ===\n";
204 report += "Total Entries: " + std::to_string(stats.total_entries) + "\n";
205 report += "Level Distribution:\n";
206
207 for (const auto& [level, count] : stats.level_counts) {
208 report += " " + level_to_string(level) + ": " + std::to_string(count) + "\n";
209 }
210
211 if (stats.total_entries > 0) {
212 auto duration = std::chrono::duration_cast<std::chrono::minutes>(
213 stats.latest_timestamp - stats.earliest_timestamp);
214 report += "Time Range: " + std::to_string(duration.count()) + " minutes\n";
215 }
216
217 return report;
218 }
219
224 size_t size() const {
225 return entries_.size();
226 }
227
232 bool empty() const {
233 return entries_.empty();
234 }
235
236private:
240
241 if (entries_.empty()) {
242 return;
243 }
244
245 // Initialize timestamps
248
249 // Count levels and update timestamps
250 for (const auto& entry : entries_) {
251 cached_stats_.level_counts[entry.level]++;
252
253 if (entry.timestamp < cached_stats_.earliest_timestamp) {
254 cached_stats_.earliest_timestamp = entry.timestamp;
255 }
256 if (entry.timestamp > cached_stats_.latest_timestamp) {
257 cached_stats_.latest_timestamp = entry.timestamp;
258 }
259 }
260 }
261
262 std::string level_to_string(common::interfaces::log_level level) const {
263 // Use underlying integer to avoid duplicate case value errors
264 // (warn and warning both = 3, fatal and critical both = 5)
265 const int level_value = static_cast<int>(level);
266 switch (level_value) {
267 case 0: return "TRACE";
268 case 1: return "DEBUG";
269 case 2: return "INFO";
270 case 3: return "WARN";
271 case 4: return "ERROR";
272 case 5: return "FATAL";
273 case 6: return "OFF";
274 default: return "UNKNOWN";
275 }
276 }
277};
278
283public:
288 static std::unique_ptr<log_analyzer> create_basic() {
289 return std::make_unique<log_analyzer>();
290 }
291};
292
293} // namespace kcenon::logger::analysis
Factory for creating log analyzers.
static std::unique_ptr< log_analyzer > create_basic()
Create a basic log analyzer.
Log analyzer for processing and analyzing log data.
Definition analysis.cppm:75
const analysis_stats & get_stats()
Get analysis statistics.
void add_entries(const std::vector< analyzed_log_entry > &entries)
Add multiple log entries.
Definition analysis.cppm:95
std::string generate_summary_report()
Generate summary report.
void add_entry(const analyzed_log_entry &entry)
Add a log entry for analysis.
Definition analysis.cppm:86
std::vector< analyzed_log_entry > search_messages(const std::string &search_text) const
Find entries containing specific text.
size_t size() const
Get the total number of entries.
std::string level_to_string(log_level level) const
bool empty() const
Check if the analyzer has no entries.
std::string level_to_string(common::interfaces::log_level level) const
double get_error_rate(const std::chrono::minutes &window=std::chrono::minutes(60)) const
Get error rate for a time window.
std::vector< analyzed_log_entry > entries_
std::vector< analyzed_log_entry > filter_by_level(common::interfaces::log_level level) const
Filter entries by log level.
std::vector< analyzed_log_entry > filter_by_time_range(const std::chrono::system_clock::time_point &start, const std::chrono::system_clock::time_point &end) const
Filter entries by time range.
Analysis result statistics.
Definition analysis.cppm:57
std::unordered_map< log_level, size_t > level_counts
std::unordered_map< common::interfaces::log_level, size_t > level_counts
Definition analysis.cppm:59
std::chrono::system_clock::time_point latest_timestamp
std::unordered_map< std::string, size_t > error_patterns
std::vector< std::string > most_frequent_messages
std::chrono::system_clock::time_point earliest_timestamp
Log entry for analysis.
Definition analysis.cppm:43
std::string message
std::string source_file
std::string function_name
int source_line
common::interfaces::log_level level
Definition analysis.cppm:44
std::chrono::system_clock::time_point timestamp