(转)日志类


#ifndef CLASSES_LOGGING_H__
#define CLASSES_LOGGING_H__

#include <iostream>
#include <iomanip>
#include <sstream>
#include <Windows.h>

#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
TypeName(const TypeName&); void operator=(const TypeName&)

enum LoggingSeverity
{
LS_SENSITIVE,
LS_VERBOSE,
LS_INFO,
LS_WARNING,
LS_ERROR,
INFO = LS_INFO,
WARNING = LS_WARNING,
LERROR = LS_ERROR
};

enum LogErrorContext
{
ERRCTX_NONE,
ERRCTX_ERRNO,
ERRCTX_HRESULT
};

class LogMessage
{
public:
LogMessage(const char* file,
int line,
LoggingSeverity sev,
LogErrorContext err_ctx = ERRCTX_NONE,
int err = 0,
const char* module = NULL);

~LogMessage();

std::ostream& stream()
{
return print_stream_;
}

static void ResetTimestamps();

private:
static const char* Describe(LoggingSeverity sev);
static const char* DescribeFile(const char* file);
static long TimeDiff(unsigned long later, unsigned long earlier);
static bool TimeIsBetween(unsigned long later, unsigned long middle, unsigned long earlier);

std::ostringstream print_stream_;

LoggingSeverity severity_;
std::string extra_;
static unsigned long start_;
HANDLE hFile_;
DISALLOW_EVIL_CONSTRUCTORS(LogMessage);
};

#define LOG_INFO() LogMessage(__FILE__, __LINE__, LS_INFO).stream()

#define LOG(sev) LogMessage(__FILE__, __LINE__, sev).stream()

#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "

#define PLOG(sev, err) LogMessage(__FILE__, __LINE__, sev, ERRCTX_ERRNO, err).stream()

#define LOG_ERR(sev) LogMessage(__FILE__, __LINE__, sev, ERRCTX_ERRNO, errno).stream()

#define LOG_GLE(sev) LogMessage(__FILE__, __LINE__, sev, \
ERRCTX_HRESULT, GetLastError()).stream()

#define LOG_GLEM(sev, mod) LogMessage(__FILE__, __LINE__, sev, \
ERRCTX_HRESULT, GetLastError(), mod) .stream()
#endif


#include "logging.h"

extern "C" BOOL WINAPI IsDebuggerPresent(void);

unsigned long LogMessage::start_ = GetTickCount();

LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev,
LogErrorContext err_ctx, int err, const char* module)
: severity_(sev)
{
unsigned long time = TimeDiff(GetTickCount(), start_);
print_stream_ << "[" << std::setfill(‘0‘) << std::setw(3) << (time / 60000)
<< ":" << std::setw(2) << (time %60000)/1000
<< ":" << std::setw(3) << time %1000 << std::setfill(‘ ‘)
<< "] ";

DWORD id = GetCurrentThreadId();
print_stream_ << "[0x" << std::setfill(‘0‘) << std::setw(8)
<< std::hex << id << std::dec << "] ";

print_stream_ << Describe(sev) << "(" << DescribeFile(file)
<< ":" << line << "): ";

if (err_ctx != ERRCTX_NONE)
{
std::ostringstream tmp;
tmp << "[0x" << std::setfill(‘0‘) << std::hex << std::setw(8) << err << "]";
switch (err_ctx)
{
case ERRCTX_ERRNO:
{
tmp << " " << strerror(err);
break;
}
case ERRCTX_HRESULT:
{
char msgbuf[256]={0};
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM;
HMODULE hmod = GetModuleHandleA(module);
if (hmod)
flags |= FORMAT_MESSAGE_FROM_HMODULE;
if (DWORD len = FormatMessageA(
flags, hmod, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
msgbuf, sizeof(msgbuf) / sizeof(msgbuf[0]), NULL))
{
while ((len > 0) &&
isspace(static_cast<unsigned char>(msgbuf[len-1])))
{
msgbuf[--len] = 0;
}
tmp << " " << msgbuf;
}
break;
}

default:
break;
}
extra_ = tmp.str();
}
}

LogMessage::~LogMessage()
{
if (!extra_.empty())
print_stream_ << " : " << extra_;
print_stream_ << "\r\n";
const std::string& str = print_stream_.str();

static bool debugger_present = (IsDebuggerPresent() != FALSE);
if (debugger_present)
{
OutputDebugStringA(str.c_str());
}
else
{
hFile_ = ::CreateFileA("Test.txt",GENERIC_WRITE,0,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
if(INVALID_HANDLE_VALUE != hFile_)
{
unsigned long written=0L;

::SetFilePointer (hFile_, 0, NULL, FILE_END);
::WriteFile(hFile_, str.data(), str.size(), &written, 0);

FlushFileBuffers(hFile_);
::CloseHandle(hFile_);
}
else
{
hFile_ = NULL;
}
}
}

void LogMessage::ResetTimestamps()
{
start_ = GetTickCount();
}

const char* LogMessage::Describe(LoggingSeverity sev)
{
switch (sev)
{
case LS_SENSITIVE: return "Sensitive";
case LS_VERBOSE: return "Verbose";
case LS_INFO: return "Info";
case LS_WARNING: return "Warning";
case LS_ERROR: return "Error";
default: return "<unknown>";
}
}

const char* LogMessage::DescribeFile(const char* file)
{
const char* end1 = ::strrchr(file, ‘/‘);
const char* end2 = ::strrchr(file, ‘\\‘);
if (!end1 && !end2)
return file;
else
return (end1 > end2) ? end1 + 1 : end2 + 1;
}

bool LogMessage::TimeIsBetween(unsigned long later, unsigned long middle, unsigned long earlier)
{
if (earlier <= later)
{
return ((earlier <= middle) && (middle <= later));
}
else
{
return !((later < middle) && (middle < earlier));
}
}

long LogMessage::TimeDiff(unsigned long later, unsigned long earlier)
{
unsigned long LAST = 0xFFFFFFFF;
unsigned long HALF = 0x80000000;
if (TimeIsBetween(earlier + HALF, later, earlier))
{
if (earlier <= later)
{
return static_cast<long>(later - earlier);
}
else
{
return static_cast<long>(later + (LAST - earlier) + 1);
}
}
else
{
if (later <= earlier)
{
return -static_cast<long>(earlier - later);
}
else
{
return -static_cast<long>(earlier + (LAST - later) + 1);
}
}
}

(转)日志类

时间: 2024-10-16 04:17:29

(转)日志类的相关文章

c++ 日志类 线程安全+缓存

根据上一次的测试,有缓存的日志类性能会更好.用到了time.h类函数,所以在linux下就要改动一下了,windows环境下写的. 思路采用(参照muduo库的日志,不过认为他线程不安全,和没用缓存,就改造了下) 1.有一个总的缓存,logboss,为一个恶汉模式的单例类,指针对象为智能指针,析构函数讲缓存写入文件. 2.有一个logger类,作为临时缓存,析构函数,将里面的缓存写入总缓存(在总缓存写入的时候加锁).如果缓存超过一定限度,就将前面的缓存写入文件先. void LogBoss::a

怎么样做好日志类的报警监控

上一篇文章写了普通数字类型类型的监控报警,本文谈一下怎么样做好日志类的监控和报警 一.日志类报警的特点 1.接受人员希望直接看到日志的内容: 2.对应技术栈涉及比较广的系统,,一个问题会引发不同主机上面不同系统同时产生日志.举例:openstack 的nova在保存快照时出错,会引起nova-api,galnce-api,horizen同时产生错误日志. 二.遇到的痛点: 1.有很多人想随时查看日志,不同的人想要查看不同的日志: 2.日志类的报警,不适合用微信直接发送内容,原因一是转义麻烦,二是

C++开源日志类

今天想给我的C++项目找一个开源的日志类,用于记录系统日志,结果浪费了半个下午的时间.从网上搜索相关资料,找到以下几个备选方案: 1.log4cplus 下载地址:http://sourceforge.net/projects/log4cplus/files/log4cplus-stable/1.1.0 2.log4cxx 下载地址:http://logging.apache.org/log4cxx/download.html (log4cxx 是由JAVA实现的 log4j 开源的,用C++实

简易的日志类

打日志是开发不可或缺的功能, 它经常比断点好用, 并且可用性更广. 在很久以前, 我总习惯性的printf, cout, 把日志打印在控制台. 直到我发现, 这除了针对性的看日志, 并没有什么乱用. 你的程序提交到测试那里, 程序出现意外, 你不能指望测试给你提供崩溃当时的日志, 也不能及时赶到现场, 发动写轮眼记下原因. 所以, 日志除了打印在屏幕, 还要写日到文件... 1 // 日志写入. 2 class Log { 3 public: 4 // 日志结束符. 5 class End {}

C#日志类记录

每个程序都要和日志打交道.程序日志的质量直接影响了排除问题的难度.普通程序调试信息直接输出控制台,复杂程序则通过文本,xml等方式记录运行时的调试信息.在C#中Diagnostics命名空间下有一个微软提供的专门用于记录信息的TraceSource类.TraceSource的使用方法很简单,只需要4行代码 TraceSource ts = new TraceSource("Code.Main", SourceLevels.All); ts.Listeners.Add(new Conso

WorldWind源码剖析系列:日志类Log

Utility工程中的日志类Log主要用来输出Debug状态下的调试信息.该类的类图如下: 日志类Log中使用到的类和内嵌结构体类型主要有以下这些: public class LogEventArgs : EventArgs//日志事件参数 { public int level; public string category; public string message; public LogEventArgs(int _l, string _c, string _m) { level = _l

关于日志类Log4j的使用

log4j 的配置 1 #下面定义日志输出级别是 INFO,并且配置了2个输出目的地,一个是A3,一个是console 2 3 log4j.rootLogger = INFO,A3,CONSOLE 4 5 #日志最低的输出级别 6 log4j.appender.A3.Threshold=INFO 7 log4j.appender.A3.encoding=UTF-8 8 #每天产生一个文件DailyRollingFileAppender 9 log4j.appender.A3 = org.apac

android Loger日志类(获取内置sd卡)

Android手机自带内部存储路径的获取 原文地址:http://my.oschina.net/liucundong/blog/288183 直接贴代码: public static String getExternalSdCardPath() { if (SDCardUtils.isSDCardEnable()) { File sdCardFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath());

日志类(三)TLog ①

功能未完善. 待续. 1 TLogThread = class(TThread) 2 private 3 FInterval: Integer; 4 FLogServers: TList; 5 FEvent: TEvent; 6 procedure SetInterval(pvInterval: Integer); 7 protected 8 property Interval: Integer read FInterval write SetInterval; 9 property LogSe

分享一个PHP调试日志类

分享一个我自己用的在 WordPress 开发中用得到的一个调试日志类. <?php /** * @author: suifengtec coolwp.com * @date: 2013-02-03 09:55:55 * @last Modified by: suifengtec coolwp.com * @last Modified time: 2015-07-12 18:40:02 */ if(function_exists('add_action')){ defined('ABSPATH'