1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #pragma once
7
8 #include <iostream>
9 #include <memory>
10 #include <sstream>
11 #include <vector>
12
13 namespace arm
14 {
15
16 namespace pipe
17 {
18
19 #if defined(__clang__) &&((__clang_major__>=3)||(__clang_major__==3 && __clang_minor__ >= 5))
20 # define ARM_PIPE_FALLTHROUGH [[clang::fallthrough]]
21 #elif defined(__GNUC__) && (__GNUC__ >= 7)
22 # define ARM_PIPE_FALLTHROUGH __attribute__((fallthrough))
23 #else
24 # define ARM_PIPE_FALLTHROUGH ((void)0)
25 #endif
26
27 enum class LogSeverity
28 {
29 Trace,
30 Debug,
31 Info,
32 Warning,
33 Error,
34 Fatal
35 };
36
LevelToString(LogSeverity level)37 inline std::string LevelToString(LogSeverity level)
38 {
39 switch(level)
40 {
41 case LogSeverity::Trace:
42 return "Trace";
43 case LogSeverity::Debug:
44 return "Debug";
45 case LogSeverity::Info:
46 return "Info";
47 case LogSeverity::Warning:
48 return "Warning";
49 case LogSeverity::Error:
50 return "Error";
51 case LogSeverity::Fatal:
52 return "Fatal";
53 default:
54 return "Log";
55 }
56 }
57
58 /// Configures the logging behaviour of the ARMNN library.
59 /// printToStandardOutput: Set to true if log messages should be printed to the standard output.
60 /// printToDebugOutput: Set to true if log messages be printed to a platform-specific debug output
61 /// (where supported).
62 /// severity: All log messages that are at this severity level or higher will be printed, others will be ignored.
63 void ConfigureLogging(bool printToStandardOutput, bool printToDebugOutput, LogSeverity severity);
64
65 class LogSink
66 {
67 public:
~LogSink()68 virtual ~LogSink(){};
69
70 virtual void Consume(const std::string&) = 0;
71 private:
72
73 };
74
75 class StandardOutputSink : public LogSink
76 {
77 public:
Consume(const std::string & s)78 void Consume(const std::string& s) override
79 {
80 std::cout << s << std::endl;
81 }
82 };
83
84 struct ScopedRecord
85 {
ScopedRecordarm::pipe::ScopedRecord86 ScopedRecord(const std::vector<std::shared_ptr<LogSink>>& sinks, LogSeverity level, bool enabled)
87 : m_LogSinks(sinks)
88 , m_Enabled(enabled)
89 {
90 if (enabled)
91 {
92 m_Os << LevelToString(level) << ": ";
93 }
94 }
95
~ScopedRecordarm::pipe::ScopedRecord96 ~ScopedRecord()
97 {
98 if (m_Enabled)
99 {
100 for (auto sink : m_LogSinks)
101 {
102 if (sink)
103 {
104 sink->Consume(m_Os.str());
105 }
106 }
107 }
108 }
109
110 ScopedRecord(const ScopedRecord&) = delete;
111 ScopedRecord& operator=(const ScopedRecord&) = delete;
112 ScopedRecord& operator=(ScopedRecord&&) = delete;
113
114 ScopedRecord(ScopedRecord&& other) = default;
115
116 template<typename Streamable>
operator <<arm::pipe::ScopedRecord117 ScopedRecord& operator<<(const Streamable& s)
118 {
119 if (m_Enabled)
120 {
121 m_Os << s;
122 }
123 return (*this);
124 }
125
126 private:
127 const std::vector<std::shared_ptr<LogSink>>& m_LogSinks;
128 std::ostringstream m_Os;
129 bool m_Enabled;
130 };
131
132 template<LogSeverity Level>
133 class SimpleLogger
134 {
135 public:
SimpleLogger()136 SimpleLogger()
137 : m_Sinks{std::make_shared<StandardOutputSink>()}
138 , m_Enable(true)
139 {
140 }
141
Get()142 static SimpleLogger<Level>& Get()
143 {
144 static SimpleLogger<Level> logger;
145 return logger;
146 }
147
Enable(bool enable=true)148 void Enable(bool enable = true)
149 {
150 m_Enable = enable;
151 }
152
StartNewRecord()153 ScopedRecord StartNewRecord()
154 {
155 ScopedRecord record(m_Sinks, Level, m_Enable);
156 return record;
157 }
158
RemoveAllSinks()159 void RemoveAllSinks()
160 {
161 m_Sinks.clear();
162 }
163
AddSink(std::shared_ptr<LogSink> sink)164 void AddSink(std::shared_ptr<LogSink> sink)
165 {
166 m_Sinks.push_back(sink);
167 }
168 private:
169 std::vector<std::shared_ptr<LogSink>> m_Sinks;
170 bool m_Enable;
171 };
172
173 void SetLogFilter(LogSeverity level);
174
175 void SetAllLoggingSinks(bool standardOut, bool debugOut, bool coloured);
176
177 enum class BoostLogSeverityMapping
178 {
179 trace,
180 debug,
181 info,
182 warning,
183 error,
184 fatal
185 };
186
ConvertLogSeverity(BoostLogSeverityMapping severity)187 constexpr LogSeverity ConvertLogSeverity(BoostLogSeverityMapping severity)
188 {
189 return static_cast<LogSeverity>(severity);
190 }
191
192
193 #define ARM_PIPE_LOG(severity) \
194 arm::pipe::SimpleLogger<ConvertLogSeverity(arm::pipe::BoostLogSeverityMapping::severity)>::Get().StartNewRecord()
195
196 } // namespace pipe
197 } // namespace arm
198