WireCellToolkit
Wire Cell Simulation, Signal Process and Reconstruction Toolki for Liquid Argon Detectors
registry.h
Go to the documentation of this file.
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 "spdlog/common.h"
15 #include "spdlog/logger.h"
16 
17 #ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
18 // support for the default stdout color logger
19 #ifdef _WIN32
21 #else
23 #endif
24 #endif // SPDLOG_DISABLE_DEFAULT_LOGGER
25 
26 #include <chrono>
27 #include <functional>
28 #include <memory>
29 #include <string>
30 #include <unordered_map>
31 
32 namespace spdlog {
33 namespace details {
34 class thread_pool;
35 
36 class registry
37 {
38 public:
39  registry(const registry &) = delete;
40  registry &operator=(const registry &) = delete;
41 
42  void register_logger(std::shared_ptr<logger> new_logger)
43  {
44  std::lock_guard<std::mutex> lock(logger_map_mutex_);
45  register_logger_(std::move(new_logger));
46  }
47 
48  void initialize_logger(std::shared_ptr<logger> new_logger)
49  {
50  std::lock_guard<std::mutex> lock(logger_map_mutex_);
51  new_logger->set_formatter(formatter_->clone());
52 
53  if (err_handler_)
54  {
55  new_logger->set_error_handler(err_handler_);
56  }
57 
58  new_logger->set_level(level_);
59  new_logger->flush_on(flush_level_);
60 
61  if (automatic_registration_)
62  {
63  register_logger_(std::move(new_logger));
64  }
65  }
66 
67  std::shared_ptr<logger> get(const std::string &logger_name)
68  {
69  std::lock_guard<std::mutex> lock(logger_map_mutex_);
70  auto found = loggers_.find(logger_name);
71  return found == loggers_.end() ? nullptr : found->second;
72  }
73 
74  std::shared_ptr<logger> default_logger()
75  {
76  std::lock_guard<std::mutex> lock(logger_map_mutex_);
77  return default_logger_;
78  }
79 
80  // Return raw ptr to the default logger.
81  // To be used directly by the spdlog default api (e.g. spdlog::info)
82  // This make the default API faster, but cannot be used concurrently with set_default_logger().
83  // e.g do not call set_default_logger() from one thread while calling spdlog::info() from another.
85  {
86  return default_logger_.get();
87  }
88 
89  // set default logger.
90  // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map.
91  void set_default_logger(std::shared_ptr<logger> new_default_logger)
92  {
93  std::lock_guard<std::mutex> lock(logger_map_mutex_);
94  // remove previous default logger from the map
95  if (default_logger_ != nullptr)
96  {
97  loggers_.erase(default_logger_->name());
98  }
99  if (new_default_logger != nullptr)
100  {
101  loggers_[new_default_logger->name()] = new_default_logger;
102  }
103  default_logger_ = std::move(new_default_logger);
104  }
105 
106  void set_tp(std::shared_ptr<thread_pool> tp)
107  {
108  std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
109  tp_ = std::move(tp);
110  }
111 
112  std::shared_ptr<thread_pool> get_tp()
113  {
114  std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
115  return tp_;
116  }
117 
118  // Set global formatter. Each sink in each logger will get a clone of this object
119  void set_formatter(std::unique_ptr<formatter> formatter)
120  {
121  std::lock_guard<std::mutex> lock(logger_map_mutex_);
122  formatter_ = std::move(formatter);
123  for (auto &l : loggers_)
124  {
125  l.second->set_formatter(formatter_->clone());
126  }
127  }
128 
129  void set_level(level::level_enum log_level)
130  {
131  std::lock_guard<std::mutex> lock(logger_map_mutex_);
132  for (auto &l : loggers_)
133  {
134  l.second->set_level(log_level);
135  }
136  level_ = log_level;
137  }
138 
139  void flush_on(level::level_enum log_level)
140  {
141  std::lock_guard<std::mutex> lock(logger_map_mutex_);
142  for (auto &l : loggers_)
143  {
144  l.second->flush_on(log_level);
145  }
146  flush_level_ = log_level;
147  }
148 
149  void flush_every(std::chrono::seconds interval)
150  {
151  std::lock_guard<std::mutex> lock(flusher_mutex_);
152  std::function<void()> clbk = std::bind(&registry::flush_all, this);
153  periodic_flusher_ = details::make_unique<periodic_worker>(clbk, interval);
154  }
155 
157  {
158  std::lock_guard<std::mutex> lock(logger_map_mutex_);
159  for (auto &l : loggers_)
160  {
161  l.second->set_error_handler(handler);
162  }
163  err_handler_ = handler;
164  }
165 
166  void apply_all(const std::function<void(const std::shared_ptr<logger>)> &fun)
167  {
168  std::lock_guard<std::mutex> lock(logger_map_mutex_);
169  for (auto &l : loggers_)
170  {
171  fun(l.second);
172  }
173  }
174 
175  void flush_all()
176  {
177  std::lock_guard<std::mutex> lock(logger_map_mutex_);
178  for (auto &l : loggers_)
179  {
180  l.second->flush();
181  }
182  }
183 
184  void drop(const std::string &logger_name)
185  {
186  std::lock_guard<std::mutex> lock(logger_map_mutex_);
187  loggers_.erase(logger_name);
188  if (default_logger_ && default_logger_->name() == logger_name)
189  {
190  default_logger_.reset();
191  }
192  }
193 
194  void drop_all()
195  {
196  std::lock_guard<std::mutex> lock(logger_map_mutex_);
197  loggers_.clear();
198  default_logger_.reset();
199  }
200 
201  // clean all resources and threads started by the registry
202  void shutdown()
203  {
204  {
205  std::lock_guard<std::mutex> lock(flusher_mutex_);
206  periodic_flusher_.reset();
207  }
208 
209  drop_all();
210 
211  {
212  std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
213  tp_.reset();
214  }
215  }
216 
217  std::recursive_mutex &tp_mutex()
218  {
219  return tp_mutex_;
220  }
221 
222  void set_automatic_registration(bool automatic_regsistration)
223  {
224  std::lock_guard<std::mutex> lock(logger_map_mutex_);
225  automatic_registration_ = automatic_regsistration;
226  }
227 
228  static registry &instance()
229  {
230  static registry s_instance;
231  return s_instance;
232  }
233 
234 private:
235  registry()
236  : formatter_(new pattern_formatter())
237  {
238 
239 #ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
240  // create default logger (ansicolor_stdout_sink_mt or wincolor_stdout_sink_mt in windows).
241 #ifdef _WIN32
242  auto color_sink = std::make_shared<sinks::wincolor_stdout_sink_mt>();
243 #else
244  auto color_sink = std::make_shared<sinks::ansicolor_stdout_sink_mt>();
245 #endif
246 
247  const char *default_logger_name = "";
248  default_logger_ = std::make_shared<spdlog::logger>(default_logger_name, std::move(color_sink));
249  loggers_[default_logger_name] = default_logger_;
250 
251 #endif // SPDLOG_DISABLE_DEFAULT_LOGGER
252  }
253 
254  ~registry() = default;
255 
256  void throw_if_exists_(const std::string &logger_name)
257  {
258  if (loggers_.find(logger_name) != loggers_.end())
259  {
260  throw spdlog_ex("logger with name '" + logger_name + "' already exists");
261  }
262  }
263 
264  void register_logger_(std::shared_ptr<logger> new_logger)
265  {
266  auto logger_name = new_logger->name();
267  throw_if_exists_(logger_name);
268  loggers_[logger_name] = std::move(new_logger);
269  }
270 
271  std::mutex logger_map_mutex_, flusher_mutex_;
272  std::recursive_mutex tp_mutex_;
273  std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;
274  std::unique_ptr<formatter> formatter_;
276  level::level_enum flush_level_ = level::off;
277  log_err_handler err_handler_;
278  std::shared_ptr<thread_pool> tp_;
279  std::unique_ptr<periodic_worker> periodic_flusher_;
280  std::shared_ptr<logger> default_logger_;
281  bool automatic_registration_ = true;
282 };
283 
284 } // namespace details
285 } // namespace spdlog
std::shared_ptr< thread_pool > get_tp()
Definition: registry.h:112
void apply_all(const std::function< void(const std::shared_ptr< logger >)> &fun)
Definition: registry.h:166
void set_formatter(std::unique_ptr< formatter > formatter)
Definition: registry.h:119
void flush_on(level::level_enum log_level)
Definition: registry.h:139
static registry & instance()
Definition: registry.h:228
void set_error_handler(log_err_handler handler)
Definition: registry.h:156
std::recursive_mutex & tp_mutex()
Definition: registry.h:217
void set_tp(std::shared_ptr< thread_pool > tp)
Definition: registry.h:106
Definition: async.h:27
static level::level_enum default_level()
Definition: logger_impl.h:359
std::shared_ptr< spdlog::details::thread_pool > thread_pool()
Definition: async.h:83
void set_level(level::level_enum log_level)
Definition: registry.h:129
registry & operator=(const registry &)=delete
void initialize_logger(std::shared_ptr< logger > new_logger)
Definition: registry.h:48
void set_default_logger(std::shared_ptr< logger > new_default_logger)
Definition: registry.h:91
void set_automatic_registration(bool automatic_regsistration)
Definition: registry.h:222
void flush_every(std::chrono::seconds interval)
Definition: registry.h:149
void drop(const std::string &logger_name)
Definition: registry.h:184
std::function< void(const std::string &err_msg)> log_err_handler
Definition: common.h:82
void register_logger(std::shared_ptr< logger > new_logger)
Definition: registry.h:42
logger * get_default_raw()
Definition: registry.h:84
std::shared_ptr< logger > default_logger()
Definition: registry.h:74