MINOR: time: add timeofday_as_iso_us() to return instant time as ISO
We often need ISO time + microseconds in traces and ring buffers, thus function does this by calling gettimeofday() and keeping a cached value of the part representing the tv_sec value, and only rewrites the microsecond part. The cache is per-thread so it's lockless and safe to use as-is. Some tests already show that it's easy to see 3-4 events in a single microsecond, thus it's likely that the nanosecond version will have to be implemented as well. But certain comments on the net suggest that some parsers are having trouble beyond microsecond, thus for now let's stick to the microsecond only.
This commit is contained in:
parent
710d987cd6
commit
93acfa2263
|
@ -103,6 +103,8 @@ REGPRM1 static inline struct timeval *tv_now(struct timeval *tv)
|
|||
*/
|
||||
REGPRM2 void tv_update_date(int max_wait, int interrupted);
|
||||
|
||||
char *timeofday_as_iso_us(int pad);
|
||||
|
||||
/*
|
||||
* sets a struct timeval to its highest value so that it can never happen
|
||||
* note that only tv_usec is necessary to detect it since a tv_usec > 999999
|
||||
|
|
30
src/time.c
30
src/time.c
|
@ -32,6 +32,9 @@ THREAD_LOCAL struct timeval after_poll; /* system date after leaving poll()
|
|||
static THREAD_LOCAL struct timeval tv_offset; /* per-thread time ofsset relative to global time */
|
||||
static volatile unsigned long long global_now; /* common date between all threads (32:32) */
|
||||
|
||||
static THREAD_LOCAL unsigned int iso_time_sec; /* last iso time value for this thread */
|
||||
static THREAD_LOCAL char iso_time_str[28]; /* ISO time representation of gettimeofday() */
|
||||
|
||||
/*
|
||||
* adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
|
||||
*/
|
||||
|
@ -262,6 +265,33 @@ REGPRM2 void tv_update_date(int max_wait, int interrupted)
|
|||
return;
|
||||
}
|
||||
|
||||
/* returns the current date as returned by gettimeofday() in ISO+microsecond
|
||||
* format. It uses a thread-local static variable that the reader can consume
|
||||
* for as long as it wants until next call. Thus, do not call it from a signal
|
||||
* handler. If <pad> is non-0, a trailing space will be added. It will always
|
||||
* return exactly 26 or 27 characters (depending on padding) and will always be
|
||||
* zero-terminated, thus it will always fit into a 28 bytes buffer.
|
||||
*/
|
||||
char *timeofday_as_iso_us(int pad)
|
||||
{
|
||||
struct timeval new_date;
|
||||
struct tm tm;
|
||||
|
||||
gettimeofday(&new_date, NULL);
|
||||
if (new_date.tv_sec != iso_time_sec || !new_date.tv_sec) {
|
||||
get_localtime(new_date.tv_sec, &tm);
|
||||
if (unlikely(strftime(iso_time_str, sizeof(iso_time_str), "%Y-%m-%dT%H:%M:%S.000000", &tm) != 26))
|
||||
strcpy(iso_time_str, "YYYY-mm-ddTHH:MM:SS.000000"); // make the failure visible but respect format.
|
||||
iso_time_sec = new_date.tv_sec;
|
||||
}
|
||||
utoa_pad(new_date.tv_usec, iso_time_str + 20, 7);
|
||||
if (pad) {
|
||||
iso_time_str[26] = ' ';
|
||||
iso_time_str[27] = 0;
|
||||
}
|
||||
return iso_time_str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
|
|
Loading…
Reference in New Issue