diff --git a/example/example.cpp b/example/example.cpp
index 89a3d077..a24b5946 100644
--- a/example/example.cpp
+++ b/example/example.cpp
@@ -57,6 +57,13 @@ int main(int, char*[])
spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
rotating_logger->info("This is another message with custom format");
+ // Using a per-logger dynamic property map
+ console->set_pattern("*** [%H:%M:%S %z] [thread %t] [%{property_name}] %v ***");
+ auto properties = console->properties();
+ (*properties)["property_name"] = "some property";
+ console->info("This message has a custom property");
+ (*properties)["property_name"] = "new property";
+ console->info("The property has changed");
// Runtime log levels
spd::set_level(spd::level::info); //Set global log level to info
diff --git a/example/example.vcxproj b/example/example.vcxproj
index 63db2b5d..2b8c4e55 100644
--- a/example/example.vcxproj
+++ b/example/example.vcxproj
@@ -56,13 +56,13 @@
Application
true
- v120
+ v140
Unicode
Application
false
- v120
+ v140
true
Unicode
diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h
index 2092f06c..f2b371b7 100644
--- a/include/spdlog/details/async_logger_impl.h
+++ b/include/spdlog/details/async_logger_impl.h
@@ -65,7 +65,7 @@ inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_forma
inline void spdlog::async_logger::_set_pattern(const std::string& pattern)
{
- _formatter = std::make_shared(pattern);
+ _formatter = std::make_shared(pattern, _properties);
_async_log_helper->set_formatter(_formatter);
}
diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h
index 2b27f105..4470fc59 100644
--- a/include/spdlog/details/logger_impl.h
+++ b/include/spdlog/details/logger_impl.h
@@ -18,7 +18,8 @@ template
inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end):
_name(logger_name),
_sinks(begin, end),
- _formatter(std::make_shared("%+"))
+ _properties(std::make_shared>()),
+ _formatter(std::make_shared("%+", _properties))
{
_level = level::info;
_flush_level = level::off;
@@ -57,6 +58,11 @@ inline void spdlog::logger::set_pattern(const std::string& pattern)
_set_pattern(pattern);
}
+inline std::shared_ptr> spdlog::logger::properties() const
+{
+ return _properties;
+}
+
template
inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args)
@@ -259,7 +265,7 @@ inline void spdlog::logger::_sink_it(details::log_msg& msg)
inline void spdlog::logger::_set_pattern(const std::string& pattern)
{
- _formatter = std::make_shared(pattern);
+ _formatter = std::make_shared(pattern, _properties);
}
inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter)
{
diff --git a/include/spdlog/details/pattern_formatter_impl.h b/include/spdlog/details/pattern_formatter_impl.h
index 3f4e9a2c..02949dec 100644
--- a/include/spdlog/details/pattern_formatter_impl.h
+++ b/include/spdlog/details/pattern_formatter_impl.h
@@ -396,6 +396,25 @@ private:
char _ch;
};
+class property_formatter:public flag_formatter
+{
+public:
+ explicit property_formatter(std::shared_ptr> properties, const std::string& property_name)
+ : properties(properties), property_name(property_name)
+ {}
+ void format(details::log_msg& msg, const std::tm&) override
+ {
+ auto it = properties->find(property_name);
+ if (it != properties->end())
+ msg.formatted << it->second;
+ else
+ msg.formatted << "null";
+ }
+private:
+ std::shared_ptr> properties;
+ std::string property_name;
+};
+
//aggregate user chars to display as is
class aggregate_formatter:public flag_formatter
@@ -469,7 +488,7 @@ class full_formatter:public flag_formatter
///////////////////////////////////////////////////////////////////////////////
// pattern_formatter inline impl
///////////////////////////////////////////////////////////////////////////////
-inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern)
+inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern, std::shared_ptr> properties): properties(properties)
{
compile_pattern(pattern);
}
@@ -485,10 +504,29 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string& patter
if (user_chars) //append user chars found so far
_formatters.push_back(std::move(user_chars));
- if (++it != end)
- handle_flag(*it);
- else
+ if (++it == end)
break;
+
+ // the right brace must be found and the string consumed up until it
+ if (*it == '{')
+ {
+ auto key_start_pos = it + 1 - pattern.begin();
+ auto key_end_pos = pattern.find('}', key_start_pos);
+
+ // ignoring rest of the pattern
+ if (key_end_pos == pattern.size())
+ break;
+
+ auto key_length = key_end_pos - key_start_pos;
+ auto key = pattern.substr(key_start_pos, key_length);
+ handle_flag(*it, key);
+
+ it += key_length + 1;
+ }
+ else
+ {
+ handle_flag(*it);
+ }
}
else // chars not following the % sign should be displayed as is
{
@@ -501,9 +539,9 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string& patter
{
_formatters.push_back(std::move(user_chars));
}
-
}
-inline void spdlog::pattern_formatter::handle_flag(char flag)
+
+inline void spdlog::pattern_formatter::handle_flag(char flag, const std::string& param)
{
switch (flag)
{
@@ -625,6 +663,9 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
case ('P'):
_formatters.push_back(std::unique_ptr(new details::pid_formatter()));
break;
+ case ('{'):
+ _formatters.push_back(std::unique_ptr(new details::property_formatter(properties, param)));
+ break;
default: //Unkown flag appears as is
_formatters.push_back(std::unique_ptr(new details::ch_formatter('%')));
diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h
index ee14adfd..f0b87b10 100644
--- a/include/spdlog/details/registry.h
+++ b/include/spdlog/details/registry.h
@@ -111,9 +111,11 @@ public:
void set_pattern(const std::string& pattern)
{
std::lock_guard lock(_mutex);
- _formatter = std::make_shared(pattern);
for (auto& l : _loggers)
+ {
+ _formatter = std::make_shared(pattern, l.second->properties());
l.second->set_formatter(_formatter);
+ }
}
void set_level(level::level_enum log_level)
diff --git a/include/spdlog/formatter.h b/include/spdlog/formatter.h
index 0ffcec03..36a5df31 100644
--- a/include/spdlog/formatter.h
+++ b/include/spdlog/formatter.h
@@ -7,9 +7,9 @@
#include
-#include
-#include
#include
+#include
+#include
namespace spdlog
{
@@ -29,14 +29,16 @@ class pattern_formatter : public formatter
{
public:
- explicit pattern_formatter(const std::string& pattern);
+ explicit pattern_formatter(const std::string& pattern, std::shared_ptr> properties);
pattern_formatter(const pattern_formatter&) = delete;
pattern_formatter& operator=(const pattern_formatter&) = delete;
void format(details::log_msg& msg) override;
private:
const std::string _pattern;
std::vector> _formatters;
- void handle_flag(char flag);
+ std::shared_ptr> properties;
+
+ void handle_flag(char flag, const std::string& param="");
void compile_pattern(const std::string& pattern);
};
}
diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h
index a2deb51d..cec94666 100644
--- a/include/spdlog/logger.h
+++ b/include/spdlog/logger.h
@@ -15,9 +15,9 @@
#include
#include
-#include
#include
-#include
+#include
+#include
namespace spdlog
{
@@ -59,6 +59,8 @@ public:
void set_pattern(const std::string&);
void set_formatter(formatter_ptr);
+ std::shared_ptr> properties() const;
+
// error handler
void set_error_handler(log_err_handler);
log_err_handler error_handler();
@@ -83,6 +85,7 @@ protected:
const std::string _name;
std::vector _sinks;
+ std::shared_ptr> _properties;
formatter_ptr _formatter;
spdlog::level_t _level;
spdlog::level_t _flush_level;