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