]> git.sesse.net Git - casparcg/commitdiff
Made calltracing configurable
authorHelge Norberg <helge.norberg@svt.se>
Wed, 16 Dec 2015 19:56:19 +0000 (20:56 +0100)
committerHelge Norberg <helge.norberg@svt.se>
Wed, 16 Dec 2015 19:56:19 +0000 (20:56 +0100)
common/enum_class.h
common/log.cpp
common/log.h
modules/psd/misc.h
protocol/amcp/AMCPCommandsImpl.cpp
shell/casparcg.config
shell/main.cpp

index c1cec94d5dba1aacbe5a3775e5ce5f034de74559..54336823bfd4de3d8b968745d58a4a5532f1ce79 100644 (file)
@@ -1,63 +1,68 @@
-#pragma once
-
-#include <type_traits>
-
-#include <boost/range/irange.hpp>
-
-#include "linq.h"
-
-// Macro that defines & and &= for an enum class. Add more when needed.
-
-#define ENUM_ENABLE_BITWISE(enum_class) \
-       static enum_class operator&(enum_class lhs, enum_class rhs) \
-       { \
-               return static_cast<enum_class>( \
-                               static_cast<std::underlying_type<enum_class>::type>(lhs) \
-                                       & static_cast<std::underlying_type<enum_class>::type>(rhs)); \
-       }; \
-       static enum_class& operator&=(enum_class& lhs, enum_class rhs) \
-       { \
-               lhs = lhs & rhs; \
-               return lhs; \
-       }; \
+#pragma once\r
+\r
+#include <type_traits>\r
+\r
+#include <boost/range/irange.hpp>\r
+\r
+#include "linq.h"\r
+\r
+// Macro that defines & and &= for an enum class. Add more when needed.\r
+\r
+#define ENUM_ENABLE_BITWISE(enum_class) \\r
+       static enum_class operator&(enum_class lhs, enum_class rhs) \\r
+       { \\r
+               return static_cast<enum_class>( \\r
+                               static_cast<std::underlying_type<enum_class>::type>(lhs) \\r
+                                       & static_cast<std::underlying_type<enum_class>::type>(rhs)); \\r
+       }; \\r
+       static enum_class& operator&=(enum_class& lhs, enum_class rhs) \\r
+       { \\r
+               lhs = lhs & rhs; \\r
+               return lhs; \\r
+       }; \\r
        static enum_class operator | (enum_class lhs, enum_class rhs) \\r
        { \\r
                return static_cast<enum_class>( \\r
                                static_cast<std::underlying_type<enum_class>::type>(lhs) \\r
                                        | static_cast<std::underlying_type<enum_class>::type>(rhs)); \\r
        }; \\r
-       static enum_class& operator|=(enum_class& lhs, enum_class rhs) \
-       { \
-               lhs = lhs | rhs; \
-               return lhs; \
-       }; \
+       static enum_class& operator|=(enum_class& lhs, enum_class rhs) \\r
+       { \\r
+               lhs = lhs | rhs; \\r
+               return lhs; \\r
+       }; \\r
        static enum_class operator ^ (enum_class lhs, enum_class rhs) \\r
        { \\r
                return static_cast<enum_class>( \\r
                                static_cast<std::underlying_type<enum_class>::type>(lhs) \\r
                                        ^ static_cast<std::underlying_type<enum_class>::type>(rhs)); \\r
        }; \\r
-       static enum_class& operator^=(enum_class& lhs, enum_class rhs) \
-       { \
-               lhs = lhs ^ rhs; \
-               return lhs; \
-       };
-
-namespace caspar {
-
-// For enum classes starting at 0 and without any gaps with a terminating count constant.
-template <typename E>
-const std::vector<E>& enum_constants()
-{
-       typedef typename std::underlying_type<E>::type integer;
-
-       static const auto ints = boost::irange(static_cast<integer>(0), static_cast<integer>(E::count));
-       static const auto result = cpplinq::from(ints.begin(), ints.end())
-               //.cast<E>()
-               .select([](int i) { return static_cast<E>(i); })
-               .to_vector();
-
-       return result;
-}
-
-}
+       static enum_class& operator^=(enum_class& lhs, enum_class rhs) \\r
+       { \\r
+               lhs = lhs ^ rhs; \\r
+               return lhs; \\r
+       }; \\r
+       static enum_class operator~ (enum_class e) \\r
+       { \\r
+               return static_cast<enum_class>( \\r
+                               ~static_cast<std::underlying_type<enum_class>::type>(e)); \\r
+       };\r
+\r
+namespace caspar {\r
+\r
+// For enum classes starting at 0 and without any gaps with a terminating count constant.\r
+template <typename E>\r
+const std::vector<E>& enum_constants()\r
+{\r
+       typedef typename std::underlying_type<E>::type integer;\r
+\r
+       static const auto ints = boost::irange(static_cast<integer>(0), static_cast<integer>(E::count));\r
+       static const auto result = cpplinq::from(ints.begin(), ints.end())\r
+               //.cast<E>()\r
+               .select([](int i) { return static_cast<E>(i); })\r
+               .to_vector();\r
+\r
+       return result;\r
+}\r
+\r
+}\r
index 78957b60a2e014731888c284b8f2fce335e9cc5f..31a34577617694555741f1e021b5d342bb45bca8 100644 (file)
@@ -55,6 +55,7 @@
 #include <boost/bind.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/property_tree/ptree.hpp>
+#include <boost/thread/mutex.hpp>
 
 #include <tbb/atomic.h>
 
@@ -152,7 +153,7 @@ void init()
 
        auto stream_sink = boost::make_shared<stream_sink_type>(stream_backend);
        // Never log calltrace to console. The terminal is too slow, so the log queue will build up faster than consumed.
-       stream_sink->set_filter(category != log_category::call);
+       stream_sink->set_filter(category != log_category::calltrace);
 
        bool print_all_characters = false;
        stream_sink->set_formatter(boost::bind(&my_formatter<boost::log::wformatting_ostream>, print_all_characters, _1, _2));
@@ -220,6 +221,7 @@ std::shared_ptr<void> add_preformatted_line_sink(std::function<void(std::string
        bool print_all_characters = true;
 
        sink->set_formatter(boost::bind(&my_formatter<boost::log::formatting_ostream>, print_all_characters, _1, _2));
+       sink->set_filter(category != log_category::calltrace);
 
        boost::log::core::get()->add_sink(sink);
 
@@ -229,20 +231,79 @@ std::shared_ptr<void> add_preformatted_line_sink(std::function<void(std::string
        });
 }
 
+boost::mutex& get_filter_mutex()
+{
+       static boost::mutex instance;
+
+       return instance;
+}
+
+boost::log::trivial::severity_level& get_level()
+{
+       static boost::log::trivial::severity_level instance;
+
+       return instance;
+}
+
+log_category& get_disabled_categories()
+{
+       static log_category instance = log_category::calltrace;
+
+       return instance;
+}
+
+void set_log_filter()
+{
+       auto severity_filter            = boost::log::trivial::severity >= get_level();
+       auto disabled_categories        = get_disabled_categories();
+
+       boost::log::core::get()->set_filter([=](const boost::log::attribute_value_set& attributes)
+       {
+               return severity_filter(attributes)
+                       && static_cast<int>(disabled_categories & attributes["Channel"].extract<log_category>().get()) == 0;
+       });
+}
+
 void set_log_level(const std::wstring& lvl)
 {
+       boost::lock_guard<boost::mutex> lock(get_filter_mutex());
+
        if (boost::iequals(lvl, L"trace"))
-               boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::trace);
+               get_level() = boost::log::trivial::trace;
        else if (boost::iequals(lvl, L"debug"))
-               boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::debug);
+               get_level() = boost::log::trivial::debug;
        else if (boost::iequals(lvl, L"info"))
-               boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::info);
+               get_level() = boost::log::trivial::info;
        else if (boost::iequals(lvl, L"warning"))
-               boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::warning);
+               get_level() = boost::log::trivial::warning;
        else if (boost::iequals(lvl, L"error"))
-               boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::error);
+               get_level() = boost::log::trivial::error;
        else if (boost::iequals(lvl, L"fatal"))
-               boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::fatal);
+               get_level() = boost::log::trivial::fatal;
+
+       set_log_filter();
+}
+
+void set_log_category(const std::wstring& cat, bool enabled)
+{
+       log_category category_to_set;
+
+       if (boost::iequals(cat, L"calltrace"))
+               category_to_set = log_category::calltrace;
+       else if (boost::iequals(cat, L"communication"))
+               category_to_set = log_category::communication;
+       else
+               return; // Ignore
+
+       boost::lock_guard<boost::mutex> lock(get_filter_mutex());
+       auto& disabled_categories = get_disabled_categories();
+
+       if (enabled)
+               disabled_categories &= ~category_to_set;
+       else
+               disabled_categories |= category_to_set;
+
+       set_log_filter();
 }
 
 void print_child(
index a4415c60f801253f03a5cd1853b60c8a183123bb..4cc983e4556f0b787a1c10df62f7bc28a17f352c 100644 (file)
@@ -24,6 +24,7 @@
 #include "os/stack_trace.h"
 #include "utf.h"
 #include "thread_info.h"
+#include "enum_class.h"
 
 #include <boost/log/trivial.hpp>
 #include <boost/log/expressions.hpp>
@@ -69,10 +70,11 @@ std::shared_ptr<void> add_preformatted_line_sink(std::function<void(std::string
 
 enum class log_category
 {
-       normal,
-       call,
-       communication
+       normal                  = 1,
+       calltrace               = 2,
+       communication   = 4
 };
+ENUM_ENABLE_BITWISE(log_category)
 BOOST_LOG_ATTRIBUTE_KEYWORD(category, "Channel", ::caspar::log::log_category)
 
 typedef boost::log::sources::wseverity_channel_logger_mt<boost::log::trivial::severity_level, log_category> caspar_logger;
@@ -88,7 +90,7 @@ BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(logger, caspar_logger)
 #define CASPAR_LOG(lvl)\
        BOOST_LOG_CHANNEL_SEV(::caspar::log::logger::get(), ::caspar::log::log_category::normal,                ::boost::log::trivial::lvl)
 #define CASPAR_LOG_CALL(lvl)\
-       BOOST_LOG_CHANNEL_SEV(::caspar::log::logger::get(), ::caspar::log::log_category::call,                  ::boost::log::trivial::lvl)
+       BOOST_LOG_CHANNEL_SEV(::caspar::log::logger::get(), ::caspar::log::log_category::calltrace,             ::boost::log::trivial::lvl)
 #define CASPAR_LOG_COMMUNICATION(lvl)\
        BOOST_LOG_CHANNEL_SEV(::caspar::log::logger::get(), ::caspar::log::log_category::communication, ::boost::log::trivial::lvl)
 
@@ -108,6 +110,7 @@ BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(logger, caspar_logger)
        catch(...){}
 
 void set_log_level(const std::wstring& lvl);
+void set_log_category(const std::wstring& cat, bool enabled);
 
 void print_child(
                boost::log::trivial::severity_level level,
index 840b365b9844f9153aee90f8b05839098b5f5489..3cf07ec9abe8e8948509e2303586dfb1784d6ef1 100644 (file)
@@ -129,15 +129,15 @@ enum class layer_tag : int {
        moveable = 4,\r
        resizable = 8,\r
        rasterized = 16,\r
-       cornerpin = 32,\r
-       all = 63\r
+       cornerpin = 32//,\r
+       //all = 63\r
 };\r
 ENUM_ENABLE_BITWISE(layer_tag);\r
 \r
-inline layer_tag operator ~ (layer_tag rhs)\r
+/*inline layer_tag operator ~ (layer_tag rhs)\r
 {\r
        return (layer_tag)(static_cast<int>(layer_tag::all) ^ static_cast<int>(rhs));\r
-}\r
+}*/\r
 \r
 layer_tag string_to_layer_tags(const std::wstring& str);\r
 \r
index 2a377d225908cd7cb9133b027c685ee20ab97d3c..9297e03f0a502c44a39dc9baf7677f026bdf81ad 100644 (file)
@@ -704,6 +704,23 @@ std::wstring log_level_command(command_context& ctx)
        return L"202 LOG OK\r\n";
 }
 
+void log_category_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+       sink.short_description(L"Enable/disable a logging category in the server.");
+       sink.syntax(L"LOG CATEGORY [category:calltrace,communication] [enable:0,1]");
+       sink.para()->text(L"Enables or disables the specified logging category.");
+       sink.para()->text(L"Examples:");
+       sink.example(L">> LOG CATEGORY calltrace 1", L"to enable call trace");
+       sink.example(L">> LOG CATEGORY calltrace 0", L"to disable call trace");
+}
+
+std::wstring log_category_command(command_context& ctx)
+{
+       log::set_log_category(ctx.parameters.at(0), ctx.parameters.at(1) == L"1");
+
+       return L"202 LOG OK\r\n";
+}
+
 void set_describer(core::help_sink& sink, const core::help_repository& repo)
 {
        sink.short_description(L"Change the value of a channel variable.");
@@ -2856,6 +2873,7 @@ void register_commands(amcp_command_repository& repo)
        repo.register_channel_command(  L"Basic Commands",              L"REMOVE",                                              remove_describer,                                       remove_command,                                 0);
        repo.register_channel_command(  L"Basic Commands",              L"PRINT",                                               print_describer,                                        print_command,                                  0);
        repo.register_command(                  L"Basic Commands",              L"LOG LEVEL",                                   log_level_describer,                            log_level_command,                              1);
+       repo.register_command(                  L"Basic Commands",              L"LOG CATEGORY",                                log_category_describer,                         log_category_command,                   2);
        repo.register_channel_command(  L"Basic Commands",              L"SET",                                                 set_describer,                                          set_command,                                    2);
        repo.register_command(                  L"Basic Commands",              L"LOCK",                                                lock_describer,                                         lock_command,                                   2);
 
index 231954018cf47b162f7881dde176623e0590e94b..076e4b0fae39bb35970d4671135de189f195fdab 100644 (file)
@@ -36,6 +36,7 @@
 \r
 <!--\r
 <log-level>           info  [trace|debug|info|warning|error|fatal]</log-level>\r
+<log-categories>      communication  [calltrace|communication|calltrace,communication]</log-categories>\r
 <force-deinterlace>   true  [true|false]</force-deinterlacing>\r
 <channel-grid>        false [true|false]</channel-grid>\r
 <mixer>\r
index 2d957f21ff40fb334913d9a58ea5ef6d4220587a..a811eb7d508b91c82786bef53e5724682c94eedc 100644 (file)
 #include <boost/thread.hpp>
 #include <boost/thread/future.hpp>
 #include <boost/algorithm/string/case_conv.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
 
 #include <tbb/atomic.h>
 
 #include <future>
+#include <set>
 
 #include <csignal>
 
@@ -299,13 +302,18 @@ int main(int argc, char** argv)
                env::configure(config_file_name);
 
                log::set_log_level(env::properties().get(L"configuration.log-level", L"info"));
+               auto log_categories_str = env::properties().get(L"configuration.log-categories", L"communication");
+               std::set<std::wstring> log_categories;
+               boost::split(log_categories, log_categories_str, boost::is_any_of(L", "));
+               for (auto& log_category : { L"calltrace", L"communication" })
+                       log::set_log_category(log_category, log_categories.find(log_category) != log_categories.end());
 
                if (env::properties().get(L"configuration.debugging.remote", false))
                        wait_for_remote_debugging();
 
                // Start logging to file.
-               log::add_file_sink(env::log_folder() + L"caspar",               caspar::log::category != caspar::log::log_category::call);
-               log::add_file_sink(env::log_folder() + L"calltrace",    caspar::log::category == caspar::log::log_category::call);
+               log::add_file_sink(env::log_folder() + L"caspar",               caspar::log::category != caspar::log::log_category::calltrace);
+               log::add_file_sink(env::log_folder() + L"calltrace",    caspar::log::category == caspar::log::log_category::calltrace);
                std::wcout << L"Logging [info] or higher severity to " << env::log_folder() << std::endl << std::endl;
                
                // Setup console window.