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