Thangaraj
Thangaraj

Reputation: 3184

How to introduce date and time in log file

I have one daemon written in C. I am logging the events in a log file, but now I want to add date and time while writing event to log file. How can I achieve that?

Current log file:-

Event one occurred: result:
Event two occurred: result:

I want the log file to look like:-

Sep 14 11:35:55 Event one occurred: result:
Sep 14 11:35:55 Event two occurred: result:

My environment is C and Linux.

Upvotes: 13

Views: 34817

Answers (4)

paxdiablo
paxdiablo

Reputation: 881523

You need to look into using date and either gmtime or localtime to get the actual date and time.

Then strftime can format it for you.

Sample program follows:

#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;
}

This outputs:

2011-09-14 04:52:11 Event occurred now

I prefer the use of UTC rather than local time since it allows you to tie together events from geographically separated machine without worrying about timezone differences. In other words, use gmtime rather than localtime unless you're very certain you won't be crossing timezones.

I also tend to prefer the YYYY-MM-DD HH:MM:SS format since it's easier to sort than month names, vital for extraction and manipulation tools.


If you have an implementation that provides the optional bounds-checking functions (as per Appendix K of C11), you can probably use gmtime_s in preference. It allows you to specify your own buffer for receiving the result and is thus safer in re-entrant and/or threaded code.

To use that, you need to change your code to something like:

#include <stdio.h>
#define __STDC_WANT_LIB_EXT1__ 1
#include <time.h>

int main (void) {
    char buff[20];
    struct tm sTm;

    time_t now = time (0);
    gmtime_s (&now, &sTm);

    strftime (buff, sizeof(buff), "%Y-%m-%d %H:%M:%S", &sTm);
    printf ("%s %s\n", buff, "Event occurred now");

    return 0;
}

Although you should be aware that the folks at Microsoft have somehow managed to get the arguments for gmtime_s around the wrong way. You'll need to take that into account.

POSIX (and Linux) also provides a gmtime_r function which performs in the same way as the standard gmtime_s function (with the arguments in the correct order).

Upvotes: 17

chen_767
chen_767

Reputation: 365

based on the answer by @inolasco, static variable is not thread safe. using local variable instead.

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__)

call them like this:

info("%s", "a log");
infol("%s", "a log");

produce:

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

Upvotes: 2

inolasco
inolasco

Reputation: 694

Adding my log functions, based on the answer by @paxdiablo. Using local time, but could use gmt just by modifying 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;
}

You can use them like this:

 LOGDEBUG("This is a log");
 LOGDEBUG("This is a log with params %d", 42);

Which produces the output:

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

Upvotes: 12

ocodo
ocodo

Reputation: 30248

To get the current time you can use time.h for example...

#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;
}

You can also use strftime as suggested by paxdiablo for more time/date formatting possibilities.

Of course, for your case, the result of ctime(&now) will go into your log entry char array/string instead of printf.

Upvotes: 5

Related Questions