blob: ca52b5c98fd839550ce298548bff1846b768323d [file] [log] [blame]
Derek Lamberti08446972019-11-26 16:38:31 +00001//
Colm Donelana98e79a2022-12-06 21:32:29 +00002// Copyright © 2019,2022 Arm Ltd and Contributors. All rights reserved.
Derek Lamberti08446972019-11-26 16:38:31 +00003// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
Matthew Benthamd3a07832020-01-15 17:21:38 +00008#include <armnn/Utils.hpp>
Colm Donelana98e79a2022-12-06 21:32:29 +00009#include <ctype.h>
Derek Lamberti08446972019-11-26 16:38:31 +000010#include <iostream>
Jan Eilers2cd18472020-12-15 10:42:38 +000011#include <algorithm>
Colm Donelana98e79a2022-12-06 21:32:29 +000012#include <memory>
13#include <string>
14#include <utility>
15#include <vector>
16
17#include <armnn/Exceptions.hpp>
Derek Lamberti08446972019-11-26 16:38:31 +000018
Derek Lamberti08446972019-11-26 16:38:31 +000019namespace armnn
20{
21
22inline std::string LevelToString(LogSeverity level)
23{
24 switch(level)
25 {
26 case LogSeverity::Trace:
27 return "Trace";
28 case LogSeverity::Debug:
29 return "Debug";
30 case LogSeverity::Info:
31 return "Info";
32 case LogSeverity::Warning:
33 return "Warning";
34 case LogSeverity::Error:
35 return "Error";
36 case LogSeverity::Fatal:
37 return "Fatal";
38 default:
39 return "Log";
40 }
41}
42
Jan Eilers2cd18472020-12-15 10:42:38 +000043inline LogSeverity StringToLogLevel(std::string level)
44{
45 // Transfer to lower case
46 std::transform(level.begin(), level.end(), level.begin(),
47 [](unsigned char c){ return std::tolower(c); }
48 );
49
50 if (level == "trace")
51 {
52 return LogSeverity::Trace;
53 }
54 else if (level == "debug")
55 {
56 return LogSeverity::Debug;
57 }
58 else if (level == "info")
59 {
60 return LogSeverity::Info;
61 }
62 else if (level == "warning")
63 {
64 return LogSeverity::Warning;
65 }
66 else if (level == "error")
67 {
68 return LogSeverity::Error;
69 }
70 else if (level == "fatal")
71 {
72 return LogSeverity::Fatal;
73 }
74 else
75 {
76 throw armnn::Exception("Unknown severity level for logging: '" + level +
77 "'. Valid options: trace, debug, info, warning, error, fatal");
78 }
79}
80
Derek Lamberti08446972019-11-26 16:38:31 +000081class LogSink
82{
83public:
84 virtual ~LogSink(){};
85
Francis Murtaghb4f312c2019-12-31 12:44:20 +000086 virtual void Consume(const std::string&) = 0;
Derek Lamberti08446972019-11-26 16:38:31 +000087private:
88
89};
90
Derek Lamberti08446972019-11-26 16:38:31 +000091class StandardOutputSink : public LogSink
92{
93public:
94 void Consume(const std::string& s) override
95 {
96 std::cout << s << std::endl;
97 }
98};
99
Derek Lamberti08446972019-11-26 16:38:31 +0000100struct ScopedRecord
101{
102 ScopedRecord(const std::vector<std::shared_ptr<LogSink>>& sinks, LogSeverity level, bool enabled)
103 : m_LogSinks(sinks)
104 , m_Enabled(enabled)
105 {
106 if (enabled)
107 {
108 m_Os << LevelToString(level) << ": ";
109 }
110 }
111
112 ~ScopedRecord()
113 {
114 if (m_Enabled)
115 {
116 for (auto sink : m_LogSinks)
117 {
118 if (sink)
119 {
120 sink->Consume(m_Os.str());
121 }
122 }
123 }
124 }
125
126 ScopedRecord(const ScopedRecord&) = delete;
127 ScopedRecord& operator=(const ScopedRecord&) = delete;
Matthew Bentham13757bd2020-02-10 17:23:39 +0000128 ScopedRecord& operator=(ScopedRecord&&) = delete;
129
Rob Hughes524a99c2022-01-26 09:30:57 +0000130 ScopedRecord(ScopedRecord&& other)
131 : m_LogSinks(other.m_LogSinks)
132 , m_Os(std::move(other.m_Os))
133 , m_Enabled(other.m_Enabled)
134 {
135 // Disable the moved-from ScopedRecord, to prevent it from sending its (now empty) message to
136 // its sinks.
137 other.m_Enabled = false;
138 }
Derek Lamberti08446972019-11-26 16:38:31 +0000139
140 template<typename Streamable>
141 ScopedRecord& operator<<(const Streamable& s)
142 {
143 if (m_Enabled)
144 {
145 m_Os << s;
146 }
147 return (*this);
148 }
149
150private:
151 const std::vector<std::shared_ptr<LogSink>>& m_LogSinks;
152 std::ostringstream m_Os;
153 bool m_Enabled;
154};
155
156template<LogSeverity Level>
157class SimpleLogger
158{
159public:
160 SimpleLogger()
161 : m_Sinks{std::make_shared<StandardOutputSink>()}
162 , m_Enable(true)
163 {
164 }
165
Sadik Armagan4a0844d2022-01-26 09:57:05 +0000166 static SimpleLogger& Get();
Derek Lamberti08446972019-11-26 16:38:31 +0000167
168 void Enable(bool enable = true)
169 {
170 m_Enable = enable;
171 }
172
173 ScopedRecord StartNewRecord()
174 {
Rob Hughes524a99c2022-01-26 09:30:57 +0000175 return ScopedRecord(m_Sinks, Level, m_Enable);
Derek Lamberti08446972019-11-26 16:38:31 +0000176 }
177
178 void RemoveAllSinks()
179 {
180 m_Sinks.clear();
181 }
182
183 void AddSink(std::shared_ptr<LogSink> sink)
184 {
185 m_Sinks.push_back(sink);
186 }
187private:
188 std::vector<std::shared_ptr<LogSink>> m_Sinks;
189 bool m_Enable;
190};
191
Matthew Benthamd3a07832020-01-15 17:21:38 +0000192void SetLogFilter(LogSeverity level);
Derek Lamberti08446972019-11-26 16:38:31 +0000193
Matthew Benthamd3a07832020-01-15 17:21:38 +0000194void SetAllLoggingSinks(bool standardOut, bool debugOut, bool coloured);
Derek Lamberti08446972019-11-26 16:38:31 +0000195
196enum class BoostLogSeverityMapping
197{
198 trace,
199 debug,
200 info,
201 warning,
202 error,
203 fatal
204};
205
206constexpr LogSeverity ConvertLogSeverity(BoostLogSeverityMapping severity)
207{
208 return static_cast<LogSeverity>(severity);
209}
210
211
212#define ARMNN_LOG(severity) \
213 armnn::SimpleLogger<ConvertLogSeverity(armnn::BoostLogSeverityMapping::severity)>::Get().StartNewRecord()
214
215} //namespace armnn