162d385b893094b974a9dfc47454a2dda1c37839
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / logger.cpp
1 /*
2  * Copyright (C) 2015 Canonical, Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 3, as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranties of
10  * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11  * PURPOSE.  See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 #include <thread>
19
20 #ifndef BOOST_LOG_DYN_LINK
21 #define BOOST_LOG_DYN_LINK
22 #endif
23 #include <boost/date_time.hpp>
24 #include <boost/filesystem.hpp>
25 #include <boost/log/expressions.hpp>
26 #include <boost/log/support/date_time.hpp>
27 #include <boost/log/trivial.hpp>
28 #include <boost/log/utility/manipulators.hpp>
29 #include <boost/log/utility/setup.hpp>
30 #define BOOST_LOG_USE_NATIVE_SYSLOG
31 #include <boost/log/sinks/syslog_backend.hpp>
32
33 #include "anbox/logger.h"
34
35 namespace {
36 namespace attrs {
37 BOOST_LOG_ATTRIBUTE_KEYWORD(Severity, "Severity", anbox::Logger::Severity)
38 BOOST_LOG_ATTRIBUTE_KEYWORD(Location, "Location", anbox::Logger::Location)
39 BOOST_LOG_ATTRIBUTE_KEYWORD(Timestamp, "Timestamp", boost::posix_time::ptime)
40 }
41
42 struct BoostLogLogger : public anbox::Logger {
43   BoostLogLogger() : initialized_(false) {}
44
45   void Init(const anbox::Logger::Severity& severity = anbox::Logger::Severity::kWarning) override {
46     if (initialized_)
47       return;
48
49     boost::log::formatter formatter =
50         boost::log::expressions::stream
51         << "[" << attrs::Severity << " "
52         << boost::log::expressions::format_date_time<boost::posix_time::ptime>(
53                "Timestamp", "%Y-%m-%d %H:%M:%S")
54         << "] "
55         << boost::log::expressions::if_(boost::log::expressions::has_attr(
56                attrs::Location))[boost::log::expressions::stream
57                                  << "[" << attrs::Location << "] "]
58         << boost::log::expressions::smessage;
59
60     boost::log::core::get()->remove_all_sinks();
61
62     // If we have a controlling tty then we use the console for log outpu
63     // and otherwise we move everything into the system syslog.
64     if (isatty(0)) {
65       auto logger = boost::log::add_console_log(std::cout);
66       logger->set_formatter(formatter);
67     } else {
68       boost::shared_ptr<boost::log::sinks::syslog_backend> backend(
69             new boost::log::sinks::syslog_backend(
70               boost::log::keywords::facility = boost::log::sinks::syslog::user,
71               boost::log::keywords::use_impl = boost::log::sinks::syslog::native));
72       backend->set_severity_mapper(boost::log::sinks::syslog::direct_severity_mapping<int>("Severity"));
73       boost::log::core::get()->add_sink(boost::make_shared<boost::log::sinks::synchronous_sink<
74                                           boost::log::sinks::syslog_backend>>(backend));
75     }
76
77     severity_ = severity;
78     initialized_ = true;
79   }
80
81   void SetSeverity(const Severity& severity) override {
82     severity_ = severity;
83   }
84
85   Severity GetSeverity() override {
86     return severity_;
87   }
88
89   void Log(Severity severity, const std::string& message, const boost::optional<Location>& loc) override {
90     if (!initialized_) Init();
91
92     // FIXME somehow set_filter doesn't work with the trivial logger. If
93     // we set a filter based on the severity attribute open_record will
94     // not return a new record. Because of that we do a poor man filtering
95     // here until we have a proper way to do this via boost.
96     if (severity < severity_)
97       return;
98
99     if (auto rec = boost::log::trivial::logger::get().open_record()) {
100       boost::log::record_ostream out{rec};
101       out << boost::log::add_value(attrs::Severity, severity)
102           << boost::log::add_value(attrs::Timestamp, boost::posix_time::microsec_clock::universal_time())
103           << message;
104
105       if (loc) {
106         // We have to pass in a temporary as boost::log (<= 1.55) expects a
107         // mutable reference to be passed to boost::log::add_value(...).
108         auto tmp = *loc;
109         out << boost::log::add_value(attrs::Location, tmp);
110       }
111
112       boost::log::trivial::logger::get().push_record(std::move(rec));
113     }
114   }
115
116  private:
117   Severity severity_;
118   bool initialized_;
119 };
120
121 std::shared_ptr<anbox::Logger>& MutableInstance() {
122   static std::shared_ptr<anbox::Logger> instance{new BoostLogLogger()};
123   return instance;
124 }
125
126 void SetInstance(const std::shared_ptr<anbox::Logger>& logger) {
127   MutableInstance() = logger;
128 }
129 }
130 namespace anbox {
131
132 bool Logger::SetSeverityFromString(const std::string& severity) {
133   if (severity == "trace")
134     SetSeverity(Severity::kTrace);
135   else if (severity == "debug")
136     SetSeverity(Severity::kDebug);
137   else if (severity == "info")
138     SetSeverity(Severity::kInfo);
139   else if (severity == "warning")
140     SetSeverity(Severity::kWarning);
141   else if (severity == "error")
142     SetSeverity(Severity::kError);
143   else if (severity == "fatal")
144     SetSeverity(Severity::kFatal);
145   else
146     return false;
147   return true;
148 }
149
150 void Logger::Trace(const std::string& message,
151                    const boost::optional<Location>& location) {
152   Log(Severity::kTrace, message, location);
153 }
154
155 void Logger::Debug(const std::string& message,
156                    const boost::optional<Location>& location) {
157   Log(Severity::kDebug, message, location);
158 }
159
160 void Logger::Info(const std::string& message,
161                   const boost::optional<Location>& location) {
162   Log(Severity::kInfo, message, location);
163 }
164
165 void Logger::Warning(const std::string& message,
166                      const boost::optional<Location>& location) {
167   Log(Severity::kWarning, message, location);
168 }
169
170 void Logger::Error(const std::string& message,
171                    const boost::optional<Location>& location) {
172   Log(Severity::kError, message, location);
173 }
174
175 void Logger::Fatal(const std::string& message,
176                    const boost::optional<Location>& location) {
177   Log(Severity::kFatal, message, location);
178 }
179
180 std::ostream& operator<<(std::ostream& strm, anbox::Logger::Severity severity) {
181   switch (severity) {
182     case anbox::Logger::Severity::kTrace:
183       return strm << "TT";
184     case anbox::Logger::Severity::kDebug:
185       return strm << "DD";
186     case anbox::Logger::Severity::kInfo:
187       return strm << "II";
188     case anbox::Logger::Severity::kWarning:
189       return strm << "WW";
190     case anbox::Logger::Severity::kError:
191       return strm << "EE";
192     case anbox::Logger::Severity::kFatal:
193       return strm << "FF";
194     default:
195       return strm << static_cast<unsigned int>(severity);
196   }
197 }
198
199 std::ostream& operator<<(std::ostream& out, const Logger::Location& location) {
200   return out << utils::string_format(
201              "%s:%d@%s",
202              boost::filesystem::path(location.file).filename().string(),
203              location.line, location.function);
204 }
205
206 Logger& Log() { return *MutableInstance(); }
207
208 void SetLogger(const std::shared_ptr<Logger>& logger) { SetInstance(logger); }
209
210 }  // namespace anbox