log.h
1 /*
2  * uuid-log - Microcontroller logging framework
3  * Copyright 2019,2021 Simon Arlott
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef UUID_LOG_H_
20 #define UUID_LOG_H_
21 
22 #include <Arduino.h>
23 
24 #include <cstdarg>
25 #include <cstdint>
26 #include <list>
27 #include <map>
28 #include <memory>
29 #include <string>
30 #include <vector>
31 
32 #include <uuid/common.h>
33 
34 namespace uuid {
35 
46 namespace log {
47 
53 enum Level : int8_t {
54  OFF = -1,
55  EMERG = 0,
57  CRIT,
58  ERR,
61  INFO,
64  ALL,
65 };
66 
72 enum Facility : uint8_t {
73  KERN = 0,
74  USER,
75  MAIL,
77  AUTH,
79  LPR,
80  NEWS,
81  UUCP,
82  CRON,
84  FTP,
85  NTP,
97 };
98 
109 std::string format_timestamp_ms(uint64_t timestamp_ms, unsigned int days_width = 1);
110 
118 std::vector<Level> levels();
119 
130 char format_level_char(Level level);
131 
139 const __FlashStringHelper *format_level_uppercase(Level level);
140 
149 std::vector<std::string> levels_uppercase();
150 
159 bool parse_level_uppercase(const std::string &name, Level &level);
160 
168 const __FlashStringHelper *format_level_lowercase(Level level);
169 
178 std::vector<std::string> levels_lowercase();
179 
188 bool parse_level_lowercase(const std::string &name, Level &level);
189 
198 struct Message {
209  Message(uint64_t uptime_ms, Level level, Facility facility, const __FlashStringHelper *name, const std::string &&text);
210  ~Message() = default;
211 
218  const uint64_t uptime_ms;
219 
225  const Level level;
226 
233 
239  const __FlashStringHelper *name;
240 
249  const std::string text;
250 };
251 
252 class Logger;
253 
259 class Handler {
266  friend Logger;
267 public:
268  virtual ~Handler();
269 
283  virtual void operator<<(std::shared_ptr<Message> message) = 0;
284 
285 protected:
286  Handler() = default;
287 
288 private:
297  std::weak_ptr<std::map<Handler*,Level>> handlers_;
298 };
299 
305 class Logger {
306 public:
315  static constexpr size_t MAX_LOG_LENGTH = 255;
316 
325  Logger(const __FlashStringHelper *name, Facility facility = Facility::LOCAL0);
326  ~Logger() = default;
327 
339  static void register_handler(Handler *handler, Level level);
340 
350  static void unregister_handler(Handler *handler);
351 
362  static Level get_log_level(const Handler *handler);
363 
372  static inline bool enabled(Level level) { return level <= level_; }
373 
381  void emerg(const char *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
389  void emerg(const __FlashStringHelper *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
390 
398  void alert(const char *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
406  void alert(const __FlashStringHelper *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
407 
415  void crit(const char *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
423  void crit(const __FlashStringHelper *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
424 
432  void err(const char *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
440  void err(const __FlashStringHelper *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
441 
449  void warning(const char *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
457  void warning(const __FlashStringHelper *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
458 
466  void notice(const char *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
474  void notice(const __FlashStringHelper *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
475 
483  void info(const char *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
490  void info(const __FlashStringHelper *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
491 
499  void debug(const char *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
507  void debug(const __FlashStringHelper *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
508 
516  void trace(const char *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
524  void trace(const __FlashStringHelper *format, ...) const /* __attribute__((format (printf, 2, 3))) */;
525 
535  void log(Level level, Facility facility, const char *format, ...) const /* __attribute__((format (printf, 3, 4))) */;
545  void log(Level level, Facility facility, const __FlashStringHelper *format, ...) const /* __attribute__((format (printf, 4, 5))) */;
546 
547 private:
553  static void refresh_log_level();
560  static std::shared_ptr<std::map<Handler*,Level>>& registered_handlers();
561 
570  void vlog(Level level, const char *format, va_list ap) const;
579  void vlog(Level level, const __FlashStringHelper *format, va_list ap) const;
580 
590  void vlog(Level level, Facility facility, const char *format, va_list ap) const;
600  void vlog(Level level, Facility facility, const __FlashStringHelper *format, va_list ap) const;
601 
614  void dispatch(Level level, Facility facility, std::vector<char> &text) const;
615 
616  static Level level_;
618  const __FlashStringHelper *name_;
620 };
621 
622 } // namespace log
623 
624 } // namespace uuid
625 
626 #endif
const __FlashStringHelper * format_level_uppercase(Level level)
Format a log level as an uppercase string.
std::vector< Level > levels()
Get all log levels.
Definition: levels.cpp:27
std::vector< std::string > levels_lowercase()
Get all log levels as lowercase strings.
const __FlashStringHelper * format_level_lowercase(Level level)
Format a log level as a lowercase string.
Facility
Facility type of the process logging a message.
Definition: log.h:72
bool parse_level_lowercase(const std::string &name, Level &level)
Parse a lowercase string to a log level.
static bool enabled(Level level)
Determine if the current log level is enabled by any registered handlers.
Definition: log.h:372
Message(uint64_t uptime_ms, Level level, Facility facility, const __FlashStringHelper *name, const std::string &&text)
Create a new log message (not directly useful).
Definition: log.cpp:38
bool parse_level_uppercase(const std::string &name, Level &level)
Parse an uppercase string to a log level.
const Facility facility
Facility type of the process that logged the message.
Definition: log.h:232
const __FlashStringHelper * name
Name of the logger used (flash string).
Definition: log.h:239
std::weak_ptr< std::map< Handler *, Level > > handlers_
Reference to registered log handlers.
Definition: log.h:297
static Level level_
Definition: log.h:616
char format_level_char(Level level)
Format a log level as a single character.
const Facility facility_
Definition: log.h:619
Log message text with timestamp and logger attributes.
Definition: log.h:198
const __FlashStringHelper * name_
Definition: log.h:618
Common utilities.
std::vector< std::string > levels_uppercase()
Get all log levels as uppercase strings.
std::string format_timestamp_ms(uint64_t timestamp_ms, unsigned int days_width)
Format a system uptime timestamp as a string.
const std::string text
Formatted log message text.
Definition: log.h:249
Logger instance used to make log messages.
Definition: log.h:305
const Level level
Severity level of the message.
Definition: log.h:225
friend Logger
Logger needs to be able to access the private reference to the registered log handlers.
Definition: log.h:266
const uint64_t uptime_ms
System uptime at the time the message was logged.
Definition: log.h:218
Level
Severity level of log messages.
Definition: log.h:53
Logger handler used to process log messages.
Definition: log.h:259