-
Notifications
You must be signed in to change notification settings - Fork 299
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The ESI logging API is intended to be agnostic of the application's logging framework. In other words, it can be adapted to the application's logging method with ease -- users must only extend one class. It also comes with a simple text logger. It is also designed to enable debug logging in Release builds with (very) minimal performance overhead if the user does not set the log level to debug. This PR introduces the API, but doesn't use it much. More plumbing will be required to actually use it. In the interest of keeping this PR small, this is left for future work.
- Loading branch information
Showing
12 changed files
with
354 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
//===- Logging.h - ESI Runtime logging --------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// ESI runtime logging is very simple but very flexible. Rather than mandating a | ||
// particular logging library, it allows users to hook into their existing | ||
// logging system by implementing a simple interface. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// DO NOT EDIT! | ||
// This file is distributed as part of an ESI package. The source for this file | ||
// should always be modified within CIRCT. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// NOLINTNEXTLINE(llvm-header-guard) | ||
#ifndef ESI_LOGGING_H | ||
#define ESI_LOGGING_H | ||
|
||
#include <any> | ||
#include <functional> | ||
#include <iosfwd> | ||
#include <map> | ||
#include <memory> | ||
#include <string> | ||
|
||
namespace esi { | ||
|
||
class Logger { | ||
public: | ||
enum class Level { Debug, Info, Warning, Error }; | ||
Logger(bool debugEnabled) : debugEnabled(debugEnabled) {} | ||
virtual ~Logger() = default; | ||
bool getDebugEnabled() { return debugEnabled; } | ||
|
||
/// Report a log message. | ||
/// Arguments: | ||
/// log: The log level as defined by the 'Level' enum above. | ||
/// subsystem: The subsystem that generated the log message. | ||
/// msg: The log message. | ||
/// details: Optional additional structured details to include in the log | ||
/// message. If there are no details, this should be nullptr. | ||
virtual void | ||
log(Level level, const std::string &subsystem, const std::string &msg, | ||
const std::map<std::string, std::any> *details = nullptr) = 0; | ||
|
||
/// Report an error. | ||
virtual void error(const std::string &subsystem, const std::string &msg, | ||
const std::map<std::string, std::any> *details = nullptr) { | ||
log(Level::Error, subsystem, msg, details); | ||
} | ||
/// Report a warning. | ||
virtual void | ||
warning(const std::string &subsystem, const std::string &msg, | ||
const std::map<std::string, std::any> *details = nullptr) { | ||
log(Level::Warning, subsystem, msg, details); | ||
} | ||
/// Report an informational message. | ||
virtual void info(const std::string &subsystem, const std::string &msg, | ||
const std::map<std::string, std::any> *details = nullptr) { | ||
log(Level::Info, subsystem, msg, details); | ||
} | ||
|
||
/// Report a debug message. This is not virtual so that it can be inlined to | ||
/// minimize performance impact that debug messages have. Allows debug | ||
/// messages in Release builds. | ||
inline void debug(const std::string &subsystem, const std::string &msg, | ||
const std::map<std::string, std::any> *details = nullptr) { | ||
if (debugEnabled) | ||
debugImpl(subsystem, msg, details); | ||
} | ||
/// Call the debug function callback only if debug is enabled. Allows users to | ||
/// run heavy weight debug message generation code only when debug is enabled. | ||
/// Allows users to provide debug messages in Release builds with minimal | ||
/// performance impact. Not virtual so that it can be inlined. | ||
inline void | ||
debug(std::function< | ||
void(std::string &subsystem, std::string &msg, | ||
std::unique_ptr<std::map<std::string, std::any>> &details)> | ||
debugFunc) { | ||
if (debugEnabled) | ||
debugImpl(debugFunc); | ||
} | ||
|
||
protected: | ||
/// Overrideable version of debug. | ||
virtual void debugImpl(const std::string &subsystem, const std::string &msg, | ||
const std::map<std::string, std::any> *details) { | ||
log(Level::Debug, subsystem, msg, details); | ||
} | ||
virtual void | ||
debugImpl(std::function< | ||
void(std::string &subsystem, std::string &msg, | ||
std::unique_ptr<std::map<std::string, std::any>> &details)> | ||
debugFunc) { | ||
if (!debugEnabled) | ||
return; | ||
std::string subsystem; | ||
std::string msg; | ||
std::unique_ptr<std::map<std::string, std::any>> details = nullptr; | ||
debugFunc(subsystem, msg, details); | ||
debugImpl(subsystem, msg, details.get()); | ||
} | ||
|
||
/// Enable or disable debug messages. | ||
bool debugEnabled = false; | ||
}; | ||
|
||
/// A logger that writes to a C++ std::ostream. | ||
class StreamLogger : public Logger { | ||
public: | ||
/// Create a stream logger that logs to the given output stream and error | ||
/// output stream. | ||
StreamLogger(Level minLevel, std::ostream &out, std::ostream &error) | ||
: Logger(minLevel == Level::Debug), minLevel(minLevel), outStream(out), | ||
errorStream(error) {} | ||
/// Create a stream logger that logs to stdout, stderr. | ||
StreamLogger(Level minLevel); | ||
void log(Level level, const std::string &subsystem, const std::string &msg, | ||
const std::map<std::string, std::any> *details) override; | ||
|
||
private: | ||
/// The minimum log level to emit. | ||
Level minLevel; | ||
|
||
/// Mutex to protect the stream from interleaved logging writes. | ||
std::mutex mutex; | ||
std::ostream &outStream; | ||
std::ostream &errorStream; | ||
}; | ||
|
||
/// A logger that does nothing. | ||
class NullLogger : public Logger { | ||
public: | ||
NullLogger() : Logger(false) {} | ||
void log(Level, const std::string &, const std::string &, | ||
const std::map<std::string, std::any> *) override {} | ||
}; | ||
|
||
/// 'Stringify' a std::any. This is used to log std::any values by some loggers. | ||
std::string toString(const std::any &a); | ||
|
||
} // namespace esi | ||
|
||
#endif // ESI_LOGGING_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.