Logger System 1.0.0
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
kcenon::logger::file_writer Class Reference

Core file writer for logging to files. More...

#include <file_writer.h>

Inheritance diagram for kcenon::logger::file_writer:
Inheritance graph
Collaboration diagram for kcenon::logger::file_writer:
Collaboration graph

Public Member Functions

 file_writer (const std::string &filename, bool append=true, std::unique_ptr< log_formatter_interface > formatter=nullptr, bool binary=false)
 Constructor.
 
 ~file_writer () override
 Destructor.
 
 file_writer (const file_writer &)=delete
 
file_writeroperator= (const file_writer &)=delete
 
 file_writer (file_writer &&)=delete
 
file_writeroperator= (file_writer &&)=delete
 
common::VoidResult write (const log_entry &entry) override
 Write a log entry to file.
 
common::VoidResult flush () override
 Flush file stream.
 
common::VoidResult close () override
 Close the file.
 
std::string get_name () const override
 Get writer name.
 
bool is_open () const override
 Check if file is open.
 
bool is_healthy () const override
 Check if writer is healthy.
 
size_t get_file_size () const
 Get current file size.
 
void set_integrity_policy (std::shared_ptr< security::integrity_policy > policy)
 Enable tamper-evident integrity signing for every record.
 
- Public Member Functions inherited from kcenon::logger::log_writer_interface
virtual ~log_writer_interface ()=default
 

Protected Member Functions

std::string format_entry (const log_entry &entry) const
 Format a log entry using the current formatter.
 
common::VoidResult open_internal ()
 Open the file (internal, caller must hold mutex)
 
void close_internal ()
 Close the file (internal, caller must hold mutex)
 
std::mutex & get_mutex () const
 Access the writer mutex for extended operations.
 

Protected Attributes

std::string filename_
 
bool append_mode_
 
bool binary_mode_ = false
 
std::ofstream file_stream_
 
std::atomic< bool > is_open_ {false}
 
std::atomic< size_t > bytes_written_ {0}
 
std::unique_ptr< log_formatter_interfaceformatter_
 
std::shared_ptr< security::integrity_policyintegrity_policy_
 Integrity policy shared with derived writers (e.g. rotating_file_writer).
 
std::mutex mutex_
 

Additional Inherited Members

- Static Public Attributes inherited from kcenon::logger::sync_writer_tag
static constexpr writer_category category = writer_category::synchronous
 

Detailed Description

Core file writer for logging to files.

Pure file I/O implementation with direct mutex management. Designed to serve as the base layer in Decorator pattern compositions.

Thread-safe with internal mutex synchronization.

Category: Synchronous (blocking I/O to file)

Since
1.0.0
1.3.0 Refactored to use thread_safe_writer base class
1.4.0 Added sync_writer_tag for category classification
4.0.0 Refactored for Decorator pattern with simplified inheritance
4.1.0 Directly implements log_writer_interface as core writer
Examples
decorator_usage.cpp.

Definition at line 46 of file file_writer.h.

Constructor & Destructor Documentation

◆ file_writer() [1/3]

kcenon::logger::file_writer::file_writer ( const std::string & filename,
bool append = true,
std::unique_ptr< log_formatter_interface > formatter = nullptr,
bool binary = false )
explicit

Constructor.

Parameters
filenamePath to the log file
appendWhether to append to existing file (default: true)
formatterCustom log formatter (default: timestamp formatter)
binaryWhether to open the file in binary mode and skip the trailing newline that is otherwise appended after each record (default: false). Required when the caller writes pre-framed binary payloads such as those produced by encrypted_writer.

Definition at line 15 of file file_writer.cpp.

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}
common::VoidResult open_internal()
Open the file (internal, caller must hold mutex)
std::unique_ptr< log_formatter_interface > formatter_

References mutex_, and open_internal().

Here is the call graph for this function:

◆ ~file_writer()

kcenon::logger::file_writer::~file_writer ( )
override

Destructor.

Definition at line 27 of file file_writer.cpp.

27 {
28 std::lock_guard<std::mutex> lock(mutex_);
30}
void close_internal()
Close the file (internal, caller must hold mutex)

References close_internal(), and mutex_.

Here is the call graph for this function:

◆ file_writer() [2/3]

kcenon::logger::file_writer::file_writer ( const file_writer & )
delete

◆ file_writer() [3/3]

kcenon::logger::file_writer::file_writer ( file_writer && )
delete

Member Function Documentation

◆ close()

common::VoidResult kcenon::logger::file_writer::close ( )
overridevirtual

Close the file.

Returns
common::VoidResult Success or error code

Implements kcenon::logger::log_writer_interface.

Definition at line 81 of file file_writer.cpp.

81 {
82 std::lock_guard<std::mutex> lock(mutex_);
84 return common::ok();
85}
VoidResult ok()

References close_internal(), mutex_, and kcenon::common::ok().

Here is the call graph for this function:

◆ close_internal()

void kcenon::logger::file_writer::close_internal ( )
protected

Close the file (internal, caller must hold mutex)

Definition at line 145 of file file_writer.cpp.

145 {
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}
std::atomic< bool > is_open_

References file_stream_, and is_open_.

Referenced by close(), and ~file_writer().

Here is the caller graph for this function:

◆ flush()

common::VoidResult kcenon::logger::file_writer::flush ( )
overridevirtual

Flush file stream.

Returns
common::VoidResult Success or error code

Implements kcenon::logger::log_writer_interface.

Definition at line 69 of file file_writer.cpp.

69 {
70 std::lock_guard<std::mutex> lock(mutex_);
71
73 if (is_open_) {
74 file_stream_.flush();
76 }
77 return common::ok();
79}
common::VoidResult check_stream_state(const Stream &stream, const std::string &operation_name="operation")
Stream state verification helper.
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.

References kcenon::logger::utils::check_stream_state(), file_stream_, kcenon::logger::flush_timeout, is_open_, mutex_, kcenon::common::ok(), and kcenon::logger::utils::try_write_operation().

Here is the call graph for this function:

◆ format_entry()

std::string kcenon::logger::file_writer::format_entry ( const log_entry & entry) const
protected

Format a log entry using the current formatter.

Definition at line 97 of file file_writer.cpp.

97 {
98 if (!formatter_) {
99 // Fallback if formatter is somehow null
100 return entry.message.to_string();
101 }
102 return formatter_->format(entry);
103}

References formatter_, kcenon::logger::log_entry::message, and kcenon::logger::small_string< SSO_SIZE >::to_string().

Referenced by write(), and kcenon::logger::rotating_file_writer::write().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_file_size()

size_t kcenon::logger::file_writer::get_file_size ( ) const
inline

Get current file size.

Definition at line 111 of file file_writer.h.

111{ return bytes_written_.load(); }
std::atomic< size_t > bytes_written_

◆ get_mutex()

std::mutex & kcenon::logger::file_writer::get_mutex ( ) const
inlineprotected

Access the writer mutex for extended operations.

Returns
Reference to the internal mutex

Definition at line 148 of file file_writer.h.

148{ return mutex_; }

Referenced by kcenon::logger::rotating_file_writer::rotate(), and kcenon::logger::rotating_file_writer::write().

Here is the caller graph for this function:

◆ get_name()

std::string kcenon::logger::file_writer::get_name ( ) const
inlineoverridevirtual

Get writer name.

Implements kcenon::logger::log_writer_interface.

Reimplemented in kcenon::logger::rotating_file_writer.

Examples
decorator_usage.cpp.

Definition at line 96 of file file_writer.h.

96{ return "file"; }

Referenced by example_core_writers().

Here is the caller graph for this function:

◆ is_healthy()

bool kcenon::logger::file_writer::is_healthy ( ) const
overridevirtual

Check if writer is healthy.

Implements kcenon::logger::log_writer_interface.

Definition at line 87 of file file_writer.cpp.

87 {
88 return is_open_ && file_stream_.good();
89}

References file_stream_, and is_open_.

◆ is_open()

bool kcenon::logger::file_writer::is_open ( ) const
inlinenodiscardoverridevirtual

Check if file is open.

Implements kcenon::logger::log_writer_interface.

Definition at line 101 of file file_writer.h.

101{ return is_open_; }

◆ open_internal()

common::VoidResult kcenon::logger::file_writer::open_internal ( )
protected

Open the file (internal, caller must hold mutex)

Definition at line 105 of file file_writer.cpp.

105 {
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}
common::VoidResult try_open_operation(F &&operation)
Error handling helper for file open 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.

References append_mode_, binary_mode_, bytes_written_, kcenon::logger::utils::check_condition(), kcenon::logger::utils::ensure_directory_exists(), kcenon::logger::file_open_failed, file_stream_, filename_, is_open_, kcenon::common::ok(), and kcenon::logger::utils::try_open_operation().

Referenced by file_writer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=() [1/2]

file_writer & kcenon::logger::file_writer::operator= ( const file_writer & )
delete

◆ operator=() [2/2]

file_writer & kcenon::logger::file_writer::operator= ( file_writer && )
delete

◆ set_integrity_policy()

void kcenon::logger::file_writer::set_integrity_policy ( std::shared_ptr< security::integrity_policy > policy)

Enable tamper-evident integrity signing for every record.

Parameters
policySigning policy (shared ownership); pass nullptr to disable.

When a policy is installed, each written record is followed by a SIGNATURE[<policy>]:<hex> suffix on the same line (Issue #612, ISO/IEC 27001 A.12.4.2 / A.12.4.3). Existing log consumers that already parse a single line per record continue to work; the signature is simply appended at end-of-line before the newline.

Must be called before the writer is handed off to a logger — it is not safe to swap policies while concurrent writes are in flight.

Definition at line 91 of file file_writer.cpp.

92 {
93 std::lock_guard<std::mutex> lock(mutex_);
94 integrity_policy_ = std::move(policy);
95}
std::shared_ptr< security::integrity_policy > integrity_policy_
Integrity policy shared with derived writers (e.g. rotating_file_writer).

References integrity_policy_, and mutex_.

◆ write()

common::VoidResult kcenon::logger::file_writer::write ( const log_entry & entry)
overridevirtual

Write a log entry to file.

Parameters
entryThe log entry to write
Returns
common::VoidResult Success or error code

Implements kcenon::logger::log_writer_interface.

Reimplemented in kcenon::logger::rotating_file_writer.

Definition at line 32 of file file_writer.cpp.

32 {
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}
std::string format_entry(const log_entry &entry) const
Format a log entry using the current formatter.
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 make_logger_void_result(logger_error_code code, const std::string &message="")

References binary_mode_, bytes_written_, kcenon::logger::utils::check_stream_state(), file_stream_, kcenon::logger::file_write_failed, format_entry(), kcenon::logger::security::format_signature_suffix(), integrity_policy_, is_open_, kcenon::logger::make_logger_void_result(), mutex_, and kcenon::logger::utils::try_write_operation().

Here is the call graph for this function:

Member Data Documentation

◆ append_mode_

bool kcenon::logger::file_writer::append_mode_
protected

◆ binary_mode_

bool kcenon::logger::file_writer::binary_mode_ = false
protected

Definition at line 153 of file file_writer.h.

Referenced by open_internal(), and write().

◆ bytes_written_

std::atomic<size_t> kcenon::logger::file_writer::bytes_written_ {0}
protected

◆ file_stream_

◆ filename_

◆ formatter_

std::unique_ptr<log_formatter_interface> kcenon::logger::file_writer::formatter_
protected

Definition at line 159 of file file_writer.h.

Referenced by format_entry().

◆ integrity_policy_

std::shared_ptr<security::integrity_policy> kcenon::logger::file_writer::integrity_policy_
protected

Integrity policy shared with derived writers (e.g. rotating_file_writer).

Definition at line 161 of file file_writer.h.

Referenced by set_integrity_policy(), write(), and kcenon::logger::rotating_file_writer::write().

◆ is_open_

std::atomic<bool> kcenon::logger::file_writer::is_open_ {false}
protected

Definition at line 156 of file file_writer.h.

156{false};

Referenced by close_internal(), flush(), is_healthy(), open_internal(), and write().

◆ mutex_

std::mutex kcenon::logger::file_writer::mutex_
mutableprotected

Definition at line 162 of file file_writer.h.

Referenced by close(), file_writer(), flush(), set_integrity_policy(), write(), and ~file_writer().


The documentation for this class was generated from the following files: