blob: 6336e96d8c582f4b60286a4bc10e2870de2ce3ff [file] [log] [blame]
//
// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
#include <armnn/Utils.hpp>
#include <iostream>
#include <algorithm>
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";
}
}
inline LogSeverity StringToLogLevel(std::string level)
{
// Transfer to lower case
std::transform(level.begin(), level.end(), level.begin(),
[](unsigned char c){ return std::tolower(c); }
);
if (level == "trace")
{
return LogSeverity::Trace;
}
else if (level == "debug")
{
return LogSeverity::Debug;
}
else if (level == "info")
{
return LogSeverity::Info;
}
else if (level == "warning")
{
return LogSeverity::Warning;
}
else if (level == "error")
{
return LogSeverity::Error;
}
else if (level == "fatal")
{
return LogSeverity::Fatal;
}
else
{
throw armnn::Exception("Unknown severity level for logging: '" + level +
"'. Valid options: trace, debug, info, warning, error, fatal");
}
}
class LogSink
{
public:
virtual ~LogSink(){};
virtual void Consume(const std::string&) = 0;
private:
};
class StandardOutputSink : public LogSink
{
public:
void Consume(const std::string& s) override
{
std::cout << s << std::endl;
}
};
struct ScopedRecord
{
ScopedRecord(const std::vector<std::shared_ptr<LogSink>>& 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& operator=(ScopedRecord&&) = delete;
ScopedRecord(ScopedRecord&& other)
: m_LogSinks(other.m_LogSinks)
, m_Os(std::move(other.m_Os))
, m_Enabled(other.m_Enabled)
{
// Disable the moved-from ScopedRecord, to prevent it from sending its (now empty) message to
// its sinks.
other.m_Enabled = false;
}
template<typename Streamable>
ScopedRecord& operator<<(const Streamable& s)
{
if (m_Enabled)
{
m_Os << s;
}
return (*this);
}
private:
const std::vector<std::shared_ptr<LogSink>>& m_LogSinks;
std::ostringstream m_Os;
bool m_Enabled;
};
template<LogSeverity Level>
class SimpleLogger
{
public:
SimpleLogger()
: m_Sinks{std::make_shared<StandardOutputSink>()}
, m_Enable(true)
{
}
static SimpleLogger& Get();
void Enable(bool enable = true)
{
m_Enable = enable;
}
ScopedRecord StartNewRecord()
{
return ScopedRecord(m_Sinks, Level, m_Enable);
}
void RemoveAllSinks()
{
m_Sinks.clear();
}
void AddSink(std::shared_ptr<LogSink> sink)
{
m_Sinks.push_back(sink);
}
private:
std::vector<std::shared_ptr<LogSink>> m_Sinks;
bool m_Enable;
};
void SetLogFilter(LogSeverity level);
void SetAllLoggingSinks(bool standardOut, bool debugOut, bool coloured);
enum class BoostLogSeverityMapping
{
trace,
debug,
info,
warning,
error,
fatal
};
constexpr LogSeverity ConvertLogSeverity(BoostLogSeverityMapping severity)
{
return static_cast<LogSeverity>(severity);
}
#define ARMNN_LOG(severity) \
armnn::SimpleLogger<ConvertLogSeverity(armnn::BoostLogSeverityMapping::severity)>::Get().StartNewRecord()
} //namespace armnn