HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
logging.h
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License.
3 
4 #pragma once
5 
6 #include <atomic>
7 #include <chrono>
8 #include <climits>
9 #include <map>
10 #include <memory>
11 #include <mutex>
12 #include <string>
13 
14 #include "core/common/common.h"
18 
20 
21 /*
22 
23  Logging overview and expected usage:
24 
25  At program startup:
26  * Create one or more ISink instances. If multiple, combine using composite_sink.
27  * Create a LoggingManager instance with the sink/s with is_default_instance set to true
28  * Only one instance should be created in this way, and it should remain valid for
29  until the program no longer needs to produce log output.
30 
31  You can either use the static default Logger which LoggingManager will create when constructed
32  via LoggingManager::DefaultLogger(), or separate Logger instances each with different log ids
33  via LoggingManager::CreateLogger.
34 
35  The log id is passed to the ISink instance with the sink determining how the log id is used
36  in the output.
37 
38  LoggingManager
39  * creates the Logger instances used by the application
40  * provides a static default logger instance
41  * owns the log sink instance
42  * applies checks on severity and output of user data
43 
44  The log macros create a Capture instance to capture the information to log.
45  If the severity and/or user filtering settings would prevent logging, no evaluation
46  of the log arguments will occur, so no performance cost beyond the severity and user
47  filtering check.
48 
49  A sink can do further filter as needed.
50 
51 */
52 
53 namespace onnxruntime {
54 
55 namespace logging {
56 
57 using Timestamp = std::chrono::time_point<std::chrono::system_clock>;
58 
59 #ifndef NDEBUG
60 ORT_ATTRIBUTE_UNUSED static bool vlog_enabled = true; // Set directly based on your needs.
61 #else
62 constexpr bool vlog_enabled = false; // no VLOG output
63 #endif
64 
65 enum class DataType {
66  SYSTEM = 0, ///< System data.
67  USER = 1 ///< Contains potentially sensitive user data.
68 };
69 
70 // Internal log categories.
71 // Logging interface takes const char* so arbitrary values can also be used.
72 struct Category {
73  static const char* onnxruntime; ///< General output
74  static const char* System; ///< Log output regarding interactions with the host system
75  // TODO: What other high level categories are meaningful? Model? Optimizer? Execution?
76 };
77 
78 class ISink;
79 class Logger;
80 class Capture;
81 
82 /// <summary>
83 /// The logging manager.
84 /// Owns the log sink and potentially provides a default Logger instance.
85 /// Provides filtering based on a minimum LogSeverity level, and of messages with DataType::User if enabled.
86 /// </summary>
87 class LoggingManager final {
88  public:
89  enum InstanceType {
90  Default, ///< Default instance of LoggingManager that should exist for the lifetime of the program
91  Temporal ///< Temporal instance. CreateLogger(...) should be used, however DefaultLogger() will NOT be provided via this instance.
92  };
93 
94  /**
95  Initializes a new instance of the LoggingManager class.
96  @param sink The sink to write to. Use CompositeSink if you need to write to multiple places.
97  @param default_min_severity The default minimum severity. Messages with lower severity will be ignored unless
98  overridden in CreateLogger.
99  @param default_filter_user_data If set to true ignore messages with DataType::USER unless overridden in CreateLogger.
100  @param instance_type If InstanceType::Default, this is the default instance of the LoggingManager
101  and is expected to exist for the lifetime of the program.
102  It creates and owns the default logger that calls to the static DefaultLogger method return.
103  @param default_logger_id Logger Id to use for the default logger. nullptr/ignored if instance_type == Temporal.
104  @param default_max_vlog_level Default maximum level for VLOG messages to be created unless overridden in CreateLogger.
105  Requires a severity of kVERBOSE for VLOG messages to be logged.
106  */
107  LoggingManager(std::unique_ptr<ISink> sink, Severity default_min_severity, bool default_filter_user_data,
108  InstanceType instance_type,
109  const std::string* default_logger_id = nullptr,
110  int default_max_vlog_level = -1);
111 
112  /**
113  Creates a new logger instance which will use the provided logger_id and default severity and vlog levels.
114  @param logger_id The log identifier.
115  @returns A new Logger instance that the caller owns.
116  */
117  std::unique_ptr<Logger> CreateLogger(const std::string& logger_id);
118 
119  /**
120  Creates a new logger instance which will use the provided logger_id, severity and vlog levels.
121  @param logger_id The log identifier.
122  @param min_severity The minimum severity. Requests to create messages with lower severity will be ignored.
123  @param filter_user_data If set to true ignore messages with DataType::USER.
124  @param max_vlog_level Maximum level for VLOG messages to be created.
125  @returns A new Logger instance that the caller owns.
126  */
127  std::unique_ptr<Logger> CreateLogger(const std::string& logger_id,
128  Severity min_severity, bool filter_user_data, int max_vlog_level = -1);
129 
130  /**
131  Gets the default logger instance if set. Throws if no default logger is currently registered.
132  @remarks
133  Creating a LoggingManager instance with is_default_instance == true registers a default logger.
134  Note that the default logger is only valid until the LoggerManager that registered it is destroyed.
135  @returns The default logger if available.
136  */
137  static const Logger& DefaultLogger();
138 
139  /**
140  Return a boolean indicating if the default logger has been initialized
141  */
142  static bool HasDefaultLogger() { return nullptr != s_default_logger_; }
143 
144  /**
145  Change the minimum severity level for log messages to be output by the default logger.
146  @param severity The severity.
147  */
149 
150  /**
151  Change the maximum verbosity level for log messages to be output by the default logger.
152  @remarks
153  To activate the verbose log, the logger severity must also be set to kVERBOSE.
154  @param vlog_level The verbosity level.
155  */
156  static void SetDefaultLoggerVerbosity(int vlog_level);
157 
158  /**
159  Logs a FATAL level message and creates an exception that can be thrown with error information.
160  @param category The log category.
161  @param location The location the log message was generated.
162  @param format_str The printf format string.
163  @param ... The printf arguments.
164  @returns A new Logger instance that the caller owns.
165  */
166  static std::exception LogFatalAndCreateException(const char* category,
167  const CodeLocation& location,
168  const char* format_str, ...);
169 
170  /**
171  Logs the message using the provided logger id.
172  @param logger_id The log identifier.
173  @param message The log message.
174  */
175  void Log(const std::string& logger_id, const Capture& message) const;
176 
177  /**
178  Sends a Profiling Event Record to the sink.
179  @param Profiling Event Record
180  */
181  void SendProfileEvent(profiling::EventRecord& eventRecord) const;
182  ~LoggingManager();
183 
184  private:
185  ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(LoggingManager);
186 
187  Timestamp GetTimestamp() const noexcept;
188  void CreateDefaultLogger(const std::string& logger_id);
189 
190  std::unique_ptr<ISink> sink_;
191  const Severity default_min_severity_;
192  const bool default_filter_user_data_;
193  const int default_max_vlog_level_;
194  bool owns_default_logger_;
195 
196  static Logger* s_default_logger_;
197 
198  struct Epochs {
199  const std::chrono::time_point<std::chrono::high_resolution_clock> high_res;
200  const std::chrono::time_point<std::chrono::system_clock> system;
201  const std::chrono::minutes localtime_offset_from_utc;
202  };
203 
204  static const Epochs& GetEpochs() noexcept;
205 };
206 
207 /**
208  Logger provides a per-instance log id. Everything else is passed back up to the LoggingManager
209 */
211  public:
212  /**
213  Initializes a new instance of the Logger class.
214  @param loggingManager The logging manager.
215  @param id The identifier for messages coming from this Logger.
216  @param severity Minimum severity for messages to be created and logged.
217  @param filter_user_data Should USER data be filtered from output.
218  @param vlog_level Minimum level for VLOG messages to be created. Note that a severity of kVERBOSE must be provided
219  for VLOG messages to be logged.
220  */
221  Logger(const LoggingManager& loggingManager, std::string id,
222  Severity severity, bool filter_user_data, int vlog_level)
223  : logging_manager_{&loggingManager},
224  id_{id},
225  min_severity_{severity},
226  filter_user_data_{filter_user_data},
227  max_vlog_level_{vlog_level} {
228  }
229 
230  /**
231  Get the minimum severity level for log messages to be output.
232  @returns The severity.
233  */
234  Severity GetSeverity() const noexcept { return min_severity_; }
235 
236  /**
237  Change the minimum severity level for log messages to be output.
238  @param severity The severity.
239  */
240  void SetSeverity(Severity severity) noexcept { min_severity_ = severity; }
241 
242  /**
243  Change the maximum verbosity level for log messages to be output.
244  @remarks
245  To activate the verbose log, the logger severity must also be set to kVERBOSE.
246  @param vlog_level The verbosity.
247  */
248  void SetVerbosity(int vlog_level) noexcept { max_vlog_level_ = vlog_level; }
249 
250  /**
251  Check if output is enabled for the provided LogSeverity and DataType values.
252  @param severity The severity.
253  @param data_type Type of the data.
254  @returns True if a message with these values will be logged.
255  */
256  bool OutputIsEnabled(Severity severity, DataType data_type) const noexcept {
257  return (severity >= min_severity_ && (data_type != DataType::USER || !filter_user_data_));
258  }
259 
260  /**
261  Return the maximum VLOG level allowed. Disabled unless logging VLOG messages
262  */
263  int VLOGMaxLevel() const noexcept {
264  return min_severity_ > Severity::kVERBOSE ? -1 : max_vlog_level_;
265  }
266 
267  /**
268  Logs the captured message.
269  @param message The log message.
270  */
271  void Log(const Capture& message) const {
272  logging_manager_->Log(id_, message);
273  }
274 
275  /**
276  Sends a Profiling Event Record to the sink.
277  @param Profiling Event Record
278  */
279  void SendProfileEvent(profiling::EventRecord& eventRecord) const {
280  logging_manager_->SendProfileEvent(eventRecord);
281  }
282 
283  private:
284  const LoggingManager* logging_manager_;
285  const std::string id_;
286  Severity min_severity_;
287  const bool filter_user_data_;
288  int max_vlog_level_;
289 };
290 
292  if (s_default_logger_ == nullptr) {
293  // fail early for attempted misuse. don't use logging macros as we have no logger.
294  ORT_THROW("Attempt to use DefaultLogger but none has been registered.");
295  }
296 
297  return *s_default_logger_;
298 }
299 
301  if (s_default_logger_ == nullptr) {
302  // fail early for attempted misuse. don't use logging macros as we have no logger.
303  ORT_THROW("Attempt to use DefaultLogger but none has been registered.");
304  }
305 
306  s_default_logger_->SetSeverity(severity);
307 }
308 
309 inline void LoggingManager::SetDefaultLoggerVerbosity(int vlog_level) {
310  if (s_default_logger_ == nullptr) {
311  // fail early for attempted misuse. don't use logging macros as we have no logger.
312  ORT_THROW("Attempt to use DefaultLogger but none has been registered.");
313  }
314 
315  s_default_logger_->SetVerbosity(vlog_level);
316 }
317 
318 inline Timestamp LoggingManager::GetTimestamp() const noexcept {
319  static const Epochs& epochs = GetEpochs();
320 
321  const auto high_res_now = std::chrono::high_resolution_clock::now();
322  return std::chrono::time_point_cast<std::chrono::system_clock::duration>(
323  epochs.system + (high_res_now - epochs.high_res) + epochs.localtime_offset_from_utc);
324 }
325 
326 /**
327  Return the current thread id.
328 */
329 unsigned int GetThreadId();
330 
331 /**
332  Return the current process id.
333 */
334 unsigned int GetProcessId();
335 
336 } // namespace logging
337 } // namespace onnxruntime
Logger(const LoggingManager &loggingManager, std::string id, Severity severity, bool filter_user_data, int vlog_level)
Definition: logging.h:221
GLuint GLsizei const GLchar * message
Definition: glcorearb.h:2543
void Log(const std::string &logger_id, const Capture &message) const
*get result *(waiting if necessary)*A common idiom is to fire a bunch of sub tasks at the and then *wait for them to all complete We provide a helper class
Definition: thread.h:623
std::unique_ptr< Logger > CreateLogger(const std::string &logger_id)
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
void SendProfileEvent(profiling::EventRecord &eventRecord) const
Definition: logging.h:279
LoggingManager(std::unique_ptr< ISink > sink, Severity default_min_severity, bool default_filter_user_data, InstanceType instance_type, const std::string *default_logger_id=nullptr, int default_max_vlog_level=-1)
void SendProfileEvent(profiling::EventRecord &eventRecord) const
static void SetDefaultLoggerSeverity(Severity severity)
Definition: logging.h:300
Contains potentially sensitive user data.
unsigned int GetThreadId()
Temporal instance. CreateLogger(...) should be used, however DefaultLogger() will NOT be provided via...
Definition: logging.h:91
unsigned int GetProcessId()
static const Logger & DefaultLogger()
Definition: logging.h:291
static const char * onnxruntime
General output.
Definition: logging.h:73
The logging manager. Owns the log sink and potentially provides a default Logger instance. Provides filtering based on a minimum LogSeverity level, and of messages with DataType::User if enabled.
Definition: logging.h:87
std::chrono::time_point< std::chrono::system_clock > Timestamp
Definition: logging.h:57
void SetVerbosity(int vlog_level) noexcept
Definition: logging.h:248
#define ORT_ATTRIBUTE_UNUSED
Definition: common.h:67
GLint location
Definition: glcorearb.h:805
GLenum GLenum severity
Definition: glcorearb.h:2539
static void SetDefaultLoggerVerbosity(int vlog_level)
Definition: logging.h:309
Severity GetSeverity() const noexcept
Definition: logging.h:234
#define ORT_THROW(...)
Definition: common.h:163
void SetSeverity(Severity severity) noexcept
Definition: logging.h:240
bool OutputIsEnabled(Severity severity, DataType data_type) const noexcept
Definition: logging.h:256
void Log(const Capture &message) const
Definition: logging.h:271
#define const
Definition: zconf.h:214
static const char * System
Log output regarding interactions with the host system.
Definition: logging.h:74
int VLOGMaxLevel() const noexcept
Definition: logging.h:263
static std::exception LogFatalAndCreateException(const char *category, const CodeLocation &location, const char *format_str,...)
Default instance of LoggingManager that should exist for the lifetime of the program.
Definition: logging.h:90