C语言日志库

17

我正在寻找一款适用于C语言的高效且简单的日志库,可以将日志输出到文件中。我希望在日志中显示的信息如下:

date-time tag message

希望能够控制消息的详细程度和文件大小。

我找到了两个适合我的项目,它们分别是 log4cnglogc

log4c似乎太大了。 nglogc非常适合,但也有一些多余的功能。也许你还能告诉我更多其他的选择?


7
如果你只需要这些,使用一个简单的fprintf包装器有什么问题呢? - Michael Mior
6个回答

22
您可以使用这个文件logger.h。
#ifndef LOGGER_H
#define LOGGER_H

void logger(const char* tag, const char* message);

#endif /* LOG_H */

文件 logger.c

#include "logger.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void logger(const char* tag, const char* message) {
   time_t now;
   time(&now);
   printf("%s [%s]: %s\n", ctime(&now), tag, message);
}

它可能并不完美,但它确实满足了你所提出的需求。


2
日志记录到文件怎么样? :) - pmg
我正在寻找能够在日志文件中输出的功能。我已经修改了问题,使其更易理解。 - trafalgarx
дҪҝз”Ёfprintfд»ЈжӣҝдёҠйқўзҡ„printfпјҒ - N.R.S.Sowrabh
1
为了可靠性,打印消息后最好刷新文件流。 - jmbr
清空缓存可能是需要的,也可能不需要。打开它将防止在您想读取日志但尚未写入时出现问题,但如果您进行大量记录,它也可能会严重影响应用程序的性能。 - Nate C-K
4
如果不进行刷新,通常会发生最需要的日志消息没有被写入磁盘的情况。如果应用程序停止,你将丢失一些消息,而这些消息通常是最重要的(导致崩溃的原因)。另一方面,现在磁盘都有小的RAM缓存,并且写入性能(虽然不是很好)至少是有缓冲的。至于读/写锁定,这是一个文件,大多数文件系统不会防止不一致的读取(但如果记录到数据库中,则情况不同)。 - Edwin Buck

11

我建议使用我自己编写的日志库 --- zlog!

在zlog中满足您需求的方法是:

$ vi /etc/zlog.conf
[formats]
simple = "%D %c %m%n"
# don't know what the tag mean in your question, so put category of zlog instead
# log level is also available here, add %V means level

[rules]
my_cat.*   "xxx.log"; simple

$ vi hello.c
#include <stdio.h> 
#include "zlog.h"

int main(int argc, char** argv)
{
int rc;
zlog_category_t *c;

rc = dzlog_init("/etc/zlog.conf", "my_cat");
if (rc) {
    printf("init failed\n");
    return -1;
}

zlog_info(c, "hello, zlog");

zlog_fini();

return 0;
} 

它将在当前目录下生成 xxx.log

2012-09-30 07:22:50 my_cat hello, zlog

链接:

下载: https://github.com/HardySimpson/zlog/archive/latest-stable.tar.gz

用户指南: http://hardysimpson.github.com/zlog/UsersGuide-EN.html

主页: http://hardysimpson.github.com/zlog/


你好@HardySimpson,当我运行hello.c时,出现了“init failed”返回255的错误。那么,在zlog_init中我可以找到哪个日志消息文件呢?zc_debug(".... zlog_init start...."); - charles.cc.hsu
1
我必须承认这有点傻和过度工程化。你实际上只是重新创建了一个非标准的syslog。我正在寻找一些可以指定为argv开关的东西,然后可以选择发送到[syslog、文件、stdout、stderr],并具有一定的可移植性到Windows。真的不应该需要这么多--只需将其发送到syslog即可! - A.B. Carroll

10
Here is mine:

log.h
------

#ifndef LOG_H 
#define LOG_H


void log_error(const char* message, ...); void log_info(const char* message, ...); void log_debug(const char* message, ...);

#endif

log.c
------
#include "log.h"


void log_format(const char* tag, const char* message, va_list args) {   time_t now;     time(&now);     char * date =ctime(&now);   date[strlen(date) - 1] = '\0';  printf("%s [%s] ", date, tag);  vprintf(message, args);     printf("\n"); }

void log_error(const char* message, ...) {  va_list args;   va_start(args, message);    log_format("error", message, args);     va_end(args); }

void log_info(const char* message, ...) {   va_list args;   va_start(args, message);    log_format("info", message, args);  va_end(args); }

void log_debug(const char* message, ...) {  va_list args;   va_start(args, message);    log_format("debug", message, args);     va_end(args); }

玩得开心!


1
这并不一定是一个坏答案,但问题已经在2011年有了一个被接受的答案。回答这么老的问题除非你有能够显著帮助读者的信息,否则并没有什么建设性。 - user308323

5
您可以使用这个简单的日志库:https://github.com/kala13x/slog 以下是使用示例:
首先,您必须使用init_log()函数初始化日志。第一个参数是日志文件名,第二个参数是是否将日志写入文件(1启用,0禁用),第三个参数是最大日志级别。
init_slog("example", 1, 3);

打印和记录一些内容

slog(0, "Test message with level 0");
slog(2, "Test message with level 2");
slog(0, "Test message with int argument: %d", int_arg);

输出将会是这样的:

2015年04月02日56秒 - 带有0级别的测试消息
2015年04月02日56秒 - 带有2级别的测试消息
2015年04月02日56秒 - 带有整数参数69的测试消息


这是一个很好的发现!谢谢。 - coterobarros

2
请看一下zf_log日志库。它很小,简单,只提供基本功能。来自README.md:
这只是sprintf()函数的一个薄包装器。它提供了比更复杂的库少于20%的功能,但涵盖了超过80%的常见用例。重点放在简单性、易用性和性能上(更精确地说是低开销)。
特点:
- 在发布版本中,调试日志被减少为无操作。 - 当消息未被记录时,不评估参数。 - 仅在日志语句中使用的变量不会出现“未使用”的警告。 - 将内存区域作为HEX和ASCII记录。 - 自定义输出函数。

0

我也在寻找这个问题的解决方案。@ edwin-buck 的答案很简单,符合我的需求。

我对多线程和线程安全一无所知,但在使用Visual Studio编译器进行编译后(它可以提供一些警告和提示),并通过谷歌搜索,我认为进行一些修改可能会使上面的代码变得更加线程安全和更好。

// file log.c
void log(const char* tag, const char* message) {
   time_t now;
   struct tm _calendar_time;
   char _buf[MAX_COUNT];

   time(&now);
   localtime_s(&_calendar_time, &now);

   strftime(_buf, MAX_COUNT, "%c", &_calendar_time);
   printf("%s [%s]: %s\n", _buf, tag, message);
}

如有错误请随时纠正


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接