如何在日志文件中引入日期和时间
问题描述:
我有一个用C编写的守护进程。我将事件记录在日志文件中,但现在我想在将事件写入日志文件时添加日期和时间。我怎样才能做到这一点?如何在日志文件中引入日期和时间
当前日志文件: -
Event one occurred: result:
Event two occurred: result:
我想日志文件看起来像: -
Sep 14 11:35:55 Event one occurred: result:
Sep 14 11:35:55 Event two occurred: result:
我的环境是C和Linux。
答
您需要查看使用date
和gmtime
或localtime
以获取实际日期和时间。
然后strftime
可以为你格式化。
示例程序如下:
#include <stdio.h>
#include <time.h>
int main (void) {
char buff[20];
struct tm *sTm;
time_t now = time (0);
sTm = gmtime (&now);
strftime (buff, sizeof(buff), "%Y-%m-%d %H:%M:%S", sTm);
printf ("%s %s\n", buff, "Event occurred now");
return 0;
}
此输出:
2011-09-14 04:52:11 Event occurred now
我喜欢使用UTC而不是本地时间,因为它可以让你绑从地理上分离机一起事件,而不必担心时区差异。换句话说,使用gmtime
而不是localtime
,除非你是非常确定你不会穿越时区。
我也倾向于选择YYYY-MM-DD HH:MM:SS
格式,因为它比月份名称更容易排序,这对于提取和操作工具来说至关重要。
答
为了得到当前的时间,你可以使用time.h
例如...
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
time_t now;
time(&now);
printf("%s", ctime(&now)); // use ctime to format time to a string.
return EXIT_SUCCESS;
}
您还可以使用strftime
由paxdiablo更多的时间/日期格式的可能性建议。
当然,对于您的情况,ctime(&now)
的结果将进入您的日志条目字符数组/字符串而不是printf
。
答
根据@paxdiablo的回答添加我的日志功能。使用本地时间,但可能只是通过修改getFormattedTime()
COMMON.H
// Returns the local date/time formatted as 2014-03-19 11:11:52
char* getFormattedTime(void);
// Remove path from filename
#define __SHORT_FILE__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
// Main log macro
#define __LOG__(format, loglevel, ...) printf("%s %-5s [%s] [%s:%d] " format "\n", getFormattedTime(), loglevel, __func__, __SHORT_FILE__, __LINE__, ## __VA_ARGS__)
// Specific log macros with
#define LOGDEBUG(format, ...) __LOG__(format, "DEBUG", ## __VA_ARGS__)
#define LOGWARN(format, ...) __LOG__(format, "WARN", ## __VA_ARGS__)
#define LOGERROR(format, ...) __LOG__(format, "ERROR", ## __VA_ARGS__)
#define LOGINFO(format, ...) __LOG__(format, "INFO", ## __VA_ARGS__)
common.c中
#include <time.h> // time_t, tm, time, localtime, strftime
// Returns the local date/time formatted as 2014-03-19 11:11:52
char* getFormattedTime(void) {
time_t rawtime;
struct tm* timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
// Must be static, otherwise won't work
static char _retval[20];
strftime(_retval, sizeof(_retval), "%Y-%m-%d %H:%M:%S", timeinfo);
return _retval;
}
您可以使用它们像这样使用GMT:
LOGDEBUG("This is a log");
LOGDEBUG("This is a log with params %d", 42);
哪个产生输出:
2014-03-19 13:22:14 DEBUG [main] [main.c:54] This is a log
2014-03-19 13:22:14 DEBUG [main] [main.c:55] This is a log with params 42
答
根据@inolasco的回答,静态变量不是线程安全的。改用局部变量。
void getFormattedTime(char * const p, int sz) {
time_t rawtime;
struct tm* timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(p, sz, "%Y-%m-%d %H:%M:%S", timeinfo);
}
int mylog(const char* fmt, ...) {
// TODO: log to file also.
// TODO: create a new log file daily
va_list argptr;
va_start(argptr, fmt);
vfprintf(stderr, fmt, argptr);//log to stderr
va_end(argptr);
}
#ifdef _WIN32
#define __SHORT_FILE__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#else
#define __SHORT_FILE__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#endif
#define ___LOG___(fmt,level,path, ...) do{\
/* using local var and using a long name to avoid conflict*/ \
char LAgGV3nzJsTholGvGL2eTNXmhsqYe___xxooxxoo___[24];\
getFormattedTime(LAgGV3nzJsTholGvGL2eTNXmhsqYe___xxooxxoo___,\
sizeof(LAgGV3nzJsTholGvGL2eTNXmhsqYe___xxooxxoo___));\
mylog("%s [%s] [%s:%d] [%s] " fmt "\n", \
LAgGV3nzJsTholGvGL2eTNXmhsqYe___xxooxxoo___, \
level,\
path,\
__LINE__, \
__func__, \
## __VA_ARGS__);\
}while(0)
#define trace(fmt, ...) ___LOG___(fmt, "TRACE",__SHORT_FILE__, ## __VA_ARGS__)
#define debug(fmt, ...) ___LOG___(fmt, "DEBUG",__SHORT_FILE__, ## __VA_ARGS__)
#define info(fmt, ...) ___LOG___(fmt, "INFO",__SHORT_FILE__, ## __VA_ARGS__)
#define warn(fmt, ...) ___LOG___(fmt, "WARN",__SHORT_FILE__, ## __VA_ARGS__)
#define error(fmt, ...) ___LOG___(fmt, "ERROR",__SHORT_FILE__, ## __VA_ARGS__)
#define tracel(fmt, ...) ___LOG___(fmt, "TRACE", __FILE__, ## __VA_ARGS__)
#define debugl(fmt, ...) ___LOG___(fmt, "DEBUG", __FILE__, ## __VA_ARGS__)
#define infol(fmt, ...) ___LOG___(fmt, "INFO", __FILE__, ## __VA_ARGS__)
#define warnl(fmt, ...) ___LOG___(fmt, "WARN", __FILE__, ## __VA_ARGS__)
#define errorl(fmt, ...) ___LOG___(fmt, "ERROR", __FILE__, ## __VA_ARGS__)
称他们是这样的:
info("%s", "a log");
infol("%s", "a log");
产品:
2017-09-06 15:55:42 [INFO] [main.c:25] [main] a log
2017-09-06 15:58:08 [INFO] [d:\main.c:25] [main] a log
@Jonathan莱弗勒,我面临的,因为很长一段时间,这些调整问题,有没有参考页至REF,并采取照顾自己? – Thangaraj
你的意思是你的问题中的布局?输入评论时,有一个帮助超链接;当输入问题或答案时,会有一个橙色问号提供打字区域上方的帮助。缩进4个空格将以下代码作为代码处理;避免制表符。项目符号列表具有以星号或短划线('*'或'-')开头的行;你可以嵌套它们(子项目缩进2个或更多的空格),并且你可以有与它们相关的代码(前缀为8个空格,而不是4个,但是对于第一级项目符号)。编号列表有从'1'开始的行(这个点很重要)。等等 –
@Jonathan Leffler,谢谢 – Thangaraj