xref: /aosp_15_r20/external/armnn/include/armnn/Logging.hpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1 //
2 // Copyright © 2019,2022 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #pragma once
7 
8 #include <armnn/Utils.hpp>
9 #include <ctype.h>
10 #include <iostream>
11 #include <algorithm>
12 #include <memory>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 
17 #include <armnn/Exceptions.hpp>
18 
19 namespace armnn
20 {
21 
LevelToString(LogSeverity level)22 inline 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 
StringToLogLevel(std::string level)43 inline 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 
81 class LogSink
82 {
83 public:
~LogSink()84     virtual ~LogSink(){};
85 
86     virtual void Consume(const std::string&) = 0;
87 private:
88 
89 };
90 
91 class StandardOutputSink : public LogSink
92 {
93 public:
Consume(const std::string & s)94     void Consume(const std::string& s) override
95     {
96         std::cout << s << std::endl;
97     }
98 };
99 
100 struct ScopedRecord
101 {
ScopedRecordarmnn::ScopedRecord102     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 
~ScopedRecordarmnn::ScopedRecord112     ~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;
128     ScopedRecord& operator=(ScopedRecord&&) = delete;
129 
ScopedRecordarmnn::ScopedRecord130     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     }
139 
140     template<typename Streamable>
operator <<armnn::ScopedRecord141     ScopedRecord& operator<<(const Streamable& s)
142     {
143         if (m_Enabled)
144         {
145             m_Os << s;
146         }
147         return (*this);
148     }
149 
150 private:
151     const std::vector<std::shared_ptr<LogSink>>& m_LogSinks;
152     std::ostringstream m_Os;
153     bool m_Enabled;
154 };
155 
156 template<LogSeverity Level>
157 class SimpleLogger
158 {
159 public:
SimpleLogger()160     SimpleLogger()
161         : m_Sinks{std::make_shared<StandardOutputSink>()}
162         , m_Enable(true)
163     {
164     }
165 
166     static SimpleLogger& Get();
167 
Enable(bool enable=true)168     void Enable(bool enable = true)
169     {
170         m_Enable = enable;
171     }
172 
StartNewRecord()173     ScopedRecord StartNewRecord()
174     {
175         return ScopedRecord(m_Sinks, Level, m_Enable);
176     }
177 
RemoveAllSinks()178     void RemoveAllSinks()
179     {
180         m_Sinks.clear();
181     }
182 
AddSink(std::shared_ptr<LogSink> sink)183     void AddSink(std::shared_ptr<LogSink> sink)
184     {
185         m_Sinks.push_back(sink);
186     }
187 private:
188     std::vector<std::shared_ptr<LogSink>> m_Sinks;
189     bool m_Enable;
190 };
191 
192 void SetLogFilter(LogSeverity level);
193 
194 void SetAllLoggingSinks(bool standardOut, bool debugOut, bool coloured);
195 
196 enum class BoostLogSeverityMapping
197 {
198     trace,
199     debug,
200     info,
201     warning,
202     error,
203     fatal
204 };
205 
ConvertLogSeverity(BoostLogSeverityMapping severity)206 constexpr 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
216