Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ project(cortex.llamacpp)
SET(TARGET engine)

if(UNIX AND NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -pthread")
add_compile_options(-fPIC -pthread)
find_package( Threads )
find_package(Threads)
endif()

set(THIRD_PARTY_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build_deps/_install)

include(CheckIncludeFileCXX)

# CPP version
check_include_file_cxx(any HAS_ANY)
check_include_file_cxx(string_view HAS_STRING_VIEW)
Expand All @@ -28,27 +29,28 @@ endif()
add_subdirectory(llama.cpp/examples/llava)
add_subdirectory(llama.cpp)

add_library(${TARGET} SHARED
src/llama_engine.cc
src/llama_server_context.cc
src/llama_client_slot.cc
add_library(${TARGET} SHARED
src/llama_engine.cc
src/llama_server_context.cc
src/llama_client_slot.cc
src/file_logger.cc
)

find_library(JSONCPP
NAMES jsoncpp
HINTS "${THIRD_PARTY_PATH}/lib"
NAMES jsoncpp
HINTS "${THIRD_PARTY_PATH}/lib"
)

find_library(TRANTOR
NAMES trantor
HINTS "${THIRD_PARTY_PATH}/lib"
NAMES trantor
HINTS "${THIRD_PARTY_PATH}/lib"
)

target_link_libraries(${TARGET} PRIVATE common llama llava ${JSONCPP} ${TRANTOR}
${CMAKE_THREAD_LIBS_INIT})
target_include_directories(${TARGET} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/base
${CMAKE_CURRENT_SOURCE_DIR}/llama.cpp
${THIRD_PARTY_PATH}/include)
${CMAKE_THREAD_LIBS_INIT})
target_include_directories(${TARGET} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/base
${CMAKE_CURRENT_SOURCE_DIR}/llama.cpp
${THIRD_PARTY_PATH}/include)

target_compile_features(${TARGET} PUBLIC cxx_std_17)
4 changes: 3 additions & 1 deletion base/cortex-common/enginei.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ class EngineI {
}
return false;
}
virtual void SetFileLogger() = 0;

// API to get running models.
virtual void GetModels(
std::shared_ptr<Json::Value> json_body,
std::function<void(Json::Value&&, Json::Value&&)>&& callback) = 0;
// API for set file logger
virtual void SetFileLogger(int max_log_lines,
const std::string& log_path) = 0;
};
2 changes: 1 addition & 1 deletion examples/server/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ int main(int argc, char** argv) {

Server server;
//set logger here
server.engine_->SetFileLogger();
// server.engine_->SetFileLogger();

SyncJsonReader r;
auto svr = std::make_unique<httplib::Server>();
Expand Down
175 changes: 175 additions & 0 deletions src/file_logger.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#include "file_logger.h"
#include <algorithm>
#include <iostream>
#include <sstream>

#ifdef _WIN32
#include <io.h>
#define ftruncate _chsize
#else
#include <unistd.h>
#endif
#include <string.h>

using namespace trantor;

FileLogger::FileLogger() : AsyncFileLogger() {}

FileLogger::~FileLogger() = default;

void FileLogger::output_(const char* msg, const uint64_t len) {
if (!circular_log_file_ptr_) {
circular_log_file_ptr_ =
std::make_unique<CircularLogFile>(fileBaseName_, max_lines_);
}
circular_log_file_ptr_->writeLog(msg, len);
}

FileLogger::CircularLogFile::CircularLogFile(const std::string& fileName,
uint64_t maxLines)
: max_lines_(maxLines), file_name_(fileName) {
std::lock_guard<std::mutex> lock(mutex_);
OpenFile();
LoadExistingLines();
TruncateFileIfNeeded();
}

FileLogger::CircularLogFile::~CircularLogFile() {
std::lock_guard<std::mutex> lock(mutex_);
CloseFile();
}
void FileLogger::CircularLogFile::writeLog(const char* logLine,
const uint64_t len) {
std::lock_guard<std::mutex> lock(mutex_);
if (!fp_)
return;

std::string logString(logLine, len);
std::istringstream iss(logString);
std::string line;
while (std::getline(iss, line)) {
if (lineBuffer_.size() >= max_lines_) {
lineBuffer_.pop_front();
}
lineBuffer_.push_back(line);
AppendToFile(line + "\n");
++linesWrittenSinceLastTruncate_;
if (linesWrittenSinceLastTruncate_.load() >= TRUNCATE_CHECK_INTERVAL) {

TruncateFileIfNeeded();
}
}
}
void FileLogger::CircularLogFile::flush() {
std::lock_guard<std::mutex> lock(mutex_);
if (fp_) {
fflush(fp_);
}
}

void FileLogger::CircularLogFile::TruncateFileIfNeeded() {
// std::cout<<"Truncating file "<< totalLines_ <<std::endl;
if (!fp_ || lineBuffer_.size() < max_lines_)
return;

// Close the current file
fclose(fp_);
fp_ = nullptr;

// Open a temporary file for writing
std::string tempFileName = file_name_ + ".temp";
FILE* tempFile = fopen(tempFileName.c_str(), "w");
if (!tempFile) {

std::cout << "Error opening temporary file for truncation: "
<< strerror(errno) << std::endl;
OpenFile(); // Reopen the original file
return;
}

// Write only the last max_lines_ lines to the temporary file
size_t startIndex =
lineBuffer_.size() > max_lines_ ? lineBuffer_.size() - max_lines_ : 0;

for (size_t i = startIndex; i < lineBuffer_.size(); ++i) {
fprintf(tempFile, "%s\n", lineBuffer_[i].c_str());
}

fclose(tempFile);

// Replace the original file with the temporary file
if (std::rename(tempFileName.c_str(), file_name_.c_str()) != 0) {
std::cout << "Error replacing original file with truncated file: "
<< strerror(errno) << std::endl;
std::remove(tempFileName.c_str()); // Clean up the temporary file
}
// else {
// totalLines_.store(lineBuffer_.size() > max_lines_ ? max_lines_
// : lineBuffer_.size());
// }

// Reopen the file
OpenFile();
// LoadExistingLines();
linesWrittenSinceLastTruncate_.store(0);
}

void FileLogger::CircularLogFile::OpenFile() {
#ifdef _WIN32
auto wFileName = utils::toNativePath(file_name_);
fp_ = _wfopen(wFileName.c_str(), L"r+");
#else
fp_ = fopen(file_name_.c_str(), "r+");
#endif

if (!fp_) {
// If file doesn't exist, create it
#ifdef _WIN32
fp_ = _wfopen(wFileName.c_str(), L"w+");
#else
fp_ = fopen(file_name_.c_str(), "w+");
#endif

if (!fp_) {
std::cerr << "Error opening file: " << strerror(errno) << std::endl;
}
}
}
void FileLogger::CircularLogFile::LoadExistingLines() {
if (!fp_)
return;

// Move to the beginning of the file
fseek(fp_, 0, SEEK_SET);

lineBuffer_.clear();

std::string line;
char buffer[4096];
while (fgets(buffer, sizeof(buffer), fp_) != nullptr) {
line = buffer;
if (!line.empty() && line.back() == '\n') {
line.pop_back(); // Remove trailing newline
}
if (lineBuffer_.size() >= max_lines_) {
lineBuffer_.pop_front();
}
lineBuffer_.push_back(line);
}

// Move back to the end of the file for appending
fseek(fp_, 0, SEEK_END);
}
void FileLogger::CircularLogFile::AppendToFile(const std::string& line) {
if (fp_) {
fwrite(line.c_str(), 1, line.length(), fp_);
fflush(fp_);
}
}

void FileLogger::CircularLogFile::CloseFile() {
if (fp_) {
fclose(fp_);
fp_ = nullptr;
}
}
72 changes: 72 additions & 0 deletions src/file_logger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#pragma once

#include <trantor/utils/AsyncFileLogger.h>
#include <trantor/utils/Utilities.h>
#include <atomic>
#include <cstddef>
#include <cstdint>
#include <deque>
#include <mutex>

#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

namespace trantor {

class TRANTOR_EXPORT FileLogger : public AsyncFileLogger {
public:
FileLogger();
~FileLogger();

/**
* @brief Set the maximum number of lines to keep in the log file.
*
* @param maxLines
*/
void setMaxLines(uint64_t maxLines) { max_lines_ = maxLines; }

/**
* @brief Set the log file name.
*
* @param fileName The full name of the log file.
*/
void setFileName(const std::string& fileName) {
filePath_ = "./";
fileBaseName_ = fileName;
fileExtName_ = "";
}
void output_(const char* msg, const uint64_t len);

protected:
class CircularLogFile {
public:
CircularLogFile(const std::string& fileName, uint64_t maxLines);
~CircularLogFile();

void writeLog(const char* logLine, const uint64_t len);
void flush();
uint64_t getLength() const { return lineBuffer_.size(); }

private:
FILE* fp_{nullptr};
uint64_t max_lines_;
std::string file_name_;
std::deque<std::string> lineBuffer_;
std::atomic<int> linesWrittenSinceLastTruncate_{0};
static const uint64_t TRUNCATE_CHECK_INTERVAL = 1000;
mutable std::mutex mutex_;

void LoadExistingLines();
void TruncateFileIfNeeded();
void AppendToFile(const std::string& line);
void OpenFile();
void CloseFile();
};
std::unique_ptr<CircularLogFile> circular_log_file_ptr_;
uint64_t max_lines_{100000}; // Default to 100000 lines
};

} // namespace trantor
Loading