1 // Copyright (C) 2021 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifdef __ANDROID__
16 #include <android-base/logging.h>
17 #include <log/log.h>
18 #endif
19
20 #include <ditto/logger.h>
21
22 #include <string.h>
23
24 #include <chrono>
25 #include <iomanip>
26
27 namespace dittosuite {
28
GetInstance()29 Logger& Logger::GetInstance() {
30 static Logger logger;
31 return logger;
32 }
33
SetLogLevel(const LogLevel log_level)34 void Logger::SetLogLevel(const LogLevel log_level) {
35 log_level_ = log_level;
36 }
37
SetLogStream(const LogStream log_stream)38 void Logger::SetLogStream(const LogStream log_stream) {
39 log_stream_ = log_stream;
40 }
41
GetLogLevel() const42 LogLevel Logger::GetLogLevel() const {
43 return log_level_;
44 }
45
GetLogStream() const46 LogStream Logger::GetLogStream() const {
47 return log_stream_;
48 }
49
LogLevelToString(const LogLevel log_level)50 std::string LogLevelToString(const LogLevel log_level) {
51 static const std::string prefixes[] = {"VERBOSE", "DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
52 return prefixes[static_cast<int>(log_level)];
53 }
54
55 #ifdef __ANDROID__
LogLevelToAndroidLogLevel(const LogLevel log_level)56 android::base::LogSeverity LogLevelToAndroidLogLevel(const LogLevel log_level) {
57 switch (log_level) {
58 case LogLevel::kVerbose:
59 return android::base::VERBOSE;
60 case LogLevel::kDebug:
61 return android::base::DEBUG;
62 case LogLevel::kInfo:
63 return android::base::INFO;
64 case LogLevel::kWarning:
65 return android::base::WARNING;
66 case LogLevel::kError:
67 return android::base::ERROR;
68 case LogLevel::kFatal:
69 return android::base::FATAL;
70 }
71 }
72 #endif
73
WriteLogMessage(const LogLevel log_level,const std::string & message,const std::string & file_name,int line,bool print_errno)74 void Logger::WriteLogMessage(const LogLevel log_level, const std::string& message,
75 const std::string& file_name, int line, bool print_errno) {
76 using namespace std::chrono;
77
78 std::stringstream ss;
79
80 auto now = system_clock::now();
81 auto ms = duration_cast<milliseconds>(now.time_since_epoch()) % 1000;
82 auto timer = system_clock::to_time_t(now);
83 std::tm bt = *std::localtime(&timer);
84
85 // Date/time
86 ss << '[' << std::put_time(&bt, "%F %T") << '.' << std::setfill('0') << std::setw(3) << ms.count()
87 << ']';
88 // Log level
89 ss << " " << LogLevelToString(log_level);
90 // File and line
91 ss << ' ' << file_name << ":" << line;
92 // Message and errno
93 ss << " " << message;
94 if (print_errno) {
95 ss << ": " << strerror(errno);
96 }
97 switch (log_stream_) {
98 case LogStream::kLogcat:
99 #ifdef __ANDROID__
100 LOG(LogLevelToAndroidLogLevel(log_level)) << ss.str();
101 break;
102 #else
103 [[fallthrough]];
104 #endif
105 case LogStream::kStdout:
106 std::cout << ss.str() << std::endl;
107 break;
108 }
109 }
110
111 } // namespace dittosuite
112