Logger System 1.0.0
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
file_writer.cpp
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
10#include <filesystem>
11#include <iostream>
12
13namespace kcenon::logger {
14
15file_writer::file_writer(const std::string& filename,
16 bool append,
17 std::unique_ptr<log_formatter_interface> formatter,
18 bool binary)
19 : filename_(filename)
20 , append_mode_(append)
21 , binary_mode_(binary)
22 , formatter_(formatter ? std::move(formatter) : std::make_unique<timestamp_formatter>()) {
23 std::lock_guard<std::mutex> lock(mutex_);
25}
26
28 std::lock_guard<std::mutex> lock(mutex_);
30}
31
33 std::lock_guard<std::mutex> lock(mutex_);
34
36 // Check precondition
37 if (!is_open_) {
39 }
40
41 // Format and write
42 std::string formatted = format_entry(entry);
43
44 // Append tamper-evident signature (Issue #612) when a policy is set.
45 // The signature covers the formatted record so verifiers can
46 // reconstruct and check it without re-formatting.
48 formatted.append(
50 }
51
52 if (binary_mode_) {
53 // Binary mode writes the payload verbatim. Callers (for example,
54 // encrypted_writer) produce fully-framed byte streams that must
55 // not be corrupted by a trailing newline or CRLF translation.
56 file_stream_.write(formatted.data(),
57 static_cast<std::streamsize>(formatted.size()));
58 bytes_written_.fetch_add(formatted.size());
59 } else {
60 file_stream_ << formatted << '\n';
61 bytes_written_.fetch_add(formatted.size() + 1); // +1 for newline
62 }
63
64 // Verify stream state
66 });
67}
68
70 std::lock_guard<std::mutex> lock(mutex_);
71
73 if (is_open_) {
74 file_stream_.flush();
76 }
77 return common::ok();
79}
80
82 std::lock_guard<std::mutex> lock(mutex_);
84 return common::ok();
85}
86
88 return is_open_ && file_stream_.good();
89}
90
92 std::shared_ptr<security::integrity_policy> policy) {
93 std::lock_guard<std::mutex> lock(mutex_);
94 integrity_policy_ = std::move(policy);
95}
96
97std::string file_writer::format_entry(const log_entry& entry) const {
98 if (!formatter_) {
99 // Fallback if formatter is somehow null
100 return entry.message.to_string();
101 }
102 return formatter_->format(entry);
103}
104
106 // IMPORTANT: Caller must hold the mutex before calling this method
107
109 // Create directory if it doesn't exist
110 std::filesystem::path file_path(filename_);
111 std::filesystem::path dir = file_path.parent_path();
112
113 auto dir_result = utils::ensure_directory_exists(dir);
114 if (dir_result.is_err()) return dir_result;
115
116 // Open file
117 auto mode = append_mode_ ? std::ios::app : std::ios::trunc;
118 auto flags = std::ios::out | mode;
119 if (binary_mode_) {
120 flags |= std::ios::binary;
121 }
122 file_stream_.open(filename_, flags);
123
124 // Check if file opened successfully
125 auto check = utils::check_condition(
126 file_stream_.is_open(),
128 "Failed to open file: " + filename_
129 );
130 if (check.is_err()) return check;
131
132 // Get current file size if appending
133 if (append_mode_) {
134 file_stream_.seekp(0, std::ios::end);
136 } else {
137 bytes_written_ = 0;
138 }
139
140 is_open_ = true;
141 return common::ok();
142 });
143}
144
146 // IMPORTANT: Caller must hold the mutex before calling this method
147
148 if (is_open_) {
149 if (file_stream_.is_open()) {
150 file_stream_.flush();
151 file_stream_.close();
152 }
153 is_open_ = false;
154 }
155}
156
157} // namespace kcenon::logger
std::shared_ptr< security::integrity_policy > integrity_policy_
Integrity policy shared with derived writers (e.g. rotating_file_writer).
~file_writer() override
Destructor.
common::VoidResult open_internal()
Open the file (internal, caller must hold mutex)
void close_internal()
Close the file (internal, caller must hold mutex)
std::unique_ptr< log_formatter_interface > formatter_
common::VoidResult write(const log_entry &entry) override
Write a log entry to file.
std::atomic< size_t > bytes_written_
std::string format_entry(const log_entry &entry) const
Format a log entry using the current formatter.
std::atomic< bool > is_open_
void set_integrity_policy(std::shared_ptr< security::integrity_policy > policy)
Enable tamper-evident integrity signing for every record.
file_writer(const std::string &filename, bool append=true, std::unique_ptr< log_formatter_interface > formatter=nullptr, bool binary=false)
Constructor.
common::VoidResult close() override
Close the file.
bool is_healthy() const override
Check if writer is healthy.
common::VoidResult flush() override
Flush file stream.
std::string to_string() const
Convert to std::string.
Default formatter with human-readable timestamp format.
Structured error context for debugging log system failures.
File writer for logging to files with optional buffering.
Tamper-evident log signing policies for writers.
Data structures for representing log entries and source locations kcenon.
VoidResult ok()
std::string format_signature_suffix(const integrity_policy &policy, const std::string &record)
Format a signature line suitable for appending to a text log record.
common::VoidResult check_stream_state(const Stream &stream, const std::string &operation_name="operation")
Stream state verification helper.
common::VoidResult try_open_operation(F &&operation)
Error handling helper for file open operations.
common::VoidResult try_write_operation(F &&operation, logger_error_code default_error_code=logger_error_code::file_write_failed)
Error handling helper for write operations.
common::VoidResult check_condition(bool condition, logger_error_code error_code, const std::string &message)
Condition verification helper.
common::VoidResult ensure_directory_exists(const std::filesystem::path &dir)
Directory creation helper.
common::VoidResult make_logger_void_result(logger_error_code code, const std::string &message="")
Represents a single log entry with all associated metadata.
Definition log_entry.h:155
small_string_256 message
The actual log message.
Definition log_entry.h:169
Default human-readable formatter with timestamps kcenon.