2011-09-14 18 views
7

Tengo un daemon escrito en C. Estoy registrando los eventos en un archivo de registro, pero ahora quiero agregar la fecha y la hora mientras escribo el evento en el archivo de registro. ¿Cómo puedo lograr eso?Cómo introducir fecha y hora en el archivo de registro

archivo de registro actual: -

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

Quiero el archivo de registro para que parezca: -

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

Mi entorno es C y Linux.

+0

@ Jonathan Leffler, estoy frente a estos problemas de alineación desde hace mucho tiempo, ¿hay alguna página de referencia a REF y tomar ¿Me cuido? – Thangaraj

+1

¿Te refieres al diseño en tu pregunta? Al ingresar un comentario, hay un hipervínculo de ayuda; Al ingresar una pregunta o respuesta, hay un signo de interrogación anaranjado que proporciona ayuda justo arriba del área de escritura. La sangría por 4 espacios trata el siguiente material como código; evitar pestañas. Las listas de viñetas tienen líneas que comienzan con una estrella o guión ('*' o '-'); puedes anidarlos (las sub-viñetas tienen sangría de 2 o más espacios), y puedes tener un código asociado a ellos (prefijado con 8 espacios en lugar de solo 4, para las viñetas de primer nivel). Las listas numeradas tienen líneas que comienzan con '1.' (el punto es crucial). Etc. –

+0

@Jonathan Leffler, Gracias – Thangaraj

Respuesta

12

Debe considerar utilizar date y gmtime o localtime para obtener la fecha y hora reales.

Luego strftime puede formatearlo para usted.

Programa de ejemplo siguiente:

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

Este salidas:

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

prefiero el uso de UTC en lugar de la hora local, ya que le permite unir los eventos de la máquina geográficamente separados sin preocuparse diferencias de zona horaria. En otras palabras, use gmtime en lugar de localtime a menos que sea muy seguro de que no cruzará las zonas horarias.

También tiendo a preferir el formato YYYY-MM-DD HH:MM:SS ya que es más fácil de ordenar que los nombres de los meses, vitales para las herramientas de extracción y manipulación.

+0

¿El uso de esta biblioteca generará problemas de portabilidad? – Thangaraj

+0

Esas son funciones C89 puras, son tan portátiles como puede razonablemente esperar. Hay muchas otras partes de tu daemon que son menos portátiles, eso es seguro. –

+0

@Thangaraj: no, todos están definidos en ISO C, tan portátiles como puedas :-) – paxdiablo

4

Para obtener la hora actual se puede utilizar, por ejemplo, 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; 
} 

También puede utilizar strftime según lo sugerido por paxdiablo para más posibilidades de formato de hora/fecha.

Por supuesto, para su caso, el resultado de ctime(&now) irá a su entrada de registro char matriz/cadena en lugar de printf.

+0

Podría ser mejor (aunque básicamente equivalente) usar: 'time_t now = time (0);'. –

+0

@Jonathan Leffler - Académico realmente pero sí, básicamente equivalente. De todos modos, la respuesta de paxdiablo es más completa que la mía ahora, acabo de publicar esto para alentarlo a agregar una muestra de código. ;) – ocodo

+0

gr8 post ... me ayuda mucho ... gracias – 2vision2

6

Agregando mis funciones de registro, basado en la respuesta de @paxdiablo. Utilizando la hora local, pero podría usar GMT con sólo modificar 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; 
} 

Puede utilizarlos como esto:

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

Que produce la salida:

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 
1

según la respuesta de @inolasco, la variable estática no es segura para subprocesos. usando la variable local en su lugar.

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

los llaman así:

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

productos:

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 
Cuestiones relacionadas