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

JSON formatter for structured logging. More...

#include <base_formatter.h>

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

Public Member Functions

std::string format (const log_entry &entry) const override
 Format a log entry into a string.
 
std::string get_format_type () const override
 
 json_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 JSON string.
 
std::string get_name () const override
 Get formatter name.
 
- Public Member Functions inherited from kcenon::logger::base_formatter
virtual ~base_formatter ()=default
 
- 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.
 

Private Member Functions

template<typename StringType >
std::string escape_json (const StringType &str) const
 

Static Private Member Functions

static void format_value (std::ostringstream &oss, const log_value &value)
 Format a log_value to JSON.
 

Additional Inherited Members

- Protected Member Functions inherited from kcenon::logger::base_formatter
std::string level_to_string (log_level level) const
 Convert log level to string.
 
std::string format_timestamp (const std::chrono::system_clock::time_point &timestamp) const
 Format timestamp to ISO8601 string.
 
std::string get_thread_id () const
 Get current thread ID as string.
 
- Protected Attributes inherited from kcenon::logger::log_formatter_interface
format_options options_
 

Detailed Description

JSON formatter for structured logging.

Formatter that outputs JSON-structured log messages.

Produces machine-readable JSON output suitable for log aggregation, analysis tools, and automated processing. Supports both compact and pretty-printed output formats.

Features:

  • ISO 8601 timestamp format (RFC 3339)
  • Proper JSON escaping of special characters
  • Optional pretty-printing for readability
  • Structured source location information
  • Compatible with JSON parsers and log aggregation systems

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

Note
This implementation provides basic JSON formatting without external dependencies. For more complex JSON structures, consider integrating nlohmann/json or similar libraries.
Since
1.2.0
Examples
structured_logging_example.cpp.

Definition at line 69 of file json_formatter.h.

Constructor & Destructor Documentation

◆ json_formatter()

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

Constructor with optional format options.

Parameters
optsInitial format options
Note
For JSON output, use_colors option is ignored
Since
1.2.0

Definition at line 79 of file json_formatter.h.

79 {}) {
80 options_ = opts;
81 // JSON doesn't support colors
82 options_.use_colors = false;
83 }

Member Function Documentation

◆ escape_json()

template<typename StringType >
std::string kcenon::logger::json_formatter::escape_json ( const StringType & str) const
inlineprivate

Definition at line 156 of file base_formatter.h.

156 {
157 std::ostringstream escaped;
158 for (unsigned char c : str) {
159 if (c == '"') escaped << "\\\"";
160 else if (c == '\\') escaped << "\\\\";
161 else if (c == '\n') escaped << "\\n";
162 else if (c == '\r') escaped << "\\r";
163 else if (c == '\t') escaped << "\\t";
164 else if (c == '\b') escaped << "\\b";
165 else if (c == '\f') escaped << "\\f";
166 // Escape all other control characters (0x00-0x1F) as \uXXXX
167 else if (c >= 0x00 && c <= 0x1F) {
168 escaped << "\\u"
169 << std::hex << std::setw(4) << std::setfill('0')
170 << static_cast<int>(c);
171 }
172 else escaped << c;
173 }
174 return escaped.str();
175 }

Referenced by format().

Here is the caller graph for this function:

◆ format() [1/2]

std::string kcenon::logger::json_formatter::format ( const log_entry & entry) const
inlineoverridevirtual

Format a log entry into a string.

Parameters
entryThe log entry to format
Returns
Formatted string representation

Implements kcenon::logger::base_formatter.

Examples
structured_logging_example.cpp.

Definition at line 124 of file base_formatter.h.

124 {
125 std::ostringstream oss;
126
127 oss << "{";
128 oss << "\"timestamp\":\"" << format_timestamp(entry.timestamp) << "\",";
129 oss << "\"level\":\"" << level_to_string(entry.level) << "\",";
130 oss << "\"message\":\"" << escape_json(entry.message) << "\",";
131 oss << "\"thread\":\"" << (entry.thread_id ? std::string(*entry.thread_id) : get_thread_id()) << "\"";
132
133 if (entry.location) {
134 oss << ",\"location\":{";
135 oss << "\"file\":\"" << escape_json(entry.location->file) << "\",";
136 oss << "\"line\":" << entry.location->line << ",";
137 oss << "\"function\":\"" << escape_json(entry.location->function) << "\"";
138 oss << "}";
139 }
140
141 if (entry.category) {
142 oss << ",\"category\":\"" << escape_json(*entry.category) << "\"";
143 }
144
145 oss << "}";
146
147 return oss.str();
148 }
std::string level_to_string(log_level level) const
Convert log level to string.
std::string format_timestamp(const std::chrono::system_clock::time_point &timestamp) const
Format timestamp to ISO8601 string.
std::string get_thread_id() const
Get current thread ID as string.
std::string escape_json(const StringType &str) const

References kcenon::logger::log_entry::category, escape_json(), kcenon::logger::base_formatter::format_timestamp(), kcenon::logger::base_formatter::get_thread_id(), kcenon::logger::log_entry::level, kcenon::logger::base_formatter::level_to_string(), kcenon::logger::log_entry::location, kcenon::logger::log_entry::message, kcenon::logger::log_entry::thread_id, and kcenon::logger::log_entry::timestamp.

Referenced by json_formatter_example().

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

◆ format() [2/2]

std::string kcenon::logger::json_formatter::format ( const log_entry & entry) const
inlineoverridevirtual

Format a log entry to JSON string.

Parameters
entryThe log entry to format
Returns
JSON-formatted string

Produces a JSON object with fields:

  • timestamp: ISO 8601 format (UTC)
  • level: Log level as string
  • thread_id: Thread ID as number
  • message: Log message (escaped)
  • file, line, function: Source location (if enabled)
Note
Thread-safe. Can be called concurrently.
Since
1.2.0

Implements kcenon::logger::base_formatter.

Definition at line 101 of file json_formatter.h.

101 {
102 std::ostringstream oss;
103 const char* indent = options_.pretty_print ? " " : "";
104 const char* newline = options_.pretty_print ? "\n" : "";
105
106 oss << "{" << newline;
107
108 bool first = true;
109
110 // Timestamp (ISO 8601)
112 if (!first) oss << "," << newline;
113 oss << indent << "\"timestamp\":\"" << utils::time_utils::format_iso8601(entry.timestamp) << "\"";
114 first = false;
115 }
116
117 // Level
119 if (!first) oss << "," << newline;
120 oss << indent << "\"level\":\"" << utils::string_utils::level_to_string(entry.level) << "\"";
121 first = false;
122 }
123
124 // Thread ID
125 if (options_.include_thread_id && entry.thread_id) {
126 if (!first) oss << "," << newline;
127 oss << indent << "\"thread_id\":\"" << utils::string_utils::escape_json(entry.thread_id->to_string()) << "\"";
128 first = false;
129 }
130
131 // Message (always include)
132 if (!first) oss << "," << newline;
133 oss << indent << "\"message\":\"" << utils::string_utils::escape_json(entry.message.to_string()) << "\"";
134 first = false;
135
136 // Source location
137 if (options_.include_source_location && entry.location) {
138 std::string file_path = entry.location->file.to_string();
139 if (!file_path.empty()) {
140 oss << "," << newline << indent << "\"file\":\"" << utils::string_utils::escape_json(file_path) << "\"";
141 }
142
143 if (entry.location->line > 0) {
144 oss << "," << newline << indent << "\"line\":" << entry.location->line;
145 }
146
147 std::string func = entry.location->function.to_string();
148 if (!func.empty()) {
149 oss << "," << newline << indent << "\"function\":\"" << utils::string_utils::escape_json(func) << "\"";
150 }
151 }
152
153 // Category (if present)
154 if (entry.category) {
155 std::string cat = entry.category->to_string();
156 if (!cat.empty()) {
157 oss << "," << newline << indent << "\"category\":\"" << utils::string_utils::escape_json(cat) << "\"";
158 }
159 }
160
161 // OpenTelemetry context (if present)
162 if (entry.otel_ctx && entry.otel_ctx->is_valid()) {
163 if (!entry.otel_ctx->trace_id.empty()) {
164 oss << "," << newline << indent << "\"trace_id\":\"" << utils::string_utils::escape_json(entry.otel_ctx->trace_id) << "\"";
165 }
166 if (!entry.otel_ctx->span_id.empty()) {
167 oss << "," << newline << indent << "\"span_id\":\"" << utils::string_utils::escape_json(entry.otel_ctx->span_id) << "\"";
168 }
169 if (!entry.otel_ctx->trace_flags.empty()) {
170 oss << "," << newline << indent << "\"trace_flags\":\"" << utils::string_utils::escape_json(entry.otel_ctx->trace_flags) << "\"";
171 }
172 }
173
174 // Structured fields (if present)
175 if (entry.fields && !entry.fields->empty()) {
176 for (const auto& [key, value] : *entry.fields) {
177 oss << "," << newline << indent << "\"" << utils::string_utils::escape_json(key) << "\":";
178 format_value(oss, value);
179 }
180 }
181
182 oss << newline << "}";
183
184 return oss.str();
185 }
static void format_value(std::ostringstream &oss, const log_value &value)
Format a log_value to JSON.
static std::string level_to_string(log_level level)
Convert log level to human-readable string.
static std::string escape_json(const std::string &str)
Escape special characters for JSON.
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, kcenon::logger::utils::string_utils::escape_json(), 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, kcenon::logger::utils::string_utils::level_to_string(), kcenon::logger::log_entry::location, kcenon::logger::log_entry::message, kcenon::logger::log_formatter_interface::options_, kcenon::logger::log_entry::otel_ctx, kcenon::logger::format_options::pretty_print, kcenon::logger::log_entry::thread_id, kcenon::logger::log_entry::timestamp, and kcenon::logger::small_string< SSO_SIZE >::to_string().

Here is the call graph for this function:

◆ format_value()

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

Format a log_value to JSON.

Parameters
ossOutput stream
valueValue to format

Definition at line 203 of file json_formatter.h.

203 {
204 std::visit([&oss](const auto& v) {
205 using T = std::decay_t<decltype(v)>;
206 if constexpr (std::is_same_v<T, std::string>) {
207 oss << "\"" << utils::string_utils::escape_json(v) << "\"";
208 } else if constexpr (std::is_same_v<T, bool>) {
209 oss << (v ? "true" : "false");
210 } else if constexpr (std::is_same_v<T, int64_t>) {
211 oss << v;
212 } else if constexpr (std::is_same_v<T, double>) {
213 oss << std::fixed << std::setprecision(6) << v;
214 } else {
215 oss << v;
216 }
217 }, value);
218 }

References kcenon::logger::utils::string_utils::escape_json().

Referenced by format().

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

◆ get_format_type()

std::string kcenon::logger::json_formatter::get_format_type ( ) const
inlineoverride

Definition at line 150 of file base_formatter.h.

150 {
151 return "json";
152 }

◆ get_name()

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

Get formatter name.

Returns
"json_formatter"
Since
1.2.0

Implements kcenon::logger::log_formatter_interface.

Definition at line 193 of file json_formatter.h.

193 {
194 return "json_formatter";
195 }

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