\r
#include "except.h"\r
#include "utf.h"\r
+#include "compiler/vs/stack_walker.h"\r
\r
#include <ios>\r
#include <string>\r
#include <ostream>\r
\r
+#include <boost/bind.hpp>\r
#include <boost/shared_ptr.hpp>\r
#include <boost/make_shared.hpp>\r
#include <boost/filesystem/convenience.hpp>\r
#include <boost/log/utility/empty_deleter.hpp>\r
#include <boost/lambda/lambda.hpp>\r
\r
+#include <tbb/enumerable_thread_specific.h>\r
+\r
namespace caspar { namespace log {\r
\r
using namespace boost;\r
\r
-void my_formatter(std::wostream& strm, boost::log::basic_record<wchar_t> const& rec)\r
+void my_formatter(bool print_all_characters, std::wostream& strm, boost::log::basic_record<wchar_t> const& rec)\r
{\r
namespace lambda = boost::lambda;\r
\r
boost::log::attributes::current_thread_id::held_type thread_id;\r
if(boost::log::extract<boost::log::attributes::current_thread_id::held_type>(L"ThreadID", rec.attribute_values(), lambda::var(thread_id) = lambda::_1))\r
strm << L"[" << thread_id << L"] ";\r
-\r
-\r
+ \r
severity_level severity;\r
if(boost::log::extract<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get(), rec.attribute_values(), lambda::var(severity) = lambda::_1))\r
{\r
strm << L" ";\r
}\r
\r
- strm << rec.message();\r
+ if (print_all_characters)\r
+ {\r
+ strm << rec.message();\r
+ }\r
+ else\r
+ {\r
+ strm << replace_nonprintable_copy(rec.message(), L'?');\r
+ }\r
}\r
\r
namespace internal{\r
// stream_sink->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= debug);\r
//#endif\r
\r
- stream_sink->locked_backend()->set_formatter(&my_formatter);\r
+ stream_sink->locked_backend()->set_formatter(boost::bind(my_formatter, false, _1, _2));\r
\r
boost::log::wcore::get()->add_sink(stream_sink);\r
}\r
\r
+std::wstring get_call_stack()\r
+{\r
+ class log_call_stack_walker : public stack_walker\r
+ {\r
+ std::string str_;\r
+ public:\r
+ log_call_stack_walker() : stack_walker() {}\r
+\r
+ std::string flush()\r
+ {\r
+ return std::move(str_);\r
+ }\r
+ protected: \r
+ virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName)\r
+ {\r
+ }\r
+ virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)\r
+ {\r
+ }\r
+ virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr)\r
+ {\r
+ }\r
+ virtual void OnOutput(LPCSTR szText)\r
+ {\r
+ std::string str = szText;\r
+\r
+ if(str.find("internal::get_call_stack") == std::string::npos && str.find("stack_walker::ShowCallstack") == std::string::npos)\r
+ str_ += std::move(str);\r
+ }\r
+ };\r
+\r
+ static tbb::enumerable_thread_specific<log_call_stack_walker> walkers;\r
+ try\r
+ {\r
+ auto& walker = walkers.local();\r
+ walker.ShowCallstack();\r
+ return u16(walker.flush());\r
+ }\r
+ catch(...)\r
+ {\r
+ return L"!!!";\r
+ }\r
+}\r
+\r
}\r
\r
void add_file_sink(const std::wstring& folder)\r
try\r
{\r
if(!boost::filesystem::is_directory(folder))\r
- BOOST_THROW_EXCEPTION(directory_not_found());\r
+ CASPAR_THROW_EXCEPTION(directory_not_found());\r
\r
auto file_sink = boost::make_shared<file_sink_type>(\r
boost::log::keywords::file_name = (folder + L"caspar_%Y-%m-%d.log"),\r
boost::log::keywords::open_mode = std::ios::app\r
);\r
\r
- file_sink->locked_backend()->set_formatter(&my_formatter);\r
+ file_sink->locked_backend()->set_formatter(boost::bind(my_formatter, true, _1, _2));\r
\r
//#ifdef NDEBUG\r
// file_sink->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= debug);\r