blob: a31c2aaa7b0177b85b342828b6028a7adda5602a [file] [log] [blame]
Jim Flynnbbfe6032020-07-20 16:57:44 +01001//
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
13namespace arm
14{
15
16namespace pipe
17{
18
19enum class LogSeverity
20{
21 Trace,
22 Debug,
23 Info,
24 Warning,
25 Error,
26 Fatal
27};
28
29inline std::string LevelToString(LogSeverity level)
30{
31 switch(level)
32 {
33 case LogSeverity::Trace:
34 return "Trace";
35 case LogSeverity::Debug:
36 return "Debug";
37 case LogSeverity::Info:
38 return "Info";
39 case LogSeverity::Warning:
40 return "Warning";
41 case LogSeverity::Error:
42 return "Error";
43 case LogSeverity::Fatal:
44 return "Fatal";
45 default:
46 return "Log";
47 }
48}
49
50class LogSink
51{
52public:
53 virtual ~LogSink(){};
54
55 virtual void Consume(const std::string&) = 0;
56private:
57
58};
59
60class StandardOutputSink : public LogSink
61{
62public:
63 void Consume(const std::string& s) override
64 {
65 std::cout << s << std::endl;
66 }
67};
68
69struct ScopedRecord
70{
71 ScopedRecord(const std::vector<std::shared_ptr<LogSink>>& sinks, LogSeverity level, bool enabled)
72 : m_LogSinks(sinks)
73 , m_Enabled(enabled)
74 {
75 if (enabled)
76 {
77 m_Os << LevelToString(level) << ": ";
78 }
79 }
80
81 ~ScopedRecord()
82 {
83 if (m_Enabled)
84 {
85 for (auto sink : m_LogSinks)
86 {
87 if (sink)
88 {
89 sink->Consume(m_Os.str());
90 }
91 }
92 }
93 }
94
95 ScopedRecord(const ScopedRecord&) = delete;
96 ScopedRecord& operator=(const ScopedRecord&) = delete;
97 ScopedRecord& operator=(ScopedRecord&&) = delete;
98
99 ScopedRecord(ScopedRecord&& other) = default;
100
101 template<typename Streamable>
102 ScopedRecord& operator<<(const Streamable& s)
103 {
104 if (m_Enabled)
105 {
106 m_Os << s;
107 }
108 return (*this);
109 }
110
111private:
112 const std::vector<std::shared_ptr<LogSink>>& m_LogSinks;
113 std::ostringstream m_Os;
114 bool m_Enabled;
115};
116
117template<LogSeverity Level>
118class SimpleLogger
119{
120public:
121 SimpleLogger()
122 : m_Sinks{std::make_shared<StandardOutputSink>()}
123 , m_Enable(true)
124 {
125 }
126
127 static SimpleLogger& Get()
128 {
129 static SimpleLogger<Level> logger;
130 return logger;
131 }
132
133 void Enable(bool enable = true)
134 {
135 m_Enable = enable;
136 }
137
138 ScopedRecord StartNewRecord()
139 {
140 ScopedRecord record(m_Sinks, Level, m_Enable);
141 return record;
142 }
143
144 void RemoveAllSinks()
145 {
146 m_Sinks.clear();
147 }
148
149 void AddSink(std::shared_ptr<LogSink> sink)
150 {
151 m_Sinks.push_back(sink);
152 }
153private:
154 std::vector<std::shared_ptr<LogSink>> m_Sinks;
155 bool m_Enable;
156};
157
158void SetLogFilter(LogSeverity level);
159
160void SetAllLoggingSinks(bool standardOut, bool debugOut, bool coloured);
161
162enum class BoostLogSeverityMapping
163{
164 trace,
165 debug,
166 info,
167 warning,
168 error,
169 fatal
170};
171
172constexpr LogSeverity ConvertLogSeverity(BoostLogSeverityMapping severity)
173{
174 return static_cast<LogSeverity>(severity);
175}
176
177
178#define ARM_PIPE_LOG(severity) \
179 arm::pipe::SimpleLogger<ConvertLogSeverity(arm::pipe::BoostLogSeverityMapping::severity)>::Get().StartNewRecord()
180
181} // namespace pipe
182} // namespace arm