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

Formatter that outputs logfmt-structured log messages. More...

#include <logfmt_formatter.h>

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

Public Member Functions

 logfmt_formatter (const format_options &opts=format_options{})
 Constructor with optional format options.
 
std::string format (const log_entry &entry) const override
 Format a log entry to logfmt string.
 
std::string get_name () const override
 Get formatter name.
 
- Public Member Functions inherited from kcenon::logger::log_formatter_interface
virtual ~log_formatter_interface ()=default
 
virtual void set_options (const format_options &opts)
 Set formatting options.
 
virtual format_options get_options () const
 Get current formatting options.
 

Static Private Member Functions

static std::string level_to_lowercase (log_level level)
 Convert log level to lowercase string.
 
static std::string escape_logfmt_key (const std::string &key)
 Escape a logfmt key (remove spaces and special characters)
 
static std::string escape_logfmt_value (const std::string &value)
 Escape a logfmt value.
 
static void format_value (std::ostringstream &oss, const log_value &value)
 Format a log_value to logfmt.
 

Additional Inherited Members

- Protected Attributes inherited from kcenon::logger::log_formatter_interface
format_options options_
 

Detailed Description

Formatter that outputs logfmt-structured log messages.

Produces machine-readable logfmt output suitable for log aggregation, analysis tools, and automated processing. The format consists of key=value pairs separated by spaces.

Features:

  • ISO 8601 timestamp format (RFC 3339)
  • Proper escaping of special characters
  • Structured source location information
  • OpenTelemetry context support (trace_id, span_id)
  • Compatible with logfmt parsers and log aggregation systems

Thread-safety: This formatter is stateless and thread-safe.

Since
3.1.0
Examples
structured_logging_example.cpp.

Definition at line 68 of file logfmt_formatter.h.

Constructor & Destructor Documentation

◆ logfmt_formatter()

kcenon::logger::logfmt_formatter::logfmt_formatter ( const format_options & opts = format_options{})
inlineexplicit

Constructor with optional format options.

Parameters
optsInitial format options
Note
For logfmt output, use_colors and pretty_print options are ignored
Since
3.1.0

Definition at line 78 of file logfmt_formatter.h.

78 {}) {
79 options_ = opts;
80 // Logfmt doesn't support colors or pretty print
81 options_.use_colors = false;
82 options_.pretty_print = false;
83 }

Member Function Documentation

◆ escape_logfmt_key()

static std::string kcenon::logger::logfmt_formatter::escape_logfmt_key ( const std::string & key)
inlinestaticprivate

Escape a logfmt key (remove spaces and special characters)

Parameters
keyKey to escape
Returns
Escaped key

Definition at line 217 of file logfmt_formatter.h.

217 {
218 std::string result;
219 result.reserve(key.size());
220 for (char c : key) {
221 if (c == ' ' || c == '=' || c == '"' || c == '\n' || c == '\t') {
222 result += '_';
223 } else {
224 result += c;
225 }
226 }
227 return result;
228 }

Referenced by format().

Here is the caller graph for this function:

◆ escape_logfmt_value()

static std::string kcenon::logger::logfmt_formatter::escape_logfmt_value ( const std::string & value)
inlinestaticprivate

Escape a logfmt value.

Parameters
valueValue to escape
Returns
Escaped value (quoted if necessary)

Values containing spaces, quotes, or special characters are wrapped in double quotes with proper escaping.

Definition at line 238 of file logfmt_formatter.h.

238 {
239 // Check if quoting is needed
240 bool needs_quoting = false;
241 for (char c : value) {
242 if (c == ' ' || c == '"' || c == '=' || c == '\n' || c == '\t' || c == '\r') {
243 needs_quoting = true;
244 break;
245 }
246 }
247
248 if (!needs_quoting && !value.empty()) {
249 return value;
250 }
251
252 // Quote and escape
253 std::ostringstream oss;
254 oss << '"';
255 for (char c : value) {
256 switch (c) {
257 case '"': oss << "\\\""; break;
258 case '\\': oss << "\\\\"; break;
259 case '\n': oss << "\\n"; break;
260 case '\r': oss << "\\r"; break;
261 case '\t': oss << "\\t"; break;
262 default: oss << c;
263 }
264 }
265 oss << '"';
266 return oss.str();
267 }

Referenced by format(), and format_value().

Here is the caller graph for this function:

◆ format()

std::string kcenon::logger::logfmt_formatter::format ( const log_entry & entry) const
inlinenodiscardoverridevirtual

Format a log entry to logfmt string.

Parameters
entryThe log entry to format
Returns
Logfmt-formatted string

Produces key=value pairs with fields:

  • level: Log level as lowercase string
  • ts: ISO 8601 format timestamp (UTC)
  • msg: Log message (escaped)
  • thread_id: Thread ID
  • file, line, function: Source location (if enabled)
  • trace_id, span_id: OpenTelemetry context (if present)
  • Additional structured fields
Note
Thread-safe. Can be called concurrently.
Since
3.1.0

Implements kcenon::logger::log_formatter_interface.

Examples
structured_logging_example.cpp.

Definition at line 103 of file logfmt_formatter.h.

103 {
104 std::ostringstream oss;
105 bool first = true;
106
107 // Level
109 oss << "level=" << level_to_lowercase(entry.level);
110 first = false;
111 }
112
113 // Timestamp (ISO 8601)
115 if (!first) {
116 oss << " ";
117 }
118 oss << "ts=" << utils::time_utils::format_iso8601(entry.timestamp);
119 first = false;
120 }
121
122 // Message (always include)
123 if (!first) {
124 oss << " ";
125 }
126 oss << "msg=" << escape_logfmt_value(entry.message.to_string());
127 first = false;
128
129 // Thread ID
130 if (options_.include_thread_id && entry.thread_id) {
131 oss << " thread_id=" << escape_logfmt_value(entry.thread_id->to_string());
132 }
133
134 // Source location
135 if (options_.include_source_location && entry.location) {
136 std::string file_path = entry.location->file.to_string();
137 if (!file_path.empty()) {
138 oss << " file=" << escape_logfmt_value(file_path);
139 }
140
141 if (entry.location->line > 0) {
142 oss << " line=" << entry.location->line;
143 }
144
145 std::string func = entry.location->function.to_string();
146 if (!func.empty()) {
147 oss << " function=" << escape_logfmt_value(func);
148 }
149 }
150
151 // Category (if present)
152 if (entry.category) {
153 std::string cat = entry.category->to_string();
154 if (!cat.empty()) {
155 oss << " category=" << escape_logfmt_value(cat);
156 }
157 }
158
159 // OpenTelemetry context (if present)
160 if (entry.otel_ctx && entry.otel_ctx->is_valid()) {
161 if (!entry.otel_ctx->trace_id.empty()) {
162 oss << " trace_id=" << entry.otel_ctx->trace_id;
163 }
164 if (!entry.otel_ctx->span_id.empty()) {
165 oss << " span_id=" << entry.otel_ctx->span_id;
166 }
167 if (!entry.otel_ctx->trace_flags.empty()) {
168 oss << " trace_flags=" << entry.otel_ctx->trace_flags;
169 }
170 }
171
172 // Structured fields (if present)
173 if (entry.fields && !entry.fields->empty()) {
174 for (const auto& [key, value] : *entry.fields) {
175 oss << " " << escape_logfmt_key(key) << "=";
176 format_value(oss, value);
177 }
178 }
179
180 return oss.str();
181 }
static void format_value(std::ostringstream &oss, const log_value &value)
Format a log_value to logfmt.
static std::string escape_logfmt_value(const std::string &value)
Escape a logfmt value.
static std::string escape_logfmt_key(const std::string &key)
Escape a logfmt key (remove spaces and special characters)
static std::string level_to_lowercase(log_level level)
Convert log level to lowercase string.
static std::string format_iso8601(const std::chrono::system_clock::time_point &tp)
Format timestamp to ISO 8601 / RFC 3339 format with UTC timezone.
Definition time_utils.h:76

References kcenon::logger::log_entry::category, escape_logfmt_key(), escape_logfmt_value(), kcenon::logger::log_entry::fields, kcenon::logger::utils::time_utils::format_iso8601(), format_value(), kcenon::logger::format_options::include_level, kcenon::logger::format_options::include_source_location, kcenon::logger::format_options::include_thread_id, kcenon::logger::format_options::include_timestamp, kcenon::logger::log_entry::level, level_to_lowercase(), kcenon::logger::log_entry::location, kcenon::logger::log_entry::message, kcenon::logger::log_formatter_interface::options_, kcenon::logger::log_entry::otel_ctx, kcenon::logger::log_entry::thread_id, kcenon::logger::log_entry::timestamp, and kcenon::logger::small_string< SSO_SIZE >::to_string().

Referenced by logfmt_formatter_example().

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

◆ format_value()

static void kcenon::logger::logfmt_formatter::format_value ( std::ostringstream & oss,
const log_value & value )
inlinestaticprivate

Format a log_value to logfmt.

Parameters
ossOutput stream
valueValue to format

Definition at line 274 of file logfmt_formatter.h.

274 {
275 std::visit([&oss](const auto& v) {
276 using T = std::decay_t<decltype(v)>;
277 if constexpr (std::is_same_v<T, std::string>) {
278 oss << escape_logfmt_value(v);
279 } else if constexpr (std::is_same_v<T, bool>) {
280 oss << (v ? "true" : "false");
281 } else if constexpr (std::is_same_v<T, int64_t>) {
282 oss << v;
283 } else if constexpr (std::is_same_v<T, double>) {
284 oss << std::fixed << std::setprecision(6) << v;
285 } else {
286 oss << v;
287 }
288 }, value);
289 }

References escape_logfmt_value().

Referenced by format().

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

◆ get_name()

std::string kcenon::logger::logfmt_formatter::get_name ( ) const
inlinenodiscardoverridevirtual

Get formatter name.

Returns
"logfmt_formatter"
Since
3.1.0

Implements kcenon::logger::log_formatter_interface.

Definition at line 189 of file logfmt_formatter.h.

189 {
190 return "logfmt_formatter";
191 }

◆ level_to_lowercase()

static std::string kcenon::logger::logfmt_formatter::level_to_lowercase ( log_level level)
inlinestaticprivate

Convert log level to lowercase string.

Parameters
levelLog level
Returns
Lowercase string representation

Definition at line 199 of file logfmt_formatter.h.

199 {
200 switch (level) {
201 case log_level::trace: return "trace";
202 case log_level::debug: return "debug";
203 case log_level::info: return "info";
204 case log_level::warning: return "warn";
205 case log_level::error: return "error";
206 case log_level::critical: return "critical";
207 case log_level::off: return "off";
208 default: return "unknown";
209 }
210 }

Referenced by format().

Here is the caller graph for this function:

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