// // Copyright © 2019 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once #include #include "Utils.hpp" #if defined(_MSC_VER) #ifndef NOMINMAX #define NOMINMAX // Prevent definition of min/max macros that interfere with std::min/max #endif #include #undef TIME_MS // Windows.h defines this but we don't need it and it interferes with our definition in Instrument.hpp #endif #if defined(__ANDROID__) #include #endif #include #include namespace armnn { inline std::string LevelToString(LogSeverity level) { switch(level) { case LogSeverity::Trace: return "Trace"; case LogSeverity::Debug: return "Debug"; case LogSeverity::Info: return "Info"; case LogSeverity::Warning: return "Warning"; case LogSeverity::Error: return "Error"; case LogSeverity::Fatal: return "Fatal"; default: return "Log"; } } class LogSink { public: virtual ~LogSink(){}; virtual void Consume(const std::string&) = 0; private: }; class StandardOutputColourSink : public LogSink { public: StandardOutputColourSink(LogSeverity level = LogSeverity::Info) : m_Level(level) { } void Consume(const std::string& s) override { std::cout << GetColour(m_Level) << s << ResetColour() << std::endl; } private: std::string ResetColour() { return "\033[0m"; } std::string GetColour(LogSeverity level) { switch(level) { case LogSeverity::Trace: return "\033[35m"; case LogSeverity::Debug: return "\033[32m"; case LogSeverity::Info: return "\033[0m"; case LogSeverity::Warning: return "\033[33m"; case LogSeverity::Error: return "\033[31m"; case LogSeverity::Fatal: return "\033[41;30m"; default: return "\033[0m"; } } LogSeverity m_Level; }; class StandardOutputSink : public LogSink { public: void Consume(const std::string& s) override { std::cout << s << std::endl; } }; class DebugOutputSink : public LogSink { public: void Consume(const std::string& s) override { boost::ignore_unused(s); #if defined(_MSC_VER) OutputDebugString(s.c_str()); OutputDebugString("\n"); #elif defined(__ANDROID__) __android_log_write(ANDROID_LOG_DEBUG, "armnn", s.c_str()); #else boost::ignore_unused(s); #endif } }; struct ScopedRecord { ScopedRecord(const std::vector>& sinks, LogSeverity level, bool enabled) : m_LogSinks(sinks) , m_Enabled(enabled) { if (enabled) { m_Os << LevelToString(level) << ": "; } } ~ScopedRecord() { if (m_Enabled) { for (auto sink : m_LogSinks) { if (sink) { sink->Consume(m_Os.str()); } } } } ScopedRecord(const ScopedRecord&) = delete; ScopedRecord& operator=(const ScopedRecord&) = delete; ScopedRecord(ScopedRecord&& other) = default; ScopedRecord& operator=(ScopedRecord&&) = default; template ScopedRecord& operator<<(const Streamable& s) { if (m_Enabled) { m_Os << s; } return (*this); } private: const std::vector>& m_LogSinks; std::ostringstream m_Os; bool m_Enabled; }; template class SimpleLogger { public: SimpleLogger() : m_Sinks{std::make_shared()} , m_Enable(true) { } static SimpleLogger& Get() { static SimpleLogger logger; return logger; } void Enable(bool enable = true) { m_Enable = enable; } ScopedRecord StartNewRecord() { ScopedRecord record(m_Sinks, Level, m_Enable); return record; } void RemoveAllSinks() { m_Sinks.clear(); } void AddSink(std::shared_ptr sink) { m_Sinks.push_back(sink); } private: std::vector> m_Sinks; bool m_Enable; }; inline void SetLogFilter(LogSeverity level) { SimpleLogger::Get().Enable(false); SimpleLogger::Get().Enable(false); SimpleLogger::Get().Enable(false); SimpleLogger::Get().Enable(false); SimpleLogger::Get().Enable(false); SimpleLogger::Get().Enable(false); switch (level) { case LogSeverity::Trace: SimpleLogger::Get().Enable(true); ARMNN_FALLTHROUGH; case LogSeverity::Debug: SimpleLogger::Get().Enable(true); ARMNN_FALLTHROUGH; case LogSeverity::Info: SimpleLogger::Get().Enable(true); ARMNN_FALLTHROUGH; case LogSeverity::Warning: SimpleLogger::Get().Enable(true); ARMNN_FALLTHROUGH; case LogSeverity::Error: SimpleLogger::Get().Enable(true); ARMNN_FALLTHROUGH; case LogSeverity::Fatal: SimpleLogger::Get().Enable(true); break; default: BOOST_ASSERT(false); } } template inline void SetLoggingSinks(bool standardOut, bool debugOut, bool coloured) { SimpleLogger::Get().RemoveAllSinks(); if (standardOut) { if (coloured) { SimpleLogger::Get().AddSink( std::make_shared(Level)); } else { SimpleLogger::Get().AddSink( std::make_shared()); } } if (debugOut) { SimpleLogger::Get().AddSink( std::make_shared()); } } inline void SetAllLoggingSinks(bool standardOut, bool debugOut, bool coloured) { SetLoggingSinks(standardOut, debugOut, coloured); SetLoggingSinks(standardOut, debugOut, coloured); SetLoggingSinks(standardOut, debugOut, coloured); SetLoggingSinks(standardOut, debugOut, coloured); SetLoggingSinks(standardOut, debugOut, coloured); SetLoggingSinks(standardOut, debugOut, coloured); } enum class BoostLogSeverityMapping { trace, debug, info, warning, error, fatal }; constexpr LogSeverity ConvertLogSeverity(BoostLogSeverityMapping severity) { return static_cast(severity); } #define ARMNN_LOG(severity) \ armnn::SimpleLogger::Get().StartNewRecord() } //namespace armnn