parent
5a9106f2a5
commit
0b59e5a94c
@ -12,6 +12,47 @@
|
||||
#include <type_traits>
|
||||
|
||||
namespace Azure { namespace Core { namespace Diagnostics { namespace _internal {
|
||||
|
||||
/** @brief Internal Log class used for generating diagnostic logs.
|
||||
*
|
||||
* When components within the Azure SDK wish to emit diagnostic log messages, they should use the
|
||||
* Azure::Core::Diagnostics::_internal::Log class to generate those messages.
|
||||
*
|
||||
* The Log class methods integrate with the public diagnostic logging infrastructure to generate
|
||||
* log messages which will be captured by either the default logger or a customer provided logger.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* There are two primary interfaces to the Log class. The first (and most common) is to use the
|
||||
* Log::Write method to write a string to the configured logger. For example:
|
||||
*
|
||||
* ```cpp
|
||||
* using namespace Azure::Core::Diagnostics::_internal;
|
||||
* using namespace Azure::Core::Diagnostics;
|
||||
* :
|
||||
* :
|
||||
* Log::Write(Logger::Level::Verbose, "This is a diagnostic message");
|
||||
* ```
|
||||
*
|
||||
* this will pass the string "This is a diagnostic message" to the configured logger at the
|
||||
* "Verbose" error level.
|
||||
*
|
||||
* The second interface is to use the Log::Stream() class to stream a string to the configured
|
||||
* logger. For example:
|
||||
*
|
||||
* ```cpp
|
||||
* using namespace Azure::Core::Diagnostics::_internal;
|
||||
* using namespace Azure::Core::Diagnostics;
|
||||
* :
|
||||
* :
|
||||
* int resultCode = 500;
|
||||
* Log::Stream(Logger::Level::Error) << "An error has occurred " << resultCode;
|
||||
* ```
|
||||
*
|
||||
* this will pass the string "An error has occurred 500" to the configured logger at the "Error"
|
||||
* error level.
|
||||
*
|
||||
*/
|
||||
class Log final {
|
||||
static_assert(
|
||||
std::is_same<int, std::underlying_type<Logger::Level>::type>::value == true,
|
||||
@ -27,20 +68,35 @@ namespace Azure { namespace Core { namespace Diagnostics { namespace _internal {
|
||||
Log() = delete;
|
||||
~Log() = delete;
|
||||
|
||||
/** @brief String buffer for use in the logger.
|
||||
*
|
||||
* A specialization of std::stringbuf for use in the logger.
|
||||
*
|
||||
* This function primarily exists to implement the sync() function which triggers a call to
|
||||
* Log::Write().
|
||||
*/
|
||||
class LoggerStringBuffer : public std::stringbuf {
|
||||
public:
|
||||
/** @brief Configure a LogStringBuffer with the specified logging level. */
|
||||
LoggerStringBuffer(Logger::Level level) : m_level{level} {}
|
||||
LoggerStringBuffer(LoggerStringBuffer&& that) = default;
|
||||
LoggerStringBuffer& operator=(LoggerStringBuffer&& that) = default;
|
||||
~LoggerStringBuffer() override = default;
|
||||
|
||||
/** @brief Implementation of std::basic_streambuf<char>::sync.
|
||||
*
|
||||
* @returns 0 on success, -1 otherwise.
|
||||
*/
|
||||
virtual int sync() override;
|
||||
|
||||
private:
|
||||
Logger::Level m_level;
|
||||
};
|
||||
|
||||
public:
|
||||
/** @brief Logger Stream used internally by the GetStream() private method.
|
||||
*
|
||||
* Stream class used to wrap a LoggerStringBuffer stringbuf object.
|
||||
*/
|
||||
class LoggerStream : public std::basic_ostream<char> {
|
||||
public:
|
||||
LoggerStream(Logger::Level level) : std::ostream(&m_stringBuffer), m_stringBuffer{level} {}
|
||||
@ -50,30 +106,105 @@ namespace Azure { namespace Core { namespace Diagnostics { namespace _internal {
|
||||
LoggerStringBuffer m_stringBuffer;
|
||||
};
|
||||
|
||||
public:
|
||||
/** @brief Stream class used to enable using iomanip operators on an I/O stream.
|
||||
* Usage:
|
||||
*
|
||||
* ```cpp
|
||||
* using namespace Azure::Core::Diagnostics::_internal;
|
||||
* using namespace Azure::Core::Diagnostics;
|
||||
* :
|
||||
* :
|
||||
* int resultCode = 500;
|
||||
* Log::Stream(Logger::Level::Error) << "An error has occurred " << resultCode;
|
||||
* ```
|
||||
*
|
||||
* this will pass the string "An error has occurred 500" to the configured logger at the "Error"
|
||||
* error level.
|
||||
*
|
||||
* @remarks The Log::Stream() construct creates a temporary Stream object whose lifetime ends a
|
||||
* the end of the statement creating the Stream object. In the destructor for the stream, the
|
||||
* underlying stream object is flushed thus ensuring that the output is generated at the end of
|
||||
* the statement, even if the caller does not insert the std::endl object.
|
||||
*/
|
||||
class Stream {
|
||||
public:
|
||||
/** @brief Construct a new Stream object with the configured I/O level.
|
||||
*
|
||||
* @param level - Represents the desired diagnostic level for the operation.
|
||||
*/
|
||||
Stream(Logger::Level level) : m_stream(GetStream(level)) {}
|
||||
|
||||
/** @brief Called when the Stream object goes out of scope. */
|
||||
~Stream() { m_stream.flush(); }
|
||||
Stream(Stream const&) = delete;
|
||||
Stream& operator=(Stream const&) = delete;
|
||||
|
||||
/** @brief Insert an object of type T into the output stream.
|
||||
*
|
||||
* @tparam T Type of the object being inserted.
|
||||
* @param val value to be inserted into the underlying stream.
|
||||
*/
|
||||
template <typename T> std::ostream& operator<<(T val) { return m_stream << val; }
|
||||
|
||||
private:
|
||||
LoggerStream& m_stream;
|
||||
};
|
||||
|
||||
/** @brief Returns true if the logger would write a string at the specified level.
|
||||
*
|
||||
* This function primarily exists to enable callers to avoid expensive computations if the
|
||||
* currently configured log level doesn't support logging at the specified level.
|
||||
*
|
||||
* @param level - log level to check.
|
||||
* @returns true if the logger will write at that log level.
|
||||
*/
|
||||
static bool ShouldWrite(Logger::Level level)
|
||||
{
|
||||
return g_isLoggingEnabled && level >= g_logLevel;
|
||||
}
|
||||
|
||||
/** @brief Write a string to the configured logger at the specified log level.
|
||||
*
|
||||
* Expected usage:
|
||||
*
|
||||
* ```cpp
|
||||
* using namespace Azure::Core::Diagnostics::_internal;
|
||||
* using namespace Azure::Core::Diagnostics;
|
||||
* :
|
||||
* :
|
||||
* Log::Write(Logger::Level::Verbose, "This is a diagnostic message");
|
||||
* ```
|
||||
*
|
||||
* this will pass the string "This is a diagnostic message" to the configured logger at the
|
||||
* "Verbose" error level.
|
||||
*
|
||||
* @param level - log level to use for the message.
|
||||
* @param message - message to write to the logger.
|
||||
*
|
||||
*/
|
||||
static void Write(Logger::Level level, std::string const& message);
|
||||
|
||||
/** @brief Enable logging.
|
||||
*
|
||||
* @param isEnabled - true if logging should be enabled, false if it should be disabled.
|
||||
*/
|
||||
static void EnableLogging(bool isEnabled);
|
||||
|
||||
/** @brief Set the current log level globally.
|
||||
*
|
||||
* Note that this overrides any customer configuration of the log level and should generally be
|
||||
* avoided.
|
||||
*
|
||||
* @param logLevel - New global log level.
|
||||
*/
|
||||
static void SetLogLevel(Logger::Level logLevel);
|
||||
|
||||
private:
|
||||
static LoggerStream g_verboseLogger;
|
||||
static LoggerStream g_informationalLogger;
|
||||
static LoggerStream g_warningLogger;
|
||||
static LoggerStream g_errorLogger;
|
||||
static LoggerStream& GetStream(Logger::Level level);
|
||||
};
|
||||
}}}} // namespace Azure::Core::Diagnostics::_internal
|
||||
|
||||
@ -61,12 +61,11 @@ int Log::LoggerStringBuffer::sync()
|
||||
str(std::string());
|
||||
return 0;
|
||||
}
|
||||
namespace {
|
||||
static Log::LoggerStream g_verboseLogger{Logger::Level::Verbose};
|
||||
static Log::LoggerStream g_informationalLogger{Logger::Level::Informational};
|
||||
static Log::LoggerStream g_warningLogger{Logger::Level::Warning};
|
||||
static Log::LoggerStream g_errorLogger{Logger::Level::Error};
|
||||
} // namespace
|
||||
|
||||
Log::LoggerStream Log::g_verboseLogger{Logger::Level::Verbose};
|
||||
Log::LoggerStream Log::g_informationalLogger{Logger::Level::Informational};
|
||||
Log::LoggerStream Log::g_warningLogger{Logger::Level::Warning};
|
||||
Log::LoggerStream Log::g_errorLogger{Logger::Level::Error};
|
||||
|
||||
/** Returns a custom ostream implementation with a logger based stream buffer.
|
||||
* @param level The level of the log message.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user