Skip to content

Commit f25f6dd

Browse files
feat-logger-update (#1173)
1 parent e180fc6 commit f25f6dd

File tree

8 files changed

+307
-8
lines changed

8 files changed

+307
-8
lines changed

engine/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ if(DEFINED CMAKE_JS_INC)
115115

116116
add_library(${PROJECT_NAME} SHARED addon.cc
117117
${CMAKE_CURRENT_SOURCE_DIR}/utils/cpuid/cpu_info.cc
118+
${CMAKE_CURRENT_SOURCE_DIR}/utils/file_logger.cc
118119
${CMAKE_JS_SRC}
119120
)
120121

@@ -131,6 +132,7 @@ if(DEFINED CMAKE_JS_INC)
131132
else() # Official build
132133
add_executable(${PROJECT_NAME} main.cc
133134
${CMAKE_CURRENT_SOURCE_DIR}/utils/cpuid/cpu_info.cc
135+
${CMAKE_CURRENT_SOURCE_DIR}/utils/file_logger.cc
134136
)
135137
endif()
136138

engine/main.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "utils/archive_utils.h"
77
#include "utils/cortex_utils.h"
88
#include "utils/dylib.h"
9+
#include "utils/file_logger.h"
910
#include "utils/file_manager_utils.h"
1011
#include "utils/logging_utils.h"
1112

@@ -29,16 +30,18 @@ void RunServer() {
2930
LOG_INFO << "Host: " << config.apiServerHost << " Port: " << config.apiServerPort << "\n";
3031

3132
// Create logs/ folder and setup log to file
32-
std::filesystem::create_directory(cortex_utils::logs_folder);
33-
trantor::AsyncFileLogger asyncFileLogger;
34-
asyncFileLogger.setFileName(cortex_utils::logs_base_name);
33+
std::filesystem::create_directory(config.logFolderPath + "/" +
34+
cortex_utils::logs_folder);
35+
trantor::FileLogger asyncFileLogger;
36+
asyncFileLogger.setFileName(config.logFolderPath + "/" +
37+
cortex_utils::logs_base_name);
38+
asyncFileLogger.setMaxLines(config.maxLogLines); // Keep last 100000 lines
3539
asyncFileLogger.startLogging();
3640
trantor::Logger::setOutputFunction(
3741
[&](const char* msg, const uint64_t len) {
38-
asyncFileLogger.output(msg, len);
42+
asyncFileLogger.output_(msg, len);
3943
},
4044
[&]() { asyncFileLogger.flush(); });
41-
asyncFileLogger.setFileSizeLimit(cortex_utils::log_file_size_limit);
4245
// Number of cortex.cpp threads
4346
// if (argc > 1) {
4447
// thread_num = std::atoi(argv[1]);
@@ -154,6 +157,18 @@ int main(int argc, char* argv[]) {
154157
RunServer();
155158
return 0;
156159
} else {
160+
auto config = file_manager_utils::GetCortexConfig();
161+
trantor::FileLogger asyncFileLogger;
162+
asyncFileLogger.setFileName(config.logFolderPath + "/" +
163+
cortex_utils::logs_cli_base_name);
164+
asyncFileLogger.setMaxLines(
165+
config.maxLogLines); // Keep last 100000 lines
166+
asyncFileLogger.startLogging();
167+
trantor::Logger::setOutputFunction(
168+
[&](const char* msg, const uint64_t len) {
169+
asyncFileLogger.output_(msg, len);
170+
},
171+
[&]() { asyncFileLogger.flush(); });
157172
CommandLineParser clp;
158173
clp.SetupCommand(argc, argv);
159174
return 0;

engine/utils/config_yaml_utils.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@
88

99
namespace config_yaml_utils {
1010
struct CortexConfig {
11+
std::string logFolderPath;
1112
std::string dataFolderPath;
13+
int maxLogLines;
1214
std::string apiServerHost;
1315
std::string apiServerPort;
1416
};
1517

1618
const std::string kCortexFolderName = "cortexcpp";
1719
const std::string kDefaultHost{"127.0.0.1"};
1820
const std::string kDefaultPort{"3928"};
21+
const int kDefaultMaxLines{100000};
1922

2023
inline void DumpYamlConfig(const CortexConfig& config,
2124
const std::string& path) {
@@ -27,7 +30,9 @@ inline void DumpYamlConfig(const CortexConfig& config,
2730
throw std::runtime_error("Failed to open output file.");
2831
}
2932
YAML::Node node;
33+
node["logFolderPath"] = config.logFolderPath;
3034
node["dataFolderPath"] = config.dataFolderPath;
35+
node["maxLogLines"] = config.maxLogLines;
3136
node["apiServerHost"] = config.apiServerHost;
3237
node["apiServerPort"] = config.apiServerPort;
3338

@@ -48,8 +53,16 @@ inline CortexConfig FromYaml(const std::string& path,
4853

4954
try {
5055
auto node = YAML::LoadFile(config_file_path.string());
56+
int max_lines;
57+
if (!node["maxLogLines"]) {
58+
max_lines = kDefaultMaxLines;
59+
} else {
60+
max_lines = node["maxLogLines"].as<int>();
61+
}
5162
CortexConfig config = {
63+
.logFolderPath = node["logFolderPath"].as<std::string>(),
5264
.dataFolderPath = node["dataFolderPath"].as<std::string>(),
65+
.maxLogLines = max_lines,
5366
.apiServerHost = node["apiServerHost"].as<std::string>(),
5467
.apiServerPort = node["apiServerPort"].as<std::string>(),
5568
};

engine/utils/cortex_utils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ constexpr static auto kTensorrtLlmPath = "/engines/cortex.tensorrt-llm";
3434

3535
inline std::string models_folder = "./models";
3636
inline std::string logs_folder = "./logs";
37-
inline std::string logs_base_name = "./logs/cortex";
38-
inline size_t log_file_size_limit = 20000000; // ~20 mb
37+
inline std::string logs_base_name = "./logs/cortex.log";
38+
inline std::string logs_cli_base_name = "./logs/cortex-cli.log";
3939

4040
inline std::string extractBase64(const std::string& input) {
4141
std::regex pattern("base64,(.*)");

engine/utils/file_logger.cc

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#include "file_logger.h"
2+
#include <algorithm>
3+
#include <iostream>
4+
#include <sstream>
5+
6+
#ifdef _WIN32
7+
#include <io.h>
8+
#define ftruncate _chsize
9+
#else
10+
#include <unistd.h>
11+
#endif
12+
#include <string.h>
13+
14+
using namespace trantor;
15+
16+
FileLogger::FileLogger() : AsyncFileLogger() {}
17+
18+
FileLogger::~FileLogger() = default;
19+
20+
void FileLogger::output_(const char* msg, const uint64_t len) {
21+
if (!circular_log_file_ptr_) {
22+
circular_log_file_ptr_ =
23+
std::make_unique<CircularLogFile>(fileBaseName_, max_lines_);
24+
}
25+
circular_log_file_ptr_->writeLog(msg, len);
26+
}
27+
28+
FileLogger::CircularLogFile::CircularLogFile(const std::string& fileName,
29+
uint64_t maxLines)
30+
: max_lines_(maxLines), file_name_(fileName) {
31+
std::lock_guard<std::mutex> lock(mutex_);
32+
OpenFile();
33+
LoadExistingLines();
34+
TruncateFileIfNeeded();
35+
}
36+
37+
FileLogger::CircularLogFile::~CircularLogFile() {
38+
std::lock_guard<std::mutex> lock(mutex_);
39+
CloseFile();
40+
}
41+
void FileLogger::CircularLogFile::writeLog(const char* logLine,
42+
const uint64_t len) {
43+
std::lock_guard<std::mutex> lock(mutex_);
44+
if (!fp_)
45+
return;
46+
47+
std::string logString(logLine, len);
48+
std::istringstream iss(logString);
49+
std::string line;
50+
while (std::getline(iss, line)) {
51+
if (lineBuffer_.size() >= max_lines_) {
52+
lineBuffer_.pop_front();
53+
}
54+
lineBuffer_.push_back(line);
55+
AppendToFile(line + "\n");
56+
++linesWrittenSinceLastTruncate_;
57+
if (linesWrittenSinceLastTruncate_.load() >= TRUNCATE_CHECK_INTERVAL) {
58+
59+
TruncateFileIfNeeded();
60+
}
61+
}
62+
}
63+
void FileLogger::CircularLogFile::flush() {
64+
std::lock_guard<std::mutex> lock(mutex_);
65+
if (fp_) {
66+
fflush(fp_);
67+
}
68+
}
69+
70+
void FileLogger::CircularLogFile::TruncateFileIfNeeded() {
71+
// std::cout<<"Truncating file "<< totalLines_ <<std::endl;
72+
if (!fp_ || lineBuffer_.size() < max_lines_)
73+
return;
74+
75+
// Close the current file
76+
fclose(fp_);
77+
fp_ = nullptr;
78+
79+
// Open a temporary file for writing
80+
std::string tempFileName = file_name_ + ".temp";
81+
FILE* tempFile = fopen(tempFileName.c_str(), "w");
82+
if (!tempFile) {
83+
84+
std::cout << "Error opening temporary file for truncation: "
85+
<< strerror(errno) << std::endl;
86+
OpenFile(); // Reopen the original file
87+
return;
88+
}
89+
90+
// Write only the last max_lines_ lines to the temporary file
91+
size_t startIndex =
92+
lineBuffer_.size() > max_lines_ ? lineBuffer_.size() - max_lines_ : 0;
93+
94+
for (size_t i = startIndex; i < lineBuffer_.size(); ++i) {
95+
fprintf(tempFile, "%s\n", lineBuffer_[i].c_str());
96+
}
97+
98+
fclose(tempFile);
99+
100+
// Replace the original file with the temporary file
101+
if (std::rename(tempFileName.c_str(), file_name_.c_str()) != 0) {
102+
std::cout << "Error replacing original file with truncated file: "
103+
<< strerror(errno) << std::endl;
104+
std::remove(tempFileName.c_str()); // Clean up the temporary file
105+
}
106+
// else {
107+
// totalLines_.store(lineBuffer_.size() > max_lines_ ? max_lines_
108+
// : lineBuffer_.size());
109+
// }
110+
111+
// Reopen the file
112+
OpenFile();
113+
// LoadExistingLines();
114+
linesWrittenSinceLastTruncate_.store(0);
115+
}
116+
117+
void FileLogger::CircularLogFile::OpenFile() {
118+
#ifdef _WIN32
119+
auto wFileName = utils::toNativePath(file_name_);
120+
fp_ = _wfopen(wFileName.c_str(), L"r+");
121+
#else
122+
fp_ = fopen(file_name_.c_str(), "r+");
123+
#endif
124+
125+
if (!fp_) {
126+
// If file doesn't exist, create it
127+
#ifdef _WIN32
128+
fp_ = _wfopen(wFileName.c_str(), L"w+");
129+
#else
130+
fp_ = fopen(file_name_.c_str(), "w+");
131+
#endif
132+
133+
if (!fp_) {
134+
std::cerr << "Error opening file: " << strerror(errno) << std::endl;
135+
}
136+
}
137+
}
138+
void FileLogger::CircularLogFile::LoadExistingLines() {
139+
if (!fp_)
140+
return;
141+
142+
// Move to the beginning of the file
143+
fseek(fp_, 0, SEEK_SET);
144+
145+
lineBuffer_.clear();
146+
147+
std::string line;
148+
char buffer[4096];
149+
while (fgets(buffer, sizeof(buffer), fp_) != nullptr) {
150+
line = buffer;
151+
if (!line.empty() && line.back() == '\n') {
152+
line.pop_back(); // Remove trailing newline
153+
}
154+
if (lineBuffer_.size() >= max_lines_) {
155+
lineBuffer_.pop_front();
156+
}
157+
lineBuffer_.push_back(line);
158+
}
159+
160+
// Move back to the end of the file for appending
161+
fseek(fp_, 0, SEEK_END);
162+
}
163+
void FileLogger::CircularLogFile::AppendToFile(const std::string& line) {
164+
if (fp_) {
165+
fwrite(line.c_str(), 1, line.length(), fp_);
166+
fflush(fp_);
167+
}
168+
}
169+
170+
void FileLogger::CircularLogFile::CloseFile() {
171+
if (fp_) {
172+
fclose(fp_);
173+
fp_ = nullptr;
174+
}
175+
}

engine/utils/file_logger.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#pragma once
2+
3+
#include <trantor/utils/AsyncFileLogger.h>
4+
#include <trantor/utils/Utilities.h>
5+
#include <atomic>
6+
#include <cstddef>
7+
#include <cstdint>
8+
#include <deque>
9+
#include <mutex>
10+
11+
#ifdef _WIN32
12+
#include <windows.h>
13+
#else
14+
#include <unistd.h>
15+
#endif
16+
17+
namespace trantor {
18+
19+
class TRANTOR_EXPORT FileLogger : public AsyncFileLogger {
20+
public:
21+
FileLogger();
22+
~FileLogger();
23+
24+
/**
25+
* @brief Set the maximum number of lines to keep in the log file.
26+
*
27+
* @param maxLines
28+
*/
29+
void setMaxLines(uint64_t maxLines) { max_lines_ = maxLines; }
30+
31+
/**
32+
* @brief Set the log file name.
33+
*
34+
* @param fileName The full name of the log file.
35+
*/
36+
void setFileName(const std::string& fileName) {
37+
filePath_ = "./";
38+
fileBaseName_ = fileName;
39+
fileExtName_ = "";
40+
}
41+
void output_(const char* msg, const uint64_t len);
42+
43+
protected:
44+
class CircularLogFile {
45+
public:
46+
CircularLogFile(const std::string& fileName, uint64_t maxLines);
47+
~CircularLogFile();
48+
49+
void writeLog(const char* logLine, const uint64_t len);
50+
void flush();
51+
uint64_t getLength() const { return lineBuffer_.size(); }
52+
53+
private:
54+
FILE* fp_{nullptr};
55+
uint64_t max_lines_;
56+
std::string file_name_;
57+
std::deque<std::string> lineBuffer_;
58+
std::atomic<int> linesWrittenSinceLastTruncate_{0};
59+
static const uint64_t TRUNCATE_CHECK_INTERVAL = 1000;
60+
mutable std::mutex mutex_;
61+
62+
void LoadExistingLines();
63+
void TruncateFileIfNeeded();
64+
void AppendToFile(const std::string& line);
65+
void OpenFile();
66+
void CloseFile();
67+
};
68+
std::unique_ptr<CircularLogFile> circular_log_file_ptr_;
69+
uint64_t max_lines_{100000}; // Default to 100000 lines
70+
};
71+
72+
} // namespace trantor

0 commit comments

Comments
 (0)