added logging module and a sandbox project
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
#ifndef MATADOR_BASIC_FILE_SINK_HPP
|
||||
#define MATADOR_BASIC_FILE_SINK_HPP
|
||||
|
||||
#include "matador/logger/log_sink.hpp"
|
||||
|
||||
namespace matador::logger {
|
||||
|
||||
/**
|
||||
* @brief A base class for the file-stream-based sinks
|
||||
*
|
||||
* This class acts like a base class for all
|
||||
* concrete sinks working with a file stream to write
|
||||
* the log message.
|
||||
*/
|
||||
class basic_file_sink : public log_sink
|
||||
{
|
||||
protected:
|
||||
basic_file_sink() = default;
|
||||
|
||||
/**
|
||||
* Creates a basic_file_sink with a given file stream
|
||||
*
|
||||
* @param f File stream to write on
|
||||
*/
|
||||
explicit basic_file_sink(FILE *f);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Writes the log message to the internal
|
||||
* file stream.
|
||||
*
|
||||
* @param message The message to write
|
||||
* @param size The size of the message
|
||||
*/
|
||||
void write(const char *message, size_t size) override;
|
||||
|
||||
/**
|
||||
* Closes the internal file stream.
|
||||
*/
|
||||
void close() override;
|
||||
|
||||
protected:
|
||||
/// @cond MATADOR_DEV
|
||||
FILE *stream = nullptr;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
}
|
||||
#endif //MATADOR_BASIC_FILE_SINK_HPP
|
||||
@@ -0,0 +1,90 @@
|
||||
#ifndef MATADOR_FILE_SINK_HPP
|
||||
#define MATADOR_FILE_SINK_HPP
|
||||
|
||||
#include "matador/logger/basic_file_sink.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace matador::logger {
|
||||
|
||||
/**
|
||||
* @brief A file sink writing the log message to one file
|
||||
*
|
||||
* The log sink writes all log messages to one single
|
||||
* file identified by a given path.
|
||||
*
|
||||
* Note because there is no limit, the file grows infinitely.
|
||||
*/
|
||||
class file_sink final : public basic_file_sink
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a file_sink with the given path.
|
||||
* If the path doesn't exist, it is created.
|
||||
*
|
||||
* @param path The log file to write to
|
||||
*/
|
||||
explicit file_sink(const std::string &path);
|
||||
|
||||
/**
|
||||
* Creates a file_sink with the given path.
|
||||
* If the path doesn't exist, it is created.
|
||||
*
|
||||
* @param path The log file to write to
|
||||
*/
|
||||
explicit file_sink(const char *path);
|
||||
|
||||
/**
|
||||
* Destroys the file_sink
|
||||
*/
|
||||
~file_sink() override;
|
||||
|
||||
/**
|
||||
* Returns the path to the log file.
|
||||
*
|
||||
* @return The path to the log file
|
||||
*/
|
||||
std::string path() const;
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Log sink writing to stdout
|
||||
*
|
||||
* This log sink writes all messages to stdout.
|
||||
*/
|
||||
class stdout_sink final : public basic_file_sink
|
||||
{
|
||||
public:
|
||||
stdout_sink();
|
||||
~stdout_sink() override = default;
|
||||
|
||||
/**
|
||||
* Do nothing on close
|
||||
*/
|
||||
void close() override {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Log sink writing to stderr
|
||||
*
|
||||
* This log sink writes all messages to stderr.
|
||||
*/
|
||||
class stderr_sink final : public basic_file_sink
|
||||
{
|
||||
public:
|
||||
stderr_sink();
|
||||
~stderr_sink() override = default;
|
||||
|
||||
/**
|
||||
* Do nothing on close
|
||||
*/
|
||||
void close() override {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //MATADOR_FILE_SINK_HPP
|
||||
@@ -0,0 +1,118 @@
|
||||
#ifndef MATADOR_LOG_DOMAIN_HPP
|
||||
#define MATADOR_LOG_DOMAIN_HPP
|
||||
|
||||
#include "matador/logger/log_level.hpp"
|
||||
#include "matador/logger/log_sink.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
namespace matador::logger {
|
||||
|
||||
/**
|
||||
* @brief Connection to a set of log sinks
|
||||
*
|
||||
* A log domain is the connection point between
|
||||
* a set of log sinks and the logger objects
|
||||
* in the user code.
|
||||
*
|
||||
* A domain consists of a unique name and a
|
||||
* list of sinks
|
||||
*/
|
||||
class log_domain final
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The time format for each log line
|
||||
*/
|
||||
static constexpr auto TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S.%f";
|
||||
|
||||
/**
|
||||
* Creates a log_domain with the given name
|
||||
* and the given log range
|
||||
*
|
||||
* @param name The name of the log domain
|
||||
* @param log_range The log range of this domain
|
||||
*/
|
||||
log_domain(std::string name, log_level_range log_range);
|
||||
|
||||
/**
|
||||
* Returns the name of the domain
|
||||
*
|
||||
* @return The name of the domain
|
||||
*/
|
||||
[[nodiscard]] std::string name() const;
|
||||
|
||||
/**
|
||||
* Sets the max log level. The default
|
||||
* max level is LVL_FATAL
|
||||
*
|
||||
* @param max_level max log level
|
||||
*/
|
||||
void max_log_level(log_level max_level);
|
||||
|
||||
/**
|
||||
* Returns the max log level
|
||||
*
|
||||
* @return The max log level
|
||||
*/
|
||||
[[nodiscard]] log_level max_log_level() const;
|
||||
|
||||
/**
|
||||
* Sets the min log level. Default
|
||||
* min leven is LVL_INFO
|
||||
*
|
||||
* @param min_level min log level
|
||||
*/
|
||||
void min_log_level(log_level min_level);
|
||||
|
||||
/**
|
||||
* Returns the min log level
|
||||
*
|
||||
* @return The min log level
|
||||
*/
|
||||
[[nodiscard]] log_level min_log_level() const;
|
||||
|
||||
/**
|
||||
* Add a sink to the domain.
|
||||
*
|
||||
* The sink must be packed into a std::shared_ptr
|
||||
* because it can be shared among other domains
|
||||
*
|
||||
* @param sink The sink to add
|
||||
*/
|
||||
void add_sink(sink_ptr sink);
|
||||
|
||||
/**
|
||||
* Logs the given message for the given source and log level
|
||||
* to this log domain.
|
||||
*
|
||||
* @param lvl Log level
|
||||
* @param source Source of the log message
|
||||
* @param message Message to log
|
||||
*/
|
||||
void log(log_level lvl, const std::string &source, const char *message);
|
||||
|
||||
/**
|
||||
* Clears the list of log sinks
|
||||
*/
|
||||
void clear();
|
||||
|
||||
private:
|
||||
void get_time_stamp(char* timestamp_buffer);
|
||||
|
||||
private:
|
||||
static std::map<log_level, std::string> level_strings;
|
||||
|
||||
std::string name_;
|
||||
std::list<sink_ptr> sinks{};
|
||||
|
||||
log_level_range log_level_range_;
|
||||
|
||||
std::mutex mutex_;
|
||||
};
|
||||
|
||||
}
|
||||
#endif //MATADOR_LOG_DOMAIN_HPP
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef MATADOR_LOG_LEVEL_HPP
|
||||
#define MATADOR_LOG_LEVEL_HPP
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace matador::logger {
|
||||
|
||||
/**
|
||||
* Represents all available log levels
|
||||
*/
|
||||
enum class log_level
|
||||
{
|
||||
LVL_FATAL, /**< If a serious error occurred, use FATAL level */
|
||||
LVL_ERROR, /**< On error use ERROR level */
|
||||
LVL_WARN, /**< Warnings should use WARN level */
|
||||
LVL_INFO, /**< Information should go with INFO level */
|
||||
LVL_DEBUG, /**< Debug output should use DEBUG level */
|
||||
LVL_TRACE, /**< Trace information should use TRACE level */
|
||||
LVL_ALL /**< This level represents all log levels and should be used for logging */
|
||||
};
|
||||
|
||||
/**
|
||||
* Write log level in a human-readable string
|
||||
* to a given std::ostream.
|
||||
*
|
||||
* @param os std::stream to write to
|
||||
* @param lvl Log level to write
|
||||
* @return The std::ostream
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream &os, log_level lvl);
|
||||
|
||||
/// @cond MATADOR_DEV
|
||||
|
||||
struct log_level_range
|
||||
{
|
||||
log_level min_level = log_level::LVL_INFO;
|
||||
log_level max_level = log_level::LVL_FATAL;
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
}
|
||||
#endif //MATADOR_LOG_LEVEL_HPP
|
||||
@@ -0,0 +1,303 @@
|
||||
#ifndef MATADOR_LOG_MANAGER_HPP
|
||||
#define MATADOR_LOG_MANAGER_HPP
|
||||
|
||||
#include "matador/utils/singleton.hpp"
|
||||
|
||||
#include "matador/logger/logger.hpp"
|
||||
#include "matador/logger/log_sink.hpp"
|
||||
#include "matador/logger/file_sink.hpp"
|
||||
#include "matador/logger/rotating_file_sink.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace matador::logger {
|
||||
|
||||
/**
|
||||
* @brief Manages all log domains
|
||||
*
|
||||
* The log_manager class is a singleton and
|
||||
* manages all available log_domains
|
||||
*
|
||||
* There ist always a default log domain
|
||||
* with the name "default"
|
||||
* available for which sinks can be added
|
||||
* and loggers can be created.
|
||||
*/
|
||||
class log_manager final : public utils::singleton<log_manager>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a logger with the given source name
|
||||
* for the default log domain
|
||||
*
|
||||
* @param source Name of the source
|
||||
* @return The created logger
|
||||
*/
|
||||
[[nodiscard]] logger create_logger(std::string source) const;
|
||||
|
||||
/**
|
||||
* Creates a logger with the given source name
|
||||
* for the log domain identified by the given
|
||||
* log domain name.
|
||||
*
|
||||
* If the log domain with the given name doesn't exist,
|
||||
* the domain is created
|
||||
*
|
||||
* @param source Name of the source
|
||||
* @param domain_name The name of the log domain to execute to
|
||||
* @return The created logger
|
||||
*/
|
||||
logger create_logger(std::string source, const std::string &domain_name);
|
||||
|
||||
/**
|
||||
* Adds a log sink to the default log_domain
|
||||
*
|
||||
* @param sink Sink to add to the default log_domain
|
||||
*/
|
||||
void add_sink(sink_ptr sink) const;
|
||||
|
||||
/**
|
||||
* Adds a log sink to the log_domain with the given name.
|
||||
* If the log domain doesn't exist, it is automatically created.
|
||||
*
|
||||
* @param sink Sink to add
|
||||
* @param domain_name Name of the log domain
|
||||
*/
|
||||
void add_sink(sink_ptr sink, const std::string &domain_name);
|
||||
|
||||
/**
|
||||
* Clears all sinks from the default log domain
|
||||
*/
|
||||
void clear_all_sinks() const;
|
||||
|
||||
/**
|
||||
* Clears all sinks from the log domain
|
||||
* with the given name
|
||||
*
|
||||
* @param domain_name Domain name to clear all sinks from
|
||||
*/
|
||||
void clear_all_sinks(const std::string &domain_name);
|
||||
|
||||
/**
|
||||
* Remove all log domains but the default log domain.
|
||||
* Clears all sinks from the default log domain.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Sets the max default log level. The default
|
||||
* max leven is LVL_FATAL. All log domains
|
||||
* will start with this default max log range
|
||||
*
|
||||
* @param max_level max log level
|
||||
*/
|
||||
static void max_default_log_level(log_level max_level);
|
||||
|
||||
/**
|
||||
* Returns the default max log level
|
||||
*
|
||||
* @return The max log level
|
||||
*/
|
||||
static log_level max_default_log_level();
|
||||
|
||||
/**
|
||||
* Sets the default min log level. The default
|
||||
* min leven is LVL_INFO. All log domains
|
||||
* will start with this default max log range
|
||||
*
|
||||
* @param min_level min log level
|
||||
*/
|
||||
static void min_default_log_level(log_level min_level);
|
||||
|
||||
/**
|
||||
* Returns the default min log level
|
||||
*
|
||||
* @return The min log level
|
||||
*/
|
||||
static log_level min_default_log_level();
|
||||
|
||||
/// @cond MATADOR_DEV
|
||||
std::shared_ptr<log_domain> find_domain(const std::string &name);
|
||||
void log_default(log_level lvl, const std::string &source, const char *message) const;
|
||||
/// @endcond
|
||||
|
||||
protected:
|
||||
/// @cond MATADOR_DEV
|
||||
log_manager()
|
||||
{
|
||||
default_log_domain_ = log_domain_map_.insert(std::make_pair("default", std::make_shared<log_domain>("default", default_log_level_range_))).first->second;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
private:
|
||||
std::shared_ptr<log_domain> acquire_domain(const std::string &name);
|
||||
|
||||
private:
|
||||
friend class utils::singleton<log_manager>;
|
||||
|
||||
std::shared_ptr<log_domain> default_log_domain_;
|
||||
|
||||
std::map<std::string, std::shared_ptr<log_domain>> log_domain_map_;
|
||||
|
||||
static log_level_range default_log_level_range_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Shortcut to create a file log sink
|
||||
* with the given path. If the path doesn't
|
||||
* exist, it is created.
|
||||
*
|
||||
* @param logfile Path to the logfile
|
||||
* @return A shared_ptr to the file_sink
|
||||
*/
|
||||
std::shared_ptr<file_sink> create_file_sink(const std::string &logfile);
|
||||
|
||||
/**
|
||||
* Shortcut to create a stderr log sink.
|
||||
*
|
||||
* @return A shared_ptr to the stderr_sink
|
||||
*/
|
||||
std::shared_ptr<stderr_sink> create_stderr_sink();
|
||||
|
||||
/**
|
||||
* Shortcut to create a stdout log sink.
|
||||
*
|
||||
* @return A shared_ptr to the stdout_sink
|
||||
*/
|
||||
std::shared_ptr<stdout_sink> create_stdout_sink();
|
||||
|
||||
/**
|
||||
* Shortcut to create a rotating file log sink
|
||||
* with the given path, max log files and max
|
||||
* log file size. If the path doesn't
|
||||
* exist, it is created.
|
||||
*
|
||||
* @param logfile Path to the log file
|
||||
* @param max_size Max log file size
|
||||
* @param file_count Max number of log files
|
||||
* @return A shared_ptr to the rotating_file_sink
|
||||
*/
|
||||
std::shared_ptr<rotating_file_sink> create_rotating_file_sink(const std::string &logfile, size_t max_size, size_t file_count);
|
||||
|
||||
/**
|
||||
* Sets the default min log level.
|
||||
*
|
||||
* @param min_lvl Default min log level
|
||||
*/
|
||||
void default_min_log_level(log_level min_lvl);
|
||||
|
||||
/**
|
||||
* Sets the default max log level.
|
||||
*
|
||||
* @param max_lvl Default max log level
|
||||
*/
|
||||
void default_max_log_level(log_level max_lvl);
|
||||
|
||||
/**
|
||||
* Sets the domain min log level for the
|
||||
* domain with the given name.
|
||||
*
|
||||
* @param name Log domain name
|
||||
* @param min_lvl Default min log level
|
||||
*/
|
||||
void domain_min_log_level(const std::string &name, log_level min_lvl);
|
||||
|
||||
/**
|
||||
* Sets the default max log level for the
|
||||
* domain with the given name.
|
||||
*
|
||||
* @param name Log domain name
|
||||
* @param max_lvl Default max log level
|
||||
*/
|
||||
void domain_max_log_level(const std::string &name, log_level max_lvl);
|
||||
|
||||
/**
|
||||
* Adds a log sink to the default log domain
|
||||
*
|
||||
* @param sink The log sink to add
|
||||
*/
|
||||
void add_log_sink(sink_ptr sink);
|
||||
|
||||
/**
|
||||
* Adds a log sink to the log domain
|
||||
* with the given name. If the domain
|
||||
* doesn't exist, it is created.
|
||||
*
|
||||
* @param sink The log sink to add
|
||||
* @param domain The log domain name to add
|
||||
*/
|
||||
void add_log_sink(sink_ptr sink, const std::string &domain);
|
||||
|
||||
/**
|
||||
* Removes all sinks from the
|
||||
* default domain
|
||||
*/
|
||||
void clear_all_log_sinks();
|
||||
|
||||
/**
|
||||
* Removes all sinks from the log domain
|
||||
* with the given domain name
|
||||
*
|
||||
* @param domain Domain name to clear all sinks
|
||||
*/
|
||||
void clear_all_log_sinks(const std::string &domain);
|
||||
|
||||
/**
|
||||
* Creates a logger with the given source name
|
||||
* connected to the default log domain.
|
||||
*
|
||||
* @param source The name of the source
|
||||
* @return The logger instance
|
||||
*/
|
||||
logger create_logger(std::string source);
|
||||
|
||||
/**
|
||||
* Creates a logger with the given source name
|
||||
* connected to the log domain with the given
|
||||
* name. If the domain doesn't exist, it is created
|
||||
*
|
||||
* @param source The name of the source
|
||||
* @param domain The name of the log domain
|
||||
* @return The logger instance
|
||||
*/
|
||||
logger create_logger(std::string source, const std::string &domain);
|
||||
|
||||
/**
|
||||
* Logs the given message for the given source and log level
|
||||
* to the default log domain.
|
||||
*
|
||||
* @param lvl Log level
|
||||
* @param source Source of the log message
|
||||
* @param message Message to log
|
||||
*/
|
||||
void log_default(log_level lvl, const std::string &source, const char *message);
|
||||
|
||||
/**
|
||||
* Log the given message with source and log level
|
||||
* to the default domain. The message will be created
|
||||
* from the what-argument and the args while the preprocessed
|
||||
* message uses the printf style to add the arguments.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments
|
||||
* @param lvl Log level
|
||||
* @param source Source of the log message
|
||||
* @param what The printf style message
|
||||
* @param args The arguments for the message
|
||||
*/
|
||||
template<typename... ARGS>
|
||||
void log(const log_level lvl, const std::string &source, const char *what, ARGS const &... args)
|
||||
{
|
||||
char message_buffer[16384];
|
||||
|
||||
#ifdef _MSC_VER
|
||||
sprintf_s(message_buffer, 912, what, args...);
|
||||
#else
|
||||
sprintf(message_buffer, what, args...);
|
||||
#endif
|
||||
|
||||
log_default(lvl, source, message_buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //MATADOR_LOG_MANAGER_HPP
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef MATADOR_LOG_SINK_HPP
|
||||
#define MATADOR_LOG_SINK_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace matador::logger {
|
||||
|
||||
/**
|
||||
* @brief Base class for all log sinks
|
||||
*
|
||||
* This class must be the base class for all
|
||||
* log sinks and provides their interface
|
||||
*
|
||||
* The main interface is the write() interface
|
||||
* defining how the log message is written.
|
||||
*
|
||||
* The close() interface defines a way to close
|
||||
* the concrete log sink
|
||||
*/
|
||||
class log_sink
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destroys the log sink
|
||||
*/
|
||||
virtual ~log_sink() = default;
|
||||
|
||||
/**
|
||||
* Writes the given log message with the given size
|
||||
* to the concrete sink
|
||||
*
|
||||
* @param message The message to log
|
||||
* @param size The size of the message
|
||||
*/
|
||||
virtual void write(const char *message, std::size_t size) = 0;
|
||||
|
||||
/**
|
||||
* Closes the log sink if necessary.
|
||||
*/
|
||||
virtual void close() = 0;
|
||||
};
|
||||
|
||||
using sink_ptr = std::shared_ptr<log_sink>; /**< Shortcut to the log sink shared pointer */
|
||||
|
||||
}
|
||||
|
||||
#endif //MATADOR_LOG_SINK_HPP
|
||||
@@ -0,0 +1,267 @@
|
||||
#ifndef MATADOR_LOGGER_HPP
|
||||
#define MATADOR_LOGGER_HPP
|
||||
|
||||
#include "matador/logger/log_level.hpp"
|
||||
#include "matador/logger/log_domain.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace matador::logger {
|
||||
|
||||
/**
|
||||
* @brief logger to write log messages to log domains
|
||||
*
|
||||
* This class is used to write log messages to a connected
|
||||
* log domain (@sa log_domain).
|
||||
* Everywhere a logger is needed, it can be instantiated with
|
||||
* @code
|
||||
* matador::create_logger(source name)
|
||||
* @endcode
|
||||
*
|
||||
* The interface provides methods to log to each relevant
|
||||
* log level (@sa log_level)
|
||||
*
|
||||
* The message format syntax is like the printf syntax.
|
||||
* If the message string contains placeholder (beginning with %)
|
||||
* an argument is expected to be part of the argument list of the
|
||||
* calling method.
|
||||
*
|
||||
* All log messages are written through the internal
|
||||
* log_domain object to the sinks.
|
||||
*/
|
||||
class logger final
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create a logger with a given source name connected
|
||||
* to the given log_domain
|
||||
*
|
||||
* @param source The name of the source
|
||||
* @param log_domain The log_domain containing the log sinks
|
||||
*/
|
||||
logger(std::string source, std::shared_ptr<log_domain> log_domain);
|
||||
|
||||
logger(const logger& l) = delete;
|
||||
logger(logger&& l) noexcept;
|
||||
logger& operator=(const logger& l) = delete;
|
||||
logger& operator=(logger&& l) noexcept;
|
||||
|
||||
/**
|
||||
* Writes a log message string with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void fatal(const std::string &what, ARGS const &... args) { fatal(what.c_str(), args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message represented by a char pointer with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void fatal(const char *what, ARGS const &... args) { log(log_level::LVL_FATAL, what, args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message string with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void error(const std::string &what, ARGS const &... args) { error(what.c_str(), args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message represented by a char pointer with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void error(const char *what, ARGS const &... args) { log(log_level::LVL_ERROR, what, args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message string with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void warn(const std::string &what, ARGS const &... args) { warn(what.c_str(), args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message represented by a char pointer with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void warn(const char *what, ARGS const &... args) { log(log_level::LVL_WARN, what, args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message string with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void info(const std::string &what, ARGS const &... args) { info(what.c_str(), args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message represented by a char pointer with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void info(const char *what, ARGS const &... args) { log(log_level::LVL_INFO, what, args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message string with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void debug(const std::string &what, ARGS const &... args) { debug(what.c_str(), args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message represented by a char pointer with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void debug(const char *what, ARGS const &... args) { log(log_level::LVL_DEBUG, what, args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message string with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void trace(const std::string &what, ARGS const &... args) { trace(what.c_str(), args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message represented by a char pointer with log level LVL_FATAL
|
||||
* to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void trace(const char *what, ARGS const &... args) { log(log_level::LVL_TRACE, what, args...); }
|
||||
|
||||
/**
|
||||
* Writes a log message represented by a char pointer
|
||||
* with the given log level to the connected log_domain.
|
||||
*
|
||||
* @tparam ARGS Type of the arguments to be replaced for the message placeholder
|
||||
* @param lvl The log level
|
||||
* @param what The message to log
|
||||
* @param args The arguments to be replaced in the message
|
||||
*/
|
||||
template<typename ... ARGS>
|
||||
void log(log_level lvl, const char *what, ARGS const &... args);
|
||||
|
||||
/**
|
||||
* Writes a log message represented by a char pointer
|
||||
* with the given log level to the connected log_domain.
|
||||
*
|
||||
* @param lvl The log level
|
||||
* @param what The message to log
|
||||
*/
|
||||
void log(log_level lvl, const char *what) const;
|
||||
|
||||
/**
|
||||
* Returns the name of the source the logger represents
|
||||
*
|
||||
* @return Represented log source name
|
||||
*/
|
||||
const std::string& source() const;
|
||||
|
||||
/**
|
||||
* Returns the name of the connected log domain
|
||||
*
|
||||
* @return The name of the log domain
|
||||
*/
|
||||
std::string domain() const;
|
||||
|
||||
private:
|
||||
std::string source_;
|
||||
std::shared_ptr<log_domain> logger_domain_;
|
||||
};
|
||||
|
||||
template<typename... ARGS>
|
||||
void logger::log(log_level lvl, const char *what, ARGS const &... args)
|
||||
{
|
||||
char message_buffer[16384];
|
||||
|
||||
#ifdef _MSC_VER
|
||||
sprintf_s(message_buffer, 16384, what, args...);
|
||||
#else
|
||||
sprintf(message_buffer, what, args...);
|
||||
#endif
|
||||
|
||||
logger_domain_->log(lvl, source_, message_buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
template<typename T>
|
||||
decltype(auto) myForward(T&& t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
template<>
|
||||
decltype(auto) myForward(std::string& t)
|
||||
{
|
||||
return t.c_str();
|
||||
}
|
||||
|
||||
template<>
|
||||
decltype(auto) myForward(std::string&& t)
|
||||
{
|
||||
return t.c_str();
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
static void log(const char* pszFmt, Args&&... args)
|
||||
{
|
||||
doSomething(pszFmt, myForward<Args>(std::forward<Args>(args))...);
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
#endif //MATADOR_LOGGER_HPP
|
||||
@@ -0,0 +1,82 @@
|
||||
#ifndef MATADOR_ROTATING_FILE_SINK_HPP
|
||||
#define MATADOR_ROTATING_FILE_SINK_HPP
|
||||
|
||||
#include "matador/logger/log_sink.hpp"
|
||||
#include "matador/utils/file.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace matador::logger {
|
||||
|
||||
/**
|
||||
* @brief A rotating log file sink
|
||||
*
|
||||
* This log sink provides a possibility to
|
||||
* rotate several log files if the current
|
||||
* log file reaches the maximum size.
|
||||
*
|
||||
* The user can define the maximum number of log files
|
||||
* and the maximum size of the current log file
|
||||
*
|
||||
* The name of the current log file is defined within the
|
||||
* given logfile path. Each rotated (moved) log file gets
|
||||
* an incremented number extension right before the
|
||||
* file extension, e.g.:
|
||||
*
|
||||
* Log file name is 'log.txt' the first rotated log file
|
||||
* is named 'log-1.txt' and so on until the maximum
|
||||
* number of log files is reached. Then it starts from
|
||||
* the beginning.
|
||||
* Keep in mind that the log file to which is currently
|
||||
* written to is always named like the file name
|
||||
* given within the path.
|
||||
*/
|
||||
class rotating_file_sink final : public log_sink
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a rotating log file sink within the given path
|
||||
* with the given maximum number of rotating log files where
|
||||
* each file size is never greater than the given max file
|
||||
* size.
|
||||
*
|
||||
* @param path Path of the log file
|
||||
* @param max_size Max log file size
|
||||
* @param file_count Max log file count
|
||||
*/
|
||||
rotating_file_sink(const std::string& path, size_t max_size, size_t file_count);
|
||||
|
||||
/**
|
||||
* Write the message to the current log file. If the
|
||||
* actual size exceeds the file size limit, the log files
|
||||
* are rotated.
|
||||
*
|
||||
* @param message Message to write
|
||||
* @param size The size of the log message
|
||||
*/
|
||||
void write(const char *message, size_t size) override;
|
||||
|
||||
/**
|
||||
* Close all open log files
|
||||
*/
|
||||
void close() override;
|
||||
|
||||
private:
|
||||
std::string calculate_filename(size_t fileno);
|
||||
|
||||
void rotate();
|
||||
void prepare(const std::string &path);
|
||||
|
||||
private:
|
||||
file logfile_;
|
||||
std::string path_;
|
||||
std::string base_path_;
|
||||
std::string extension_;
|
||||
size_t max_size_ = 0;
|
||||
size_t current_size_ = 0;
|
||||
size_t current_file_no_ = 0;
|
||||
size_t file_count_ = 0;
|
||||
};
|
||||
|
||||
}
|
||||
#endif //MATADOR_ROTATING_FILE_SINK_HPP
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef SCHEMA_HPP
|
||||
#define SCHEMA_HPP
|
||||
|
||||
#include "matador/logger/log_manager.hpp"
|
||||
#include "matador/object/many_to_many_relation.hpp"
|
||||
#include "matador/object/primary_key_resolver.hpp"
|
||||
#include "matador/object/error_code.hpp"
|
||||
@@ -10,6 +11,8 @@
|
||||
#include "matador/utils/result.hpp"
|
||||
#include "matador/utils/error.hpp"
|
||||
|
||||
#include "matador/logger/logger.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
@@ -77,9 +80,7 @@ public:
|
||||
static void on_attribute(const char * /*id*/, std::optional<AttributeType> &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||
|
||||
template<class ForeignPointerType>
|
||||
void on_belongs_to(const char * /*id*/, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/) {
|
||||
on_foreign_key<ForeignPointerType>();
|
||||
}
|
||||
void on_belongs_to(const char *id, ForeignPointerType &obj, const utils::foreign_attributes &attr);
|
||||
template<class ForeignPointerType>
|
||||
void on_has_one(const char * /*id*/, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/);
|
||||
|
||||
@@ -93,19 +94,16 @@ public:
|
||||
template<class ContainerType>
|
||||
void on_has_many_to_many(const char *id, ContainerType &collection, const utils::foreign_attributes &attr);
|
||||
|
||||
private:
|
||||
template<class ForeignPointerType>
|
||||
void on_foreign_key();
|
||||
|
||||
private:
|
||||
explicit relation_completer(schema_node& node)
|
||||
: node_(node)
|
||||
, schema_(node.schema_){}
|
||||
|
||||
, schema_(node.schema_)
|
||||
, log_(logger::create_logger("relation_completer")) {}
|
||||
|
||||
private:
|
||||
schema_node &node_;
|
||||
schema& schema_;
|
||||
logger::logger log_;
|
||||
};
|
||||
|
||||
|
||||
@@ -239,6 +237,7 @@ private:
|
||||
t_node_map node_map_;
|
||||
t_type_index_node_map type_index_node_map_;
|
||||
t_type_index_node_map expected_node_map_;
|
||||
logger::logger log_;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
@@ -250,7 +249,7 @@ void relation_completer<Type>::on_has_many( const char *id, CollectionType&, con
|
||||
return new many_to_many_relation<value_type, Type>(join_column, "id");
|
||||
});
|
||||
|
||||
schema_.attach_node(node, typeid(many_to_many_relation<value_type, Type>));
|
||||
// schema_.attach_node(node, typeid(many_to_many_relation<value_type, Type>));
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
@@ -262,7 +261,7 @@ void relation_completer<Type>::on_has_many( const char *id, CollectionType&, con
|
||||
return new many_to_many_relation<value_type, Type>(join_column, "value");
|
||||
});
|
||||
|
||||
const auto result = schema_.attach<many_to_many_relation<value_type, Type>>(id);
|
||||
const auto result = schema_.attach<many_to_relation<Type, value_type>>(id);
|
||||
if (!result) {
|
||||
// Todo: throw internal exception
|
||||
}
|
||||
@@ -280,15 +279,23 @@ void relation_completer<Type>::on_has_many_to_many( const char *id, CollectionTy
|
||||
return new many_to_many_relation<typename CollectionType::value_type, Type>(join_column, inverse_join_column);
|
||||
};
|
||||
|
||||
auto node = schema_node::make_relation_node<relation_type>(schema_, id);
|
||||
// auto node = schema_node::make_relation_node<relation_type>(schema_, id);
|
||||
|
||||
schema_.attach_node(node, typeid(relation_type));
|
||||
// schema_.attach_node(node, typeid(relation_type));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
template<class ContainerType>
|
||||
void relation_completer<Type>::on_has_many_to_many( const char *id, ContainerType &collection, const utils::foreign_attributes &attr ) {
|
||||
auto result = schema_.find_node(id);
|
||||
if (!result) {
|
||||
using relation_type = many_to_many_relation<typename ContainerType::value_type, Type>;
|
||||
// auto creator = [attr] {
|
||||
// return new relation_type(attr.join_column, attr.inverse_join_column);
|
||||
// };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
@@ -311,6 +318,11 @@ void relation_completer<Type>::on_has_one(const char * id, ForeignPointerType &/
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
template<class ForeignPointerType>
|
||||
void relation_completer<Type>::on_belongs_to( const char* id, ForeignPointerType& obj, const utils::foreign_attributes& attr ) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@ public:
|
||||
static std::shared_ptr<schema_node> make_relation_node(object::schema& tree, const std::string& name, CreatorFunc &&creator) {
|
||||
auto node = std::shared_ptr<schema_node>(new schema_node(tree, name));
|
||||
|
||||
auto info = std::make_unique<object_info<Type>>(
|
||||
node,
|
||||
object_definition{attribute_definition_generator::generate<Type>(tree)}
|
||||
);
|
||||
node->info_ = std::move(info);
|
||||
// auto info = std::make_unique<object_info<Type>>(
|
||||
// node,
|
||||
// object_definition{attribute_definition_generator::generate<Type>(tree)}
|
||||
// );
|
||||
// node->info_ = std::move(info);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
#ifndef MATADOR_FILE_HPP
|
||||
#define MATADOR_FILE_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace matador {
|
||||
|
||||
/**
|
||||
* File class representing file stream
|
||||
*
|
||||
* The open methods uses internally fopen() thus
|
||||
* the open modes are the same:
|
||||
*
|
||||
* "r" read: Open file for input operations. The file must exist.
|
||||
* "w" write: Create an empty file for output operations. If a
|
||||
* file with the same name already exists, its contents are discarded and
|
||||
* the file is treated as a new empty file.
|
||||
* "a" append: Open file for output at the end of a file. Output operations
|
||||
* always write data at the end of the file, expanding it. Repositioning
|
||||
* operations (fseek, fsetpos, rewind) are ignored. The file is created
|
||||
* if it does not exist.
|
||||
* "r+" read/update: Open a file for update (both for input and output).
|
||||
* The file must exist.
|
||||
* "w+" write/update: Create an empty file and open it for update (both for input
|
||||
* and output). If a file with the same name already exists its contents
|
||||
* are discarded and the file is treated as a new empty file.
|
||||
* "a+" append/update: Open a file for update (both for input and output) with
|
||||
* all output operations writing data at the end of the file. Repositioning
|
||||
* operations (fseek, fsetpos, rewind) affects the next input operations, but
|
||||
* output operations move the position back to the end of file. The file is
|
||||
* created if it does not exist.
|
||||
*/
|
||||
class file final
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates an uninitialized file.
|
||||
*/
|
||||
file() = default;
|
||||
|
||||
/**
|
||||
* Creates and open a file stream.
|
||||
*
|
||||
* @param path Path of the file to create
|
||||
* @param mode The file mode to open
|
||||
*/
|
||||
file(const char *path, const char *mode);
|
||||
|
||||
/**
|
||||
* Creates and open a file stream.
|
||||
*
|
||||
* @param path Path of the file to create
|
||||
* @param mode The file mode to open
|
||||
*/
|
||||
file(const std::string &path, const char *mode);
|
||||
file(const file&) = delete;
|
||||
file operator=(const file&) = delete;
|
||||
~file();
|
||||
|
||||
/**
|
||||
* Opens a file stream with the given path.
|
||||
* If the file is already open it is closed
|
||||
*
|
||||
* @param path Path of the file to create
|
||||
* @param mode The file mode to open
|
||||
*/
|
||||
void open(const char *path, const char *mode);
|
||||
|
||||
/**
|
||||
* Opens a file stream with the given path.
|
||||
* If the file is already open it is closed
|
||||
*
|
||||
* @param path Path of the file to create
|
||||
* @param mode The file mode to open
|
||||
*/
|
||||
void open(const std::string &path, const char *mode);
|
||||
|
||||
/**
|
||||
* Closes the file stream if it is open
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Returns the size of the file
|
||||
*
|
||||
* @return The size of the file
|
||||
*/
|
||||
[[nodiscard]] size_t size() const;
|
||||
|
||||
/**
|
||||
* Returns the path to the file
|
||||
*
|
||||
* @return The path to the file
|
||||
*/
|
||||
[[nodiscard]] std::string path() const;
|
||||
|
||||
/**
|
||||
* Returns the internal file stream pointer
|
||||
*
|
||||
* @return The internal file stream pointer
|
||||
*/
|
||||
[[nodiscard]] FILE* stream() const;
|
||||
|
||||
/**
|
||||
* Returns true if file is open.
|
||||
*
|
||||
* @return True if file is open
|
||||
*/
|
||||
[[nodiscard]] bool is_open() const;
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
FILE *stream_ = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reads a given file as text and
|
||||
* returns its content as string
|
||||
*
|
||||
* @param f File to read in
|
||||
* @return The content of the file as string
|
||||
*/
|
||||
std::string read_as_text(const file &f);
|
||||
|
||||
}
|
||||
#endif //MATADOR_FILE_HPP
|
||||
@@ -18,7 +18,7 @@ template < typename T >
|
||||
class singleton
|
||||
{
|
||||
public:
|
||||
typedef T value_type; /**< Shortcut for the singletons type */
|
||||
typedef T value_type; /**< Shortcut for the singleton type */
|
||||
|
||||
/**
|
||||
* @brief Access the instance of the class.
|
||||
|
||||
Reference in New Issue
Block a user