您的位置:首页 > 编程语言 > C语言/C++

logger(一):C++ & logger模块配置及开发

2016-01-12 14:42 417 查看
该logger模块是一种本地缓存形式的logger处理方法:用于相关软件开发过程中的日志记录;适用于windows和linux

Linux下的主要使用的是syslog-ng库,以下贴出源码,详情请下载开发包。

logger.h

-----------------------------------------------------------------------------------------------------------------------------

/*

* logger.h

* Author: ws

* Data: 2015-12-24

*/

#ifndef WS_LOGGER_H_

#define WS_LOGGER_H_

#include <cstdlib>

#include <cstdio>

#include <string>

//------------------------------------------------------------------------

// 日志系统

// 根据不同的系统使用不同的库

// 若是windows系统使用宏#define WIN32

// 若是linux系统中旧的log日志系统,使用宏#define L_LOG_OLD

// 若是linux系统中的syslog-ng日志系统(需要单独安装及配置),使用宏#define L_LOG_NG

//------------------------------------------------------------------------

//#define WIN32 // 表示使用的是windows系统

//#define L_LOG_OLD // 表示使用的是linux旧的syslog库

#define L_LOG_NG // 表示使用的是linux新的syslog-ng库,syslog的升级版

//-----------------------------------------------------------------------

// 声明部分

//-----------------------------------------------------------------------

# define MAXLOGLINE1024

#ifdef WIN32 // windows

//#define FOLDER_PATH // 表示日志地址是使用系统路径

#define MODEL_PATH // 表示日志地址是进程所在的文件路径

#include <fstream>

#include <shlwapi.h>

enum LogLevel {

Fatal = 0,//0 最高级,致命的

Alert = 1,//1
最高级,必须采取措施

Crit = 2,//2 最高级,临界状态

Error = 3,//3 高级,错误

Warn = 4,//4 高级,警告

Notice
= 5, //5 高级,正常但重要

Info = 6,//6 高级,一般信息

Debug = 7,//7 一般,调试信息

};

#else // "Linux syslog"(L_LOG_OLD) Or "linux syslog-ng"(L_LOG_NG)

#include <syslog.h>

enum LogLevel {

Fatal = LOG_EMERG,//0 最高级,致命的

Alert = LOG_ALERT,//1
最高级,必须采取措施

Crit = LOG_CRIT,//2 最高级,临界状态

Error = LOG_ERR,//3 高级,错误

Warn = LOG_WARNING,//4 高级,警告

Notice
= LOG_NOTICE, //5 高级,正常但重要

Info = LOG_INFO,//6 高级,一般信息

Debug = LOG_DEBUG,//7 一般,调试信息

};

#endif

//--------------------------------------------------------------

// 日志功能

//--------------------------------------------------------------

extern int syslogDevLevel; // 默认日志等级(默认等级debug)

void initLog(); // 初始化系统记录器

void logxxx(int l, char *file, int line, const char *fmt, ...); // 打印日志

void closeLog(); // 关闭log系统

int setLogLevel(); // 获取日志等级

int setLogLevel(int l); // 设置日志等级,返回旧的等级(这里不修改环境变量,防止更改所有进程的输出等级)

// 日志检测平台接入

struct ISyslogObserver {

virtual void watch(int level, const char *file, int line, const char *fmt, ...) = 0;

virtual bool interested(int level) = 0; // 判断是否对当前Level感兴趣,感兴趣才传递过去

virtual ~ISyslogObserver(){}

};

extern ISyslogObserver * SyslogWatcher; // 系统日志检测

extern ISyslogObserver * logStatWatcher; // 日志状态检测

// 日志

#define log(l, ...) \

if (SyslogWatcher && SyslogWatcher->interested(l)) { SyslogWatcher->watch(l, __FILE__, __LINE__, __VA_ARGS__); } \

if (logStatWatcher && logStatWatcher->interested(l)) { logStatWatcher->watch(l, __FILE__, __LINE__, __VA_ARGS__); } \

if (syslogDevLevel >= l) {logxxx(l, (char *)__FILE__, __LINE__, __VA_ARGS__); }

#endif // WS_LOGGER_H_

logger.cpp

--------------------------------------------------------------------------------------------------------------------------------------------

/*

* logger.cpp

* Author: ws

* Data: 2015-12-24

*/

//--------------------------------------------------------------

// 日志系统

//--------------------------------------------------------------

#include "logger.h"

#include <iostream>

#include <stdarg.h>

#include <ctime>

#include <cassert>

#include <stdlib.h>

#ifdef WIN32 // windows

#include <tchar.h>

#include <shlobj.h>

#include <windows.h>

#else // linux

#include <syslog.h>

#ifdef L_LOG_NG // linux syslog-ng

#include "syslog-nb.h"

#endif

#endif

#include <iostream>

using namespace std;

//--------------------------------------------------------------

// 全局变量

//--------------------------------------------------------------

ISyslogObserver * SyslogWatcher = NULL;

ISyslogObserver * logStatWatcher = NULL;

char * pDevLevel = getenv("DEV_LOG_LEVEL"); // 获取环境变量,系统默认日志等级

int syslogDevLevel = (NULL == pDevLevel) ? Debug : atol(pDevLevel);

// 获取日志等级

int setLogLevel()

{

return syslogDevLevel;

}

// 设置日志等级,返回旧的等级(这里不修改环境变量,防止更改所有进程的输出等级)

int setLogLevel(int l)

{

int old_level = syslogDevLevel;

syslogDevLevel = l;

return old_level;

}

#ifdef WIN32 // windows

std::ofstream fout; // 文件句柄

static long __log_lock = 0; //加锁计数器

// 等级名称

const char * levelnames[] = { "Fatal - ", "Alert - ", "Crit - ", "Error - ", "Warn - ", "Notice - ", "Info - ", "Debug - ", " - " };

const char * LevelToName(int l) {

return levelnames[l];

}

// 获取当前时间

std::string safe_time()

{

time_t t = time(NULL);

char *ct = ctime(&t);

if(ct){

size_t len = strlen(ct);

if(len > 0){

ct[len - 1] = '\0';

return std::string(ct, len - 1);

}

}

return "empty time";

}

// 长字符串转短

std::string Wchar2Ansi(const wchar_t* pStr, int len)

{

int nChars = 0;

std::string buf;

if (pStr == NULL)

{

assert(NULL);

return buf;

}

if (len < 0 && len != -1)

{

assert(NULL);

//OutputDebugStringW(_T("Invalid string length: ") + len); // 调试器

return buf;

}

// 长转短

nChars = WideCharToMultiByte(CP_ACP, 0, pStr, len, NULL, 0, NULL, NULL);

if (len == -1)

--nChars;

if (nChars == 0)

return "";

buf.resize(nChars);

WideCharToMultiByte(CP_ACP, 0, pStr, len, const_cast<char*>(buf.c_str()), nChars, NULL, NULL);

return buf;

}

// 短转长

std::wstring Ansi2WChar(LPCSTR pszSrc)

{

int nSize = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, _tcslen(pszSrc), 0, 0);

if (nSize <= 0) return NULL;

WCHAR *pwszDst = new WCHAR[nSize + 1];

if (NULL == pwszDst) return NULL;

MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, _tcslen(pszSrc), pwszDst, nSize);

pwszDst[nSize] = 0;

if (pwszDst[0] == 0xFEFF) // skip Oxfeff

{

for (int i = 0; i < nSize; i++)

{

pwszDst[i] = pwszDst[i + 1];

}

}

std::wstring wcharString(pwszDst);

delete pwszDst;

return wcharString;

}

// 解析出文件路径

std::string GetFileDirFromPath(LPCTSTR filepath)

{

unsigned int orgLen = _tcslen(filepath);

TCHAR end = filepath[orgLen - 1];

if (end != _T('\\') && end != _T(':'))

{

LPCTSTR FN = PathFindFileName(filepath); // 获取路径中的文件名

return std::string(filepath, orgLen - _tcslen(FN));

}

else

{

return std::string(filepath);

}

}

// 获取当前模块进程文件所在的路径

std::string GetModulePathDir()

{

TCHAR buffer[MAX_PATH];

ZeroMemory(buffer, sizeof(TCHAR) * MAX_PATH);

::GetModuleFileName(NULL, buffer, MAX_PATH); // 获取当前进程模块的文件名,含路径

std::string path = GetFileDirFromPath(buffer); // 获取文件路径

return path;

}

// 字符串中特殊字符替换

static std::string TransformInstallPath2FolderName(std::string const& strPath)

{

std::string strReturn;

strReturn.resize(strPath.size());

for (size_t i = 0; i < strPath.length(); i++)

{

TCHAR c = TCHAR(strPath[i]);

if (c == _T(':') || c == _T('\\') || c == _T(' ') || c == _T('/'))

{

strReturn[i] = _T('_');

}

else

{

strReturn[i] = strPath[i];

}

}

return strReturn;

}

// 获取指定系统路径

std::wstring GetUserAppDataDir()

{

TCHAR buffer[MAX_PATH];

ZeroMemory(buffer, MAX_PATH*sizeof(TCHAR));

SHGetSpecialFolderPath(NULL,buffer, CSIDL_APPDATA, NULL); // 获取指定系统路径

std::string path = std::string(buffer) + _T("\\ws\\");

path += TransformInstallPath2FolderName(GetModulePathDir());

path += _T("\\");

int nReturn = SHCreateDirectoryEx(NULL, path.c_str(), NULL);

std::wstring strPath = Ansi2WChar(path.c_str());

return strPath;

}

//-----------------------------------------

// 功能部分

//-----------------------------------------

// 初始化系统记录器,获取日志文件路径

void initLog() {

char buffer[MAX_PATH * 2];

ZeroMemory(buffer, sizeof(char) * MAX_PATH * 2);

std::string str;

#ifdef MODEL_PATH // 表示日志地址是进程所在的文件路径

str = GetModulePathDir();

#else // 表示日志地址是使用系统路径

std::wstring strW = GetUserAppDataDir();

strW = Wchar2Ansi(strW.c_str(), strW.length());

#endif

sprintf(buffer, "%sprotocol.log", str.data());

fout.open(buffer, std::ios_base::trunc);

fout << "program start: " << safe_time() << std::endl;

}

// 输出log

void logxxx(int l, char *file, int line, const char *fmt, ...)

{

va_list
param;

va_start(param, fmt);

// 锁

while (true)

{

if (InterlockedIncrement(&__log_lock) == 1)

{

break;

}

InterlockedDecrement(&__log_lock);

}

if (l <= syslogDevLevel)

{

char buf[MAXLOGLINE * 4];

_vsnprintf(buf, MAXLOGLINE * 4, fmt, param);

fout << safe_time()<< file << line << ":" << LevelToName(l) << buf << std::endl;

fout.flush();

}

InterlockedDecrement(&__log_lock);

va_end(param);

}

// 关闭log系统

void closeLog()

{

fout << "program end:" << safe_time() << std::endl;

fout.close();

}

#else // linux

//--------------------------------------------------------------

// 日志系统

//--------------------------------------------------------------

// 初始化系统记录器

void initLog(){

#ifdef L_LOG_OLD // "Linux syslog"(L_LOG_OLD)

openlog(NULL, LOG_PID, LOG_LOCAL0); // LOG_PID:包括每个消息的进程号; LOG_LOCAL0:保留到本地

#else // "linux syslog-ng"(L_LOG_NG)

openlog_nb(NULL, LOG_PID, LOG_LOCAL0); // LOG_PID:包括每个消息的进程号; LOG_LOCAL0:保留到本地

#endif

}

// 输出log

void logxxx(int l, char *file, int line, const char *fmt, ...) {

if (l <= syslogDevLevel) {

char msg[MAXLOGLINE];

va_list
ap;

va_start(ap, fmt);

int ret = vsnprintf(msg, MAXLOGLINE, fmt, ap);

va_end(ap);

if (ret < 0) { return; }

#ifdef L_LOG_OLD // "Linux syslog"(L_LOG_OLD)

syslog(l, "[%s:%d]: %s\n", file, line, msg);

#else // "linux syslog-ng"(L_LOG_NG)

syslog_nb(l, "[%s:%d]: %s\n", file, line, msg);

#endif

}

else

{

return;

}

}

// 关闭log系统

void closeLog()

{

#ifdef L_LOG_OLD // "Linux syslog"(L_LOG_OLD)

closelog();

#else // "linux syslog-ng"(L_LOG_NG)

closelog_nb();

#endif

}

#endif

--------------------------------------------------------------

配置信息请参照下一篇:syslog &syslog-ng详解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: