Bläddra i källkod

* 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 6 år sedan
förälder
incheckning
b02440d1c1
10 ändrade filer med 179 tillägg och 73 borttagningar
  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 Visa fil

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

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

+ 10
- 3
include/cpplogging/manager/consumer/consumer.h Visa fil

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

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

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

struct manager;

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

friend manager;

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

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

/**
* @breif Destructor.


+ 6
- 6
include/cpplogging/manager/consumer/consumer_stream.h Visa fil

@@ -30,9 +30,9 @@ namespace cpplogging
* @param[in] format Format to use for logging.
*/
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.
@@ -42,9 +42,9 @@ namespace cpplogging
* @param[in] format Format to use for logging.
*/
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.


+ 44
- 16
include/cpplogging/manager/manager.h Visa fil

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

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:
/**
* @brief Constructor.
*/
inline manager();

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

/**
* @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.
*/
static logger& get_logger(const std::string& name = "");
logger& get_logger(const std::string& name = "");

/**
* @brief Register a new consumer in the logging framework.
*
* @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.
*
* @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.
*
* @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.
*
* @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.
@@ -137,7 +147,7 @@ namespace cpplogging
*
* @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&& consumer_matcher,
log_level min_level = log_level::debug,
@@ -148,12 +158,12 @@ namespace cpplogging
*
* @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.
*/
static void reset();
void reset();

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

private:
/**
* @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 Visa fil

@@ -41,4 +41,21 @@ namespace cpplogging
::operator*() const
{ 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 Visa fil

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

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 Visa fil

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

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)
, _format (parse_format(format))
{ }

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

+ 5
- 5
src/cpplogging/manager/consumer/consumer_stream.cpp Visa fil

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

consumer_stream::consumer_stream(
const std::string& name,
std::ostream& stream,
const std::string& name,
std::ostream& stream,
const std::string& format)
: consumer (name, format)
, _stream (stream)
@@ -16,9 +16,9 @@ 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)
, _stream (*stream)
, _storage (std::move(stream))


+ 68
- 21
src/cpplogging/manager/manager.cpp Visa fil

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

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)
{
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);
if (name.empty())
return _default;

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

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

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& c = **it;
auto& c = const_cast<struct consumer&>(**it);
c._manager.emplace(this);
for (auto& rule : _rules)
{
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& ret = **it;
auto& c = const_cast<struct consumer&>(**it);
c._manager.emplace(this);
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)
{
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);
consumer._manager.erase(this);
unregister_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));
if (it == _consumer.end())
return;

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

/* create rule */
_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)
{
std::lock_guard<std::mutex> lg(_mutex);
std::lock_guard<std::recursive_mutex> lg(_mutex);

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

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();
_rules.clear();
_consumer.clear();
@@ -323,3 +328,45 @@ logger_impl& manager::init_logger(logger_impl& 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 Visa fil

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

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

struct consumer_mock
: public consumer
{
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)
{
manager::register_consumer(*this);
mngr.register_consumer(*this);
}
};

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

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

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

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

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

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

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

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

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

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

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(
log_level::info,
@@ -109,7 +107,7 @@ TEST(LoggingTests, log_base)
std::string("logger0"),
std::string("test1 warn"))));

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

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(
log_level::debug,
@@ -141,7 +140,7 @@ TEST(LoggingTests, log_inverted_regex)
std::string("logger2"),
std::string("test2"))));

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

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

Laddar…
Avbryt
Spara