TinyLlama.cpp 1.0
A lightweight C++ implementation of the TinyLlama language model
Loading...
Searching...
No Matches
logger.cpp
Go to the documentation of this file.
1#include "logger.h"
2
3#include <algorithm>
4#include <cmath>
5#include <cstdlib>
6#include <fstream>
7#include <iostream>
8#include <mutex>
9#include <numeric>
10#include <vector>
11#include <chrono>
12#include <iomanip>
13#include <sstream>
14
15namespace {
16
17void ensure_log_truncated() {
18 static bool truncated = false;
19 if (!truncated) {
20 std::ofstream log("debugging.log", std::ios::trunc);
21 truncated = true;
22 }
23}
24} // namespace
25
26// Initialize static members
28std::ofstream Logger::log_file_stream_;
29std::string Logger::log_file_path_ = "debugging.log"; // Default log file
30bool Logger::console_enabled_ = false; // MODIFIED: Default to console logging DISABLED
32std::mutex logger_mutex; // Global mutex for logger operations
33
34void Logger::set_level(Level new_level) {
35 std::lock_guard<std::mutex> lock(logger_mutex);
36 current_level_ = new_level;
37}
38
40 std::lock_guard<std::mutex> lock(logger_mutex);
41 return current_level_;
42}
43
44void Logger::set_logfile(const std::string& filename) {
45 std::lock_guard<std::mutex> lock(logger_mutex);
46 if (log_file_stream_.is_open()) {
47 log_file_stream_.close();
48 }
49 log_file_path_ = filename;
50 log_file_truncated_ = false; // Force truncation for new file
51 ensure_logfile_open_and_truncated(); // Open new file
52}
53
54void Logger::enable_console(bool enabled) {
55 std::lock_guard<std::mutex> lock(logger_mutex);
56 console_enabled_ = enabled;
57}
58
59std::string Logger::level_to_string(Level level) {
60 switch (level) {
61 case Level::DEBUG: return "DEBUG";
62 case Level::INFO: return "INFO";
63 case Level::WARNING: return "WARNING";
64 case Level::ERROR: return "ERROR";
65 case Level::CRITICAL: return "CRITICAL";
66 case Level::OFF: return "OFF"; // Should not happen if check is done before
67 default: return "UNKNOWN";
68 }
69}
70
72 if (!log_file_stream_.is_open() || !log_file_truncated_) {
73 if (log_file_stream_.is_open()) {
74 log_file_stream_.close();
75 }
77 log_file_stream_.open(log_file_path_, std::ios::out | std::ios::trunc);
79 } else {
80 log_file_stream_.open(log_file_path_, std::ios::out | std::ios::app);
81 }
82
83 if (!log_file_stream_.is_open()) {
84 // Fallback to cerr if file cannot be opened
85 std::cerr << "[LOGGER_ERROR] Failed to open log file: " << log_file_path_ << std::endl;
86 }
87 } else if (log_file_stream_.is_open() && log_file_stream_.tellp() == 0 && !log_file_truncated_) {
88 // File was opened by another instance/call but not truncated by this instance yet.
89 // This case is tricky with static loggers if not managed carefully.
90 // For simplicity, we assume first successful open truncates.
91 // Re-opening in trunc mode if it's empty and we haven't truncated.
92 log_file_stream_.close();
93 log_file_stream_.open(log_file_path_, std::ios::out | std::ios::trunc);
95 if (!log_file_stream_.is_open()) {
96 std::cerr << "[LOGGER_ERROR] Failed to re-open/truncate log file: " << log_file_path_ << std::endl;
97 }
98 }
99}
100
101void Logger::log_internal(Level level, const std::string& message) {
102 std::lock_guard<std::mutex> lock(logger_mutex);
103 if (level < current_level_ || level == Level::OFF) {
104 return;
105 }
106
108
109 auto now = std::chrono::system_clock::now();
110 auto now_c = std::chrono::system_clock::to_time_t(now);
111
112 std::ostringstream log_line_stream;
113 log_line_stream << std::put_time(std::localtime(&now_c), "%Y-%m-%d %H:%M:%S")
114 << " [" << level_to_string(level) << "] " << message;
115 std::string log_line = log_line_stream.str();
116
117 if (console_enabled_) {
118 if (level == Level::ERROR || level == Level::CRITICAL || level == Level::WARNING) {
119 std::cerr << log_line << std::endl;
120 } else {
121 std::cout << log_line << std::endl;
122 }
123 }
124
125 if (log_file_stream_.is_open()) {
126 log_file_stream_ << log_line << std::endl;
127 log_file_stream_.flush(); // Ensure it's written immediately
128 }
129}
130
131void Logger::debug(const std::string& message) {
132 log_internal(Level::DEBUG, message);
133}
134
135void Logger::info(const std::string& message) {
136 log_internal(Level::INFO, message);
137}
138
139void Logger::warning(const std::string& message) {
141}
142
143void Logger::error(const std::string& message) {
144 log_internal(Level::ERROR, message);
145}
146
147void Logger::critical(const std::string& message) {
149}
150
151void Logger::fatal(const std::string& message) {
152 log_internal(Level::CRITICAL, "[FATAL] " + message); // Log as critical
153 if (log_file_stream_.is_open()) {
154 log_file_stream_.close();
155 }
156 std::cerr << "[FATAL] " << message << std::endl; // Ensure it goes to cerr
157 std::exit(EXIT_FAILURE);
158}
159
160void Logger::log_vector_stats(const std::string& name,
161 const std::vector<float>& v, int n_show) {
162 if (v.empty()) {
163 log_internal(Level::INFO, name + ": (empty vector)");
164 return;
165 }
166 float min_val = v[0];
167 float max_val = v[0];
168 double sum_val = 0.0;
169 bool all_finite_vals = true;
170
171 for (float val : v) {
172 if (std::isnan(val) || std::isinf(val)) {
173 all_finite_vals = false;
174 }
175 if (val < min_val) min_val = val;
176 if (val > max_val) max_val = val;
177 sum_val += static_cast<double>(val);
178 }
179 float mean_val = static_cast<float>(sum_val / v.size());
180
181 std::ostringstream oss;
182 oss << name << ": size=" << v.size()
183 << ", min=" << min_val
184 << ", max=" << max_val
185 << ", mean=" << mean_val
186 << ", all_finite=" << (all_finite_vals ? "yes" : "no")
187 << ", first_vals=[";
188 for (int i = 0; i < std::min((int)v.size(), n_show); ++i) {
189 oss << v[i] << (i == std::min((int)v.size(), n_show) - 1 ? "" : ", ");
190 }
191 oss << "]";
192 log_internal(Level::INFO, oss.str());
193}
194
195void Logger::log_vector_stats_int8(const std::string& name, const std::vector<int8_t>& v, int n_show) {
196 if (v.empty()) {
197 log_internal(Level::INFO, name + ": (empty int8_t vector)");
198 return;
199 }
200 int8_t min_val = v[0];
201 int8_t max_val = v[0];
202 long long sum_val = 0; // Use long long for sum to avoid overflow with many int8_t values
203
204 for (int8_t val : v) {
205 if (val < min_val) min_val = val;
206 if (val > max_val) max_val = val;
207 sum_val += static_cast<long long>(val);
208 }
209 // Cast sum to double for mean calculation to preserve precision before casting to float
210 float mean_val = static_cast<float>(static_cast<double>(sum_val) / v.size());
211
212 std::ostringstream oss;
213 oss << name << ": size=" << v.size()
214 << ", min=" << static_cast<int>(min_val) // Cast to int for printing
215 << ", max=" << static_cast<int>(max_val) // Cast to int for printing
216 << ", mean=" << mean_val
217 << ", first_vals=[";
218 for (int i = 0; i < std::min((int)v.size(), n_show); ++i) {
219 oss << static_cast<int>(v[i]) << (i == std::min((int)v.size(), n_show) - 1 ? "" : ", ");
220 }
221 oss << "]";
222 log_internal(Level::INFO, oss.str());
223}
224
225std::string Logger::ptrToString(const void* ptr) {
226 std::ostringstream oss;
227 oss << ptr;
228 return oss.str();
229}
230
231// Templated helper to convert unsigned integral types to hex string
232template <typename T>
233std::string Logger::to_hex(T val) {
234 std::ostringstream oss;
235 oss << "0x" << std::hex << static_cast<unsigned long long>(val); // Cast to larger type if necessary
236 return oss.str();
237}
238
239// Explicit template instantiation for uint16_t if needed, or ensure it's defined in a way that uint16ToHex can find it.
240// Or, make uint16ToHex call the templated version directly.
241
242std::string Logger::uint16ToHex(uint16_t val) {
243 return to_hex(val); // Now calls the templated version
244}
static void log_vector_stats(const std::string &name, const std::vector< float > &v, int n_show=5)
Definition logger.cpp:160
static bool log_file_truncated_
Definition logger.h:95
static std::string log_file_path_
Definition logger.h:93
static void debug(const std::string &message)
Definition logger.cpp:131
static std::string to_hex(T val)
Definition logger.cpp:233
static void log_internal(Level level, const std::string &message)
Definition logger.cpp:101
static void warning(const std::string &message)
Definition logger.cpp:139
static std::string ptrToString(const void *ptr)
Definition logger.cpp:225
static void ensure_logfile_open_and_truncated()
Definition logger.cpp:71
static bool console_enabled_
Definition logger.h:94
static void set_level(Level new_level)
Definition logger.cpp:34
static void enable_console(bool enabled)
Definition logger.cpp:54
static std::string level_to_string(Level level)
Definition logger.cpp:59
static Level current_level_
Definition logger.h:91
static Level get_level()
Definition logger.cpp:39
Level
Definition logger.h:55
static std::string uint16ToHex(uint16_t val)
Definition logger.cpp:242
static std::ofstream log_file_stream_
Definition logger.h:92
static void info(const std::string &message)
Definition logger.cpp:135
static void error(const std::string &message)
Definition logger.cpp:143
static void fatal(const std::string &message)
Definition logger.cpp:151
static void log_vector_stats_int8(const std::string &name, const std::vector< int8_t > &v, int n_show=5)
Definition logger.cpp:195
static void critical(const std::string &message)
Definition logger.cpp:147
static void set_logfile(const std::string &filename)
Definition logger.cpp:44
std::mutex logger_mutex
Definition logger.cpp:32
Logging utilities for the TinyLlama implementation.