bitz-server  2.0.1
registry.h
1 //
2 // Copyright(c) 2015 Gabi Melman.
3 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
4 //
5 
6 #pragma once
7 
8 // Loggers registy of unique name->logger pointer
9 // An attempt to create a logger with an already existing name will be ignored
10 // If user requests a non existing logger, nullptr will be returned
11 // This class is thread safe
12 
13 #include "../async_logger.h"
14 #include "../common.h"
15 #include "../details/null_mutex.h"
16 #include "../logger.h"
17 
18 #include <chrono>
19 #include <functional>
20 #include <memory>
21 #include <mutex>
22 #include <string>
23 #include <unordered_map>
24 
25 namespace spdlog {
26 namespace details {
27 template<class Mutex>
29 {
30 public:
31  registry_t<Mutex>(const registry_t<Mutex> &) = delete;
32  registry_t<Mutex> &operator=(const registry_t<Mutex> &) = delete;
33 
34  void register_logger(std::shared_ptr<logger> logger)
35  {
36  std::lock_guard<Mutex> lock(_mutex);
37  auto logger_name = logger->name();
38  throw_if_exists(logger_name);
39  _loggers[logger_name] = logger;
40  }
41 
42  std::shared_ptr<logger> get(const std::string &logger_name)
43  {
44  std::lock_guard<Mutex> lock(_mutex);
45  auto found = _loggers.find(logger_name);
46  return found == _loggers.end() ? nullptr : found->second;
47  }
48 
49  template<class It>
50  std::shared_ptr<logger> create(const std::string &logger_name, const It &sinks_begin, const It &sinks_end)
51  {
52  std::lock_guard<Mutex> lock(_mutex);
53  throw_if_exists(logger_name);
54  std::shared_ptr<logger> new_logger;
55  if (_async_mode)
56  {
57  new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy,
58  _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb);
59  }
60  else
61  {
62  new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
63  }
64 
65  if (_formatter)
66  {
67  new_logger->set_formatter(_formatter);
68  }
69 
70  if (_err_handler)
71  {
72  new_logger->set_error_handler(_err_handler);
73  }
74 
75  new_logger->set_level(_level);
76  new_logger->flush_on(_flush_level);
77 
78  // Add to registry
79  _loggers[logger_name] = new_logger;
80  return new_logger;
81  }
82 
83  template<class It>
84  std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
85  const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
86  const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb, const It &sinks_begin,
87  const It &sinks_end)
88  {
89  std::lock_guard<Mutex> lock(_mutex);
90  throw_if_exists(logger_name);
91  auto new_logger = std::make_shared<async_logger>(
92  logger_name, sinks_begin, sinks_end, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
93 
94  if (_formatter)
95  {
96  new_logger->set_formatter(_formatter);
97  }
98 
99  if (_err_handler)
100  {
101  new_logger->set_error_handler(_err_handler);
102  }
103 
104  new_logger->set_level(_level);
105  new_logger->flush_on(_flush_level);
106 
107  // Add to registry
108  _loggers[logger_name] = new_logger;
109  return new_logger;
110  }
111 
112  void apply_all(std::function<void(std::shared_ptr<logger>)> fun)
113  {
114  std::lock_guard<Mutex> lock(_mutex);
115  for (auto &l : _loggers)
116  {
117  fun(l.second);
118  }
119  }
120 
121  void drop(const std::string &logger_name)
122  {
123  std::lock_guard<Mutex> lock(_mutex);
124  _loggers.erase(logger_name);
125  }
126 
127  void drop_all()
128  {
129  std::lock_guard<Mutex> lock(_mutex);
130  _loggers.clear();
131  }
132 
133  std::shared_ptr<logger> create(const std::string &logger_name, sinks_init_list sinks)
134  {
135  return create(logger_name, sinks.begin(), sinks.end());
136  }
137 
138  std::shared_ptr<logger> create(const std::string &logger_name, sink_ptr sink)
139  {
140  return create(logger_name, {sink});
141  }
142 
143  std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
144  const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
145  const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb, sinks_init_list sinks)
146  {
147  return create_async(
148  logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks.begin(), sinks.end());
149  }
150 
151  std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
152  const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
153  const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb, sink_ptr sink)
154  {
155  return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, {sink});
156  }
157 
158  void formatter(formatter_ptr f)
159  {
160  std::lock_guard<Mutex> lock(_mutex);
161  _formatter = f;
162  for (auto &l : _loggers)
163  {
164  l.second->set_formatter(_formatter);
165  }
166  }
167 
168  void set_pattern(const std::string &pattern)
169  {
170  std::lock_guard<Mutex> lock(_mutex);
171  _formatter = std::make_shared<pattern_formatter>(pattern);
172  for (auto &l : _loggers)
173  {
174  l.second->set_formatter(_formatter);
175  }
176  }
177 
178  void set_level(level::level_enum log_level)
179  {
180  std::lock_guard<Mutex> lock(_mutex);
181  for (auto &l : _loggers)
182  {
183  l.second->set_level(log_level);
184  }
185  _level = log_level;
186  }
187 
188  void flush_on(level::level_enum log_level)
189  {
190  std::lock_guard<Mutex> lock(_mutex);
191  for (auto &l : _loggers)
192  {
193  l.second->flush_on(log_level);
194  }
195  _flush_level = log_level;
196  }
197 
198  void set_error_handler(log_err_handler handler)
199  {
200  for (auto &l : _loggers)
201  {
202  l.second->set_error_handler(handler);
203  }
204  _err_handler = handler;
205  }
206 
207  void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
208  const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
209  {
210  std::lock_guard<Mutex> lock(_mutex);
211  _async_mode = true;
212  _async_q_size = q_size;
213  _overflow_policy = overflow_policy;
214  _worker_warmup_cb = worker_warmup_cb;
215  _flush_interval_ms = flush_interval_ms;
216  _worker_teardown_cb = worker_teardown_cb;
217  }
218 
219  void set_sync_mode()
220  {
221  std::lock_guard<Mutex> lock(_mutex);
222  _async_mode = false;
223  }
224 
225  static registry_t<Mutex> &instance()
226  {
227  static registry_t<Mutex> s_instance;
228  return s_instance;
229  }
230 
231 private:
232  registry_t<Mutex>() = default;
233 
234  void throw_if_exists(const std::string &logger_name)
235  {
236  if (_loggers.find(logger_name) != _loggers.end())
237  {
238  throw spdlog_ex("logger with name '" + logger_name + "' already exists");
239  }
240  }
241 
242  Mutex _mutex;
243  std::unordered_map<std::string, std::shared_ptr<logger>> _loggers;
244  formatter_ptr _formatter;
245  level::level_enum _level = level::info;
246  level::level_enum _flush_level = level::off;
247  log_err_handler _err_handler;
248  bool _async_mode = false;
249  size_t _async_q_size = 0;
250  async_overflow_policy _overflow_policy = async_overflow_policy::block_retry;
251  std::function<void()> _worker_warmup_cb;
252  std::chrono::milliseconds _flush_interval_ms{std::chrono::milliseconds::zero()};
253  std::function<void()> _worker_teardown_cb;
254 };
255 
256 #ifdef SPDLOG_NO_REGISTRY_MUTEX
258 #else
260 #endif
261 
262 } // namespace details
263 } // namespace spdlog
Definition: lib/spdlog/common.h:146
Definition: logger.h:24
Definition: formatter.h:19
Definition: async_logger.h:26
Definition: registry.h:28