DCCL v4
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 <cstdio>
29#include <deque>
30#include <functional>
31#include <iomanip>
32#include <iostream>
33#include <sstream>
34#include <stack>
35#include <string>
36#include <vector>
37
38#include "thread_safety.h"
39
40namespace dccl
41{
42namespace logger
43{
45enum Verbosity
46{
47 WARN = 1 << 1,
48 INFO = 1 << 2,
49 DEBUG1 = 1 << 3,
50 DEBUG2 = 1 << 4,
51 DEBUG3 = 1 << 5,
52 ALL = DEBUG3 | (DEBUG3 - 1),
53 WARN_PLUS = WARN | (WARN - 1),
54 INFO_PLUS = INFO | (INFO - 1),
55 DEBUG1_PLUS = DEBUG1 | (DEBUG1 - 1),
56 DEBUG2_PLUS = DEBUG2 | (DEBUG2 - 1),
57 DEBUG3_PLUS = DEBUG3 | (DEBUG3 - 1),
58 UNKNOWN = 0
59};
60enum Group
61{
62 GENERAL,
63 ENCODE,
64 DECODE,
65 SIZE
66};
67
68} // namespace logger
69
70void to_ostream(const std::string& msg, dccl::logger::Verbosity vrb, dccl::logger::Group grp,
71 std::ostream* os, bool add_timestamp);
72
73class Logger;
74
75namespace internal
76{
77class LogBuffer : public std::streambuf
78{
79 public:
80 LogBuffer() : buffer_(1) {}
81 ~LogBuffer() override = default;
82
84 template <typename Slot> void connect(int verbosity_mask, Slot slot)
85 {
86 enabled_verbosities_ |= verbosity_mask;
87 if (verbosity_mask & logger::WARN)
88 warn_signal.emplace_back(slot);
89 if (verbosity_mask & logger::INFO)
90 info_signal.emplace_back(slot);
91 if (verbosity_mask & logger::DEBUG1)
92 debug1_signal.emplace_back(slot);
93 if (verbosity_mask & logger::DEBUG2)
94 debug2_signal.emplace_back(slot);
95 if (verbosity_mask & logger::DEBUG3)
96 debug3_signal.emplace_back(slot);
97 }
98
99 void disconnect(int verbosity_mask)
100 {
101 enabled_verbosities_ &= ~verbosity_mask;
102 if (verbosity_mask & logger::WARN)
103 warn_signal.clear();
104 if (verbosity_mask & logger::INFO)
105 info_signal.clear();
106 if (verbosity_mask & logger::DEBUG1)
107 debug1_signal.clear();
108 if (verbosity_mask & logger::DEBUG2)
109 debug2_signal.clear();
110 if (verbosity_mask & logger::DEBUG3)
111 debug3_signal.clear();
112 }
113
115 void set_verbosity(logger::Verbosity verbosity) { verbosity_.push(verbosity); }
116
117 void set_group(logger::Group group) { group_.push(group); }
118
119 bool contains(logger::Verbosity verbosity) const { return verbosity & enabled_verbosities_; }
120
121 private:
124 int sync() override;
125
128 int overflow(int c = EOF) override;
129
130 void display(const std::string& s)
131 {
132 if (verbosity() & logger::WARN)
133 {
134 for (auto& slot : warn_signal) slot(s, logger::WARN, group());
135 }
136 if (verbosity() & logger::INFO)
137 {
138 for (auto& slot : info_signal) slot(s, logger::INFO, group());
139 }
140 if (verbosity() & logger::DEBUG1)
141 {
142 for (auto& slot : debug1_signal) slot(s, logger::DEBUG1, group());
143 }
144 if (verbosity() & logger::DEBUG2)
145 {
146 for (auto& slot : debug2_signal) slot(s, logger::DEBUG2, group());
147 }
148 if (verbosity() & logger::DEBUG3)
149 {
150 for (auto& slot : debug3_signal) slot(s, logger::DEBUG3, group());
151 }
152 }
153
154 logger::Verbosity verbosity()
155 {
156 return verbosity_.empty() ? logger::UNKNOWN : verbosity_.top();
157 }
158 logger::Group group() { return group_.empty() ? logger::GENERAL : group_.top(); }
159
160 private:
161 std::stack<logger::Verbosity> verbosity_;
162 std::stack<logger::Group> group_;
163 std::deque<std::string> buffer_;
164 int enabled_verbosities_; // mask of verbosity settings enabled
165
166 using LogSignal = std::vector<
167 std::function<void(const std::string& msg, logger::Verbosity vrb, logger::Group grp)>>;
168
169 LogSignal warn_signal, info_signal, debug1_signal, debug2_signal, debug3_signal;
170};
171} // namespace internal
172
174class Logger : public std::ostream
175{
176 public:
177 Logger() : std::ostream(&buf_) {}
178 ~Logger() override = default;
179
181 bool check(logger::Verbosity verbosity) { return buf_.contains(verbosity); }
182
192 bool is(logger::Verbosity verbosity, logger::Group group = logger::GENERAL)
193 {
194 if (!buf_.contains(verbosity))
195 {
196 return false;
197 }
198 else
199 {
200#if DCCL_THREAD_SUPPORT
201 g_dlog_mutex.lock();
202#endif
203 buf_.set_verbosity(verbosity);
204 buf_.set_group(group);
205 return true;
206 }
207 }
208
214 template <typename Slot> void connect(int verbosity_mask, Slot slot)
215 {
216 DCCL_LOCK_DLOG_MUTEX
217 buf_.connect(verbosity_mask, slot);
218 }
219
226 template <typename Obj>
227 void connect(int verbosity_mask, Obj* obj,
228 void (Obj::*mem_func)(const std::string& msg, logger::Verbosity vrb,
229 logger::Group grp))
230 {
231 DCCL_LOCK_DLOG_MUTEX
232 connect(verbosity_mask, std::bind(mem_func, obj, std::placeholders::_1,
233 std::placeholders::_2, std::placeholders::_3));
234 }
235
241 void connect(int verbosity_mask, std::ostream* os, bool add_timestamp = true)
242 {
243 DCCL_LOCK_DLOG_MUTEX
244 buf_.connect(verbosity_mask,
245 std::bind(to_ostream, std::placeholders::_1, std::placeholders::_2,
246 std::placeholders::_3, os, add_timestamp));
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:175
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:192
bool check(logger::Verbosity verbosity)
Same as is() but doesn't set the verbosity or lock the mutex.
Definition logger.h:181
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:227
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:214
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:241
void connect(int verbosity_mask, Slot slot)
connect a signal to a slot (function pointer or similar)
Definition logger.h:84
void set_verbosity(logger::Verbosity verbosity)
sets the verbosity level until the next sync()
Definition logger.h:115
Dynamic Compact Control Language namespace.
Definition any.h:47