Procházet zdrojové kódy

* Removed singleton implementation for manager

Users can now create own instances of the manager. To not break the old interface,
the single global instance is still created by the logging framework if necessary.
If a custom intance is created this one will be used.
master
bergmann před 6 roky
rodič
revize
b02440d1c1
10 změnil soubory, kde provedl 179 přidání a 73 odebrání
  1. +3
    -0
      include/cpplogging/manager.h
  2. +10
    -3
      include/cpplogging/manager/consumer/consumer.h
  3. +6
    -6
      include/cpplogging/manager/consumer/consumer_stream.h
  4. +44
    -16
      include/cpplogging/manager/manager.h
  5. +17
    -0
      include/cpplogging/manager/manager.inl
  6. +1
    -1
      src/cpplogging/interface/logger.cpp
  7. +5
    -2
      src/cpplogging/manager/consumer/consumer.cpp
  8. +5
    -5
      src/cpplogging/manager/consumer/consumer_stream.cpp
  9. +68
    -21
      src/cpplogging/manager/manager.cpp
  10. +20
    -19
      test/cpplogging/cpplogging_tests.cpp

+ 3
- 0
include/cpplogging/manager.h Zobrazit soubor

@@ -5,3 +5,6 @@
#include "manager/logger_impl.h" #include "manager/logger_impl.h"
#include "manager/matcher.h" #include "manager/matcher.h"
#include "manager/rule.h" #include "manager/rule.h"

#include "manager/manager.inl"
#include "manager/rule.inl"

+ 10
- 3
include/cpplogging/manager/consumer/consumer.h Zobrazit soubor

@@ -1,7 +1,8 @@
#pragma once #pragma once


#include <memory>
#include <set>
#include <vector> #include <vector>
#include <memory>
#include <iostream> #include <iostream>


#include <cpplogging/types.h> #include <cpplogging/types.h>
@@ -9,6 +10,8 @@
namespace cpplogging namespace cpplogging
{ {


struct manager;

/** /**
* @brief Class to consume log entries. * @brief Class to consume log entries.
*/ */
@@ -16,10 +19,14 @@ namespace cpplogging
{ {
private: private:
using format_type = std::vector<std::string>; using format_type = std::vector<std::string>;
using manager_set = std::set<manager*>;

friend manager;


protected: protected:
std::string _name; //!< name of the consumer std::string _name; //!< name of the consumer
format_type _format; //!< parsed logging format format_type _format; //!< parsed logging format
manager_set _manager; //!< Set of manager this consumer is assigned to.


public: public:
/** /**
@@ -54,8 +61,8 @@ namespace cpplogging
* @param[in] format Format to use for logging. * @param[in] format Format to use for logging.
*/ */
consumer( consumer(
const std::string& name,
const std::string& format = default_format());
const std::string& name,
const std::string& format = default_format());


/** /**
* @breif Destructor. * @breif Destructor.


+ 6
- 6
include/cpplogging/manager/consumer/consumer_stream.h Zobrazit soubor

@@ -30,9 +30,9 @@ namespace cpplogging
* @param[in] format Format to use for logging. * @param[in] format Format to use for logging.
*/ */
consumer_stream( consumer_stream(
const std::string& name,
std::ostream& stream,
const std::string& format = default_format());
const std::string& name,
std::ostream& stream,
const std::string& format = default_format());


/** /**
* @brief Constructor. * @brief Constructor.
@@ -42,9 +42,9 @@ namespace cpplogging
* @param[in] format Format to use for logging. * @param[in] format Format to use for logging.
*/ */
consumer_stream( consumer_stream(
const std::string& name,
stream_ptr_u&& stream,
const std::string& format = default_format());
const std::string& name,
stream_ptr_u&& stream,
const std::string& format = default_format());


/** /**
* @brief Consume a log entry. * @brief Consume a log entry.


+ 44
- 16
include/cpplogging/manager/manager.h Zobrazit soubor

@@ -81,13 +81,23 @@ namespace cpplogging
using consumer_set = std::set<consumer_wrapper>; using consumer_set = std::set<consumer_wrapper>;


private: private:
static std::mutex _mutex; //!< mutex to protect the engine
static logger_impl _default; //!< default logger
static logger_map _logger; //!< normal logger instances
static rule_list _rules; //!< rules to combine loggers with consumers
static consumer_set _consumer; //!< consumers registered
std::recursive_mutex _mutex; //!< mutex to protect the manager
logger_impl _default; //!< default logger
logger_map _logger; //!< normal logger instances
rule_list _rules; //!< rules to combine loggers with consumers
consumer_set _consumer; //!< consumers registered


public: public:
/**
* @brief Constructor.
*/
inline manager();

/**
* @brief Destructor.
*/
inline ~manager();

/** /**
* @brief Get the instance of the logger with the requested name. * @brief Get the instance of the logger with the requested name.
* *
@@ -95,37 +105,37 @@ namespace cpplogging
* *
* @return Instance of the logger with the requested name. * @return Instance of the logger with the requested name.
*/ */
static logger& get_logger(const std::string& name = "");
logger& get_logger(const std::string& name = "");


/** /**
* @brief Register a new consumer in the logging framework. * @brief Register a new consumer in the logging framework.
* *
* @param[in] consumer Reference of the consumer to register. * @param[in] consumer Reference of the consumer to register.
*/ */
static void register_consumer(consumer& consumer);
void register_consumer(consumer& consumer);


/** /**
* @brief Register a new consumer in the logging framework. * @brief Register a new consumer in the logging framework.
* *
* @param[in] consumer Consumer to register (the logging framework will own the consumer). * @param[in] consumer Consumer to register (the logging framework will own the consumer).
* *
* @return Pointer to the consumer.
* @return Reference to the consumer.
*/ */
static const consumer* register_consumer(consumer_ptr_u&& consumer);
const consumer& register_consumer(consumer_ptr_u&& consumer);


/** /**
* @brief Unregister a consumer from the logging framework. * @brief Unregister a consumer from the logging framework.
* *
* @param[in] consumer Reference of the consumer to unregister * @param[in] consumer Reference of the consumer to unregister
*/ */
static void unregister_consumer(consumer& consumer);
void unregister_consumer(consumer& consumer);


/** /**
* @brief Unregister a consumer from the logging framework. * @brief Unregister a consumer from the logging framework.
* *
* @param[in] consumer Consumer to unregister from the framework. * @param[in] consumer Consumer to unregister from the framework.
*/ */
static void unregister_consumer(consumer* consumer);
void unregister_consumer(consumer* consumer);


/** /**
* @brief Define a new rule in the logging framework. * @brief Define a new rule in the logging framework.
@@ -137,7 +147,7 @@ namespace cpplogging
* *
* @return Return the handle to the rule (for removing). * @return Return the handle to the rule (for removing).
*/ */
static rule_handle define_rule(
rule_handle define_rule(
matcher_ptr_u&& logger_matcher, matcher_ptr_u&& logger_matcher,
matcher_ptr_u&& consumer_matcher, matcher_ptr_u&& consumer_matcher,
log_level min_level = log_level::debug, log_level min_level = log_level::debug,
@@ -148,12 +158,12 @@ namespace cpplogging
* *
* @param[in] handle Handle of the rule to remove. * @param[in] handle Handle of the rule to remove.
*/ */
static void undefine_rule(rule_handle handle);
void undefine_rule(rule_handle handle);


/** /**
* @brief Remove all consumers, rules, matchers and loggers. * @brief Remove all consumers, rules, matchers and loggers.
*/ */
static void reset();
void reset();


#ifdef CPPLOGGING_HAS_LOAD_CONFIG #ifdef CPPLOGGING_HAS_LOAD_CONFIG
/** /**
@@ -161,14 +171,32 @@ namespace cpplogging
* *
* @param[in] filename Filename to load configuration from. * @param[in] filename Filename to load configuration from.
*/ */
static void load(const std::string& filename);
void load(const std::string& filename);
#endif #endif


private: private:
/** /**
* @brief Initialize the given logger instance. * @brief Initialize the given logger instance.
*/ */
static logger_impl& init_logger(logger_impl& logger);
logger_impl& init_logger(logger_impl& logger);

private:
static manager* _instance; //!< First created manager instance.
static std::unique_ptr<manager> _singleton; //!< Default manager instance.

public:
/**
* @brief Get the global manager instance
*
* This method will return the first created manager. If no manager is created yet,
* a new global manager is created.
*/
static manager& instance();

/**
* @brief Create the default manager writing all output to stdout and stderr.
*/
static std::unique_ptr<manager> default_();
}; };


} }

+ 17
- 0
include/cpplogging/manager/manager.inl Zobrazit soubor

@@ -41,4 +41,21 @@ namespace cpplogging
::operator*() const ::operator*() const
{ return _consumer; } { return _consumer; }


/* manager */

manager::manager()
: _default("")
{
init_logger(_default);
if (_instance == nullptr)
_instance = this;
}

manager::~manager()
{
reset();
if (_instance == this)
_instance = nullptr;
}

} }

+ 1
- 1
src/cpplogging/interface/logger.cpp Zobrazit soubor

@@ -4,4 +4,4 @@
using namespace ::cpplogging; using namespace ::cpplogging;


logger& logger::get(const std::string& name) logger& logger::get(const std::string& name)
{ return manager::get_logger(name); }
{ return manager::instance().get_logger(name); }

+ 5
- 2
src/cpplogging/manager/consumer/consumer.cpp Zobrazit soubor

@@ -3,12 +3,15 @@


using namespace ::cpplogging; using namespace ::cpplogging;


consumer::consumer(const std::string& name, const std::string& format)
consumer::consumer(
const std::string& name,
const std::string& format)
: _name (name) : _name (name)
, _format (parse_format(format)) , _format (parse_format(format))
{ } { }


consumer::~consumer() consumer::~consumer()
{ {
manager::unregister_consumer(this);
for (auto& mrg : _manager)
mrg->unregister_consumer(this);
} }

+ 5
- 5
src/cpplogging/manager/consumer/consumer_stream.cpp Zobrazit soubor

@@ -7,8 +7,8 @@
using namespace ::cpplogging; using namespace ::cpplogging;


consumer_stream::consumer_stream( consumer_stream::consumer_stream(
const std::string& name,
std::ostream& stream,
const std::string& name,
std::ostream& stream,
const std::string& format) const std::string& format)
: consumer (name, format) : consumer (name, format)
, _stream (stream) , _stream (stream)
@@ -16,9 +16,9 @@ consumer_stream::consumer_stream(
{ } { }


consumer_stream::consumer_stream( consumer_stream::consumer_stream(
const std::string& name,
stream_ptr_u&& stream,
const std::string& format)
const std::string& name,
stream_ptr_u&& stream,
const std::string& format)
: consumer (name, format) : consumer (name, format)
, _stream (*stream) , _stream (*stream)
, _storage (std::move(stream)) , _storage (std::move(stream))


+ 68
- 21
src/cpplogging/manager/manager.cpp Zobrazit soubor

@@ -13,15 +13,12 @@


using namespace ::cpplogging; using namespace ::cpplogging;


std::mutex manager::_mutex;
logger_impl manager::_default("");
manager::logger_map manager::_logger;
manager::rule_list manager::_rules;
manager::consumer_set manager::_consumer;
manager* manager::_instance;
std::unique_ptr<manager> manager::_singleton;


logger& manager::get_logger(const std::string& name) logger& manager::get_logger(const std::string& name)
{ {
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);
if (name.empty()) if (name.empty())
return _default; return _default;


@@ -29,7 +26,7 @@ logger& manager::get_logger(const std::string& name)
if (it == _logger.end()) if (it == _logger.end())
{ {
it = _logger.emplace_hint(it, name, std::make_unique<logger_impl>(name)); it = _logger.emplace_hint(it, name, std::make_unique<logger_impl>(name));
manager::init_logger(*it->second);
init_logger(*it->second);
} }


return *it->second; return *it->second;
@@ -37,9 +34,10 @@ logger& manager::get_logger(const std::string& name)


void manager::register_consumer(consumer& consumer) void manager::register_consumer(consumer& consumer)
{ {
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);
auto it = _consumer.emplace(consumer).first; auto it = _consumer.emplace(consumer).first;
auto& c = **it;
auto& c = const_cast<struct consumer&>(**it);
c._manager.emplace(this);
for (auto& rule : _rules) for (auto& rule : _rules)
{ {
if (rule.consumer_matcher->match(c)) if (rule.consumer_matcher->match(c))
@@ -47,33 +45,36 @@ void manager::register_consumer(consumer& consumer)
} }
} }


const consumer* manager::register_consumer(consumer_ptr_u&& consumer)
const consumer& manager::register_consumer(consumer_ptr_u&& consumer)
{ {
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);
auto it = _consumer.emplace(std::move(consumer)).first; auto it = _consumer.emplace(std::move(consumer)).first;
auto& ret = **it;
auto& c = const_cast<struct consumer&>(**it);
c._manager.emplace(this);
for (auto& rule : _rules) for (auto& rule : _rules)
{ {
if (rule.consumer_matcher->match(ret))
rule.add_consumer(ret);
if (rule.consumer_matcher->match(c))
rule.add_consumer(c);
} }
return &ret;
return c;
} }


void manager::unregister_consumer(consumer& consumer) void manager::unregister_consumer(consumer& consumer)
{ {
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);
consumer._manager.erase(this);
unregister_consumer(&consumer); unregister_consumer(&consumer);
} }


void manager::unregister_consumer(consumer* consumer) void manager::unregister_consumer(consumer* consumer)
{ {
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);
auto it = _consumer.find(consumer_wrapper(*consumer)); auto it = _consumer.find(consumer_wrapper(*consumer));
if (it == _consumer.end()) if (it == _consumer.end())
return; return;


auto& c = **it;
auto& c = const_cast<struct consumer&>(**it);
c._manager.erase(this);
for (auto& rule : _rules) for (auto& rule : _rules)
rule.remove_consumer(c); rule.remove_consumer(c);
} }
@@ -84,7 +85,7 @@ rule_handle manager::define_rule(
log_level min_level, log_level min_level,
log_level max_level) log_level max_level)
{ {
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);


/* create rule */ /* create rule */
_rules.emplace_back(std::move(logger_matcher), std::move(consumer_matcher), min_level, max_level); _rules.emplace_back(std::move(logger_matcher), std::move(consumer_matcher), min_level, max_level);
@@ -112,7 +113,7 @@ rule_handle manager::define_rule(


void manager::undefine_rule(rule_handle handle) void manager::undefine_rule(rule_handle handle)
{ {
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);


/* find the rule in the list */ /* find the rule in the list */
auto r = static_cast<rule*>(handle); auto r = static_cast<rule*>(handle);
@@ -133,7 +134,11 @@ void manager::undefine_rule(rule_handle handle)


void manager::reset() void manager::reset()
{ {
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);

for (auto it = _consumer.rbegin(); it != _consumer.rend(); ++it)
unregister_consumer(const_cast<consumer&>(**it));

_logger.clear(); _logger.clear();
_rules.clear(); _rules.clear();
_consumer.clear(); _consumer.clear();
@@ -323,3 +328,45 @@ logger_impl& manager::init_logger(logger_impl& logger)
} }
return logger; return logger;
} }

manager& manager::instance()
{
if (!_instance)
_singleton.reset(new manager());
return *_instance;
}

std::unique_ptr<manager> manager::default_()
{
std::unique_ptr<manager> m(new manager());

/* consumers */
m->register_consumer(
std::make_unique<consumer_stream>("cout", std::cout,
"$n[${runtime:-016.6f}] "
"${level:5S} "
"${name} ${sender_type}(0x${sender:-016x})@0x${thread:-016x} "
"${filename}:${line}$n"
"${message}"));
m->register_consumer(
std::make_unique<consumer_stream>("cerr", std::cerr,
"$n[${runtime:-016.6f}] "
"${level:5S} "
"${sender_type}(0x${sender:-016x})@0x${thread:-016x} "
"${filename}:${line}$n"
"${message}"));

/* log rules */
m->define_rule(
std::make_unique<matcher_all>(),
std::make_unique<matcher_regex>("^cout$"),
log_level::debug,
log_level::warn);
m->define_rule(
std::make_unique<matcher_all>(),
std::make_unique<matcher_regex>("^cerr$"),
log_level::error,
log_level::error);

return m;
}

+ 20
- 19
test/cpplogging/cpplogging_tests.cpp Zobrazit soubor

@@ -6,21 +6,15 @@
using namespace ::testing; using namespace ::testing;
using namespace ::cpplogging; using namespace ::cpplogging;


struct LoggingReset
{
~LoggingReset()
{ manager::reset(); }
};

struct consumer_mock struct consumer_mock
: public consumer : public consumer
{ {
MOCK_CONST_METHOD1(write_entry, void (const log_entry_ptr_s& entry)); MOCK_CONST_METHOD1(write_entry, void (const log_entry_ptr_s& entry));


consumer_mock(const std::string& n) :
consumer_mock(manager& mngr, const std::string& n) :
consumer(n) consumer(n)
{ {
manager::register_consumer(*this);
mngr.register_consumer(*this);
} }
}; };


@@ -39,7 +33,8 @@ MATCHER_P5(MatchLogData, level, sender, thread, name, message, "")


TEST(LoggingTests, matcher_all) TEST(LoggingTests, matcher_all)
{ {
LoggingReset loggingReset;
manager mngr;

consumer_stream c0("TestConsumer1", std::cout); consumer_stream c0("TestConsumer1", std::cout);
consumer_stream c1("TestConsumer2", std::cout); consumer_stream c1("TestConsumer2", std::cout);


@@ -56,7 +51,8 @@ TEST(LoggingTests, matcher_all)


TEST(LoggingTests, matcher_default) TEST(LoggingTests, matcher_default)
{ {
LoggingReset loggingReset;
manager mngr;

consumer_stream c0("TestConsumer1", std::cout); consumer_stream c0("TestConsumer1", std::cout);
consumer_stream c1("TestConsumer2", std::cout); consumer_stream c1("TestConsumer2", std::cout);


@@ -73,7 +69,8 @@ TEST(LoggingTests, matcher_default)


TEST(LoggingTests, matcher_regex) TEST(LoggingTests, matcher_regex)
{ {
LoggingReset loggingReset;
manager mngr;

consumer_stream c0("TestConsumer1", std::cout); consumer_stream c0("TestConsumer1", std::cout);
consumer_stream c1("TestConsumer2", std::cout); consumer_stream c1("TestConsumer2", std::cout);


@@ -91,9 +88,10 @@ TEST(LoggingTests, matcher_regex)


TEST(LoggingTests, log_base) TEST(LoggingTests, log_base)
{ {
LoggingReset loggingReset;
StrictMock<consumer_mock> c0("consumer0");
StrictMock<consumer_mock> c1("Consumer1");
manager mngr;

StrictMock<consumer_mock> c0(mngr, "consumer0");
StrictMock<consumer_mock> c1(mngr, "Consumer1");


EXPECT_CALL(c0, write_entry(MatchLogData( EXPECT_CALL(c0, write_entry(MatchLogData(
log_level::info, log_level::info,
@@ -109,7 +107,7 @@ TEST(LoggingTests, log_base)
std::string("logger0"), std::string("logger0"),
std::string("test1 warn")))); std::string("test1 warn"))));


manager::define_rule(
mngr.define_rule(
std::make_unique<matcher_regex>("logger0"), std::make_unique<matcher_regex>("logger0"),
std::make_unique<matcher_regex>("consumer0"), std::make_unique<matcher_regex>("consumer0"),
log_level::info, log_level::info,
@@ -131,8 +129,9 @@ TEST(LoggingTests, log_base)


TEST(LoggingTests, log_inverted_regex) TEST(LoggingTests, log_inverted_regex)
{ {
LoggingReset loggingReset;
StrictMock<consumer_mock> c0("consumer0");
manager mngr;

StrictMock<consumer_mock> c0(mngr, "consumer0");


EXPECT_CALL(c0, write_entry(MatchLogData( EXPECT_CALL(c0, write_entry(MatchLogData(
log_level::debug, log_level::debug,
@@ -141,7 +140,7 @@ TEST(LoggingTests, log_inverted_regex)
std::string("logger2"), std::string("logger2"),
std::string("test2")))); std::string("test2"))));


manager::define_rule(
mngr.define_rule(
std::make_unique<matcher_regex>("^logger[0-1]+$", true), std::make_unique<matcher_regex>("^logger[0-1]+$", true),
std::make_unique<matcher_regex>("consumer0"), std::make_unique<matcher_regex>("consumer0"),
log_level::debug, log_level::debug,
@@ -159,6 +158,8 @@ TEST(LoggingTests, log_inverted_regex)
#ifdef CPPLOGGING_HAS_LOAD_CONFIG #ifdef CPPLOGGING_HAS_LOAD_CONFIG
TEST(LoggingTests, load) TEST(LoggingTests, load)
{ {
manager::load("./cpplogging/test_config.json");
manager mngr;

mngr.load("./cpplogging/test_config.json");
} }
#endif #endif

Načítá se…
Zrušit
Uložit