Line data Source code
1 : /**
2 : * Copyright (C) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
3 : *
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : * Unless required by applicable law or agreed to in writing, software
9 : * distributed under the License is distributed on an "AS IS" BASIS,
10 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 : * See the License for the specific language governing permissions and
12 : * limitations under the License.
13 : */
14 : /**
15 : * @file nntrainer_logger.cpp
16 : * @date 02 April 2020
17 : * @brief NNTrainer Logger
18 : * This allows to logging nntrainer logs.
19 : * @see https://github.com/nnstreamer/nntrainer
20 : * @author Jijoong Moon <jijoong.moon@samsung.com>
21 : * @bug No known bugs except for NYI items
22 : */
23 :
24 : #include <cstring>
25 : #include <ctime>
26 : #include <filesystem>
27 : #include <iomanip>
28 : #include <iostream>
29 : #include <mutex>
30 : #include <nntrainer_logger.h>
31 : #include <sstream>
32 : #include <stdarg.h>
33 : #include <stdexcept>
34 : #include <util_func.h>
35 :
36 : namespace nntrainer {
37 :
38 : /**
39 : * @brief logfile name
40 : */
41 : const char *const Logger::logfile_name = "log_nntrainer_";
42 : const char *const Logger::logfile_dir = "./logs/";
43 : /**
44 : * @brief instance for single logger
45 : */
46 : Logger *Logger::ainstance = nullptr;
47 :
48 : /**
49 : * @brief mutex for lock
50 : */
51 : std::mutex Logger::smutex;
52 :
53 56734 : Logger &Logger::instance() {
54 56734 : static Cleanup cleanup;
55 :
56 : std::lock_guard<std::mutex> guard(smutex);
57 56734 : if (ainstance == nullptr)
58 30 : ainstance = new Logger();
59 56734 : return *ainstance;
60 : }
61 :
62 30 : Logger::Cleanup::~Cleanup() {
63 : std::lock_guard<std::mutex> guard(Logger::smutex);
64 30 : delete Logger::ainstance;
65 30 : Logger::ainstance = nullptr;
66 30 : }
67 :
68 60 : Logger::~Logger() {
69 : try {
70 30 : outputstream.close();
71 0 : } catch (...) {
72 0 : std::cerr << "Error closing the log file\n";
73 0 : }
74 60 : }
75 :
76 30 : Logger::Logger() : ts_type(NNTRAINER_LOG_TIMESTAMP_SEC) {
77 : struct tm now;
78 30 : getLocaltime(&now);
79 30 : std::stringstream ss;
80 30 : ss << logfile_name << std::dec << (now.tm_year + 1900) << std::setfill('0')
81 60 : << std::setw(2) << (now.tm_mon + 1) << std::setfill('0') << std::setw(2)
82 30 : << now.tm_mday << std::setfill('0') << std::setw(2) << now.tm_hour
83 30 : << std::setfill('0') << std::setw(2) << now.tm_min << std::setfill('0')
84 60 : << std::setw(2) << now.tm_sec << ".out";
85 60 : if (!std::filesystem::exists(logfile_dir)) {
86 1 : std::filesystem::create_directories(logfile_dir);
87 : }
88 60 : outputstream.open(logfile_dir + ss.str(), std::ios_base::app);
89 30 : if (!outputstream.good()) {
90 0 : char buf[256] = {
91 : 0,
92 : };
93 0 : std::string cur_path = std::string(buf);
94 : std::string err_msg =
95 0 : "Unable to initialize the Logger on path(" + cur_path + ")";
96 0 : throw std::runtime_error(err_msg);
97 : }
98 30 : }
99 :
100 56734 : void Logger::log(const std::string &message,
101 : const nntrainer_loglevel loglevel) {
102 : std::lock_guard<std::mutex> guard(smutex);
103 56734 : std::stringstream ss;
104 :
105 56734 : switch (loglevel) {
106 14434 : case NNTRAINER_LOG_INFO:
107 14434 : ss << "[NNTRAINER INFO ";
108 : break;
109 1922 : case NNTRAINER_LOG_WARN:
110 1922 : ss << "[NNTRAINER WARN ";
111 : break;
112 788 : case NNTRAINER_LOG_ERROR:
113 788 : ss << "[NNTRAINER ERROR ";
114 : break;
115 39590 : case NNTRAINER_LOG_DEBUG:
116 39590 : ss << "[NNTRAINER DEBUG ";
117 : break;
118 : default:
119 : break;
120 : }
121 :
122 56734 : if (ts_type == NNTRAINER_LOG_TIMESTAMP_MS) {
123 0 : static auto start = std::chrono::system_clock::now().time_since_epoch();
124 : auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
125 0 : std::chrono::system_clock::now().time_since_epoch() - start)
126 : .count();
127 :
128 0 : ss << "[ " << ms << " ]";
129 56734 : } else if (ts_type == NNTRAINER_LOG_TIMESTAMP_SEC) {
130 : struct tm now;
131 56734 : getLocaltime(&now);
132 :
133 56734 : ss << std::dec << (now.tm_year + 1900) << '-' << std::setfill('0')
134 56734 : << std::setw(2) << (now.tm_mon + 1) << '-' << std::setfill('0')
135 56734 : << std::setw(2) << now.tm_mday << ' ' << std::setfill('0')
136 56734 : << std::setw(2) << now.tm_hour << ':' << std::setfill('0')
137 113468 : << std::setw(2) << now.tm_min << ':' << std::setfill('0') << std::setw(2)
138 56734 : << now.tm_sec << ']';
139 : }
140 :
141 56734 : outputstream << ss.str() << " " << message << std::endl;
142 113468 : }
143 :
144 : } /* namespace nntrainer */
145 :
146 : #ifdef __cplusplus
147 : extern "C" {
148 : #endif
149 56734 : void __nntrainer_log_print(nntrainer_loglevel loglevel,
150 : const std::string format_str, ...) {
151 56734 : int final_n, n = ((int)format_str.size()) * 2;
152 : std::unique_ptr<char[]> formatted;
153 : va_list ap;
154 : while (1) {
155 113071 : formatted.reset(new char[n]);
156 : std::strncpy(&formatted[0], format_str.c_str(), format_str.size());
157 113071 : va_start(ap, format_str);
158 : final_n = vsnprintf(&formatted[0], n, format_str.c_str(), ap);
159 113071 : va_end(ap);
160 113071 : if (final_n < 0 || final_n >= n)
161 56337 : n += abs(final_n - n + 1);
162 : else
163 : break;
164 : }
165 :
166 56734 : std::string ss = std::string(formatted.get());
167 :
168 : #if defined(__LOGGING__)
169 56734 : nntrainer::Logger::instance().log(ss, loglevel);
170 : #else
171 :
172 : #if defined(DEBUG)
173 : switch (loglevel) {
174 : case NNTRAINER_LOG_ERROR:
175 : std::cerr << ss << std::endl;
176 : break;
177 : case NNTRAINER_LOG_INFO:
178 : case NNTRAINER_LOG_WARN:
179 : case NNTRAINER_LOG_DEBUG:
180 : std::cout << ss << std::endl;
181 : default:
182 : break;
183 : }
184 : #endif
185 : #endif
186 56734 : }
187 :
188 : #ifdef __cplusplus
189 : }
190 : #endif
|