简单的跨平台c/c++日志记录
CLog.h
#include <stdlib.h>
#pragma once
#ifndef _CLOG
#define _CLOG
#define CLOG_DEBUG 0
#define CLOG_INFO 1
#define CLOG_WARNING 2
#define CLOG_ERROR 3
#define stderr_message(exp, message) \
{ \
fprintf(stderr,"-------------ERROR-----------------\n"); \
fprintf(stderr,"Failed:%s\nMessage:%s\nLine:%d\nFile:%s\n",#exp,message,__LINE__,__FILE__);\
fprintf(stderr,"-------------ERROR-----------------\n"); \
/*exit(EXIT_FAILURE);*/\
}
//Clog(int level, char *msg)
#define CLog(level,msg)\
{\
_CLog(level,msg,__LINE__,__FILE__);\
}\
//CLogDebug(char *msg)
#define CLogDebug(msg)\
{\
CLog(CLOG_DEBUG,msg);\
}\
//CLogError(char *msg)
#define CLogError(msg)\
{\
CLog(CLOG_ERROR,msg);\
}\
//CLogInfo(char *msg)
#define CLogInfo(msg)\
{\
CLog(CLOG_INFO,msg);\
}\
//CLogWarning(char *msg)
#define CLogWarning(msg)\
{\
CLog(CLOG_WARNING,msg);\
}\
#endif
#ifdef __cplusplus
extern "C" {
#endif
//init clog ! log_path is logfile path!
void InitCLog(char *log_path);
//this fun is logging!
void _CLog(int level, char *msg,int line,char *file);
//freee clog!
void FreeeClog();
#ifdef __cplusplus
}
#endif
CLog.c
#include "CLog.h"
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#ifdef WIN32
#include <windows.h>
#else
#include <pthread.h>
#endif
#ifndef _CLOGSTATIC
#define _CLOGSTATIC
const char CLOGLevelName[4][8] = { "debug", "info", "warning", "error" };
FILE *fp = NULL;
char now_file_name[11];
char *log_path;
#ifdef WIN32
CRITICAL_SECTION g_cs;
#else
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
#endif
#endif
void now_date_str(char *date_str)
{
time_t nowtime;
struct tm *timeinfo;
time(&nowtime);
timeinfo = localtime(&nowtime);
sprintf(date_str, "%d_%d_%d",
timeinfo->tm_year + 1900,
timeinfo->tm_mon + 1,
timeinfo->tm_mday);
}
void now_datetime_str(char *datetime_str)
{
time_t nowtime;
struct tm *timeinfo;
time(&nowtime);
timeinfo = localtime(&nowtime);
sprintf(datetime_str, "%d_%d_%d %d:%d:%d",
timeinfo->tm_year + 1900,
timeinfo->tm_mon + 1,
timeinfo->tm_mday,
timeinfo->tm_hour,
timeinfo->tm_min,
timeinfo->tm_sec
);
}
void lock()
{
#ifdef WIN32
EnterCriticalSection(&g_cs);
#else
pthread_mutex_lock(&mutex1);
#endif
}
void unlock()
{
#ifdef WIN32
LeaveCriticalSection(&g_cs);
#else
pthread_mutex_unlock(&mutex1);
#endif
}
long thread_id()
{
#ifdef WIN32
return GetCurrentThreadId();
#else
return pthread_self();
#endif
}
void open_log_file()
{
char *filename = (char*)malloc(strlen(log_path) + strlen(now_file_name) + 1);
sprintf(filename, "%s/%s.%s", log_path, now_file_name, "txt");
fp = fopen(filename, "ab+");
if (fp == NULL)
{
stderr_message(fp == NULL, "(clog) fopen error !");
return;
}
}
//mk dirs
void mkdir_p(char *dir)
{
//copy
char * dir_c = (char*)malloc(strlen(dir) + 1);
memcpy(dir_c, dir, strlen(dir) + 1);
dir = dir_c;
char * temppath = (char*)malloc(strlen(dir) + 1);
int tempindex = 0;
while (*dir_c != '\0')
{
if (*dir_c == '\\')
*dir_c = '/';
if (*dir_c == '/')
{
tempindex = dir_c - dir;
memcpy(temppath, dir, tempindex);
temppath[tempindex] = '\0';
if (_access(temppath, 0) != 0)
_mkdir(temppath);
}
dir_c++;
}
if (_access(dir, 0) != 0)
_mkdir(dir);
free(dir);
free(temppath);
}
void InitCLog(char *path)
{
#ifdef WIN32
InitializeCriticalSection(&g_cs);
#endif
if (path == NULL)
stderr_message(path == NULL, "(clog) logpath is null !");
now_date_str(now_file_name);
int pathlength = strlen(path);
log_path = (char*)malloc(pathlength*sizeof(char) + 1);
strcpy(log_path, path);
if (log_path[pathlength - 1] == '/')
log_path[pathlength - 1] = '\0';
mkdir_p(log_path);
open_log_file();
}
void _CLog(int level, char *msg, int line, char *file)
{
lock();
if (level<0 || level>3)
{
stderr_message(level<0 || level>3, "(clog) level overflow!");
return;
}
if (fp == NULL)
{
stderr_message(fp == NULL, "(clog) clog not init!");
return;
}
char temp_now_file_name[11];
now_date_str(temp_now_file_name);
if (strcmp(temp_now_file_name, now_file_name) != 0)
{
strcpy(now_file_name, temp_now_file_name);
fclose(fp);
open_log_file();
if (fp == NULL)
{
stderr_message(fp == NULL, "(clog) clog init error!");
return;
}
}
char* info = (char*)malloc(strlen(msg) + 80 + strlen(file));
char datetimestr[21];
now_datetime_str(datetimestr);
sprintf(info, "%s thread:%d %s \r\n%s\r\nfile:%s line:%d\r\n",
datetimestr,
thread_id(),
CLOGLevelName[level],
msg,
file,
line);
fwrite(info, strlen(info), 1, fp);
fflush(fp);
free(info);
unlock();
}
void FreeeClog()
{
lock();
if (fp != NULL)
fclose(fp);
free(log_path);
unlock();
}
Example:
#include "stdafx.h"//Without this header file under linux
#include "CLog.h"
#include <stdlib.h>
#ifdef WIN32
#include <Windows.h>
#include <process.h>
#else
#include <pthread.h>
#endif
#define thread_num 10
void thread_fun()
{
int i = 0;
for (; i < 1000; i++)
{
CLog(CLOG_DEBUG, "this debug message!");
CLog(CLOG_INFO, "this info!╮(╯▽╰)╭");
CLog(CLOG_WARNING, "警告!this warning!!");
CLog(CLOG_ERROR, "Error!!");
}
}
#ifdef WIN32
unsigned _stdcall ThreadProc(void* param)
{
thread_fun();
return 0;
}
void win32_thread_test()
{
HANDLE handle[thread_num];
int i = 0;
for (; i < thread_num; i++)
{
handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, NULL, NULL);
}
for (i = 0; i < thread_num; i++)
{
WaitForSingleObject(handle[i], INFINITE);
CloseHandle(handle[i]);
}
}
#else
void *linux_threadfun(void *arg)
{
thread_fun();
}
void linux_thread_test()
{
pthread_t pthreadarray[thread_num];
int i = 0;
for (; i < thread_num; i++)
{
pthreadarray[i] = pthread_create(&pthreadarray[i], NULL, linux_threadfun, NULL);
}
for (i = 0; i < thread_num; i++)
{
pthread_join(&pthreadarray[i], NULL);
}
}
#endif
int main()
{
/*Example:
InitCLog ("D:/ntg/logs"); disk directory
InitCLog ("logs"); the current directory under the logs directory
InitCLog ("test/log/codelog"); the current directory est/log/codelog directory
*/
InitCLog("D:/Logs");
//Loging Example:
CLog(CLOG_DEBUG, "this debug message!");
CLog(CLOG_INFO, "this info!╮(╯▽╰)╭");
CLog(CLOG_WARNING, "this warning! ( ⊙ o ⊙ )啊!");
CLog(CLOG_ERROR, "Error!!");
//or
CLogInfo("这是info!");
CLogError("报错!");
CLogDebug("debug!!");
CLogWarning("指针为null!");
//Multithreaded Test Start
#ifdef WIN32
win32_thread_test();
#else
linux_thread_test();
#endif
//Multithreaded Test End
//The program exits when the need to call FreeeClog free
FreeeClog();
system("pause");
return 0;
}
简单的跨平台c/c++日志记录的更多相关文章
- Ibatis.net 1.6.2 简单配置及Log4.Net日志记录
看似简单的Ibatis配置起来注意的地方还挺多.里面的设置及功能还算强大.昨晚配置了半宿,结果一运行还是各种错误.急的直冒汗.果断下载实例去研究.英文不好文档只能作为功能参考. 下面一步步进入Ibat ...
- 【转】使用Log4Net进行日志记录
首先说说为什么要进行日志记录.在一个完整的程序系统里面,日志系统是一个非常重要的功能组成部分.它可以记录下系统所产生的所有行为,并按照某种规范表达出来.我们可以使用日志系统所记录的信息为系统进行排错, ...
- php 简单通用的日志记录方法
使用file_put_contents 方法来实现简单便捷的日志记录功能 方法1: // use \r\n for new line on windows, just \n on linux func ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存
代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...
- Net Core平台灵活简单的日志记录框架NLog+SqlServer初体验
Net Core平台灵活简单的日志记录框架NLog+SqlServer初体验 前几天分享的"[Net Core平台灵活简单的日志记录框架NLog+Mysql组合初体验][http://www ...
- Net Core平台灵活简单的日志记录框架NLog+Mysql组合初体验
Net Core平台灵活简单的日志记录框架NLog初体验 前几天分享的"[Net Core集成Exceptionless分布式日志功能以及全局异常过滤][https://www.cnblog ...
- Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存
本文梯子 本文3.0版本文章 代码已上传Github+Gitee,文末有地址 大神反馈: 零.今天完成的深红色部分 一.AOP 之 实现日志记录(服务层) 1.定义服务接口与实现类 2.在API层中添 ...
- 简单的C#日志记录和弹出提示
记录这个博客的想法只有两点, 一,在使用webserver的时候如果你不好调用本地server端,那么你可以启用日志来查看异常.当然也可以调用本地的server端.这里简单说一下.不是本文的重点. 发 ...
- C++实现简单的日志记录
C++实现简单的日志记录 //dlogger.h #ifndef DLOGGER_H #define DLOGGER_H #include <iostream> #include < ...
随机推荐
- java 枚举类型知识点记录
在日常开发中,我们常用接口装常量或者在类里面写静态常量,java1.5以后加入了枚举类型enum.枚举类型是由一组固定的常量组成的类型.枚举本质是int值.因为枚举类型没有可以访问的构造器,所以枚举类 ...
- 【转】Python中的赋值、浅拷贝、深拷贝介绍
这篇文章主要介绍了Python中的赋值.浅拷贝.深拷贝介绍,Python中也分为简单赋值.浅拷贝.深拷贝这几种"拷贝"方式,需要的朋友可以参考下 和很多语言一样,Python中 ...
- Titanium系列--对Window和View的一点理解
1. window相当于一块屏幕,view相当于一个div层.window拥有全屏和模态化属性,view则没有这2个属性. 2. 创建一个window作为我们的APP的屏幕,之后我们将添加其他元素来丰 ...
- Integrate non-OSGi Dependencies
Consider a scenario where you need to use a non-OSGi jar in your OSGi project. Most libraries are no ...
- ofbiz 代码日记
写代码一定要尽善尽美.. //修改方法 //条件查询 用于修改 List<GenericValue> stoList = delegator.findByAnd("YcrossS ...
- 做WP程序时遇到的一些问题及解决方法
问题1:Type 'JDBYSJ.Data.NewsChannel' cannot be serialized. Consider marking it with the DataContractAt ...
- JAVA设计模式--工厂方法模式
工厂方法设计模式 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关.是具体工厂角色必须实现的接口或者必须继承的父类.在java中它由抽象类或者接口来实现.具体工厂角色:它含有和具体业务逻辑有关 ...
- nginx.conf各参数的意义
搬运+翻译至 http://qiita.com/syou007/items/3e2d410bbe65a364b603 /etc/nginx/nginx.conf 记录各个参数的意义 user user ...
- Android下集成Paypal支付
近期项目需要研究paypal支付,官网上的指导写的过于复杂,可能是老外的思维和中国人不一样吧.难得是发现下面这篇文章: http://www.androidhive.info/2015/02/andr ...
- Java设计模式3:工厂方法模式
工厂方法模式 工厂方法模式是类的创建模式.工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工厂推迟到子类中. 工厂方法模式 工厂方法模式是对简单工厂模式进一步抽象的结果. 假如是不使用反 ...