add log header include and adjust .gitignore file

This commit is contained in:
lovelyyoung 2024-01-08 18:09:40 +08:00
parent 30c6dbb429
commit a95d882324
5 changed files with 986 additions and 1 deletions

1
.gitignore vendored
View File

@ -1,5 +1,4 @@
./build/* ./build/*
Debug/* Debug/*
Log/*
.vs/* .vs/*
.vscode/* .vscode/*

115
Log/applog.cpp Normal file
View File

@ -0,0 +1,115 @@
#include "applog.h"
#include "spdlog/spdlog.h"
#include "spdlog/async.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "stringex.h"
#include <iostream>
#include <algorithm>
inline std::string string_toupper(const std::string& str)
{
std::string s = str;
transform(s.begin(), s.end(), s.begin(), toupper);
return s;
}
void log_init(const std::string& name, bool benv)
{
if(spdlog::get(name))
return;
const auto max_size = 1048576 * 5;
const auto max_files = 3;
auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("logs/"+name+".log", max_size, max_files);
file_sink->set_level(spdlog::level::info);
auto logger = std::shared_ptr<spdlog::logger>(new spdlog::logger("logs/" + name+".log", {file_sink}));
spdlog::register_logger(logger);
}
void log_info(const std::string& name, const std::string& msg)
{
if(auto log = spdlog::get("logs/" + name + ".log"))
{
log->info(msg);
log->flush();
}
}
void log_warn(const std::string& name, const std::string& msg)
{
if (auto log = spdlog::get("logs/" + name + ".log"))
{
log->warn(msg);
log->flush();
}
}
void log_trace(const std::string& name, const std::string& msg)
{
if (auto log = spdlog::get("logs/" + name + ".log"))
{
log->trace(msg);
log->flush();
}
}
void log_debug(const std::string& name, const std::string& msg)
{
if (auto log = spdlog::get("logs/" + name + ".log"))
{
log->debug(msg);
log->flush();
}
}
void log_error(const std::string& name, const std::string& msg)
{
if (auto log = spdlog::get("logs/" + name + ".log"))
{
log->error(msg);
log->flush();
}
}
void log_critical(const std::string name, const std::string& msg)
{
if (auto log = spdlog::get("logs/" + name + ".log"))
{
log->critical(msg);
log->flush();
}
}
bool log_set_level(const std::string& name, int type ,int level)
{
if (auto log = spdlog::get("logs/" + name + ".log"))
{
spdlog::level::level_enum actLevel = (spdlog::level::level_enum)std::min(std::max((int)spdlog::level::trace, level), (int)spdlog::level::off);
if(type < log->sinks().size())
log->sinks()[type]->set_level(actLevel);
else
log->set_level(actLevel);
return true;
}
return false;
}
bool log_get_level(const std::string& name, int type ,int& level)
{
if (auto log = spdlog::get("logs/" + name + ".log"))
{
if(type < log->sinks().size())
level = log->sinks()[type]->level();
else
level = log->level();
return true;
}
return false;
}

20
Log/applog.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <string>
#define LOG_INIT() log_init(loggername, true)
#define LOG_INITX() log_init(loggername, false)
#define LOG_INFO(X) log_info(loggername, X)
#define LOG_WARN(X) log_warn(loggername, X)
#define LOG_TRACE(X) log_trace(loggername, X)
#define LOG_DEBUG(X) log_debug(loggername, X)
#define LOG_ERROR(X) log_error(loggername, X)
#define LOG_CRITICAL(X) log_critical(loggername, X)
void log_init(const std::string& name, bool benv);
void log_info(const std::string& name, const std::string& msg);
//void log_warn(const std::string& name, const std::string& msg);
//void log_trace(const std::string& name, const std::string& msg);
//void log_debug(const std::string& name, const std::string& msg);
//void log_error(const std::string& name, const std::string& msg);
//void log_critical(const std::string& name, const std::string& msg);
//bool log_set_level(const std::string& name, int type ,int level);
//bool log_get_level(const std::string& name, int type ,int& level);

769
Log/hg_log.cpp Normal file
View File

@ -0,0 +1,769 @@
#include <vector>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <stdarg.h>
#if defined(WIN32) || defined(_WIN64)
#include <Windows.h>
#include <direct.h>
#include <Psapi.h>
#include <Tlhelp32.h>
#include <imagehlp.h>
#define MKDIR(a, b) mkdir(a)
#pragma comment(lib, "imagehlp.lib")
#pragma comment(lib, "Psapi.lib")
#pragma comment(lib, "shlwapi.lib")
#else
#define MKDIR(a, b) mkdir(a, b)
#include <pthread.h>
#include <sys/sysinfo.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#endif
#include <time.h>
#include <algorithm>
#include <mutex>
#include "hg_log.h"
#define VMRSS_LINE 21 //实际物理内存使用<E4BDBF>?
#define MAX_LOG_FILE_SIZE 10 * 1024 * 1024
#ifdef _INTSIZEOF
#undef _INTSIZEOF
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(long) - 1) & ~(sizeof(long) - 1))
#endif
//extern std::string g_scanner_path; // Ending with '\\'
static std::string log_divider("=========================================================================\n");
void hg_get_current_time(char* tmbuf, struct tm* t)
{
#if defined(WIN32) || defined(_WIN64)
static long bias = -1;
static bool as_start = true;
//if (bias == -1)
//{
// _get_timezone(&bias);
// as_start = hg_log::ini_get("time", "adjust") != "no";
//}
#endif
time_t now = time(nullptr);
struct tm* l = localtime(&now);
#if defined(WIN32) || defined(_WIN64)
long after = 0;
if (as_start && _get_timezone(&after) == 0 &&
(after != bias && after != -bias))
{
now += bias;
l = localtime(&now);
}
#endif
if (t)
*t = *l;
if (tmbuf)
sprintf(tmbuf, "%04d-%02d-%02d %02d:%02d:%02d--->", l->tm_year + 1900, l->tm_mon + 1, l->tm_mday, l->tm_hour, l->tm_min, l->tm_sec);
}
class log_cls
{
typedef void(*log_to)(const char*, void*, void*);
std::string path_file_;
FILE* file_;
log_to log_;
int level_;
std::mutex lock_;
static log_cls* inst_;
static FILE* create_log_file(const char* path_file, bool truncate)
{
FILE* file_ = fopen(path_file, "a+b");
if (file_)
{
fseek(file_, 0, SEEK_END);
if (ftell(file_) == 0)
{
unsigned char bom[] = { 0x0ef, 0x0bb, 0x0bf };
fwrite(bom, sizeof(bom), 1, file_);
}
std::string now(g_time_tag + hg_log::current_time() + g_time_tag);
now += truncate ? " trcated.\n" : " started.\n";
now.insert(0, log_divider);
fwrite(now.c_str(), 1, now.length(), file_);
}
return file_;
}
static void log_none(const char* info, void* param, void* param2)
{}
static void log_consonle(const char* info, void* param, void* param2)
{
printf(info);
}
static void log_file(const char* info, void* param, void* param2)
{
FILE** file = (FILE**)param;
if(*file == nullptr)
*file = create_log_file(((std::string*)param2)->c_str(), false);
if (*file)
{
fwrite(info, 1, strlen(info), *file);
fflush(*file);
if (ftell(*file) >= MAX_LOG_FILE_SIZE)
{
fclose(*file);
remove(((std::string*)param2)->c_str());
*file = create_log_file(((std::string*)param2)->c_str(), true);
}
}
}
protected:
log_cls() : path_file_(""), file_(0), log_(&log_cls::log_consonle)
{}
~log_cls()
{
if (file_)
{
fclose(file_);
file_ = 0;
}
}
public:
static std::string g_time_tag;
static log_cls* instance(void)
{
if (!log_cls::inst_)
log_cls::inst_ = new log_cls();
return log_cls::inst_;
}
static void clear(void)
{
if (log_cls::inst_)
{
delete log_cls::inst_;
log_cls::inst_ = nullptr;
}
}
int set_log_type(int type, void* param)
{
int ret = 0;
if (file_)
{
fclose(file_);
file_ = 0;
}
log_ = NULL;
if (type == LOG_TYPE_NONE)
log_ = &log_cls::log_none;
else if(type == LOG_TYPE_CONSOLE)
log_ = &log_cls::log_consonle;
else if (type == LOG_TYPE_FILE)
{
log_ = &log_cls::log_file;
ret = -1;
if (param)
{
path_file_ = (char*)param;
file_ = create_log_file(path_file_.c_str(), false);
if (file_)
ret = 0;
}
}
if(ret != 0)
log_ = &log_cls::log_none;
return ret;
}
void set_log_level(int level)
{
level_ = level;
}
bool is_log_level_enabled(int level)
{
return level >= level_;
}
void log(const char* info)
{
std::lock_guard<std::mutex> lock(lock_);
log_(info, &file_, &path_file_);
}
std::string get_log_file_path(bool copy)
{
std::string file("");
if (log_ == &log_cls::log_file && file_)
{
file = path_file_;
if (copy)
{
file += ".txt";
FILE* dst = fopen(file.c_str(), "wb");
if (!dst)
file = "";
else
{
std::lock_guard<std::mutex> lock(lock_);
char buf[1024] = { 0 };
size_t l = 0;
fseek(file_, 0, SEEK_SET);
while ((l = fread(buf, 1, sizeof(buf), file_)))
fwrite(buf, 1, l, dst);
fclose(dst);
}
}
}
return file;
}
void clear_log(void)
{
if (log_ == &log_cls::log_file && file_)
{
std::lock_guard<std::mutex> lock(lock_);
fclose(file_);
remove(path_file_.c_str());
file_ = create_log_file(path_file_.c_str(), true);
}
}
};
log_cls* log_cls::inst_ = NULL;
std::string log_cls::g_time_tag = "=====";
#ifdef EXPORT_AS_C
extern "C"
{
#endif
namespace hg_log
{
static log_callback lcb_ = NULL;
typedef struct _find_file
{
std::string pattern;
std::string found;
}FINDFILE, * LPFF;
static bool on_found(const char* file, void* param)
{
LPFF lpff = (LPFF)param;
char pth = PATH_SEPARATOR[0];
const char* name = strrchr(file, pth);
if (name++ == nullptr)
name = file;
std::string lc(name);
str_tolower(lc);
if (lc.find(lpff->pattern) != std::string::npos)
{
lpff->found = file;
return false;
}
return true;
}
#if defined(WIN32) || defined(_WIN64)
static std::string u2a(const wchar_t* u, UINT cp = CP_ACP)
{
std::string a("");
if (u)
{
char stack[256] = { 0 }, * ansi = NULL;
int len = 0;
len = WideCharToMultiByte(cp, 0, u, lstrlenW(u), NULL, 0, NULL, NULL);
ansi = new char[len + 2];
len = WideCharToMultiByte(cp, 0, u, lstrlenW(u), ansi, len, NULL, NULL);
ansi[len--] = 0;
a = ansi;
delete[] ansi;
}
return a;
}
static int enum_files(const char* dir, bool recursive, bool(*found_file)(const char* path_file, void* param), void* param)
{
int ret = 0;
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
MODULEENTRY32W pei = { 0 };
if (h == INVALID_HANDLE_VALUE)
ret = GetLastError();
else
{
pei.dwSize = sizeof(pei);
if (Module32FirstW(h, &pei))
{
do
{
std::string ansi(u2a(pei.szExePath));
if (!found_file(ansi.c_str(), param))
break;
pei.dwSize = sizeof(pei);
} while (Module32NextW(h, &pei));
}
CloseHandle(h);
}
return ret;
}
#else
static std::string link_file(const char* lnk)
{
char path[256] = { 0 };
int len = readlink(lnk, path, sizeof(path) - 1);
return len > 0 ? path : lnk;
}
static int enum_files(const char* dir, bool recursive, bool(*found_file)(const char* path_file, void* param), void* param)
{
int ret = 0;
DIR* pdir = nullptr;
struct dirent* ent = nullptr;
pdir = opendir(dir);
if (!pdir)
return errno;
while ((ent = readdir(pdir)))
{
if (ent->d_type & DT_DIR)
{
if (recursive)
{
if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
{
std::string sub(dir);
sub += "/";
sub += ent->d_name;
ret = enum_files(sub.c_str(), recursive, found_file, param);
if (ret == 0x5e17)
break;
}
}
}
else
{
std::string file(dir);
file += "/";
file += ent->d_name;
if (!found_file(link_file(file.c_str()).c_str(), param))
{
ret = 0x5e17;
break;
}
}
}
return ret;
}
#endif
std::string get_scanimage_ver()
{
#if defined(WIN32) || defined(_WIN64)
return "";
#else
FILE* fp = NULL;
char buf[128] = { 0 };
fp = popen("scanimage -V", "r");
if (!fp)
return "";
int ret = fread(buf, 1, sizeof(buf) - 1, fp);
if(ret<1)
return "";
pclose(fp);
std::string str = buf;
return str.substr(str.size()-7);
#endif
}
void clear_log(void)
{
log_cls::instance()->clear_log();
}
//static std::string get_scanimage_ver()
//{
// FILE* fp = popen("scanimage -V","r");
// if (!fp)
// {
// return "";
// }
// long len = 0;
// fseek(fp, 0, SEEK_END);
// len = ftell(fp);
// fseek(fp, 0, SEEK_SET);
// char* buf = new char[len];
// if (!buf)
// {
// return "";
// }
// int ret = fread(buf, 1, sizeof(buf) - 1, fp);
// pclose();
//}
std::string format_ptr(void* ptr)
{
char buf[40];
if (sizeof(ptr) == sizeof(int))
{
sprintf(buf, "0x%08x", ptr);
}
else
{
unsigned int* n = (unsigned int*)&ptr;
sprintf(buf, "0x%x%08x", n[1], n[0]);
}
return buf;
}
std::string format_current_thread_id(void)
{
#if defined(WIN32) || defined(_WIN64)
return format_ptr((void*)GetCurrentThreadId());
#else
return format_ptr((void*)pthread_self());
#endif
}
std::string current_time(void)
{
char buf[40] = { 0 };
hg_get_current_time(buf,nullptr);
return buf;
}
std::string format_size(unsigned long size)
{
char buf[40];
if (size > 1024 * 1024 * 1024)
{
double d = size;
d /= 1024 * 1024 * 1024;
sprintf(buf, "%.2fGB", d);
}
else if (size > 1024 * 1024)
{
double d = size;
d /= 1024 * 1024;
sprintf(buf, "%.2fMB", d);
}
else if (size > 1024)
{
double d = size;
d /= 1024;
sprintf(buf, "%.1fKB", d);
}
else
{
sprintf(buf, "%u bytes", (unsigned int)size);
}
return buf;
}
std::string u2utf8(const wchar_t* u)
{
std::string utf8("");
#if defined(WIN32) || defined(_WIN64)
utf8 = u2a(u, CP_UTF8);
#else
#endif
return utf8;
}
std::string pe_path(std::string* name)
{
#if defined(WIN32) || defined(_WIN64)
wchar_t path[MAX_PATH] = { 0 }, * last = NULL;
GetModuleFileNameW(NULL, path, _countof(path) - 1);
last = wcsrchr(path, L'\\');
if (last)
{
if (name)
*name = u2utf8(last + 1);
*last = 0;
}
return u2utf8(path);
#else
char path[256] = { 0 };
int len = readlink("/proc/self/exe", path, sizeof(path) - 1);
if (len > 0 && len < sizeof(path))
{
for (--len; len > 0; --len)
{
if (path[len] == '/')
{
path[len] = 0;
if (name)
*name = path + len + 1;
break;
}
}
}
return path;
#endif
}
unsigned long long available_memory(void)
{
#if defined(WIN32) || defined(_WIN64)
MEMORYSTATUSEX ms;
if (GlobalMemoryStatusEx(&ms))
return ms.ullAvailPhys;
else
return -1;
#else
struct sysinfo si;
if (sysinfo(&si) == 0)
return si.freeram * si.mem_unit;
#endif
}
void str_tolower(std::string& str)
{
std::transform(str.begin(), str.end(), str.begin(), tolower);
}
bool create_folder(const char* fodler)
{
return MKDIR(fodler, S_IREAD | S_IWRITE | S_IEXEC) == 0 || errno == EEXIST;
}
std::string get_module_full_path(const char* module_part_name)
{
char path[128] = { 0 };
FINDFILE ff;
ff.pattern = module_part_name;
str_tolower(ff.pattern);
#if defined(WIN32) || defined(_WIN64)
#else
sprintf(path, "/proc/%u/map_files/", getpid());
#endif
enum_files(path, false, on_found, &ff);
return ff.found;
}
std::string get_scanner_path(void)
{
return "";
}
unsigned int get_page_size(unsigned int* map_unit)
{
unsigned int ps = 1024;
#if defined(WIN32) || defined(_WIN64)
SYSTEM_INFO si = { 0 };
GetSystemInfo(&si);
ps = si.dwPageSize;
if (map_unit)
*map_unit = si.dwAllocationGranularity;
#else
ps = sysconf(_SC_PAGESIZE);
if(ps < 1024 || (ps & 0x0fe0000ff)) // nKB && < 16MB
ps = getpagesize();
if (map_unit)
*map_unit = ps;
#endif
if (ps < 1024 || (ps & 0x0fe0000ff)) // nKB && < 16MB
ps = 1024;
return ps;
}
static int get_log_config(const std::string& root, hg_log_type* type, std::string* path)
{
std::string me(root + PATH_SEPARATOR + "config" + PATH_SEPARATOR + "debug.cfg");
int lv = LOG_LEVEL_ALL;
hg_log_type tp = LOG_TYPE_FILE;
if (!type)
type = &tp;
*type = LOG_TYPE_FILE;
create_folder((root + PATH_SEPARATOR + "config").c_str());
return lv;
}
std::string local_data_path(void)
{
static std::string local_data_path(".");
static bool load_first = true;
std::string home(local_data_path);
create_folder(home.c_str());
return home;
}
std::string log_file_path(void)
{
return log_cls::instance()->get_log_file_path(true);
}
int init(void)
{
char* file = nullptr;
std::string path("");
hg_log_type type = LOG_TYPE_FILE;
int level = get_log_config(local_data_path(), &type, &path);
if (type == LOG_TYPE_FILE)
{
std::string name(""),
paths[] = { local_data_path(), pe_path(&name), get_scanner_path()};
int ind = 0;
if (!path.empty() && create_folder(path.c_str()))
ind = sizeof(paths) / sizeof(paths[0]) + 2;
for (; ind < sizeof(paths) / sizeof(paths[0]); ++ind)
{
path = paths[ind] + PATH_SEPARATOR + "Log";
if (create_folder(path.c_str()))
break;
}
if(ind == sizeof(paths) / sizeof(paths[0]))
{
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "# Try PE, scanner and temporary path failed(%d), log to console\n", errno);
type = LOG_TYPE_CONSOLE;
}
if (type == LOG_TYPE_FILE)
{
if (name.empty())
path += std::string(PATH_SEPARATOR) + "scanner.log";
else
path += PATH_SEPARATOR + name + ".log";
file = &path[0];
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "# Log to file: '%s'\n", path.c_str());
}
}
log_cls::instance()->set_log_level(level);
return log_cls::instance()->set_log_type(type, file);
}
void unint(void)
{
std::string now(log_cls::g_time_tag + hg_log::current_time() + log_cls::g_time_tag + " exited.\n");
log(now.c_str());
log((log_divider + "\n\n\n\n").c_str());
log_cls::clear();
}
void log(int level, const char* info)
{
if (lcb_)
lcb_(level, info);
else if (log_cls::instance()->is_log_level_enabled(level))
log_cls::instance()->log(info);
}
bool is_log_level_enabled(int level)
{
return log_cls::instance()->is_log_level_enabled(level);
}
void log(const char* info)
{
log_cls::instance()->log(info);
}
float GetMemoryUsage(int pid)
{
#ifdef WIN32
uint64_t mem = 0, vmem = 0;
PROCESS_MEMORY_COUNTERS pmc;
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (GetProcessMemoryInfo(process, &pmc, sizeof(pmc)))
{
mem = pmc.WorkingSetSize;
vmem = pmc.PagefileUsage;
}
CloseHandle(process);
return mem / 1024.0 / 1024.0;//byte TO MB
#else
char file_name[64] = { 0 };
FILE* fd;
char line_buff[512] = { 0 };
sprintf(file_name, "/proc/%d/status", pid);
fd = fopen(file_name, "r");
if (nullptr == fd)
return 0;
char name[64];
int vmrss = 0;
for (int i = 0; i < VMRSS_LINE - 1; i++)
fgets(line_buff, sizeof(line_buff), fd);
fgets(line_buff, sizeof(line_buff), fd);
sscanf(line_buff, "%s %d", name, &vmrss);
fclose(fd);
return vmrss / 1024.0;//KB TO MB
#endif
}
float GetAppMemoryUsage()
{
return GetMemoryUsage(getpid());
}
const char* lang_load(uint32_t id)
{
int err = 0;
const char *lang ="unused ";
if (err != 0)
{
return "";
}
return lang;
}
}
#ifdef EXPORT_AS_C
}
#endif
#if defined(WIN32) || defined(_WIN64)
void hg_debug_log(int level, const char* info)
{
hg_log::log(level, info);
}
#endif

82
Log/hg_log.h Normal file
View File

@ -0,0 +1,82 @@
// this file is include huagao logging tools
//
// created: 2022-02-09
//
#pragma once
#include <string>
#if defined(WIN32) || defined(_WIN64)
#define bzero(a, l) memset(a, 0, l)
#define PATH_SEPARATOR "\\"
#define DLL_EXTESION ".dll"
#define STRICMP stricmp
#else
#include <string.h>
#define PATH_SEPARATOR "/"
#define DLL_EXTESION ".so"
#define STRICMP strcasecmp
#endif
enum hg_log_type
{
LOG_TYPE_NONE = 0, // no logging
LOG_TYPE_CONSOLE, // print to console
LOG_TYPE_FILE, // write log into file
LOG_TYPE_CALLBACK, // invoke callback log_callback
};
enum log_level
{
LOG_LEVEL_ALL = 0,
LOG_LEVEL_DEBUG_INFO,
LOG_LEVEL_WARNING,
LOG_LEVEL_FATAL,
};
typedef void (*log_callback)(int, const char* info);
#ifdef EXPORT_AS_C
extern "C"
{
#endif
namespace hg_log
{
std::string format_ptr(void* ptr);
std::string format_current_thread_id(void);
std::string current_time(void);
std::string format_size(unsigned long size);
std::string u2utf8(const wchar_t* u);
std::string pe_path(std::string* name = nullptr);
std::string get_module_full_path(const char* module_part_name);
std::string get_scanner_path(void);
std::string local_data_path(void);
//std::string temporary_path(void);
std::string log_file_path(void);
std::string get_scanimage_ver();
void clear_log(void);
float GetMemoryUsage(int pid);
float GetAppMemoryUsage();
const char* lang_load(uint32_t id);
unsigned int get_page_size(unsigned int* map_unit = nullptr);
unsigned long long available_memory(void);
void str_tolower(std::string& str);
bool create_folder(const char* fodler);
//std::string ini_get(const char* app, const char* key);
// void ini_set(const char* app, const char* key, const char* val);
// Function: initialize the logging type and level
//
// Return: 0 - success, or -1 in LOG_TYPE_FILE and log_file cannot be created
int init(void);
void unint(void);
void log(int level, const char* info);
bool is_log_level_enabled(int level);
void log(const char* info);
}
#ifdef EXPORT_AS_C
}
#endif