9 #include "quill/bundled/fmt/base.h" 10 #include "quill/core/Attributes.h" 11 #include "quill/core/Filesystem.h" 12 #include "quill/core/LogLevel.h" 13 #include "quill/core/MacroMetadata.h" 14 #include "quill/sinks/FileSink.h" 15 #include "quill/sinks/StreamSink.h" 17 #include "quill/bundled/fmt/format.h" 23 #include <string_view> 33 template <
typename TBase>
37 using base_type = TBase;
40 using base_type::base_type;
61 std::string_view thread_id, std::string_view thread_name,
62 std::string
const& process_id, std::string_view logger_name,
63 LogLevel log_level, std::string_view log_level_description,
64 std::string_view log_level_short_code,
65 std::vector<std::pair<std::string, std::string>>
const* named_args,
66 std::string_view log_message, std::string_view log_statement)
override 68 if (!_json_message_ready)
70 char const* message_format = log_metadata->message_format();
72 if (strchr(message_format,
'\n') !=
nullptr)
75 _format = message_format;
77 for (
size_t pos = 0; (pos = _format.find(
'\n', pos)) != std::string::npos; pos++)
79 _format.replace(pos, 1,
" ");
83 message_format = _format.data();
86 _json_message.clear();
89 logger_name, log_level, log_level_description, log_level_short_code,
90 named_args, log_message, log_statement, message_format);
92 _json_message.append(std::string_view{
"}\n"});
95 _json_message_ready =
false;
97 base_type::write_log(log_metadata, log_timestamp, thread_id, thread_name, process_id, logger_name, log_level,
98 log_level_description, log_level_short_code, named_args, std::string_view{},
99 std::string_view{_json_message.data(), _json_message.size()});
112 MacroMetadata const* log_metadata, uint64_t log_timestamp, std::string_view thread_id,
113 std::string_view , std::string
const& ,
114 std::string_view logger_name, LogLevel ,
115 std::string_view log_level_description, std::string_view ,
116 std::vector<std::pair<std::string, std::string>>
const* named_args,
117 std::string_view , std::string_view ,
char const* message_format)
119 _json_message.append(std::string_view{
"{\"timestamp\":\""});
120 _append_json_escaped(_json_message, std::to_string(log_timestamp));
121 _json_message.append(std::string_view{
"\",\"file_name\":\""});
122 _append_json_escaped(_json_message, log_metadata->file_name());
123 _json_message.append(std::string_view{
"\",\"line\":\""});
124 _append_json_escaped(_json_message, log_metadata->line());
125 _json_message.append(std::string_view{
"\",\"thread_id\":\""});
126 _append_json_escaped(_json_message, thread_id);
127 _json_message.append(std::string_view{
"\",\"logger\":\""});
128 _append_json_escaped(_json_message, logger_name);
129 _json_message.append(std::string_view{
"\",\"log_level\":\""});
130 _append_json_escaped(_json_message, log_level_description);
131 _json_message.append(std::string_view{
"\",\"message\":\""});
132 _append_json_escaped(_json_message, message_format);
133 _json_message.append(std::string_view{
"\""});
138 for (
auto const& [key,
value] : *named_args)
140 _json_message.append(std::string_view{
",\""});
141 _append_json_escaped(_json_message, key);
142 _json_message.append(std::string_view{
"\":\""});
143 _append_json_escaped(_json_message,
value);
144 _json_message.append(std::string_view{
"\""});
150 QUILL_NODISCARD
size_t estimate_write_size(
MacroMetadata const* log_metadata, uint64_t log_timestamp,
151 std::string_view thread_id, std::string_view thread_name,
152 std::string
const& process_id, std::string_view logger_name,
153 LogLevel log_level, std::string_view log_level_description,
154 std::string_view log_level_short_code,
155 std::vector<std::pair<std::string, std::string>>
const* named_args,
156 std::string_view log_message, std::string_view log_statement)
override 158 _json_message.clear();
160 char const* message_format = log_metadata->message_format();
161 if (strchr(message_format,
'\n') !=
nullptr)
163 _format = message_format;
165 for (
size_t pos = 0; (pos = _format.find(
'\n', pos)) != std::string::npos; pos++)
167 _format.replace(pos, 1,
" ");
170 message_format = _format.data();
174 logger_name, log_level, log_level_description, log_level_short_code,
175 named_args, log_message, log_statement, message_format);
177 _json_message.append(std::string_view{
"}\n"});
178 _json_message_ready =
true;
179 return _json_message.size();
182 static void _append_json_escaped(fmtquill::memory_buffer& out, std::string_view
value)
186 static constexpr
char control_escape_table[32][7] = {
187 "\\u0000",
"\\u0001",
"\\u0002",
"\\u0003",
"\\u0004",
"\\u0005",
"\\u0006",
"\\u0007",
188 "\\u0008",
"\\u0009",
"\\u000A",
"\\u000B",
"\\u000C",
"\\u000D",
"\\u000E",
"\\u000F",
189 "\\u0010",
"\\u0011",
"\\u0012",
"\\u0013",
"\\u0014",
"\\u0015",
"\\u0016",
"\\u0017",
190 "\\u0018",
"\\u0019",
"\\u001A",
"\\u001B",
"\\u001C",
"\\u001D",
"\\u001E",
"\\u001F"};
192 size_t const size = value.size();
193 char const*
const data = value.data();
195 for (
size_t i = 0; i < size; ++i)
197 unsigned char const c =
static_cast<unsigned char>(data[i]);
201 out.append(std::string_view{
"\\\""});
204 out.append(std::string_view{
"\\\\"});
207 out.append(std::string_view{
"\\b"});
210 out.append(std::string_view{
"\\f"});
213 out.append(std::string_view{
"\\n"});
216 out.append(std::string_view{
"\\r"});
219 out.append(std::string_view{
"\\t"});
225 if (i + 2 < size && static_cast<unsigned char>(data[i + 1]) == 0x80 &&
226 (static_cast<unsigned char>(data[i + 2]) == 0xA8 || static_cast<unsigned char>(data[i + 2]) == 0xA9))
228 out.append(static_cast<unsigned char>(data[i + 2]) == 0xA8 ? std::string_view{
"\\u2028"}
229 : std::string_view{
"\\u2029"});
234 out.push_back(static_cast<char>(c));
240 out.append(std::string_view{control_escape_table[c], 6});
244 out.push_back(static_cast<char>(c));
251 fmtquill::memory_buffer _json_message;
253 bool _json_message_ready{
false};
268 std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now())
270 std::move(file_event_notifier), do_fopen, start_time)
Definition: JsonSink.h:34
QUILL_ATTRIBUTE_HOT void write_log(MacroMetadata const *log_metadata, uint64_t log_timestamp, std::string_view thread_id, std::string_view thread_name, std::string const &process_id, std::string_view logger_name, LogLevel log_level, std::string_view log_level_description, std::string_view log_level_short_code, std::vector< std::pair< std::string, std::string >> const *named_args, std::string_view log_message, std::string_view log_statement) override
Logs a formatted log message to the sink.
Definition: JsonSink.h:60
JSON File Sink.
Definition: JsonSink.h:263
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:28
JSON Console Sink.
Definition: JsonSink.h:280
The FileSinkConfig class holds the configuration options for the FileSink.
Definition: FileSink.h:67
Notifies on file events by calling the appropriate callback.
Definition: StreamSink.h:68
virtual QUILL_ATTRIBUTE_HOT void generate_json_message(MacroMetadata const *log_metadata, uint64_t log_timestamp, std::string_view thread_id, std::string_view, std::string const &, std::string_view logger_name, LogLevel, std::string_view log_level_description, std::string_view, std::vector< std::pair< std::string, std::string >> const *named_args, std::string_view, std::string_view, char const *message_format)
Generates a JSON-formatted log message.
Definition: JsonSink.h:111