1 //
2 // Copyright(c) 2015 Gabi Melman.
3 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
4 //
5
6 #pragma once
7
8 #include "spdlog/details/fmt_helper.h"
9 #include "spdlog/details/null_mutex.h"
10 #include "spdlog/details/os.h"
11 #include "spdlog/sinks/base_sink.h"
12
13 #include <android/log.h>
14 #include <chrono>
15 #include <mutex>
16 #include <string>
17 #include <thread>
18
19 #if !defined(SPDLOG_ANDROID_RETRIES)
20 #define SPDLOG_ANDROID_RETRIES 2
21 #endif
22
23 namespace spdlog {
24 namespace sinks {
25
26 /*
27 * Android sink (logging using __android_log_write)
28 */
29 template<typename Mutex>
30 class android_sink SPDLOG_FINAL : public base_sink<Mutex>
31 {
32 public:
android_sink(std::string tag = �, bool use_raw_msg = false)33 explicit android_sink(std::string tag = "spdlog", bool use_raw_msg = false)
34 : tag_(std::move(tag))
35 , use_raw_msg_(use_raw_msg)
36 {
37 }
38
39 protected:
40 void sink_it_(const details::log_msg &msg) override
41 {
42 const android_LogPriority priority = convert_to_android_(msg.level);
43 fmt::memory_buffer formatted;
44 if (use_raw_msg_)
45 {
46 details::fmt_helper::append_buf(msg.raw, formatted);
47 }
48 else
49 {
50 sink::formatter_->format(msg, formatted);
51 }
52 formatted.push_back('\0');
53 const char *msg_output = formatted.data();
54
55 // See system/core/liblog/logger_write.c for explanation of return value
56 int ret = __android_log_write(priority, tag_.c_str(), msg_output);
57 int retry_count = 0;
58 while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES))
59 {
60 details::os::sleep_for_millis(5);
61 ret = __android_log_write(priority, tag_.c_str(), msg_output);
62 retry_count++;
63 }
64
65 if (ret < 0)
66 {
67 throw spdlog_ex("__android_log_write() failed", ret);
68 }
69 }
70
71 void flush_() override {}
72
73 private:
convert_to_android_(spdlog::level::level_enum level)74 static android_LogPriority convert_to_android_(spdlog::level::level_enum level)
75 {
76 switch (level)
77 {
78 case spdlog::level::trace:
79 return ANDROID_LOG_VERBOSE;
80 case spdlog::level::debug:
81 return ANDROID_LOG_DEBUG;
82 case spdlog::level::info:
83 return ANDROID_LOG_INFO;
84 case spdlog::level::warn:
85 return ANDROID_LOG_WARN;
86 case spdlog::level::err:
87 return ANDROID_LOG_ERROR;
88 case spdlog::level::critical:
89 return ANDROID_LOG_FATAL;
90 default:
91 return ANDROID_LOG_DEFAULT;
92 }
93 }
94
95 std::string tag_;
96 bool use_raw_msg_;
97 };
98
99 using android_sink_mt = android_sink<std::mutex>;
100 using android_sink_st = android_sink<details::null_mutex>;
101 } // namespace sinks
102
103 // Create and register android syslog logger
104
105 template<typename Factory = default_factory>
android_logger_mt(const std::string &logger_name, const std::string &tag = �)106 inline std::shared_ptr<logger> android_logger_mt(const std::string &logger_name, const std::string &tag = "spdlog")
107 {
108 return Factory::template create<sinks::android_sink_mt>(logger_name, tag);
109 }
110
111 template<typename Factory = default_factory>
android_logger_st(const std::string &logger_name, const std::string &tag = �)112 inline std::shared_ptr<logger> android_logger_st(const std::string &logger_name, const std::string &tag = "spdlog")
113 {
114 return Factory::template create<sinks::android_sink_st>(logger_name, tag);
115 }
116
117 } // namespace spdlog
118