Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2023 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include "Logger.h"
21 : #include <chrono>
22 : #include <ctime>
23 : #include <iomanip>
24 : #include <iostream>
25 : #include <unistd.h>
26 :
27 : #ifdef USE_ETHANLOG
28 :
29 : #include <ethanlog.h>
30 :
31 : #define SYSTEM_LOG_FATAL(filename, function, line, ...) ethanlog(ETHAN_LOG_FATAL, filename, function, line, __VA_ARGS__)
32 : #define SYSTEM_LOG_ERROR(filename, function, line, ...) ethanlog(ETHAN_LOG_ERROR, filename, function, line, __VA_ARGS__)
33 : #define SYSTEM_LOG_WARN(filename, function, line, ...) \
34 : ethanlog(ETHAN_LOG_WARNING, filename, function, line, __VA_ARGS__)
35 : #define SYSTEM_LOG_MIL(filename, function, line, ...) \
36 : ethanlog(ETHAN_LOG_MILESTONE, filename, function, line, __VA_ARGS__)
37 : #define SYSTEM_LOG_INFO(filename, function, line, ...) ethanlog(ETHAN_LOG_INFO, filename, function, line, __VA_ARGS__)
38 : #define SYSTEM_LOG_DEBUG(filename, function, line, ...) ethanlog(ETHAN_LOG_DEBUG, filename, function, line, __VA_ARGS__)
39 :
40 : #else
41 :
42 : #include <syslog.h>
43 :
44 : #define SYSTEM_LOG_FATAL(filename, function, line, ...) syslog(LOG_CRIT, __VA_ARGS__)
45 : #define SYSTEM_LOG_ERROR(filename, function, line, ...) syslog(LOG_ERR, __VA_ARGS__)
46 : #define SYSTEM_LOG_WARN(filename, function, line, ...) syslog(LOG_WARNING, __VA_ARGS__)
47 : #define SYSTEM_LOG_MIL(filename, function, line, ...) syslog(LOG_NOTICE, __VA_ARGS__)
48 : #define SYSTEM_LOG_INFO(filename, function, line, ...) syslog(LOG_INFO, __VA_ARGS__)
49 : #define SYSTEM_LOG_DEBUG(filename, function, line, ...) syslog(LOG_DEBUG, __VA_ARGS__)
50 :
51 : #endif
52 :
53 : namespace
54 : {
55 576 : Severity getLogLevel()
56 : {
57 576 : const char *debugVar = getenv("RIALTO_DEBUG");
58 576 : if (debugVar)
59 : {
60 1140 : std::string varStr{debugVar};
61 570 : if ("0" == varStr)
62 6 : return Severity::fatal;
63 564 : if ("1" == varStr)
64 6 : return Severity::error;
65 558 : if ("2" == varStr)
66 6 : return Severity::warn;
67 552 : if ("3" == varStr)
68 6 : return Severity::mil;
69 546 : if ("4" == varStr)
70 6 : return Severity::info;
71 540 : if ("5" == varStr)
72 540 : return Severity::debug;
73 570 : }
74 6 : return Severity::warn;
75 : }
76 :
77 1066 : bool isConsoleLogEnabled()
78 : {
79 1066 : const char *debugVar = getenv("RIALTO_CONSOLE_LOG");
80 1066 : if (debugVar)
81 : {
82 2106 : return std::string(debugVar) == "1";
83 : }
84 13 : return false;
85 : }
86 :
87 15 : std::string getRialtoLogPath()
88 : {
89 15 : const char *logPathEnvVar = getenv("RIALTO_LOG_PATH");
90 15 : if (logPathEnvVar)
91 : {
92 14 : return std::string(logPathEnvVar);
93 : }
94 16 : return "";
95 : }
96 :
97 576 : std::string toString(const Severity &severity)
98 : {
99 576 : if (Severity::fatal == severity)
100 18 : return "ftl";
101 567 : if (Severity::error == severity)
102 166 : return "err";
103 484 : if (Severity::warn == severity)
104 44 : return "wrn";
105 462 : if (Severity::mil == severity)
106 20 : return "mil";
107 452 : if (Severity::info == severity)
108 310 : return "inf";
109 297 : if (Severity::debug == severity)
110 590 : return "dbg";
111 4 : return "???";
112 : }
113 :
114 : } // namespace
115 :
116 1170 : LogFile &LogFile::instance()
117 : {
118 1170 : static LogFile logFile;
119 1170 : return logFile;
120 : }
121 :
122 24 : bool LogFile::write(const std::string &line)
123 : {
124 24 : std::unique_lock<std::mutex> lock{m_mutex};
125 24 : m_file << line << std::endl;
126 24 : return true;
127 : }
128 :
129 1132 : bool LogFile::isEnabled() const
130 : {
131 1132 : return m_file.is_open();
132 : }
133 :
134 14 : void LogFile::reset()
135 : {
136 14 : tryCloseFile();
137 14 : tryOpenFile();
138 : }
139 :
140 1 : LogFile::LogFile()
141 : {
142 1 : tryOpenFile();
143 : }
144 :
145 1 : LogFile::~LogFile()
146 : {
147 1 : tryCloseFile();
148 : }
149 :
150 15 : void LogFile::tryOpenFile()
151 : {
152 15 : std::string logPath{getRialtoLogPath()};
153 15 : if (!logPath.empty())
154 : {
155 : // Add suffix to have rialto client and rialto ocdm logs in separate files
156 7 : logPath += ".ocdm";
157 7 : m_file = std::fstream(logPath, std::fstream::out);
158 : }
159 15 : }
160 :
161 15 : void LogFile::tryCloseFile()
162 : {
163 15 : if (m_file.is_open())
164 : {
165 7 : m_file.close();
166 : }
167 15 : }
168 :
169 576 : Flusher::Flusher(std::stringstream &stream, const std::string &componentName, const Severity &severity)
170 576 : : m_stream{stream}, m_severity{severity}
171 : {
172 576 : if (LogFile::instance().isEnabled() || isConsoleLogEnabled())
173 : {
174 569 : const std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
175 569 : const std::time_t t_c = std::chrono::system_clock::to_time_t(now);
176 569 : m_stream << std::put_time(std::localtime(&t_c), "[%F %T]");
177 : }
178 576 : m_stream << "[" << componentName << "][" << toString(severity) << "]: ";
179 : }
180 :
181 576 : Flusher::~Flusher()
182 : {
183 576 : if (getLogLevel() >= m_severity)
184 : {
185 556 : if (LogFile::instance().isEnabled())
186 : {
187 24 : LogFile::instance().write(m_stream.str());
188 : }
189 532 : else if (isConsoleLogEnabled())
190 : {
191 526 : std::cout << m_stream.str() << std::endl;
192 : }
193 : else
194 : {
195 6 : switch (m_severity)
196 : {
197 1 : case Severity::fatal:
198 1 : SYSTEM_LOG_FATAL(nullptr, nullptr, -1, "%s", m_stream.str().c_str());
199 1 : break;
200 1 : case Severity::error:
201 1 : SYSTEM_LOG_ERROR(nullptr, nullptr, -1, "%s", m_stream.str().c_str());
202 1 : break;
203 1 : case Severity::warn:
204 1 : SYSTEM_LOG_WARN(nullptr, nullptr, -1, "%s", m_stream.str().c_str());
205 1 : break;
206 1 : case Severity::mil:
207 1 : SYSTEM_LOG_MIL(nullptr, nullptr, -1, "%s", m_stream.str().c_str());
208 1 : break;
209 1 : case Severity::info:
210 1 : SYSTEM_LOG_INFO(nullptr, nullptr, -1, "%s", m_stream.str().c_str());
211 1 : break;
212 1 : case Severity::debug:
213 : default:
214 1 : SYSTEM_LOG_DEBUG(nullptr, nullptr, -1, "%s", m_stream.str().c_str());
215 1 : break;
216 : }
217 : }
218 : }
219 1152 : m_stream.str("");
220 576 : }
221 :
222 189 : Logger::Logger(const std::string &componentName) : m_componentName{componentName} {}
223 :
224 576 : Flusher Logger::operator<<(const Severity &severity) const
225 : {
226 576 : return Flusher(m_stream, m_componentName, severity);
227 : }
|