Program Listing for File logger.hpp¶
↰ Return to documentation for file (stream-client/logger.hpp
)
#pragma once
#include <chrono>
#include <functional>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <string>
// TODO: Move to __FILE_NAME__ with gcc 12.1+
#define FILE_NAME (__builtin_strrchr("/" __FILE__, '/') + 1)
#ifndef STREAM_LOG_CALL
#define STREAM_LOG_CALL(level, ...) \
do { \
const auto logger = stream_client::detail::logger_instance(); \
if (logger && logger->get_level() <= level) { \
logger->message(level, std::string(FILE_NAME) + ":" + std::to_string(__LINE__), __VA_ARGS__); \
} \
} while (0)
#endif
#ifndef STREAM_LOG_ERROR
#define STREAM_LOG_ERROR(...) STREAM_LOG_CALL(stream_client::log_level::error, __VA_ARGS__)
#endif
#ifndef STREAM_LOG_WARN
#define STREAM_LOG_WARN(...) STREAM_LOG_CALL(stream_client::log_level::warning, __VA_ARGS__)
#endif
#ifndef STREAM_LOG_INFO
#define STREAM_LOG_INFO(...) STREAM_LOG_CALL(stream_client::log_level::info, __VA_ARGS__)
#endif
#ifndef STREAM_LOG_DEBUG
#define STREAM_LOG_DEBUG(...) STREAM_LOG_CALL(stream_client::log_level::debug, __VA_ARGS__)
#endif
#ifndef STREAM_LOG_TRACE
#define STREAM_LOG_TRACE(...) STREAM_LOG_CALL(stream_client::log_level::trace, __VA_ARGS__)
#endif
namespace stream_client {
// Forward declaration
class log_interface;
namespace detail {
inline std::shared_ptr<log_interface> logger_instance(std::shared_ptr<log_interface> new_logger = nullptr);
} // namespace detail
enum class log_level : int
{
mute = -1,
trace = 0,
debug,
info,
warning,
error,
};
using log_func_type = std::function<void(log_level level, const std::string& location, const std::string& message)>;
class log_interface
{
public:
virtual ~log_interface() = default;
virtual void set_level(log_level level) noexcept = 0;
virtual log_level get_level() const noexcept = 0;
virtual void message(log_level level, const std::string& location, const std::string& message) const = 0;
};
class base_logger: public stream_client::log_interface
{
public:
base_logger(log_level level);
virtual void set_level(log_level level) noexcept override;
virtual log_level get_level() const noexcept override;
private:
log_level level_;
};
class func_logger: public stream_client::base_logger
{
public:
func_logger(log_level level, stream_client::log_func_type log_func);
func_logger(const func_logger& other) = default;
func_logger& operator=(const func_logger& other) = default;
func_logger(func_logger&& other) = default;
func_logger& operator=(func_logger&& other) = default;
virtual ~func_logger() = default;
virtual void message(log_level level, const std::string& location, const std::string& message) const override;
private:
stream_client::log_func_type log_func_;
};
class cout_logger: public stream_client::base_logger
{
public:
cout_logger(log_level level = log_level::trace);
cout_logger(const cout_logger& other) = delete;
cout_logger& operator=(const cout_logger& other) = delete;
cout_logger(cout_logger&& other) = delete;
cout_logger& operator=(cout_logger&& other) = delete;
virtual ~cout_logger() = default;
virtual void message(log_level level, const std::string& location, const std::string& message) const override;
private:
mutable std::mutex mutex_;
};
inline void set_logger(std::shared_ptr<log_interface> logger);
inline void set_logger(log_level level, stream_client::log_func_type log_func);
inline void set_log_level(log_level level);
inline log_level get_log_level();
inline void log_message(log_level level, const std::string& location, const std::string& message);
} // namespace stream_client
#include "impl/logger.ipp"