用C 实现一个Log系统
- 格式:pdf
- 大小:144.94 KB
- 文档页数:5
C#添加Log⽂件、记录Log其实在平时的开发过程中都是不怎么写log的,觉得在debug中能看得⼀清⼆楚。
同事⼩姐姐前辈,⼀直就我不写log进⾏批判,但是我从来不改,哈哈。
也算是遇到报应了,在最近⼀个⼯程⾥,本地调试⼀切正常,到了服务器上就不好使,百般⽆奈写了⼈⽣第⼀个log,也记录下来,⽅便以后查漏补缺,与⼤家共勉。
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////⾸先提供⼀个范本,着急⽤的童鞋可以直接下载,然后跳过2,直接看1和3。
Logger.cs: https:///s/1dZHxuQLoggerEnum.cs: https:///s/1i7gUEZr1.创建⽂件: 按照以下⽂件⽬录建好,也可以⾃⾏安排,⽆关紧要。
主要⽤到的就是Logger.cs,LoggerEnum.cs就是记录log的type的枚举。
2.填充内容: 根据⾃⼰的项⽬改⼀下namespace就好了 1)⾸先LoggerEnum.cs 类型枚举,没啥好讲的namespace ICUValidationService.Log{public enum LogType{All,Information,Debug,Success,Failure,Warning,Error}} 2)Logger.csusing System;using System.IO;using System.Reflection;namespace ICUValidationService.Log{public class Logger{#region Instanceprivate static object logLock;private static Logger _instance;private static string logFileName;private Logger() { }///<summary>/// Logger instance///</summary>public static Logger Instance{get{if (_instance == null){_instance = new Logger();logLock = new object();logFileName = Guid.NewGuid() + ".log";}return _instance;}}#endregion///<summary>/// Write log to log file///</summary>///<param name="logContent">Log content</param>///<param name="logType">Log type</param>public void WriteLog(string logContent, LogType logType = rmation,string fileName =null){try{string basePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);basePath = @"C:\APILogs";if (!Directory.Exists(basePath + "\\Log")){Directory.CreateDirectory(basePath + "\\Log");}string dataString = DateTime.Now.ToString("yyyy-MM-dd");if (!Directory.Exists(basePath + "\\Log\\" + dataString)){Directory.CreateDirectory(basePath + "\\Log\\" + dataString);}string[] logText = new string[] { DateTime.Now.ToString("hh:mm:ss") + ": " + logType.ToString() + ": " + logContent };if (!string.IsNullOrEmpty(fileName)){fileName = fileName +"_"+ logFileName;}else{fileName = logFileName;}lock (logLock){File.AppendAllLines(basePath + "\\Log\\" + dataString + "\\" + fileName, logText);}}catch (Exception) { }}///<summary>/// Write exception to log file///</summary>///<param name="exception">Exception</param>public void WriteException(Exception exception,string specialText= null){if (exception != null){Type exceptionType = exception.GetType();string text = string.Empty;if (!string.IsNullOrEmpty(specialText)){text = text + specialText + Environment.NewLine;}text = "Exception: " + + Environment.NewLine;text += "" + "Message: " + exception.Message + Environment.NewLine;text += "" + "Source: " + exception.Source + Environment.NewLine;text += "" + "StackTrace: " + exception.StackTrace + Environment.NewLine;WriteLog(text, LogType.Error);}}}} 简单⽽⾔,就两个⽅法,⼀个写简单信息(WriteLog),⼀个写error信息(WriteException)。
C++实现⼀个⽇志类转载:我们可能遇到发包后,在客户机器上出现各种未知错误,如果没有⽇志打印,对于问题解决是很困难的,因此常规的解决办法就是打印⽇志。
在此⽤C++ 实现⼀个简单的⽇志类,使⽤cout输出调试信息,同时把⽇志写到⽂件中,实现了⼀个Logger类,主要考虑实现以下功能:⽇志等级: 参考python的logger类,我设置了四个⽇志等级, 从低到⾼依次为debug, info, warning, error,这样的话我想输出⼀条debug 信息就可以这样写logger.debug("something..."), (关于⽇志等级是什么意思可以参考⼀下python的logger类,简单来说就是当⽇志等级⼤于等于设置的初始等级时才会记录⽇志)输出⽬标: 我设置了三种输出⽬标: 仅输出到终端、仅输出到⽂件、既输出到终端⼜输出到⽂件为了⽅便的设置⽇志等级,可以⽤⼀个枚举类表⽰四种⽇志等级,同理⽤⼀个枚举类表⽰三种输出⽬标enum log_level{debug, info, warning, error};// ⽇志等级enum log_target{file, terminal, file_and_terminal};// ⽇志输出⽬标Logger.h#ifndef _LOGGER_H_#define _LOGGER_H_#include <iostream>#include <fstream>#include <time.h>#pragma warning (disable:4996)class Logger{public:enum log_level { debug, info, warning, error };// ⽇志等级enum log_target { file, terminal, file_and_terminal };// ⽇志输出⽬标public:Logger();Logger(log_target target, log_level level, const std::string& path);~Logger();void DEBUG(const std::string& text);void INFO(const std::string& text);void WARNING(const std::string& text);void ERRORS(const std::string& text);private:std::ofstream m_outfile; // 将⽇志输出到⽂件的流对象log_target m_target; // ⽇志输出⽬标std::string m_path; // ⽇志⽂件路径log_level m_level; // ⽇志等级void output(const std::string &text, log_level act_level); // 输出⾏为};#endif//_LOGGER_H_Logger.cpp#include "Logger.h"#include <string>std::string currTime(){// 获取当前时间,并规范表⽰char tmp[64];time_t ptime;time(&ptime); // time_t time (time_t* timer);strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", localtime(&ptime));return tmp;}Logger::Logger(){// 默认构造函数m_target = terminal;m_level = debug;std::cout << /*"[WELCOME] " << __FILE__ << " " <<*/ currTime() << " : " << "=== Start logging ===" << std::endl;}Logger::Logger(log_target target, log_level level, const std::string& path){m_target = target;m_path = path;m_level = level;std::string strContent = currTime() + " : " + "=== Start logging ===\n"; if (target != terminal) {m_outfile.open(path, std::ios::out | std::ios::app); // 打开输出⽂件 m_outfile << strContent;}if (target != file){// 如果⽇志对象不是仅⽂件std::cout << strContent;}}Logger::~Logger(){std::string strContent = currTime() + " : " + "=== End logging ===\r\n"; if (m_outfile.is_open()){m_outfile << strContent;}m_outfile.flush();m_outfile.close();}void Logger::DEBUG(const std::string& text){output(text, debug);}void Logger::INFO(const std::string& text){output(text, info);}void Logger::WARNING(const std::string& text){output(text, warning);}void Logger::ERRORS(const std::string& text){output(text, error);}void Logger::output(const std::string &text, log_level act_level){std::string prefix;if (act_level == debug) prefix = "[DEBUG] ";else if (act_level == info) prefix = "[INFO] ";else if (act_level == warning) prefix = "[WARNING] ";else if (act_level == error) prefix = "[ERROR] ";//else prefix = "";//prefix += __FILE__;//prefix += " ";std::string outputContent = prefix + currTime() + " : " + text + "\n";if (m_level <= act_level && m_target != file){// 当前等级设定的等级才会显⽰在终端,且不能是只⽂件模式std::cout << outputContent;}if (m_target != terminal)m_outfile << outputContent;m_outfile.flush();//刷新缓冲区}测试#include "Logger.h"void test() {Logger logger(Logger::file_and_terminal, Logger::debug, "Log.log");logger.DEBUG("Debug info");("This is variable");logger.WARNING("This function or variable may be unsafe");logger.ERRORS("Memory leak");}int main(){test();getchar(); return0; }。
分享⼀个⽇志系统源码(C语⾔)代码路径: 这是⼀个简单、⾼效和轻量级C语⾔写的的⽇志系统,linux下不需要第三⽅库安装。
⽬前主要是在linux下编写和测试,通⽤分⽀()为⼀个基于Apache的(⼀个C语⾔跨平台的开源库)编写的跨平台版本,由于精⼒有限只基于最简单的⽇志打印功能进⾏了改写,仅供参考。
⽇志系统⽀持多线程多句柄、印级别控制、IO缓存设置、备份控制、⽇志⽂件⼤⼩控制、异常退出堆栈打印、加密(AES-128)、压缩(lz4)和散列校验(MD5)。
所有配置和接⼝都在log.h内。
堆栈打印是接收所有异常退出信号时打印堆栈,输出⽂件名通过TRACE_PRINT_PATH宏控制,在其信号处理时还对所有⽇志句柄进⾏刷新处理,减少⽇志丢失可能。
下⾯介绍下接⼝使⽤:⽇志创建: //log_filename:输出⽂件名。
//max_file_size:每个⽂件最⼤上限。
//max_file_bak:最⼤备份⽂件数量,备份⽂件名为输出⽂件名末尾+备份序号,如有其它需要可⾃⾏修改。
//max_iobuf_size:IO缓存⼤⼩,可以设为0⽆缓存。
//cflag:三个宏选项,NORMALIZE, ENCRYPT, COMPRESS 或者 ENCRYPT|COMPRESS,分别对应正常,只加密/压缩,加密和压缩。
//password:密码,在cflag有设ENCRYPT时⽣效。
//返回为⼀个log句柄,可以创建多个,数量最⼤值由MAX_HANDLE_NUM宏控制。
log_t* log_create(const char *log_filename, size_t max_file_size, size_t max_file_bak, size_t max_iobuf_size, int cflag, const char *password);刷新和销毁为: //刷新是将IO缓存内数据刷新到⽂件内,lh为创建返回的句柄指针。
C语言技术中的日志记录方法与工具推荐在软件开发中,日志记录是一项非常重要的技术,它可以帮助开发人员追踪和调试程序的运行过程,以及记录关键信息和错误日志。
对于C语言技术而言,日志记录同样具有重要性。
本文将介绍C语言中的日志记录方法以及一些工具的推荐。
一、日志记录方法1. printf语句最简单的日志记录方法就是使用printf语句将关键信息输出到控制台。
这种方法简单直接,适用于小规模的项目或者调试阶段。
但是,它的缺点是无法自动记录时间戳、无法保存到文件中,且不便于管理和过滤。
2. 文件输出为了解决printf语句的缺点,我们可以将日志信息输出到文件中。
通过使用标准库函数fopen、fprintf和fclose,我们可以将信息写入到指定的文件中。
这种方法可以记录时间戳,且方便管理和过滤。
但是,需要注意的是,频繁的文件操作可能会对性能产生一定的影响。
3. 宏定义宏定义是一种更加高效的日志记录方法。
通过定义一些宏,我们可以在代码中插入日志语句,并且可以根据需要灵活地开启或关闭日志记录。
例如,我们可以定义一个宏LOG,用于输出日志信息。
在发布版本中,我们可以将这些宏定义为空,从而避免日志记录对性能的影响。
二、日志记录工具推荐1. log4clog4c是一个开源的C语言日志记录工具,它提供了丰富的功能和灵活的配置选项。
使用log4c,我们可以将日志信息输出到控制台、文件、网络等不同的目标中,并且可以按照不同的级别进行过滤和管理。
log4c还支持多线程环境下的日志记录,可以满足大部分项目的需求。
2. syslogsyslog是一个标准的日志记录系统,可以在大多数Unix-like系统中使用。
它提供了一个守护进程,负责接收和处理日志信息,并且可以将日志信息输出到指定的文件中。
syslog还支持日志的远程传输和集中管理,适用于分布式系统和大规模项目。
3. GlogGlog是Google开发的一个C++日志记录库,但它同样适用于C语言。
C/C++log日志实例+代码刚在网上看了下C/c++ log日志的用法找了两个例子希望大家喜欢简单的分级别写日志程序#ifndef __WRITELOG_H__#define __WRITELOG_H__#include "stdafx.h"#include <time.h>#include <memory.h>#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <windows.h>#define _LOG_WRITE_STATE_ 1 /* 条件编译开关,1:写日志,0:不写日志*/#define LOG_SUCCESS (0)#define LOG_FAILED (-1)#define LOG_BOOL_TRUE (1)#define LOG_BOOL_FALSE (0)#define DWORD_NULL (0xFFFFFFFF)#define MAX_LOGTEXT_LEN (2048) /* 每行日志的最大长度*/#define MAX_FILE_P ATH (255) /* 日志文件路径的最大长度*/#define MAX_LOG_FILE_SIZE (512 * 1024) /* 日志文件内容的最大长度*/#define MAX_LOG_FILE_NAME_LEN (256) /* 日志文件名的最大长度*/#define LOG_TYPE_INFO 0 /* 日志类型: 信息类型*/#define LOG_TYPE_ERROR 1 /* 日志类型: 错误类型*/#define LOG_TYPE_SYSTEM 2 /* 日志类型: 系统类型*/#define TEST_CASE_MAX_FILE_LEN (1024) /* 测试函数中文件内容最大长度*/ const char g_LogRootPath[] = "C:\\My_APPLOG"; /*日志文件根路径,由用户指定*/ #pragma pack(push, 1)typedef struct tagLOG_DA TA /* 日志内容结构体*/{char strDate[11]; /* 日期:格式为如:2009-10-11*/char strTime[9]; /* 时间:格式为如:16:10:57*/unsigned int iType; /* 日志类型:3种:INFO(0)/ERROR(1)/SYSTEM(2)*/ char strText[MAX_LOGTEXT_LEN]; /*日志内容*/}LOG_DATA, *LPLOG_DATA;#pragma pack(pop)int Create_LogDir(const char *pStrPath);int Create_LogFile(const char *pStrFile, int iPos);int IsFileExist(const char *pStrFile);int GetLogPath(char *pStrPath);DWORD GetFileLenth(const char *pFile);int Write_Log_Text(LPLOG_DATA lpLogData);void Write_Log(unsigned int uiLogType, char *pstrFmt, ...);void TestLogCase_One();int main(int argc, char* argv[]){Write_Log(LOG_TYPE_SYSTEM, "Program begin.");TestLogCase_One();Write_Log(LOG_TYPE_SYSTEM, "Program end.");return 0;}/********************************************************************** 函数名称:void TestLogCase_One()* 说明:简单的测试函数,读文件* 调用者:main* 输入参数:* 无* 输出参数:* 无* 返回值:* void --* 作者: duanyongxing* 时间: 2009-10-11*********************************************************************/void TestLogCase_One(){FILE *pFile = NULL;char *pFieldContent = NULL;char szFileName[] = "test_case.txt";pFieldContent = (char *)malloc(TEST_CASE_MAX_FILE_LEN);if(NULL == pFieldContent){Write_Log(LOG_TYPE_ERROR, "malloc memory failed,program exit!");return;}memset(pFieldContent, 0, TEST_CASE_MAX_FILE_LEN);Write_Log(LOG_TYPE_INFO, "malloc memory for pFiled successful,memory size is: %ld", TEST_CASE_MAX_FILE_LEN);pFile = fopen(szFileName, "r");if(NULL == pFile){fprintf(stderr, "open file failed.");Write_Log(LOG_TYPE_ERROR, "Open file %s failed. program exit!", szFileName); return;}Write_Log(LOG_TYPE_INFO, "Open file %s successful.", szFileName);fread(pFieldContent, 1, TEST_CASE_MAX_FILE_LEN, pFile);pFieldContent[TEST_CASE_MAX_FILE_LEN -1] = '\0';fclose(pFile);printf("The file %s content is: \n%s\n", szFileName, pFieldContent);Write_Log(LOG_TYPE_INFO, "The file %s content is: \n%s\n", szFileName, pFieldContent); }/********************************************************************** 函数名称:void Write_Log(unsigned int uiLogType, char *pstrFmt, ...)* 说明:日志写函数,支持变长参数* 调用者:任何需要写日志的地方* 输入参数:* unsigned iType -- 日志类别* char *pstrFmt -- 日志内容* ... -- 变长参数* 输出参数:* 无* 返回值:* void --* 作者: duanyongxing* 时间: 2009-10-11*********************************************************************/void Write_Log(unsigned int uiLogType, char *pstrFmt, ...){#if _LOG_WRITE_STATE_ /* 写日志与否的编译开关*/LOG_DA TA data;time_t curTime;struct tm *mt;va_list v1;memset(&data, 0, sizeof(LOG_DA TA));va_start(v1, pstrFmt);_vsnprintf(data.strText, MAX_LOGTEXT_LEN, pstrFmt, v1);va_end(v1);data.iType = uiLogType;curTime = time(NULL);mt = localtime(&curTime);strftime(data.strDate, sizeof(data.strDate), "%Y-%m-%d", mt);strftime(data.strTime, sizeof(data.strTime), "%H:%M:%S", mt);Write_Log_Text(&data);#endif _LOG_WRITE_STATE_}/********************************************************************* * 函数名称:int GetLogPath(char *pStrPath)* 说明:获取日志文件路径* 调用者:Write_Log_Text* 输入参数:* 无* 输出参数:* char *pStrPath* 返回值:* int -- LOG_FAILED: 失败* -- LOG_SUCCESS: 成功* 作者: duanyongxing* 时间: 2009-10-11*********************************************************************/ int GetLogPath(char *pStrPath){if(NULL == pStrPath){return LOG_FAILED;}int iRet = 0;time_t curTime = time(NULL);struct tm *mt = localtime(&curTime);/* 根据日期组成文件夹名称*/sprintf(pStrPath, "%s\\%d%02d%02d", g_LogRootPath, mt->tm_year + 1900, mt->tm_mon + 1, mt->tm_mday);iRet = Create_LogDir(pStrPath);return iRet;}/********************************************************************* * 函数名称:int GetLogFileName(int iLogType, const char *pStrPath, char *pStrName) * 说明:获取日志文件名* 调用者:Write_Log_Text* 输入参数:* int iLogType -- 日志类型3种:INFO(0)/ERROR(1)/SYSTEM(2)* const char *pStrPath -- 日志路径由GetLogPath得到* 输出参数:* char *pStrName -- 日志文件名* 返回值:* int -- LOG_FAILED: 失败* -- LOG_SUCCESS: 成功* 作者: duanyongxing* 时间: 2009-10-11*********************************************************************/ int GetLogFileName(int iLogType, const char *pStrPath, char *pS trName){if(NULL == pStrPath){return LOG_FAILED;}char szLogName[MAX_FILE_PA TH];FILE *pFile = NULL;memset(szLogName, 0, MAX_FILE_PA TH);switch (iLogType){case LOG_TYPE_INFO:sprintf(szLogName, "%s\\app_info", pStrPath);break;case LOG_TYPE_ERROR:sprintf(szLogName, "%s\\app_error", pStrPath);break;case LOG_TYPE_SYSTEM:sprintf(szLogName, "%s\\app_system", pStrPath);break;default:return LOG_FAILED;break;}strcat(szLogName, ".log");if(IsFileExist(szLogName)){/* 如果文件长度大于指定的最大长度,重新创建一文件,覆盖原文件*/ if((int)GetFileLenth(szLogName) + 256 >= MAX_LOG_FILE_SIZE) {Create_LogFile(szLogName, 0);}}else{Create_LogFile(szLogName, 0);}sprintf(pStrName, "%s", szLogName);return LOG_SUCCESS;}/********************************************************************* * 函数名称:int Create_LogDir(const char *pStrPath)* 说明:创建日志存放路径* 调用者:GetLogPath* 输入参数:* const char *pStrPath --用户指定的根路径* 输出参数:* 无* 返回值:* int -- LOG_FAILED: 失败* -- LOG_SUCCESS: 成功* 作者: duanyongxing* 时间: 2009-10-11*********************************************************************/ int Create_LogDir(const char *pStrPath){if(NULL == pStrPath){return LOG_FAILED;}int iRet = 0;char szSub[MAX_FILE_PA TH];char *pSub = NULL;int iIndex = 0;int iLen = 0;int bFind = 0;memset(szSub, 0, sizeof(MAX_FILE_PA TH));/* 逐层创建目录*/while(1){pSub = strchr(pStrPath + iLen, '\\');if(NULL == pSub){if(iLen == 0){return LOG_FAILED;}iRet = CreateDirectory(pStrPath, NULL); if(0 == iRet){iRet = GetLastError();if(ERROR_ALREADY_EXISTS == iRet) {return LOG_SUCCESS;}return LOG_FAILED;}return LOG_SUCCESS;}else{if (!bFind){bFind = 1;}else{memset(szSub, 0, sizeof(szSub));strncpy(szSub, pStrPath, pSub - pStrPath);CreateDirectory(szSub, NULL);}iLen = pSub - pStrPath + 1;}}return LOG_SUCCESS;}/********************************************************************* * 函数名称:int Create_LogFile(const char *pStrFile, int iPos)* 说明:创建日志文件* 调用者:GetLogFileName* 输入参数:* const char *pStrFile --文件名* int iPos --文件指针位置* 输出参数:* 无* 返回值:* int -- LOG_FAILED: 失败* -- LOG_SUCCESS: 成功* 作者: duanyongxing* 时间: 2009-10-11*********************************************************************/ int Create_LogFile(const char *pStrFile, int iPos){HANDLE hd = 0;int iRet = 0;if(NULL == pStrFile){return LOG_FAILED;}hd = CreateFile(pStrFile,GENERIC_READ | GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);{return LOG_FAILED;}if(DWORD_NULL == SetFilePointer(hd, iPos, NULL, FILE_BEGIN)){return LOG_FAILED;}iRet = SetEndOfFile(hd);CloseHandle(hd);return iRet;}/********************************************************************* * 函数名称:int IsFileExist(const char *pStrFile)* 说明:判断指定的文件是否存在* 调用者:GetLogFileName* 输入参数:* const char *pStrFile --文件名* 输出参数:* 无* 返回值:* int -- LOG_BOOL_FALSE: 不存在* -- LOG_BOOL_TRUE: 存在* 作者: duanyongxing* 时间: 2009-10-11*********************************************************************/ int IsFileExist(const char *pStrFile){int iLen = 0;WIN32_FIND_DA TA finddata;memset(&finddata, 0, sizeof(WIN32_FIND_DA TA));HANDLE hd = FindFirstFile(pStrFile, &finddata);{DWORD dwRet = GetLastError();if(ERROR_FILE_NOT_FOUND == dwRet || ERROR_P ATH_NOT_FOUND == dwRet) {return LOG_BOOL_F ALSE;}}FindClose(hd);return LOG_BOOL_TRUE;}/********************************************************************** 函数名称:DWORD GetFileLenth(const char *pFile)* 说明:判断指定的文件大小* 调用者:GetLogFileName* 输入参数:* const char *pFile --文件名* 输出参数:* 无* 返回值:* DWORD -- 文件大小* 作者: duanyongxing* 时间: 2009-10-11*********************************************************************/ DWORD GetFileLenth(const char *pFile){WIN32_FIND_DA TA buff;HANDLE hd = NULL;memset(&buff, 0, sizeof(WIN32_FIND_DATA));hd = FindFirstFile(pFile, &buff);FindClose(hd);return (buff.nFileSizeHigh * MAXDWORD) + buff.nFileSizeLow;}/********************************************************************* * 函数名称:int Write_Log_Text(LPLOG_DA TA lpLogData)* 说明:写日志内容* 调用者:Write_Log* 输入参数:* LPLOG_DA TA lpLogData --日志内容结构体量* 输出参数:* 无* 返回值:* int -- LOG_FAILED: 失败* -- LOG_SUCCESS: 成功* 作者: duanyongxing* 时间: 2009-10-11*********************************************************************/ int Write_Log_Text(LPLOG_DATA lpLogData){char szFilePath[MAX_FILE_PA TH];char szFileName[MAX_LOG_FILE_NAME_LEN];FILE *pFile = NULL;char szLogText[MAX_LOGTEXT_LEN];memset(szFilePath, 0, MAX_FILE_PA TH);memset(szFileName, 0, MAX_LOG_FILE_NAME_LEN);memset(szLogText, 0, MAX_LOGTEXT_LEN);GetLogPath(szFilePath);GetLogFileName(lpLogData->iType, szFilePath, szFileName);pFile = fopen(szFileName, "a+");if(NULL == pFile){return LOG_FAILED;}sprintf(szLogText, "%s %s %s\n", lpLogData->strDate, lpLogData->strTime,lpLogData->strText);fwrite(szLogText, 1, strlen(szLogText), pFile);fclose(pFile);return LOG_SUCCESS;}]C++ log 日志2010-09-27 11:01/*********************************************************************** *****************Function:将错误信息写到指定的文件中Params:szErrMsg:错误内容szFileName:日志文件的路径Result:voidAuthor:Date:************************************************************************ ****************/bool LogFile(const char *szErrMsg, const char *szFileName){CTime tCurrentTime = CTime::GetCurrentTime() ;FILE *fp = NULL;CString strFileName ;if(szFileName == NULL)//如果为空就使用默认值,与应用程序同名+.log{strFileName = ".\\error.log";}else{strFileName.Format("%s", szFileName) ;TrimStr(strFileName) ;}if((fp = fopen(strFileName, "a")) == NULL){LogMsg("打开记录文件失败。
c语言写日志文件的代码以C语言写日志文件的代码在软件开发中,日志文件是一种记录程序运行过程中重要信息的方式。
通过记录日志,可以追踪程序的执行流程、排查问题以及对程序进行性能分析。
本文将介绍如何使用C语言来编写一个简单的日志文件记录程序。
我们需要定义一个用于记录日志的结构体。
这个结构体包含了日志的级别、时间戳、文件名、函数名以及日志内容。
代码如下:```c#include <stdio.h>#include <time.h>typedef struct {int level;time_t timestamp;char file_name[256];char function_name[256];char message[4096];} LogEntry;```接下来,我们需要实现一个函数,用于将日志写入文件中。
这个函数将接收一个LogEntry结构体作为参数,并将其内容写入日志文件。
代码如下:```cvoid write_log(LogEntry log_entry) {FILE *file = fopen("log.txt", "a");if (file != NULL) {char timestamp[20];strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&log_entry.timestamp));fprintf(file, "[%s] [%d] [%s:%s] %s\n", timestamp, log_entry.level, log_entry.file_name, log_entry.function_name, log_entry.message);fclose(file);}}```在这个函数中,我们首先打开一个名为"log.txt"的文件,使用"a"参数表示以追加的方式打开文件,这样新的日志内容将追加到文件末尾。
c语言中log输出函数C语言中log输出函数在C语言中,log输出函数是一种常见的用于调试和输出程序运行信息的函数。
它可以打印出程序运行过程中的一些关键信息,帮助开发者定位错误和调试代码。
在本文中,我们将详细介绍C语言中常用的log输出函数,并探讨它们的用法和注意事项。
一、printf函数printf函数是C语言中最常用的输出函数之一,它可以将指定的格式化字符串输出到标准输出设备(通常是控制台)。
在使用printf 函数时,我们可以使用特定的格式控制符来输出不同类型的数据,如字符串、整数、浮点数等。
例如,以下代码使用printf函数输出了一个字符串和一个整数:```c#include <stdio.h>int main() {char str[] = "Hello, world!";int num = 123;printf("%s\n", str);printf("%d\n", num);return 0;}```在上述代码中,"%s"和"%d"是printf函数的格式控制符,分别用于输出字符串和整数。
需要注意的是,在使用printf函数输出字符串时,需要使用"%s"格式控制符,并将字符串作为参数传入。
同样地,在输出整数时,需要使用"%d"格式控制符,并将整数作为参数传入。
二、fprintf函数fprintf函数与printf函数类似,都可以用于输出信息。
不同的是,fprintf函数可以将指定的格式化字符串输出到指定的文件中,而不仅仅是标准输出设备。
例如,以下代码使用fprintf函数将一个字符串输出到文件中:```c#include <stdio.h>int main() {FILE *file = fopen("output.txt", "w");char str[] = "Hello, world!";fprintf(file, "%s\n", str);fclose(file);return 0;}```在上述代码中,我们首先使用fopen函数打开一个名为"output.txt"的文件,并指定以写入模式打开。
[转]C#实现⾃动化Log⽇志原⽂地址在开发项⽬的时候,我们不免要使⽤Log记录⽇志,使⽤最多的是Log4Net和EntLib Log,在需要记录⽇志的代码处加⼊log.Write(⽇志信息),假设我需要跟踪业务⽅法,记录⽅法的传递参数,执⾏时间,返回数据等;或者我需要查看⽅法的调⽤关系,希望进⼊⽅法的时候⾃动记录参数信息,出⽅法时记录结果和执⾏时间信息。
这时就是⼀个典型的AOP运⽤,Java在AOP⽅⾯是很容易实现的,因为java有类加载器。
但是.Net在AOP⽅⾯就不怎么容易,严格意义上.Net没有真正的AOP。
这话并不代表.Net不能实现AOP,⽐如:PostSharp和Enterprise library就能实现。
先介绍⼀下PostSharp,我们知道.net代码将编译成MSIL(微软中间语⾔),然后CPU将MSIL的exe⽂件⽣成本地CPU的⼆进制⽂件格式,PostSharp就是在编译过程中加⼊IL代码,因⽽完成AOP功能。
缺点:编译器需要PostSharp组件,维护代码困难,因为IL代码不好识别;优点:使⽤⽅便(PostSharp2是收费版,破解也⽐较⽅便,在此不介绍破解)这⾥我重点介绍如何使⽤Enterprise Library实现⾃动化Log。
1.⾸先我们需要下载Enterprise Library,最新为5.0版本;2.新建⼀个控制台项⽬,并添加以下程序集monMicrosoft.Practices.EnterpriseLibrary.LoggingMicrosoft.Practices.EnterpriseLibrary.PolicyInjectionMicrosoft.Practices.ServiceLocationMicrosoft.Practices.UnityMicrosoft.Practices.Unity.Interception3.添加AutoLogCallHandler类,实现ICallHandler接⼝这个类是执⾏调⽤⽬标⽅法,在调⽤⽬标⽅法前获取⽅法的参数信息,并⽤EntLib Log记录⽇志;⽅法结束后,再次记录⽇志,并统计执⾏时间和异常处理using System;using System.Collections.Generic;using System.Linq;using System.Text;using Microsoft.Practices.Unity.InterceptionExtension;using Microsoft.Practices.EnterpriseLibrary.Logging;using mon.Configuration;using System.Diagnostics;using System.Reflection;namespace AutoLog {public class AutoLogCallHandler:ICallHandler {private LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();public AutoLogCallHandler() { }public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {StringBuilder sb = null;ParameterInfo pi = null;string methodName = ;logWriter.Write(string.Format("Enter method " + methodName));if (input.Arguments != null && input.Arguments.Count > 0) {sb = new StringBuilder();for (int i = 0; i < input.Arguments.Count; i++) {pi = input.Arguments.GetParameterInfo(i);sb.Append().Append(" : ").Append(input.Arguments[i]).AppendLine();}logWriter.Write(sb.ToString());}Stopwatch sw = new Stopwatch();sw.Start();IMethodReturn result = getNext()(input, getNext);//如果发⽣异常则,result.Exception != nullif (result.Exception != null) {logWriter.Write("Exception:" + result.Exception.Message);//必须将异常处理掉,否则⽆法继续执⾏result.Exception = null;}sw.Stop();logWriter.Write(string.Format("Exit method {0}, use {1}.",methodName, sw.Elapsed));return result;}public int Order { get; set; }}}4.要⾃动化⽇志就需要创建⼀个标记属性,指定⽅法能⾃动进⾏⽇志这⾥就创建AutoLogCallHandlerAttribute标记属性using System;using System.Collections.Generic;using System.Linq;using System.Text;using Microsoft.Practices.Unity.InterceptionExtension;using Microsoft.Practices.EnterpriseLibrary.Logging;using System.Diagnostics;using mon.Configuration;namespace AutoLog {public class AutoLogCallHandlerAttribute:HandlerAttribute {public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container) {return new AutoLogCallHandler() { Order = this.Order };}}}5.创建实体类注意:我在Work和ToString⽅法上⽅加上了AutoLogCallHandler属性,它是AutoLogCallHandlerAttribute的简写形式。
浅谈C++⽇志系统log4cxx的使⽤⼩结详解本⽂主要从log4cxx级别、layout、格式化、命名规则、Filter⼏个⽅⾯介绍。
Logger由⼀个String类的名字识别,logger的名字是⼤⼩写敏感的,且名字之间具有继承的关系,⼦名有⽗名作为前缀,⽤点号.分隔。
如:x.y是x.y.z的⽗亲。
根logger (root logger)是所有logger的祖先,它具有如下属性:1) 它总是存在的;2) 它不可以通过名字获得。
通过调⽤public static Logger Logger.getRootLogger()获得root logger;通过调⽤public static Logger Logger.getLogger(String name)或者public static Logger Logger.getLogger(Class clazz)获得或者创建)⼀个named logger。
后者相当于调⽤Logger.getLogger(clazz.getName())。
在某对象中,⽤该对象所属的类为参数,调⽤Logger.getLogger(Class clazz)以获得logger被认为是⽬前所知的最理智的命名logger的⽅法。
每个logger都被分配了⼀个⽇志级别 (log level),⽤来控制⽇志信息的输出。
未被分配level的 logger将继承它最近的⽗logger 的level。
每条输出到logger的⽇志请求(logging request)也都有⼀个 level,如果该request的level⼤于等于该logger的level,则该request将被处理(称为enabled);否则该 request将被忽略。
故可得知:1、logger的level越低,表⽰该logger越详细2、logging request的 level越⾼,表⽰该logging request越优先输出 3、如果没有设置⽇志记录器(Logger)的级别,那么它将会继承最近的祖先的级别。
提要最近在写一些C++的图形代码,在调试和测试过程中都会需要在终端打印一些信息出来。
之前的做法是直接用std::cout<<"Some Word"<<std::endl;这样做其实非常的麻烦,每次都要打很多的字母还有特殊符号,除去我要打印的内容,还需要按下28下键盘,简直不能忍!参考Unity里面的打log的方式Debug.Log("Some Word");或者Qt中的处理方式qDebug() << "Some Word";这两种都方便太多。
今天要实现的Log系统需要满足的特性有:1.很方便地在终端打印各种类型数据信息;2.可以区分Log等级;3.打印信息的同时能够提供打印语句的文件,函数名,行号类说明简单地画了下UML,主要分为下面几个类简单说一下类的作用MessageLogContext记录Log的上下文,也就是Log处在的文件,函数名,行号。
MessageLogger主要的Log类,提供了上次调用的一些接口,注意一下这个宏比较有意思qDebug MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug这样当使用qDebug()的时候,宏替换就直接转换成了MessageLogger的构造函数MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug()等于是先构造MessageLogger,然后调用这个对象的debug()方法。
Debug具体处理Debug信息的类。
用了一个内部Stream结构体来记录Debug信息,记得在使用前要new,析构的时候delete掉。
重构了很多的<<方法,就是为了能处理多种数据类型,包括自定义的类。
还可以通过模板来打印stl里面的东西。
LogToConsole是将log信息打印到终端的函数,在析构函数中会被调用。
如果想要实现更加炫酷的打印log方式(各种颜色),扩展这个函数就好了。
整个Log的流程如下图测试代码void DebugTest(){Vector2 v = Vector2(1, 1);Vector2 v2 = Vector2(2, 1);Vector3 v3 = Vector3(0, 2, 1);Vector3 v4 = Vector3(0, 2, 1);Vector3 v5 = Vector3(23, 112, 22);Vector3 v6 = Vector3(23, 112, 22);std::vector<Vector3> vec;vec.push_back(v3);vec.push_back(v4);vec.push_back(v5);vec.push_back(v6);vec.push_back(v6);vec.push_back(v6);vec.push_back(v6);vec.push_back(v6);std::string testStr = "vector Test";qDebug() << "Hello Debug";qDebug() <<""<< v << v2<< v3;qDebug() << v3;qWarning() << vec;}运行结果代码清单MessageLogContext.h#pragma once#include <string>class MessageLogContext{public:MessageLogContext() : line(0), file(0), function(0) {}MessageLogContext(const char *fileName, const char *functionName, int lineNumber) : file(fileName), function(functionName), line(lineNumber) {}int line;const char *file;const char *function;void copy(const MessageLogContext &logContext){this->file = logContext.file;this->line = logContext.line;this->function = logContext.function;}private:friend class MessageLogger;friend class Debug;};Log.h#pragma once#define qDebug MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug#define qInfo MessageLogger(__FILE__, __FUNCTION__, __LINE__).info#define qWarning MessageLogger(__FILE__, __FUNCTION__, __LINE__).warning#define qCritical MessageLogger(__FILE__, __FUNCTION__, __LINE__).critical#define qFatal MessageLogger(__FILE__, __FUNCTION__, __LINE__).fatal#include "Debug.h"#include "MessageLogContext.h"class MessageLogger{public:MessageLogger() : context(){}MessageLogger(const char *fileName, const char *functionName, int lineNumber) : context(fileName, functionName, lineNumber) {}Debug info() const;Debug warning() const;Debug critical() const;Debug debug() const;protected:private:MessageLogContext context;};Log.cpp#include "Log.h"Debug MessageLogger::debug() const{std::string debug = "debug";Debug dbg = Debug(&debug);MessageLogContext &ctxt = dbg.stream->context;ctxt.copy(context);dbg.stream->logType = Info;return dbg;}Debug MessageLogger::info() const{Debug dbg = Debug();MessageLogContext &ctxt = dbg.stream->context;ctxt.copy(context);dbg.stream->logType = Info;return dbg;}Debug MessageLogger::warning() const{Debug dbg = Debug();MessageLogContext &ctxt = dbg.stream->context;ctxt.copy(context);dbg.stream->logType = Warning;return dbg;}Debug MessageLogger::critical() const{Debug dbg = Debug();MessageLogContext &ctxt = dbg.stream->context;ctxt.copy(context);dbg.stream->logType = Error;return dbg;}Debug.h#pragma once#include <iostream>#include <iomanip>#include <fstream>#include <string>#include <cstdlib>#include <stdint.h>#include <sstream>#include "Math/Vector2.h"#include "Math/Vector3.h"#include <vector>//#include "Log.h"#include "MessageLogContext.h"enum LogType{Info,Warning,Error,Default,};class Debug{public:struct Stream {Stream():ss(), space(true), context() {}Stream(std::string *s) :ss(*s), space(true), context(){}std::ostringstream ss;bool space;MessageLogContext context;LogType logType;} *stream;Debug() : stream(new Stream()) {}inline Debug(std::string *s) : stream(new Stream(s)) {}~Debug();inline Debug &operator<<(bool t) { stream->ss<<(t ? "true" : "false"); return maybeSpace(); } inline Debug &operator<<(char t) { stream->ss<< t; return maybeSpace(); }inline Debug &operator<<(signed short t) { stream->ss << t; return maybeSpace(); }inline Debug &operator<<(unsigned short t) { stream->ss << t; return maybeSpace(); }inline Debug &operator<<(std::string s) { stream->ss << s; return maybeSpace(); }inline Debug &operator<<(const char* c) { stream->ss << c; return maybeSpace(); }inline Debug &operator<<(Vector2 vec) { stream->ss << "(" << vec.x <<","<< vec.y<<")"; return ma inline Debug &operator<<(Vector3 vec) { stream->ss << "(" << vec.x << "," << vec.y <<"," << vec.inline Debug &space() { stream->space = true; stream->ss << ' '; return *this; }inline Debug &nospace() { stream->space = false; return *this; }inline Debug &maybeSpace() { if (stream->space) stream->ss << ' '; return *this; }template <typename T>inline Debug &operator<<(const std::vector<T> &vec){stream->ss << '(';for (int i = 0; i < vec.size(); ++i) {stream->ss << vec.at(i);stream->ss << ", ";}stream->ss << ')';return maybeSpace();}void LogToConsole(LogType type, const MessageLogContext &context, std::string logBuffer); private:static Debug* _instance;};Debug.cpp#include "Debug.h"Debug::~Debug(){LogToConsole(stream->logType, stream->context, stream->ss.str());delete stream;}void Debug::LogToConsole(LogType type, const MessageLogContext &context, std::string logBuffer){std::string logString;switch (type){case Error:logString.append("Error! ");break;case Info://logString.append("");break;case Warning:logString.append("Warning! ");break;default:break;}logString.append(logBuffer);logString.append("......");logString.append(context.file);logString.append(" ");logString.append(context.function);logString.append("()");std::cout << logString <<" line: " << context.line << " " << std::endl;//logString.append(context.line);}参考Qt source codeQt Documentation http://doc.qt.io/qt-4.8/qdebug.html/。