1 // Copyright (C) 2020 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
2 // This Source Code Form is subject to the terms of the Mozilla Public
3 // License, v. 2.0. If a copy of the MPL was not distributed with this
4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
6 #include <chrono>
7 #include <ctime>
8 #include <fstream>
9 #include <iomanip>
10 #include <iostream>
11
12 #ifdef ANDROID
13 #include <android/log.h>
14
15 #ifndef LOG_TAG
16 #define LOG_TAG NULL
17 #endif
18 #endif
19
20 #include <vsomeip/internal/logger.hpp>
21
22 #include "../include/logger_impl.hpp"
23 #include "../../configuration/include/configuration.hpp"
24
25 namespace vsomeip_v3 {
26 namespace logger {
27
28 std::mutex message::mutex__;
29
message(level_e _level)30 message::message(level_e _level)
31 : std::ostream(&buffer_),
32 level_(_level) {
33
34 when_ = std::chrono::system_clock::now();
35 }
36
~message()37 message::~message() {
38 std::lock_guard<std::mutex> its_lock(mutex__);
39 auto its_logger = logger_impl::get();
40 auto its_configuration = its_logger->get_configuration();
41
42 if (!its_configuration)
43 return;
44
45 if (level_ > its_configuration->get_loglevel())
46 return;
47
48 if (its_configuration->has_console_log()
49 || its_configuration->has_file_log()) {
50
51 // Prepare log level
52 const char *its_level;
53 switch (level_) {
54 case level_e::LL_FATAL:
55 its_level = "fatal";
56 break;
57 case level_e::LL_ERROR:
58 its_level = "error";
59 break;
60 case level_e::LL_WARNING:
61 its_level = "warning";
62 break;
63 case level_e::LL_INFO:
64 its_level = "info";
65 break;
66 case level_e::LL_DEBUG:
67 its_level = "debug";
68 break;
69 case level_e::LL_VERBOSE:
70 its_level = "verbose";
71 break;
72 default:
73 its_level = "none";
74 };
75
76 // Prepare time stamp
77 auto its_time_t = std::chrono::system_clock::to_time_t(when_);
78 auto its_time = std::localtime(&its_time_t);
79 auto its_ms = (when_.time_since_epoch().count() / 100) % 1000000;
80
81 if (its_configuration->has_console_log()) {
82 #ifndef ANDROID
83 std::cout
84 << std::dec << std::setw(4) << its_time->tm_year + 1900 << "-"
85 << std::dec << std::setw(2) << std::setfill('0') << its_time->tm_mon << "-"
86 << std::dec << std::setw(2) << std::setfill('0') << its_time->tm_mday << " "
87 << std::dec << std::setw(2) << std::setfill('0') << its_time->tm_hour << ":"
88 << std::dec << std::setw(2) << std::setfill('0') << its_time->tm_min << ":"
89 << std::dec << std::setw(2) << std::setfill('0') << its_time->tm_sec << "."
90 << std::dec << std::setw(6) << std::setfill('0') << its_ms << " ["
91 << its_level << "] "
92 << buffer_.data_.str()
93 << std::endl;
94 #else
95 switch (level_) {
96 case level_e::LL_FATAL:
97 (void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "%s", buffer_.data_.str().c_str());
98 break;
99 case level_e::LL_ERROR:
100 (void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "%s", buffer_.data_.str().c_str());
101 break;
102 case level_e::LL_WARNING:
103 (void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "%s", buffer_.data_.str().c_str());
104 break;
105 case level_e::LL_INFO:
106 (void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "%s", buffer_.data_.str().c_str());
107 break;
108 case level_e::LL_DEBUG:
109 (void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "%s", buffer_.data_.str().c_str());
110 break;
111 case level_e::LL_VERBOSE:
112 (void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", buffer_.data_.str().c_str());
113 break;
114 default:
115 (void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "%s", buffer_.data_.str().c_str());
116 };
117 #endif // !ANDROID
118 }
119
120 if (its_configuration->has_file_log()) {
121 std::ofstream its_logfile(
122 its_configuration->get_logfile(),
123 std::ios_base::app);
124 if (its_logfile.is_open()) {
125 its_logfile
126 << std::dec << std::setw(4) << its_time->tm_year + 1900 << "-"
127 << std::dec << std::setw(2) << std::setfill('0') << its_time->tm_mon << "-"
128 << std::dec << std::setw(2) << std::setfill('0') << its_time->tm_mday << " "
129 << std::dec << std::setw(2) << std::setfill('0') << its_time->tm_hour << ":"
130 << std::dec << std::setw(2) << std::setfill('0') << its_time->tm_min << ":"
131 << std::dec << std::setw(2) << std::setfill('0') << its_time->tm_sec << "."
132 << std::dec << std::setw(6) << std::setfill('0') << its_ms << " ["
133 << its_level << "] "
134 << buffer_.data_.str()
135 << std::endl;
136 }
137 }
138 }
139 if (its_configuration->has_dlt_log()) {
140 #ifdef USE_DLT
141 its_logger->log(level_, buffer_.data_.str().c_str());
142 #endif // USE_DLT
143 }
144 }
145
146 std::streambuf::int_type
overflow(std::streambuf::int_type c)147 message::buffer::overflow(std::streambuf::int_type c) {
148 if (c != EOF) {
149 data_ << (char)c;
150 }
151
152 return (c);
153 }
154
155 std::streamsize
xsputn(const char * s,std::streamsize n)156 message::buffer::xsputn(const char *s, std::streamsize n) {
157 data_.write(s, n);
158 return (n);
159 }
160
161 } // namespace logger
162 } // namespace vsomeip_v3
163