Skip to content
Snippets Groups Projects
Select Git revision
  • 5fec463bf67d7ec11d13fda48d82db5e9b8fd70e
  • main default protected
  • f-sss4grpc
  • dev
  • 108-implement-rpc-call-for-server-side-scripting
  • f-windows-conan-create
  • f-to-string
  • f-update-requirements
  • f-related-projects
  • f-role
  • f-remote-path
  • f-rel-path
  • f-consol-message
  • v0.3.0
  • v0.2.2
  • v0.2.1
  • v0.2.0
  • v0.1.2
  • v0.1.1
  • v0.1
  • v0.0.19
  • v0.0.18
  • v0.0.16
  • v0.0.15
  • v0.0.10
  • v0.0.9
  • v0.0.8
  • v0.0.7
  • v0.0.6
  • v0.0.5
  • v0.0.4
  • v0.0.3
  • v0.0.2
33 results

logging.h

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    logging.h 9.12 KiB
    
    /*
     * This file is a part of the LinkAhead Project.
     *
     * Copyright (C) 2021-2022 Timm Fitschen <t.fitschen@indiscale.com>
     * Copyright (C) 2021-2022 IndiScale GmbH <info@indiscale.com>
     *
     * This program is free software: you can redistribute it and/or modify
     * it under the terms of the GNU Affero General Public License as
     * published by the Free Software Foundation, either version 3 of the
     * License, or (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU Affero General Public License for more details.
     *
     * You should have received a copy of the GNU Affero General Public License
     * along with this program. If not, see <https://www.gnu.org/licenses/>.
     *
     */
    
    #ifndef LINKAHEAD_LOGGING_H
    #define LINKAHEAD_LOGGING_H
    
    #include "linkahead/log_level.h" // for LINKAHEAD_LOG_...
    #include <cstdint>               // for uint64_t
    #include <iosfwd>                // for streamsize
    #include <memory>                // for shared_ptr
    #include <string>                // for string
    #include <vector>                // for vector
    #include <filesystem>            // for path
    
    namespace linkahead::logging {
    
    const std::string logger_name = "linkahead::logging";
    
    class LoggerOutputStream {
    public:
      LoggerOutputStream(std::string channel, int level);
      auto operator<<(std::ostream &(*f)(std::ostream &)) -> LoggerOutputStream &;
      auto operator<<(bool msg) -> LoggerOutputStream &;
      auto operator<<(int msg) -> LoggerOutputStream &;
      auto operator<<(uint64_t msg) -> LoggerOutputStream &;
      auto operator<<(int64_t msg) -> LoggerOutputStream &;
      auto operator<<(std::streambuf *msg) -> LoggerOutputStream &;
      auto operator<<(const char *msg) -> LoggerOutputStream &;
      auto operator<<(const std::string &msg) -> LoggerOutputStream &;
      auto operator<<(void *msg) -> LoggerOutputStream &;
      auto operator<<(std::filesystem::path *path) -> LoggerOutputStream &;
      auto operator<<(const std::filesystem::path &path) -> LoggerOutputStream &;
    
      static auto get(const std::string &channel, int level) -> LoggerOutputStream {
        return LoggerOutputStream(channel, level);
      }
    
    private:
      std::string channel;
      int level;
    };
    
    /**
     * Helper class for logging the entering and leaving of a function or method.
     *
     * Please Use the macro
     *
     *   LINKAHEAD_LOG_TRACE_ENTER_AND_LEAVE(logger_name, function_name);
     */
    class TraceEnterLeaveLogger {
    public:
      inline TraceEnterLeaveLogger(const std::string &channel, const std::string &function_name)
        : channel(channel), function_name(function_name) {
        linkahead::logging::LoggerOutputStream::get(this->channel, LINKAHEAD_LOG_LEVEL_TRACE)
          << "Enter " << this->function_name;
      }
      inline ~TraceEnterLeaveLogger() {
        linkahead::logging::LoggerOutputStream::get(this->channel, LINKAHEAD_LOG_LEVEL_TRACE)
          << "Leave " << this->function_name;
      }
    
    private:
      const std::string &channel;
      const std::string function_name;
    };
    
    /**
     * This class stores the integer log level.
     */
    class LevelConfiguration {
    public:
      LevelConfiguration(int level) : level(level){};
      [[nodiscard]] inline auto GetLevel() const -> int { return this->level; }
    
    private:
      int level;
    };
    
    class SinkConfiguration;
    
    /**
     * This class stores the logging level and log sinks.
     *
     * Sinks are represented by SinkConfiguration objects.
     */
    class LoggingConfiguration : public LevelConfiguration {
    public:
      virtual ~LoggingConfiguration() = default;
      LoggingConfiguration(int level);
      auto AddSink(const std::shared_ptr<SinkConfiguration> &sink) -> void;
      auto GetSinks() const -> const std::vector<std::shared_ptr<SinkConfiguration>> &;
    
    private:
      std::vector<std::shared_ptr<SinkConfiguration>> sinks;
    };
    
    auto initialize_logging_defaults() -> int;
    auto initialize_logging(const LoggingConfiguration &configuration) -> void;
    
    /**
     * A logging sink is characterized by a name and destination.
     *
     * Typical inheriting configurations exist for console, files and syslog.
     *
     * When a SinkConfiguration is created from a configuration, the sink
     * configuration must contain a \p destination key which matches one of the
     * keywords for implemented sinks.  At the moment of writing this documentation,
     * valid destinations are:
     *
     * \li \p file
     * \li \p console
     * \li \p syslog
     *
     * A \p level keyword sets the logging level, if it exists at the sink or
     * logging level of the configuration.
     */
    class SinkConfiguration : public LevelConfiguration {
    public:
      virtual ~SinkConfiguration() = default;
      SinkConfiguration(std::string name, int level);
      [[nodiscard]] auto GetName() const -> const std::string &;
      [[nodiscard]] virtual auto GetDestination() const -> const std::string & = 0;
    
      friend auto initialize_logging_defaults() -> int;
      friend auto initialize_logging(const LoggingConfiguration &logging_configuration) -> void;
    
    protected:
      virtual auto Configure(void *settings) const -> void;
    
    private:
      std::string name;
    };
    
    class ConsoleSinkConfiguration : public SinkConfiguration {
    public:
      virtual ~ConsoleSinkConfiguration() = default;
      ConsoleSinkConfiguration(const std::string &name, int level);
      [[nodiscard]] auto GetDestination() const -> const std::string & override;
      friend auto initialize_logging_defaults() -> int;
      friend auto initialize_logging(const LoggingConfiguration &logging_configuration) -> void;
    
    protected:
      typedef SinkConfiguration sink_configuration;
      virtual auto Configure(void *settings) const -> void override;
    
    private:
      const std::string destination = "Console";
    };
    
    /**
     * The file name is the destination, the directory can be set separately.
     *
     * If there is a `directory` key in the configuration, that will be used as a
     * default, otherwise it is the current directory.
     */
    class FileSinkConfiguration : public SinkConfiguration {
    public:
      virtual ~FileSinkConfiguration() = default;
      FileSinkConfiguration(const std::string &name, int level);
      [[nodiscard]] virtual auto GetDestination() const -> const std::string & override;
      auto SetDirectory(const std::string &directory) -> void;
      friend auto initialize_logging_defaults() -> int;
      friend auto initialize_logging(const LoggingConfiguration &logging_configuration) -> void;
    
    protected:
      typedef SinkConfiguration sink_configuration;
      virtual auto Configure(void *settings) const -> void override;
    
    private:
      const std::string destination = "TextFile";
      std::string directory = "./";
    };
    
    class SyslogSinkConfiguration : public SinkConfiguration {
    public:
      virtual ~SyslogSinkConfiguration() = default;
      SyslogSinkConfiguration(const std::string &name, int level);
      [[nodiscard]] virtual auto GetDestination() const -> const std::string & override;
    
    private:
      const std::string destination = "Syslog";
    };
    
    /**
     * Convenience function for the C interface.
     */
    void linkahead_log_fatal(const char *channel, const char *msg);
    /**
     * Convenience function for the C interface.
     */
    void linkahead_log_error(const char *channel, const char *msg);
    /**
     * Convenience function for the C interface.
     */
    void linkahead_log_warn(const char *channel, const char *msg);
    /**
     * Convenience function for the C interface.
     */
    void linkahead_log_info(const char *channel, const char *msg);
    /**
     * Convenience function for the C interface.
     */
    void linkahead_log_debug(const char *channel, const char *msg);
    /**
     * Convenience function for the C interface.
     */
    void linkahead_log_trace(const char *channel, const char *msg);
    
    } // namespace linkahead::logging
    
    #define LINKAHEAD_LOG_FATAL(Channel)                                                               \
      linkahead::logging::LoggerOutputStream::get(Channel, LINKAHEAD_LOG_LEVEL_FATAL)
    #define LINKAHEAD_LOG_ERROR(Channel)                                                               \
      linkahead::logging::LoggerOutputStream::get(Channel, LINKAHEAD_LOG_LEVEL_ERROR)
    #define LINKAHEAD_LOG_WARN(Channel)                                                                \
      linkahead::logging::LoggerOutputStream::get(Channel, LINKAHEAD_LOG_LEVEL_WARN)
    #define LINKAHEAD_LOG_INFO(Channel)                                                                \
      linkahead::logging::LoggerOutputStream::get(Channel, LINKAHEAD_LOG_LEVEL_INFO)
    #define LINKAHEAD_LOG_DEBUG(Channel)                                                               \
      linkahead::logging::LoggerOutputStream::get(Channel, LINKAHEAD_LOG_LEVEL_DEBUG)
    #define LINKAHEAD_LOG_TRACE(Channel)                                                               \
      linkahead::logging::LoggerOutputStream::get(Channel, LINKAHEAD_LOG_LEVEL_TRACE)
    
    #define LINKAHEAD_LOG_TRACE_ENTER_AND_LEAVE(Channel, FunctionName)                                 \
      const linkahead::logging::TraceEnterLeaveLogger trace_enter_leave_logger(Channel, FunctionName);
    
    #define LINKAHEAD_LOG_ERROR_AND_RETURN_STATUS(Channel, StatusCode, Message)                        \
      LINKAHEAD_LOG_ERROR(Channel) << "StatusCode (" << StatusCode << ") "                             \
                                   << linkahead::get_status_description(StatusCode) << ": "            \
                                   << Message;                                                         \
      return StatusCode;
    
    #endif