f8/f8/udplog.cc
2023-04-27 08:57:13 +00:00

225 lines
6.3 KiB
C++

#include <thread>
#include <mutex>
#include <condition_variable>
#include <a8/a8.h>
#include <f8/f8.h>
#include <f8/udplog.h>
namespace f8
{
struct UdpLogMsgNode
{
std::string logmsg;
UdpLogMsgNode* next = nullptr;
};
struct UdpLogImpl
{
unsigned short log_level = 0;
bool debuging = false;
std::string log_filename;
std::thread* save_thread = nullptr;
bool save_thread_shutdown = false;
std::mutex msg_mutex;
UdpLogMsgNode* top_node = nullptr;
UdpLogMsgNode* bot_node = nullptr;
UdpLogMsgNode* work_node = nullptr;
std::mutex *save_cond_mutex = nullptr;
std::condition_variable *save_cond = nullptr;
};
UdpLog::UdpLog()
{
impl_ = new UdpLogImpl();
impl_->save_cond_mutex = new std::mutex();
impl_->save_cond = new std::condition_variable();
impl_->log_level = 0;
#ifdef DEBUG
impl_->debuging = true;
#endif
impl_->top_node = nullptr;
impl_->bot_node = nullptr;
impl_->work_node = nullptr;
}
UdpLog::~UdpLog()
{
delete impl_->save_cond_mutex;
impl_->save_cond_mutex = nullptr;
delete impl_->save_cond;
impl_->save_cond = nullptr;
delete impl_;
impl_ = nullptr;
}
void UdpLog::Init()
{
impl_->save_thread_shutdown = false;
impl_->save_thread = new std::thread(&UdpLog::SaveToFileThreadProc, this);
}
void UdpLog::UnInit()
{
impl_->save_thread_shutdown = true;
impl_->save_thread->join();
delete impl_->save_thread;
impl_->save_thread = nullptr;
impl_->msg_mutex.lock();
if (!impl_->work_node) {
impl_->work_node = impl_->top_node;
impl_->top_node = nullptr;
impl_->bot_node = nullptr;
}
while (impl_->work_node) {
UdpLogMsgNode* pdelnode = impl_->work_node;
impl_->work_node = impl_->work_node->next;
if (!impl_->work_node) {
impl_->work_node = impl_->top_node;
impl_->top_node = nullptr;
impl_->bot_node = nullptr;
}
delete pdelnode;
}
impl_->msg_mutex.unlock();
}
void UdpLog::SetLogFileName(const std::string& filename)
{
impl_->log_filename = filename;
}
void UdpLog::Emergency(const char *format, std::initializer_list<a8::XValue> args)
{
if (impl_->log_level > 6) {
return;
}
SendLog("[EMERGENCY]", format, args);
}
void UdpLog::Alert(const char *format, std::initializer_list<a8::XValue> args)
{
if (impl_->log_level > 5) {
return;
}
SendLog("[ALERT]", format, args);
}
void UdpLog::Error(const char *format, std::initializer_list<a8::XValue> args)
{
if (impl_->log_level > 4) {
return;
}
SendLog("[ERROR]", format, args);
}
void UdpLog::Warning(const char *format, std::initializer_list<a8::XValue> args)
{
if (impl_->log_level > 3) {
return;
}
SendLog("[WARNING]", format, args);
}
void UdpLog::Notice(const char *format, std::initializer_list<a8::XValue> args)
{
if (impl_->log_level > 2) {
return;
}
SendLog("[NOTICE]", format, args);
}
void UdpLog::Info(const char *format, std::initializer_list<a8::XValue> args)
{
if (impl_->log_level > 1) {
return;
}
SendLog("[INFO]", format, args);
}
void UdpLog::Debug(const char *format, std::initializer_list<a8::XValue> args)
{
if (impl_->log_level > 0) {
return;
}
SendLog("[DEBUG]", format, args);
}
void UdpLog::SendLog(const char *category, const char *format,
std::initializer_list<a8::XValue>& args)
{
time_t nowtime = time(nullptr);
struct tm tm_nowtime = {0};
struct tm *ptr = localtime_r(&nowtime, &tm_nowtime);
char strtime[80];
strftime(strtime, 80, "%F %T", ptr);
UdpLogMsgNode *p = new UdpLogMsgNode();
p->logmsg.reserve(128);
p->logmsg.append((char*)strtime);
p->logmsg.append(category);
p->logmsg.append(" ");
p->logmsg.append(a8::FormatEx(format, args));
p->logmsg.append("\n");
if (impl_->debuging) {
printf("%s", p->logmsg.c_str());
}
impl_->msg_mutex.lock();
if (impl_->bot_node) {
impl_->bot_node->next = p;
impl_->bot_node = p;
} else {
impl_->top_node = p;
impl_->bot_node = p;
}
impl_->msg_mutex.unlock();
{
std::unique_lock<std::mutex> lk(*impl_->save_cond_mutex);
impl_->save_cond->notify_all();
}
}
void UdpLog::SaveToFileThreadProc()
{
while (!impl_->save_thread_shutdown) {
if (!impl_->work_node && impl_->top_node) {
impl_->msg_mutex.lock();
impl_->work_node = impl_->top_node;
impl_->top_node = nullptr;
impl_->bot_node = nullptr;
impl_->msg_mutex.unlock();
}
if (impl_->work_node) {
time_t nowtime = time(nullptr);
struct tm tm_nowtime = {0};
localtime_r(&nowtime, &tm_nowtime);
char szfilename[256];
strftime(szfilename, a8::ArraySize(szfilename), impl_->log_filename.c_str(), &tm_nowtime);
std::string filename((char*)szfilename);
FILE *logfile = fopen(filename.c_str(), "a+");
if (logfile) {
while (impl_->work_node) {
UdpLogMsgNode *nextnode = impl_->work_node->next;
fwrite(impl_->work_node->logmsg.c_str(), 1, impl_->work_node->logmsg.length(), logfile);
delete impl_->work_node;
impl_->work_node = nextnode;
}
fclose(logfile);
}
}
{
std::unique_lock<std::mutex> lk(*impl_->save_cond_mutex);
impl_->save_cond->wait_for(lk, std::chrono::seconds(10));
}
}
}
}