aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/logging/msvcsink.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zencore/logging/msvcsink.cpp')
-rw-r--r--src/zencore/logging/msvcsink.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/zencore/logging/msvcsink.cpp b/src/zencore/logging/msvcsink.cpp
new file mode 100644
index 000000000..457a4d6e1
--- /dev/null
+++ b/src/zencore/logging/msvcsink.cpp
@@ -0,0 +1,80 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include <zencore/zencore.h>
+
+#if ZEN_PLATFORM_WINDOWS
+
+# include <zencore/logging/helpers.h>
+# include <zencore/logging/messageonlyformatter.h>
+# include <zencore/logging/msvcsink.h>
+
+ZEN_THIRD_PARTY_INCLUDES_START
+# include <Windows.h>
+ZEN_THIRD_PARTY_INCLUDES_END
+
+namespace zen::logging {
+
+// Default formatter for MSVC debug output: [level] message\n
+// For error/critical messages with source info, prepends file(line): so that
+// the message is clickable in the Visual Studio Output window.
+class DefaultMsvcFormatter : public Formatter
+{
+public:
+ void Format(const LogMessage& Msg, MemoryBuffer& Dest) override
+ {
+ const auto& Source = Msg.GetSource();
+ if (Msg.GetLevel() >= LogLevel::Err && Source)
+ {
+ helpers::AppendStringView(Source.Filename, Dest);
+ Dest.push_back('(');
+ helpers::AppendInt(Source.Line, Dest);
+ Dest.push_back(')');
+ Dest.push_back(':');
+ Dest.push_back(' ');
+ }
+
+ Dest.push_back('[');
+ helpers::AppendStringView(helpers::LevelToShortString(Msg.GetLevel()), Dest);
+ Dest.push_back(']');
+ Dest.push_back(' ');
+ helpers::AppendStringView(Msg.GetPayload(), Dest);
+ Dest.push_back('\n');
+ }
+
+ std::unique_ptr<Formatter> Clone() const override { return std::make_unique<DefaultMsvcFormatter>(); }
+};
+
+MsvcSink::MsvcSink() : m_Formatter(std::make_unique<DefaultMsvcFormatter>())
+{
+}
+
+void
+MsvcSink::Log(const LogMessage& Msg)
+{
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+
+ MemoryBuffer Formatted;
+ m_Formatter->Format(Msg, Formatted);
+
+ // Null-terminate for OutputDebugStringA
+ Formatted.push_back('\0');
+
+ OutputDebugStringA(Formatted.data());
+}
+
+void
+MsvcSink::Flush()
+{
+ // Nothing to flush for OutputDebugString
+}
+
+void
+MsvcSink::SetFormatter(std::unique_ptr<Formatter> InFormatter)
+{
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ m_Formatter = std::move(InFormatter);
+}
+
+} // namespace zen::logging
+
+#endif // ZEN_PLATFORM_WINDOWS