DCCL v5
Loading...
Searching...
No Matches
logger.h
1// Copyright 2012-2023:
2// GobySoft, LLC (2013-)
3// Massachusetts Institute of Technology (2007-2014)
4// Community contributors (see AUTHORS file)
5// File authors:
6// Toby Schneider <toby@gobysoft.org>
7// Chris Murphy <cmurphy@aphysci.com>
8//
9//
10// This file is part of the Dynamic Compact Control Language Library
11// ("DCCL").
12//
13// DCCL is free software: you can redistribute it and/or modify
14// it under the terms of the GNU Lesser General Public License as published by
15// the Free Software Foundation, either version 2.1 of the License, or
16// (at your option) any later version.
17//
18// DCCL is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU Lesser General Public License for more details.
22//
23// You should have received a copy of the GNU Lesser General Public License
24// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
25#ifndef DCCLLOGGER20121009H
26#define DCCLLOGGER20121009H
27
28#include <deque>
29#include <functional>
30#include <iomanip>
31#include <iostream>
32#include <sstream>
33#include <stack>
34#include <string>
35#include <vector>
36
37#include "thread_safety.h"
38
39namespace dccl
40{
41namespace logger
42{
44enum Verbosity
45{
46 WARN = 1 << 1,
47 INFO = 1 << 2,
48 DEBUG1 = 1 << 3,
49 DEBUG2 = 1 << 4,
50 DEBUG3 = 1 << 5,
51 ALL = DEBUG3 | (DEBUG3 - 1),
52 WARN_PLUS = WARN | (WARN - 1),
53 INFO_PLUS = INFO | (INFO - 1),
54 DEBUG1_PLUS = DEBUG1 | (DEBUG1 - 1),
55 DEBUG2_PLUS = DEBUG2 | (DEBUG2 - 1),
56 DEBUG3_PLUS = DEBUG3 | (DEBUG3 - 1),
57 UNKNOWN = 0
58};
59enum Group
60{
61 GENERAL,
62 ENCODE,
63 DECODE,
64 SIZE
65};
66
67} // namespace logger
68
69void to_ostream(const std::string& msg, dccl::logger::Verbosity vrb, dccl::logger::Group grp,
70 std::ostream* os, bool add_timestamp);
71
72class Logger;
73
74namespace internal
75{
76class LogBuffer : public std::streambuf
77{
78 public:
79 LogBuffer() : buffer_(1) {}
80 ~LogBuffer() override = default;
81
83 template <typename Slot> void connect(int verbosity_mask, Slot slot)
84 {
85 enabled_verbosities_ |= verbosity_mask;
86 if (verbosity_mask & logger::WARN)
87 warn_signal.emplace_back(slot);
88 if (verbosity_mask & logger::INFO)
89 info_signal.emplace_back(slot);
90 if (verbosity_mask & logger::DEBUG1)
91 debug1_signal.emplace_back(slot);
92 if (verbosity_mask & logger::DEBUG2)
93 debug2_signal.emplace_back(slot);
94 if (verbosity_mask & logger::DEBUG3)
95 debug3_signal.emplace_back(slot);
96 }
97
98 void disconnect(int verbosity_mask)
99 {
100 enabled_verbosities_ &= ~verbosity_mask;
101 if (verbosity_mask & logger::WARN)
102 warn_signal.clear();
103 if (verbosity_mask & logger::INFO)
104 info_signal.clear();
105 if (verbosity_mask & logger::DEBUG1)
106 debug1_signal.clear();
107 if (verbosity_mask & logger::DEBUG2)
108 debug2_signal.clear();
109 if (verbosity_mask & logger::DEBUG3)
110 debug3_signal.clear();
111 }
112
114 void set_verbosity(logger::Verbosity verbosity) { verbosity_.push(verbosity); }
115
116 void set_group(logger::Group group) { group_.push(group); }
117
118 bool contains(logger::Verbosity verbosity) const { return verbosity & enabled_verbosities_; }
119
120 private:
123 int sync() override;
124
127 int overflow(int c = EOF) override;
128
129 void display(const std::string& s)
130 {
131 if (verbosity() & logger::WARN)
132 {
133 for (auto& slot : warn_signal) slot(s, logger::WARN, group());
134 }
135 if (verbosity() & logger::INFO)
136 {
137 for (auto& slot : info_signal) slot(s, logger::INFO, group());
138 }
139 if (verbosity() & logger::DEBUG1)
140 {
141 for (auto& slot : debug1_signal) slot(s, logger::DEBUG1, group());
142 }
143 if (verbosity() & logger::DEBUG2)
144 {
145 for (auto& slot : debug2_signal) slot(s, logger::DEBUG2, group());
146 }
147 if (verbosity() & logger::DEBUG3)
148 {
149 for (auto& slot : debug3_signal) slot(s, logger::DEBUG3, group());
150 }
151 }
152
153 logger::Verbosity verbosity()
154 {
155 return verbosity_.empty() ? logger::UNKNOWN : verbosity_.top();
156 }
157 logger::Group group() { return group_.empty() ? logger::GENERAL : group_.top(); }
158
159 private:
160 std::stack<logger::Verbosity> verbosity_;
161 std::stack<logger::Group> group_;
162 std::deque<std::string> buffer_;
163 int enabled_verbosities_; // mask of verbosity settings enabled
164
165 using LogSignal = std::vector<
166 std::function<void(const std::string& msg, logger::Verbosity vrb, logger::Group grp)>>;
167
168 LogSignal warn_signal, info_signal, debug1_signal, debug2_signal, debug3_signal;
169};
170} // namespace internal
171
173class Logger : public std::ostream
174{
175 public:
176 Logger() : std::ostream(&buf_) {}
177 ~Logger() override = default;
178
180 bool check(logger::Verbosity verbosity) { return buf_.contains(verbosity); }
181
191 bool is(logger::Verbosity verbosity, logger::Group group = logger::GENERAL)
192 {
193 if (!buf_.contains(verbosity))
194 {
195 return false;
196 }
197 else
198 {
199#if DCCL_THREAD_SUPPORT
200 g_dlog_mutex.lock();
201#endif
202 buf_.set_verbosity(verbosity);
203 buf_.set_group(group);
204 return true;
205 }
206 }
207
213 template <typename Slot> void connect(int verbosity_mask, Slot slot)
214 {
215 DCCL_LOCK_DLOG_MUTEX
216 buf_.connect(verbosity_mask, slot);
217 }
218
225 template <typename Obj>
226 void connect(int verbosity_mask, Obj* obj,
227 void (Obj::*mem_func)(const std::string& msg, logger::Verbosity vrb,
228 logger::Group grp))
229 {
230 DCCL_LOCK_DLOG_MUTEX
231 connect(verbosity_mask, [obj, mem_func](const std::string& msg, logger::Verbosity vrb,
232 logger::Group grp) { (obj->*mem_func)(msg, vrb, grp); });
233 }
234
240 void connect(int verbosity_mask, std::ostream* os, bool add_timestamp = true)
241 {
242 DCCL_LOCK_DLOG_MUTEX
243 buf_.connect(verbosity_mask, [os, add_timestamp](const std::string& msg,
244 logger::Verbosity vrb, logger::Group grp) {
245 to_ostream(msg, vrb, grp, os, add_timestamp);
246 });
247 }
248
250 void disconnect(int verbosity_mask)
251 {
252 DCCL_LOCK_DLOG_MUTEX
253 buf_.disconnect(verbosity_mask);
254 }
255
256 private:
258};
259
260extern Logger dlog;
261
262inline std::string hash_as_string(std::size_t hash)
263{
264 std::stringstream hash_stream;
265 hash_stream << "0x" << std::setfill('0') << std::setw(sizeof(std::size_t) * 2) << std::hex
266 << hash;
267 return hash_stream.str();
268}
269
270} // namespace dccl
271
272#endif // DCCLLOGGER20121009H
The DCCL Logger class. Do not instantiate this class directly. Rather, use the dccl::dlog object.
Definition logger.h:174
bool is(logger::Verbosity verbosity, logger::Group group=logger::GENERAL)
Indicates the verbosity of the Logger until the next std::flush or std::endl. The boolean return is u...
Definition logger.h:191
bool check(logger::Verbosity verbosity)
Same as is() but doesn't set the verbosity or lock the mutex.
Definition logger.h:180
void disconnect(int verbosity_mask)
Disconnect all slots for one or more given verbosities.
Definition logger.h:250
void connect(int verbosity_mask, Obj *obj, void(Obj::*mem_func)(const std::string &msg, logger::Verbosity vrb, logger::Group grp))
Connect the output of one or more given verbosities to a member function.
Definition logger.h:226
void connect(int verbosity_mask, Slot slot)
Connect the output of one or more given verbosities to a slot (function pointer or similar)
Definition logger.h:213
void connect(int verbosity_mask, std::ostream *os, bool add_timestamp=true)
Connect the output of one or more given verbosities to a std::ostream.
Definition logger.h:240
void connect(int verbosity_mask, Slot slot)
connect a signal to a slot (function pointer or similar)
Definition logger.h:83
void set_verbosity(logger::Verbosity verbosity)
sets the verbosity level until the next sync()
Definition logger.h:114
Dynamic Compact Control Language namespace.
Definition any.h:28