]> git.sesse.net Git - casparcg/blobdiff - common/log.cpp
Don't start a flash player for CG commands that are only useful if one or more templa...
[casparcg] / common / log.cpp
index 0dd326cab49fce8bf3114d2f9168686dc237252c..8ae7c35bba9221604aa13be32c8e2c9abfb89a15 100644 (file)
@@ -54,6 +54,7 @@
 #include <boost/lambda/lambda.hpp>
 #include <boost/bind.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/property_tree/ptree.hpp>
 
 #include <tbb/atomic.h>
 
@@ -96,7 +97,7 @@ public:
        template<typename Stream, typename Val>
        void write(Stream& out, const Val& value)
        {
-               std::string to_string = boost::lexical_cast<std::string>(value);
+               std::wstring to_string = boost::lexical_cast<std::wstring>(value);
                int length = static_cast<int>(to_string.size());
                int read_width;
 
@@ -117,18 +118,24 @@ void my_formatter(bool print_all_characters, const boost::log::record_view& rec,
        static column_writer severity_column(7);
        namespace expr = boost::log::expressions;
 
-       append_timestamp(strm);
+       std::wstringstream pre_message_stream;
+       append_timestamp(pre_message_stream);
+       thread_id_column.write(pre_message_stream, boost::log::extract<boost::log::attributes::current_thread_id::value_type>("ThreadID", rec).get().native_id());
+       severity_column.write(pre_message_stream, boost::log::extract<boost::log::trivial::severity_level>("Severity", rec));
 
-       thread_id_column.write(strm, boost::log::extract<boost::log::attributes::current_thread_id::value_type>("ThreadID", rec).get().native_id());
-       severity_column.write(strm, boost::log::extract<boost::log::trivial::severity_level>("Severity", rec));
+       auto pre_message = pre_message_stream.str();
+
+       strm << pre_message;
+
+       auto line_break_replacement = L"\n" + pre_message;
 
        if (print_all_characters)
        {
-               strm << rec[expr::message];
+               strm << boost::replace_all_copy(rec[expr::message].get<std::wstring>(), "\n", line_break_replacement);
        }
        else
        {
-               strm << replace_nonprintable_copy(rec[expr::message].get<std::wstring>(), L'?');
+               strm << boost::replace_all_copy(replace_nonprintable_copy(rec[expr::message].get<std::wstring>(), L'?'), L"\n", line_break_replacement);
        }
 }
 
@@ -160,7 +167,7 @@ void add_file_sink(const std::wstring& folder)
        try
        {
                if (!boost::filesystem::is_directory(folder))
-                       BOOST_THROW_EXCEPTION(directory_not_found());
+                       CASPAR_THROW_EXCEPTION(directory_not_found());
 
                auto file_sink = boost::make_shared<file_sink_type>(
                        boost::log::keywords::file_name = (folder + L"caspar_%Y-%m-%d.log"),
@@ -180,6 +187,45 @@ void add_file_sink(const std::wstring& folder)
        }
 }
 
+std::shared_ptr<void> add_preformatted_line_sink(std::function<void(std::string line)> formatted_line_sink)
+{
+       class sink_backend : public boost::log::sinks::basic_formatted_sink_backend<char>
+       {
+               std::function<void(std::string line)> formatted_line_sink_;
+       public:
+               sink_backend(std::function<void(std::string line)> formatted_line_sink)
+                       : formatted_line_sink_(std::move(formatted_line_sink))
+               {
+               }
+
+               void consume(const boost::log::record_view& rec, const std::string& formatted_message)
+               {
+                       try
+                       {
+                               formatted_line_sink_(formatted_message);
+                       }
+                       catch (...)
+                       {
+                               std::cerr << "[sink_backend] Error while consuming formatted message: " << formatted_message << std::endl << std::endl;
+                       }
+               }
+       };
+
+       typedef boost::log::sinks::synchronous_sink<sink_backend> sink_type;
+
+       auto sink = boost::make_shared<sink_type>(std::move(formatted_line_sink));
+       bool print_all_characters = true;
+
+       sink->set_formatter(boost::bind(&my_formatter<boost::log::formatting_ostream>, print_all_characters, _1, _2));
+
+       boost::log::core::get()->add_sink(sink);
+
+       return std::shared_ptr<void>(nullptr, [=](void*)
+       {
+               boost::log::core::get()->remove_sink(sink);
+       });
+}
+
 void set_log_level(const std::wstring& lvl)
 {
        if (boost::iequals(lvl, L"trace"))
@@ -196,4 +242,21 @@ void set_log_level(const std::wstring& lvl)
                boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::fatal);
 }
 
+void print_child(
+               boost::log::trivial::severity_level level,
+               const std::wstring& indent,
+               const std::wstring& elem,
+               const boost::property_tree::wptree& tree)
+{
+       auto& data = tree.data();
+
+       if (!data.empty())
+               BOOST_LOG_STREAM_WITH_PARAMS(log::logger::get(), (boost::log::keywords::severity = level)) << indent << elem << L" " << replace_nonprintable_copy(data, L'?');
+       else if (tree.size() == 0)
+               BOOST_LOG_STREAM_WITH_PARAMS(log::logger::get(), (boost::log::keywords::severity = level)) << indent << elem;
+
+       for (auto& child : tree)
+               print_child(level, indent + (elem.empty() ? L"" : elem + L"."), child.first, child.second);
+}
+
 }}