CIRCT  20.0.0git
Logging.h
Go to the documentation of this file.
1 //===- Logging.h - ESI Runtime logging --------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // ESI runtime logging is very simple but very flexible. Rather than mandating a
10 // particular logging library, it allows users to hook into their existing
11 // logging system by implementing a simple interface.
12 //
13 //===----------------------------------------------------------------------===//
14 //
15 // DO NOT EDIT!
16 // This file is distributed as part of an ESI package. The source for this file
17 // should always be modified within CIRCT.
18 //
19 //===----------------------------------------------------------------------===//
20 
21 // NOLINTNEXTLINE(llvm-header-guard)
22 #ifndef ESI_LOGGING_H
23 #define ESI_LOGGING_H
24 
25 #include <any>
26 #include <functional>
27 #include <iosfwd>
28 #include <map>
29 #include <memory>
30 #include <mutex>
31 #include <string>
32 
33 namespace esi {
34 
35 class Logger {
36 public:
37  enum class Level {
38  Debug, // Everything and the kitchen sink, possibly including _all_
39  // messages written and read.
40  Info, // General information, like connecting to an accelerator.
41  Warning, // May indicate a problem.
42  Error, // Many errors will be followed by exceptions which may get caught.
43  };
45  virtual ~Logger() = default;
46  bool getDebugEnabled() { return debugEnabled; }
47 
48  /// Report a log message.
49  /// Arguments:
50  /// level: The log level as defined by the 'Level' enum above.
51  /// subsystem: The subsystem that generated the log message.
52  /// msg: The log message.
53  /// details: Optional additional structured details to include in the log
54  /// message. If there are no details, this should be nullptr.
55  virtual void
56  log(Level level, const std::string &subsystem, const std::string &msg,
57  const std::map<std::string, std::any> *details = nullptr) = 0;
58 
59  /// Report an error.
60  virtual void error(const std::string &subsystem, const std::string &msg,
61  const std::map<std::string, std::any> *details = nullptr) {
62  log(Level::Error, subsystem, msg, details);
63  }
64  /// Report a warning.
65  virtual void
66  warning(const std::string &subsystem, const std::string &msg,
67  const std::map<std::string, std::any> *details = nullptr) {
68  log(Level::Warning, subsystem, msg, details);
69  }
70  /// Report an informational message.
71  virtual void info(const std::string &subsystem, const std::string &msg,
72  const std::map<std::string, std::any> *details = nullptr) {
73  log(Level::Info, subsystem, msg, details);
74  }
75 
76  /// Report a debug message. This is not virtual so that it can be inlined to
77  /// minimize performance impact that debug messages have, allowing debug
78  /// messages in Release builds.
79  inline void debug(const std::string &subsystem, const std::string &msg,
80  const std::map<std::string, std::any> *details = nullptr) {
81  if (debugEnabled)
82  debugImpl(subsystem, msg, details);
83  }
84  /// Call the debug function callback only if debug is enabled then log a debug
85  /// message. Allows users to run heavy weight debug message generation code
86  /// only when debug is enabled, which in turns allows users to provide
87  /// fully-featured debug messages in Release builds with minimal performance
88  /// impact. Not virtual so that it can be inlined.
89  inline void
90  debug(std::function<
91  void(std::string &subsystem, std::string &msg,
92  std::unique_ptr<std::map<std::string, std::any>> &details)>
93  debugFunc) {
94  if (debugEnabled)
95  debugImpl(debugFunc);
96  }
97 
98 protected:
99  /// Overrideable version of debug. Only gets called if debug is enabled.
100  virtual void debugImpl(const std::string &subsystem, const std::string &msg,
101  const std::map<std::string, std::any> *details) {
102  log(Level::Debug, subsystem, msg, details);
103  }
104  /// Overrideable version of debug. Only gets called if debug is enabled.
105  virtual void
106  debugImpl(std::function<
107  void(std::string &subsystem, std::string &msg,
108  std::unique_ptr<std::map<std::string, std::any>> &details)>
109  debugFunc) {
110  if (!debugEnabled)
111  return;
112  std::string subsystem;
113  std::string msg;
114  std::unique_ptr<std::map<std::string, std::any>> details = nullptr;
115  debugFunc(subsystem, msg, details);
116  debugImpl(subsystem, msg, details.get());
117  }
118 
119  /// Enable or disable debug messages.
120  bool debugEnabled = false;
121 };
122 
123 /// A thread-safe logger which calls functions implemented by subclasses. Only
124 /// protects the `log` method. If subclasses override other methods and need to
125 /// protect them, they need to do that themselves.
126 class TSLogger : public Logger {
127 public:
128  using Logger::Logger;
129 
130  /// Grabs the lock and calls logImpl.
131  void log(Level level, const std::string &subsystem, const std::string &msg,
132  const std::map<std::string, std::any> *details) override final;
133 
134 protected:
135  /// Subclasses must implement this method to log messages.
136  virtual void logImpl(Level level, const std::string &subsystem,
137  const std::string &msg,
138  const std::map<std::string, std::any> *details) = 0;
139 
140  /// Mutex to protect the stream from interleaved logging writes.
141  std::mutex mutex;
142 };
143 
144 /// A logger that writes to a C++ std::ostream.
145 class StreamLogger : public TSLogger {
146 public:
147  /// Create a stream logger that logs to the given output stream and error
148  /// output stream.
149  StreamLogger(Level minLevel, std::ostream &out, std::ostream &error)
150  : TSLogger(minLevel == Level::Debug), minLevel(minLevel), outStream(out),
151  errorStream(error) {}
152  /// Create a stream logger that logs to stdout, stderr.
154  void logImpl(Level level, const std::string &subsystem,
155  const std::string &msg,
156  const std::map<std::string, std::any> *details) override;
157 
158 private:
159  /// The minimum log level to emit.
161 
162  /// Everything except errors goes here.
163  std::ostream &outStream;
164  /// Just for errors.
165  std::ostream &errorStream;
166 };
167 
168 /// A logger that does nothing.
169 class NullLogger : public Logger {
170 public:
171  NullLogger() : Logger(false) {}
172  void log(Level, const std::string &, const std::string &,
173  const std::map<std::string, std::any> *) override {}
174 };
175 
176 /// 'Stringify' a std::any. This is used to log std::any values by some loggers.
177 std::string toString(const std::any &a);
178 
179 } // namespace esi
180 
181 #endif // ESI_LOGGING_H
virtual void error(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report an error.
Definition: Logging.h:60
virtual void warning(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report a warning.
Definition: Logging.h:66
virtual void info(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report an informational message.
Definition: Logging.h:71
bool debugEnabled
Enable or disable debug messages.
Definition: Logging.h:120
virtual void debugImpl(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details)
Overrideable version of debug. Only gets called if debug is enabled.
Definition: Logging.h:100
bool getDebugEnabled()
Definition: Logging.h:46
virtual ~Logger()=default
void debug(std::function< void(std::string &subsystem, std::string &msg, std::unique_ptr< std::map< std::string, std::any >> &details)> debugFunc)
Call the debug function callback only if debug is enabled then log a debug message.
Definition: Logging.h:90
virtual void debugImpl(std::function< void(std::string &subsystem, std::string &msg, std::unique_ptr< std::map< std::string, std::any >> &details)> debugFunc)
Overrideable version of debug. Only gets called if debug is enabled.
Definition: Logging.h:106
Logger(bool debugEnabled)
Definition: Logging.h:44
void debug(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report a debug message.
Definition: Logging.h:79
virtual void log(Level level, const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)=0
Report a log message.
A logger that does nothing.
Definition: Logging.h:169
void log(Level, const std::string &, const std::string &, const std::map< std::string, std::any > *) override
Report a log message.
Definition: Logging.h:172
A logger that writes to a C++ std::ostream.
Definition: Logging.h:145
Level minLevel
The minimum log level to emit.
Definition: Logging.h:160
void logImpl(Level level, const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details) override
Subclasses must implement this method to log messages.
Definition: Logging.cpp:34
std::ostream & outStream
Everything except errors goes here.
Definition: Logging.h:163
std::ostream & errorStream
Just for errors.
Definition: Logging.h:165
StreamLogger(Level minLevel, std::ostream &out, std::ostream &error)
Create a stream logger that logs to the given output stream and error output stream.
Definition: Logging.h:149
A thread-safe logger which calls functions implemented by subclasses.
Definition: Logging.h:126
std::mutex mutex
Mutex to protect the stream from interleaved logging writes.
Definition: Logging.h:141
virtual void logImpl(Level level, const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details)=0
Subclasses must implement this method to log messages.
void log(Level level, const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details) override final
Grabs the lock and calls logImpl.
Definition: Logging.cpp:23
Definition: esi.py:1
std::string toString(const std::any &a)
'Stringify' a std::any. This is used to log std::any values by some loggers.
Definition: Logging.cpp:74