FinanceSim 0.1.0
Financial Simulation Library
Loading...
Searching...
No Matches
log_writer.cpp
Go to the documentation of this file.
1#include "core/log_writer.hpp"
2#include <iostream>
3#include <iomanip>
4#include <sstream>
5
6namespace financesim {
7
8// ============================================================================
9// ConsoleWriter Implementation
10// ============================================================================
11
12void ConsoleWriter::write(const Event& event, LogLevel level) {
13 std::cout << "[" << std::setw(5) << log_level_to_string(level) << "] "
14 << "t=" << std::fixed << std::setprecision(1) << event.timestamp()
15 << " [" << event.source_id() << "] "
16 << event.type_name()
17 << std::endl;
18}
19
21 std::cout.flush();
22}
23
25 // Nothing to close for console
26}
27
28// ============================================================================
29// JsonWriter Implementation
30// ============================================================================
31
32JsonWriter::JsonWriter(const std::string& filename)
33 : filename_(filename) {
34 file_.open(filename, std::ios::out | std::ios::trunc);
35 if (!file_.is_open()) {
36 throw std::runtime_error("Failed to open log file: " + filename);
37 }
38}
39
43
44namespace {
45 // Helper to escape strings for JSON
46 std::string escape_json(const std::string& s) {
47 std::ostringstream o;
48 for (char c : s) {
49 switch (c) {
50 case '"': o << "\\\""; break;
51 case '\\': o << "\\\\"; break;
52 case '\b': o << "\\b"; break;
53 case '\f': o << "\\f"; break;
54 case '\n': o << "\\n"; break;
55 case '\r': o << "\\r"; break;
56 case '\t': o << "\\t"; break;
57 default:
58 if ('\x00' <= c && c <= '\x1f') {
59 o << "\\u" << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
60 } else {
61 o << c;
62 }
63 }
64 }
65 return o.str();
66 }
67}
68
69void JsonWriter::write(const Event& event, LogLevel level) {
70 if (!file_.is_open()) return;
71
72 // Build JSON object manually (avoiding external JSON library)
73 file_ << "{"
74 << "\"timestamp\":" << std::fixed << std::setprecision(6) << event.timestamp() << ","
75 << "\"level\":\"" << log_level_to_string(level) << "\","
76 << "\"type\":\"" << event.type_name() << "\","
77 << "\"source_id\":\"" << escape_json(event.source_id()) << "\"";
78
79 // Add type-specific fields
80 if (auto* income = dynamic_cast<const IncomeEvent*>(&event)) {
81 file_ << ",\"amount\":" << income->amount()
82 << ",\"category\":\"" << escape_json(income->category()) << "\""
83 << ",\"target_account\":\"" << escape_json(income->target_account()) << "\"";
84 } else if (auto* expense = dynamic_cast<const ExpenseEvent*>(&event)) {
85 file_ << ",\"amount\":" << expense->amount()
86 << ",\"category\":\"" << escape_json(expense->category()) << "\""
87 << ",\"target_account\":\"" << escape_json(expense->target_account()) << "\"";
88 } else if (auto* asset = dynamic_cast<const AssetEvent*>(&event)) {
89 file_ << ",\"asset_id\":\"" << escape_json(asset->asset_id()) << "\""
90 << ",\"value\":" << asset->value()
91 << ",\"delta\":" << asset->delta();
92 } else if (auto* liability = dynamic_cast<const LiabilityEvent*>(&event)) {
93 file_ << ",\"liability_id\":\"" << escape_json(liability->liability_id()) << "\""
94 << ",\"value\":" << liability->value()
95 << ",\"delta\":" << liability->delta();
96 } else if (auto* account = dynamic_cast<const AccountEvent*>(&event)) {
97 file_ << ",\"account_id\":\"" << escape_json(account->account_id()) << "\""
98 << ",\"balance\":" << account->balance()
99 << ",\"delta\":" << account->delta()
100 << ",\"reason\":\"" << escape_json(account->reason()) << "\"";
101 } else if (auto* transfer = dynamic_cast<const TransferEvent*>(&event)) {
102 file_ << ",\"from_account\":\"" << escape_json(transfer->from_account()) << "\""
103 << ",\"to_account\":\"" << escape_json(transfer->to_account()) << "\""
104 << ",\"amount\":" << transfer->amount()
105 << ",\"reason\":\"" << escape_json(transfer->reason()) << "\"";
106 }
107
108 file_ << "}\n";
109}
110
112 if (file_.is_open()) {
113 file_.flush();
114 }
115}
116
118 if (file_.is_open()) {
119 file_.close();
120 }
121}
122
123} // namespace financesim
Event emitted when an account balance changes.
Definition event.hpp:129
Event emitted when asset value changes.
Definition event.hpp:85
void flush() override
Flush any buffered output.
void write(const Event &event, LogLevel level) override
Write an event to the output.
void close() override
Close the writer and release resources.
Base class for all typed events in the simulation.
Definition event.hpp:10
const std::string & source_id() const
Source model ID that generated this event.
Definition event.hpp:21
Event emitted when an expense occurs.
Definition event.hpp:62
Event emitted when income is received.
Definition event.hpp:39
void close() override
Close the writer and release resources.
void write(const Event &event, LogLevel level) override
Write an event to the output.
JsonWriter(const std::string &filename)
void flush() override
Flush any buffered output.
Event emitted when liability value changes.
Definition event.hpp:107
Event emitted when funds are transferred between accounts.
Definition event.hpp:155
const char * log_level_to_string(LogLevel level)
Convert LogLevel to string representation.
Definition log_level.hpp:14
LogLevel
Log severity levels for filtering.
Definition log_level.hpp:6