MySQL 9.4.0
Source Code Documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
registry.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2016, 2025, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef MYSQL_HARNESS_LOGGER_REGISTRY_INCLUDED
27#define MYSQL_HARNESS_LOGGER_REGISTRY_INCLUDED
28
29#include "harness_export.h"
34
35#include <atomic>
36#include <map>
37#include <shared_mutex>
38#include <stdexcept>
39#include <string>
40
41namespace mysql_harness {
42
43namespace logging {
44
45class Handler;
46class ExternalHandler;
47
48class HARNESS_EXPORT Registry {
49 public:
50 Registry() = default;
51 Registry(const Registry &) = delete;
52 Registry &operator=(const Registry &) = delete;
53
54 ~Registry() = default;
55
56 //----[ logger CRUD
57 //]-----------------------------------------------------------
58
59 /**
60 * Create a logger in the internal registry
61 *
62 * @param name Logger id (log domain it services)
63 * @param level Log level for logger
64 *
65 * @throws std::logic_error if there is a logger already registered with given
66 * module name
67 */
68 void create_logger(const std::string &name,
70
71 /**
72 * Remove a named logger from the internal registry
73 *
74 * @param name Logger id (log domain it services)
75 *
76 * @throws std::logic_error if there is no logger registered with given
77 * module name
78 */
79 void remove_logger(const std::string &name);
80
81 /**
82 * Return logger for particular module
83 *
84 * The reason why this function returns by value is thread-safety.
85 *
86 * @param name Logger id (log domain it services)
87 *
88 * @throws std::logic_error if no logger is registered for given module name
89 */
90 Logger get_logger(const std::string &name) const;
91
92 /**
93 * Return logger for particular module.
94 *
95 * if it doesn't exist, get the default logger.
96 *
97 * @param name Logger id (log domain it services)
98 * @param default_name name of the default logger
99 *
100 * @throws std::logic_error if neither logger is registered for given module
101 * name
102 */
103 Logger get_logger_or_default(const std::string &name,
104 const std::string &default_name) const;
105
106 /**
107 * Return logger for particular module.
108 *
109 * if it doesn't exist, get the default logger.
110 *
111 * @param name Logger id (log domain it services)
112 *
113 * @throws std::logic_error if neither logger is registered for given module
114 * name
115 */
116 Logger get_logger_or_default(const std::string &name) const;
117
118 /**
119 * Update logger for particular module
120 *
121 * This function provides a thread-safe way of updating the Logger object in
122 * the registry.
123 *
124 * @param name Logger id (log domain it services)
125 * @param logger Logger object
126 *
127 * @throws std::logic_error if no logger is registered for given module name
128 */
129 void update_logger(const std::string &name, const Logger &logger);
130
131 /**
132 * Get the logger names (id's) from the internal registry
133 */
134 std::set<std::string> get_logger_names() const;
135
136 //----[ handler CRUD
137 //]----------------------------------------------------------
138
139 /**
140 * Add a handler to the internal registry
141 *
142 * @param name Handler id
143 * @param handler Shared pointer to handler
144 *
145 * @throws std::logic_error if there is a handler already registered with
146 * given module name
147 */
148 void add_handler(std::string name, std::shared_ptr<Handler> handler);
149
150 /**
151 * Remove handler from the internal registry
152 *
153 * @param name Handler id
154 *
155 * @throws std::logic_error if no handler is registered for given name
156 */
157 void remove_handler(std::string name);
158
159 /**
160 * Return handler in the internal registry
161 *
162 * @param name Handler id
163 *
164 * @throws std::logic_error if no handler is registered for given name
165 */
166 std::shared_ptr<Handler> get_handler(const std::string &name) const;
167
168 /**
169 * Get the handler names from the internal registry
170 */
171 std::set<std::string> get_handler_names() const;
172
173 /**
174 * Check if a log-level is handled by at least one handler.
175 *
176 * @returns if at least one handler handles the log-level
177 * @retval true at least one handler
178 * @retval false log-level will be ignored.
179 */
180 bool is_handled(LogLevel level) const;
181
182 /**
183 * Flag that the registry has been initialized
184 *
185 * This method should be called after log initialization is complete to
186 * flag that logging facility is now available. Note that this is a
187 * convenience flag - it does not directly affect the operation of Registry.
188 * However, a logging function (i.e. log_message()) might want to query
189 * this flag when called and do whatever it deems appropriate.
190 */
191 void set_ready() noexcept { ready_ = true; }
192
193 /**
194 * Query if logging facility is ready to use
195 *
196 * The exact meaning of this flag is not defined here, see description in
197 * set_ready()
198 */
199 bool is_ready() const noexcept { return ready_; }
200
201 /**
202 * Force the flush (reopen) on all registered logger handlers, while moving
203 * old logger file to dst.
204 * @param dst destination filename for old log
205 */
206 void flush_all_loggers(const std::string &dst = "");
207
208 private:
209 mutable std::shared_mutex mtx_;
210 std::map<std::string, Logger> loggers_; // key = log domain
211 std::map<std::string, std::shared_ptr<Handler>>
212 handlers_; // key = handler id
213 std::atomic<bool> ready_{false};
214
215}; // class Registry
216
217////////////////////////////////////////////////////////////////////////////////
218//
219// high-level utility functions
220//
221////////////////////////////////////////////////////////////////////////////////
222/**
223 * Converts string with log level description to LogLevel type
224 *
225 * @param name string with log level description
226 *
227 * @throws std::invalid_argument if log level string is invalid
228 */
229HARNESS_EXPORT
230LogLevel log_level_from_string(std::string name);
231
232/**
233 * Converts LogLevel type to its string name
234 *
235 * @param log_level value to convert
236 */
237HARNESS_EXPORT
239
240/**
241 * Get default log level
242 *
243 * Fetches default log level set in the configuration file
244 *
245 * @param config Configuration items from configuration file
246 * @param raw_mode true if the default level should be for the raw mode, false
247 * otherwise
248 *
249 * @throws std::invalid_argument if [logger].level in configuration is invalid
250 */
251HARNESS_EXPORT
252LogLevel get_default_log_level(const Config &config, bool raw_mode = false);
253
254/**
255 * Get default log filename
256 *
257 * Fetches default log filename set in the configuration file
258 *
259 * @param config Configuration items from configuration file
260 */
261HARNESS_EXPORT
262std::string get_default_log_filename(const Config &config);
263
264/**
265 * Attach handler to all loggers
266 *
267 * @param registry Registry object, typically managed by DIM
268 * @param name Logger id (log domain it services)
269 */
270HARNESS_EXPORT
271void attach_handler_to_all_loggers(Registry &registry, std::string name);
272
273/**
274 * Set log levels for all the loggers to specified value
275 *
276 * @param registry Registry object, typically managed by DIM
277 * @param level Log level for logger
278 */
279HARNESS_EXPORT
280void set_log_level_for_all_loggers(Registry &registry, LogLevel level);
281
282/**
283 * Set log level for selected handler to specified value
284 *
285 * @param name Name of the registry in the singleton (DIM)
286 * @param level Log level for handler
287 */
288HARNESS_EXPORT
289void set_log_level_for_handler(std::string name, LogLevel level);
290
291/**
292 * Set log levels for all handlers to specified value
293 *
294 * @param registry Registry object, typically managed by DIM
295 * @param level Log level for logger
296 */
297HARNESS_EXPORT
298void set_log_level_for_all_handlers(const Registry &registry, LogLevel level);
299
300/**
301 * Converts string with log timestamp precision description to
302 * LogTimestampPrecision type.
303 *
304 * @param name string with log timestamp precision description
305 *
306 * @throws std::invalid_argument if log timestamp precision string is invalid
307 */
308HARNESS_EXPORT
310
311HARNESS_EXPORT
313
314/**
315 * Get default timestamp precision
316 *
317 * Fetches default timestamp precision for logfiles
318 *
319 * @param config Configuration items from configuration file
320 */
321HARNESS_EXPORT
323
324/**
325 * Set timestamp precision for all the loggers
326 *
327 * @param registry Registry object, typically managed by DIM
328 * @param precision Precision of timestamps
329 */
330HARNESS_EXPORT
331void set_timestamp_precision_for_all_loggers(Registry &registry,
332 LogTimestampPrecision precision);
333
334/**
335 * Clear registry
336 *
337 * Removes all Loggers and removes all references to Handlers (they're held
338 * as shared pointers, which may mean they will also be deleted)
339 *
340 * @param registry Registry object, typically managed by DIM
341 */
342HARNESS_EXPORT
343void clear_registry(Registry &registry);
344
345/**
346 * Initialize logging facility
347 *
348 * Initializes logging facility by creating and registering a logger for each
349 * given module. Loggers will have their log level set to the log level passed
350 * as a parameter.
351 *
352 * @note Loggers will not have any handlers attached, this needs to be done
353 * separately (see `create_main_log_handler()`)
354 *
355 * @param registry Registry object, typically managed by DIM
356 * @param level The log level of the logger
357 * @param modules List of plugin names loaded
358 * @param main_app_log_domain Log domain (logger id) to be used as the main
359 * program logger. This logger must exist, because
360 * log_*() functions might fail
361 * @throws std::logic_error On error.
362 */
363HARNESS_EXPORT
364void create_module_loggers(Registry &registry, const LogLevel level,
365 const std::list<std::string> &modules,
366 const std::string &main_app_log_domain);
367
368/*
369 * Creates a logger and registers it in the Registry.
370 *
371 * Register a logger for a given name and given log level.
372 *
373 * @param registry Registry object, typically managed by DIM
374 * @param log_level The log level of the logger
375 * @param logger_name The name under which the logger is registered
376 *
377 * @throws std::logic_error
378 */
379HARNESS_EXPORT
380void create_logger(Registry &registry, const LogLevel level,
381 const std::string &logger_name);
382
383/**
384 * Initialize logfile handler
385 *
386 * Initializes handler which will handle application's log. This handler
387 * will be attached to all currently-registered loggers.
388 * If `logging_folder` is provided, handler will log messages to logfile; its
389 * path and filename will be derived from `program` and `logging_folder`
390 * parameters.
391 * If `logging_folder` is empty, handler will log messages to console, unless
392 * `use_os_log` is set to true, in which case it will log to system logger
393 * instead (i.e. Syslog, Windows Eventlog, etc. Currently, only Windows
394 * Eventlog is supported).
395 *
396 * @param registry Registry object, typically managed by DIM
397 * @param program Name of the main program (Router)
398 * @param logging_folder logging_folder provided in configuration file
399 * @param format_messages If set to true, log messages will be formatted
400 * (prefixed with log level, timestamp, etc) before logging
401 * @param use_os_log If true, use system logger instead of STDERR (currently,
402 * only Windows Eventlog is supported)
403 *
404 * @throws std::runtime_error if opening log file or OS log fails
405 */
406HARNESS_EXPORT
407void create_main_log_handler(Registry &registry, const std::string &program,
408 const std::string &logging_folder,
409 bool format_messages, bool use_os_log = false);
410
411////////////////////////////////////////////////////////////////////////////////
412//
413// These functions are simple proxies that can be used by logger plugins
414// to register their logging services. Note that they can only be called after
415// logging facility has been initialized; but by the time the plugins are
416// loaded, logging facility is already operational, so this is fine for plugin
417// use.
418//
419////////////////////////////////////////////////////////////////////////////////
420
421/** Set log level for all registered loggers. */
422HARNESS_EXPORT
424
425/** Set log level for all registered handlers. */
426HARNESS_EXPORT
428
429/** Set timestamp precision for all registered loggers. */
430HARNESS_EXPORT
432
433/**
434 * Register handler for all plugins.
435 *
436 * This will register a handler for all plugins that have been
437 * registered with the logging subsystem (normally all plugins that
438 * have been loaded by `Loader`).
439 *
440 * @param name The name under which handler is registered
441 * @param handler Shared pointer to dynamically allocated handler.
442 *
443 * For example, to register a custom handler from a plugin, you would
444 * do the following:
445 *
446 * @code
447 * void init() {
448 * ...
449 * register_handler(std::make_shared<MyHandler>(...));
450 * ...
451 * }
452 * @endcode
453 */
454HARNESS_EXPORT
455void register_handler(std::string name, std::shared_ptr<Handler> handler);
456
457/**
458 * Unregister a handler.
459 *
460 * This will unregister a previously registered handler.
461 *
462 * @param name name of registered handler.
463 */
464HARNESS_EXPORT
465void unregister_handler(std::string name);
466
467/**
468 * Returns true if a given handler is in the registry, false otherwise.
469 *
470 * @param name name of the handler to check.
471 */
472HARNESS_EXPORT
473bool handler_registered(std::string name);
474
475/**
476 * Returns pointer to the default logger sink stream.
477 */
478HARNESS_EXPORT
479std::ostream *get_default_logger_stream();
480
481} // namespace logging
482
483} // namespace mysql_harness
484
485#endif /* MYSQL_HARNESS_LOGGER_REGISTRY_INCLUDED */
The handler class is the interface for dynamically loadable storage engines.
Definition: handler.h:4666
Configuration.
Definition: config_parser.h:253
Logger class.
Definition: logger.h:50
Definition: registry.h:48
bool is_ready() const noexcept
Query if logging facility is ready to use.
Definition: registry.h:199
Registry(const Registry &)=delete
void set_ready() noexcept
Flag that the registry has been initialized.
Definition: registry.h:191
std::map< std::string, Logger > loggers_
Definition: registry.h:210
Registry & operator=(const Registry &)=delete
std::map< std::string, std::shared_ptr< Handler > > handlers_
Definition: registry.h:212
std::shared_mutex mtx_
Definition: registry.h:209
Logging interface for using and extending the logging subsystem.
static loglevel log_level(const Sql_condition *condition)
Definition: histogram.cc:1650
HARNESS_EXPORT void set_log_level_for_all_handlers(const Registry &registry, LogLevel level)
Set log levels for all handlers to specified value.
Definition: registry.cc:272
LogLevel
Log level values.
Definition: logging.h:90
HARNESS_EXPORT bool handler_registered(std::string name)
Returns true if a given handler is in the registry, false otherwise.
Definition: registry.cc:511
HARNESS_EXPORT void set_timestamp_precision_for_all_loggers(Registry &registry, LogTimestampPrecision precision)
Set timestamp precision for all the loggers.
Definition: registry.cc:279
HARNESS_EXPORT void register_handler(std::string name, std::shared_ptr< Handler > handler)
Register handler for all plugins.
Definition: registry.cc:498
HARNESS_EXPORT std::string get_default_log_filename(const Config &config)
Get default log filename.
Definition: registry.cc:416
HARNESS_EXPORT void clear_registry(Registry &registry)
Clear registry.
Definition: registry.cc:288
HARNESS_EXPORT LogLevel get_default_log_level(const Config &config, bool raw_mode=false)
Get default log level.
Definition: registry.cc:397
HARNESS_EXPORT std::string log_timestamp_precision_to_string(LogTimestampPrecision tsp)
Definition: registry.cc:459
HARNESS_EXPORT void create_logger(Registry &registry, const LogLevel level, const std::string &logger_name)
Definition: registry.cc:346
HARNESS_EXPORT void set_log_level_for_handler(std::string name, LogLevel level)
Set log level for selected handler to specified value.
Definition: registry.cc:263
HARNESS_EXPORT void create_main_log_handler(Registry &registry, const std::string &program, const std::string &logging_folder, bool format_messages, bool use_os_log=false)
Initialize logfile handler.
Definition: registry.cc:300
HARNESS_EXPORT void set_log_level_for_all_loggers(Registry &registry, LogLevel level)
Set log levels for all the loggers to specified value.
Definition: registry.cc:255
HARNESS_EXPORT void unregister_handler(std::string name)
Unregister a handler.
Definition: registry.cc:505
HARNESS_EXPORT LogTimestampPrecision get_default_timestamp_precision(const Config &config)
Get default timestamp precision.
Definition: registry.cc:468
HARNESS_EXPORT std::ostream * get_default_logger_stream()
Returns pointer to the default logger sink stream.
Definition: registry.cc:298
HARNESS_EXPORT LogLevel log_level_from_string(std::string name)
Converts string with log level description to LogLevel type.
Definition: registry.cc:363
LogTimestampPrecision
Log timestamp precision values.
Definition: logging.h:160
HARNESS_EXPORT std::string log_level_to_string(LogLevel log_level)
Converts LogLevel type to its string name.
Definition: registry.cc:387
HARNESS_EXPORT void create_module_loggers(Registry &registry, const LogLevel level, const std::list< std::string > &modules, const std::string &main_app_log_domain)
Initialize logging facility.
Definition: registry.cc:351
HARNESS_EXPORT void set_timestamp_precison_for_all_loggers(LogTimestampPrecision precision)
Set timestamp precision for all registered loggers.
HARNESS_EXPORT LogTimestampPrecision log_timestamp_precision_from_string(std::string name)
Converts string with log timestamp precision description to LogTimestampPrecision type.
Definition: registry.cc:437
HARNESS_EXPORT void attach_handler_to_all_loggers(Registry &registry, std::string name)
Attach handler to all loggers.
Definition: registry.cc:245
Definition: common.h:44
static Logger logger
The "top-level" logger used when no connection context is given.
Definition: test_trace_plugin.cc:296