quill
JsonSink.h
1 
7 #pragma once
8 
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"
16 
17 #include "quill/bundled/fmt/format.h"
18 
19 #include <cstdint>
20 #include <cstring>
21 #include <string>
22 #include <string_view>
23 #include <utility>
24 #include <vector>
25 
26 QUILL_BEGIN_NAMESPACE
27 
28 namespace detail
29 {
30 template <typename TBase>
31 class JsonSink : public TBase
32 {
33 public:
34  using base_type = TBase;
35 
37  using base_type::base_type;
38 
39  ~JsonSink() override = default;
40 
57  QUILL_ATTRIBUTE_HOT void write_log(MacroMetadata const* log_metadata, uint64_t log_timestamp,
58  std::string_view thread_id, std::string_view thread_name,
59  std::string const& process_id, std::string_view logger_name,
60  LogLevel log_level, std::string_view log_level_description,
61  std::string_view log_level_short_code,
62  std::vector<std::pair<std::string, std::string>> const* named_args,
63  std::string_view log_message, std::string_view log_statement) override
64  {
65  char const* message_format = log_metadata->message_format();
66 
67  if (strchr(log_metadata->message_format(), '\n') != nullptr)
68  {
69  // The format string contains at least one new line and that would break the json message, it needs to be removed
70  _format = log_metadata->message_format();
71 
72  for (size_t pos = 0; (pos = _format.find('\n', pos)) != std::string::npos; pos++)
73  {
74  _format.replace(pos, 1, " ");
75  }
76 
77  // we do not want newlines in the json message, use the modified message_format
78  message_format = _format.data();
79  }
80 
81  _json_message.clear();
82 
83  generate_json_message(log_metadata, log_timestamp, thread_id, thread_name, process_id,
84  logger_name, log_level, log_level_description, log_level_short_code,
85  named_args, log_message, log_statement, message_format);
86 
87  _json_message.append(std::string_view{"}\n"});
88 
89  StreamSink::write_log(log_metadata, log_timestamp, thread_id, thread_name, process_id, logger_name, log_level,
90  log_level_description, log_level_short_code, named_args, std::string_view{},
91  std::string_view{_json_message.data(), _json_message.size()});
92  }
93 
103  QUILL_ATTRIBUTE_HOT virtual void generate_json_message(
104  MacroMetadata const* log_metadata, uint64_t log_timestamp, std::string_view thread_id,
105  std::string_view , std::string const& ,
106  std::string_view logger_name, LogLevel ,
107  std::string_view log_level_description, std::string_view ,
108  std::vector<std::pair<std::string, std::string>> const* named_args,
109  std::string_view , std::string_view , char const* message_format)
110  {
111  _json_message.append(fmtquill::format(
112  R"({{"timestamp":"{}","file_name":"{}","line":"{}","thread_id":"{}","logger":"{}","log_level":"{}","message":"{}")",
113  std::to_string(log_timestamp), log_metadata->file_name(), log_metadata->line(), thread_id,
114  logger_name, log_level_description, message_format));
115 
116  // Add args as key-values
117  if (named_args)
118  {
119  for (auto const& [key, value] : *named_args)
120  {
121  _json_message.append(std::string_view{",\""});
122  _json_message.append(key);
123  _json_message.append(std::string_view{"\":\""});
124  _json_message.append(value);
125  _json_message.append(std::string_view{"\""});
126  }
127  }
128  }
129 
130 protected:
131  fmtquill::memory_buffer _json_message;
132  std::string _format;
133 };
134 } // namespace detail
135 
139 class JsonFileSink : public detail::JsonSink<FileSink>
140 {
141 public:
142  JsonFileSink(fs::path const& filename, FileSinkConfig const& config,
143  FileEventNotifier file_event_notifier = FileEventNotifier{}, bool do_fopen = true)
144  : detail::JsonSink<FileSink>(filename, static_cast<FileSinkConfig const&>(config),
145  std::move(file_event_notifier), do_fopen)
146  {
147  }
148 
149  ~JsonFileSink() override = default;
150 };
151 
155 class JsonConsoleSink : public detail::JsonSink<StreamSink>
156 {
157 public:
158  JsonConsoleSink() : detail::JsonSink<StreamSink>("stdout", nullptr) {}
159  ~JsonConsoleSink() override = default;
160 };
161 
162 QUILL_END_NAMESPACE
QUILL_ATTRIBUTE_HOT void write_log(MacroMetadata const *, uint64_t, std::string_view, std::string_view, std::string const &, std::string_view, LogLevel, std::string_view, std::string_view, std::vector< std::pair< std::string, std::string >> const *, std::string_view, std::string_view log_statement) override
Writes a formatted log message to the stream.
Definition: StreamSink.h:133
Captures and stores information about a logging event in compile time.
Definition: MacroMetadata.h:22
Definition: JsonSink.h:31
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:57
JSON File Sink.
Definition: JsonSink.h:139
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:24
Definition: base.h:2147
JSON Console Sink.
Definition: JsonSink.h:155
The FileSinkConfig class holds the configuration options for the FileSink.
Definition: FileSink.h:57
Notifies on file events by calling the appropriate callback, the callback is executed on the backend ...
Definition: StreamSink.h:36
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:103