1 /*
2  * Copyright (C) 2018-2019 Codership Oy <info@codership.com>
3  *
4  * This file is part of wsrep-lib.
5  *
6  * Wsrep-lib is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Wsrep-lib is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with wsrep-lib.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef WSREP_LOGGER_HPP
21 #define WSREP_LOGGER_HPP
22 
23 #include "mutex.hpp"
24 #include "lock.hpp"
25 #include "atomic.hpp"
26 
27 #include <iosfwd>
28 #include <sstream>
29 
30 #define WSREP_LOG_DEBUG(debug_level_fn, debug_level, msg)               \
31     do {                                                                \
32         if (debug_level_fn >= debug_level) wsrep::log_debug() << msg;   \
33     } while (0)
34 
35 namespace wsrep
36 {
37     class log
38     {
39     public:
40         enum level
41         {
42             debug,
43             info,
44             warning,
45             error,
46             unknown
47         };
48 
49         enum debug_level
50         {
51             debug_level_server_state = 1,
52             debug_level_transaction,
53             debug_level_streaming,
54             debug_level_client_state
55         };
56 
57         /**
58          * Signature for user defined logger callback function.
59          *
60          * @param pfx optional internally defined prefix for the message
61          * @param msg message to log
62          */
63         typedef void (*logger_fn_type)(level l,
64                                        const char* pfx, const char* msg);
65 
to_c_string(enum level level)66         static const char* to_c_string(enum level level)
67         {
68             switch (level)
69             {
70             case debug:   return "debug";
71             case info:    return "info";
72             case warning: return "warning";
73             case error:   return "error";
74             case unknown: break;
75             };
76             return "unknown";
77         }
78 
log(enum wsrep::log::level level,const char * prefix="L:")79         log(enum wsrep::log::level level, const char* prefix = "L:")
80             : level_(level)
81             , prefix_(prefix)
82             , oss_()
83         { }
84 
~log()85         ~log()
86         {
87             if (logger_fn_)
88             {
89                 logger_fn_(level_, prefix_, oss_.str().c_str());
90             }
91             else
92             {
93                 wsrep::unique_lock<wsrep::mutex> lock(mutex_);
94                 os_ << prefix_ << oss_.str() << std::endl;
95             }
96         }
97 
98         template <typename T>
operator <<(const T & val)99         std::ostream& operator<<(const T& val)
100         {
101             return (oss_ << val);
102         }
103 
104         /**
105          * Set user defined logger callback function.
106          */
107         static void logger_fn(logger_fn_type);
108 
109         /**
110          * Set debug log level from client
111          */
112         static void debug_log_level(int debug_level);
113 
114         /**
115          * Get current debug log level
116          */
117         static int debug_log_level();
118 
119     private:
120         log(const log&);
121         log& operator=(const log&);
122         enum level level_;
123         const char* prefix_;
124         std::ostringstream oss_;
125         static wsrep::mutex& mutex_;
126         static std::ostream& os_;
127         static logger_fn_type logger_fn_;
128         static std::atomic_int debug_log_level_;
129     };
130 
131     class log_error : public log
132     {
133     public:
log_error()134         log_error()
135             : log(error) { }
136     };
137 
138     class log_warning : public log
139     {
140     public:
log_warning()141         log_warning()
142             : log(warning) { }
143     };
144 
145     class log_info : public log
146     {
147     public:
log_info()148         log_info()
149             : log(info) { }
150     };
151 
152     class log_debug : public log
153     {
154     public:
log_debug()155         log_debug()
156             : log(debug) { }
157     };
158 }
159 
160 #endif // WSREP_LOGGER_HPP
161