Printing timestamps is rather common thing in OpenMetrics so add a native function for this. The benefit is that it prints the timestamp as pseudo float with higher precision than a regular float.
Also adjust output of doubles to include enough significant digits to print the value in full precision. -- :wq Claudio Index: ometric.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpctl/ometric.c,v retrieving revision 1.5 diff -u -p -r1.5 ometric.c --- ometric.c 5 Dec 2022 11:50:11 -0000 1.5 +++ ometric.c 6 Dec 2022 10:55:51 -0000 @@ -17,6 +17,7 @@ */ #include <sys/queue.h> +#include <sys/time.h> #include <err.h> #include <stdarg.h> @@ -42,6 +43,7 @@ struct olabels { enum ovalue_type { OVT_INTEGER, OVT_DOUBLE, + OVT_TIMEVAL, }; struct ovalue { @@ -50,6 +52,7 @@ struct ovalue { union { unsigned long long i; double f; + struct timeval tv; } value; enum ovalue_type valtype; }; @@ -273,7 +276,10 @@ ometric_output_value(FILE *out, const st case OVT_INTEGER: return fprintf(out, "%llu", ov->value.i); case OVT_DOUBLE: - return fprintf(out, "%g", ov->value.f); + return fprintf(out, "%.17g", ov->value.f); + case OVT_TIMEVAL: + return fprintf(out, "%lld.%06d", (long long)ov->value.tv.tv_sec, + (int)ov->value.tv.tv_usec); } return -1; } @@ -366,6 +372,28 @@ ometric_set_float(struct ometric *om, do } /* + * Set an timeval value with label ol. ol can be NULL. + */ +void +ometric_set_timeval(struct ometric *om, const struct timeval *tv, + struct olabels *ol) +{ + struct ovalue *ov; + + if (om->type != OMT_GAUGE) + errx(1, "%s incorrect ometric type", __func__); + + if ((ov = malloc(sizeof(*ov))) == NULL) + err(1, NULL); + + ov->value.tv = *tv; + ov->valtype = OVT_TIMEVAL; + ov->labels = olabels_ref(ol); + + STAILQ_INSERT_TAIL(&om->vals, ov, entry); +} + +/* * Add an info value (which is the value 1 but with extra key-value pairs). */ void @@ -422,5 +450,16 @@ ometric_set_int_with_labels(struct ometr extra = olabels_add_extras(ol, keys, values); ometric_set_int(om, val, extra); + olabels_free(extra); +} + +void +ometric_set_timeval_with_labels(struct ometric *om, struct timeval *tv, + const char **keys, const char **values, struct olabels *ol) +{ + struct olabels *extra; + + extra = olabels_add_extras(ol, keys, values); + ometric_set_timeval(om, tv, extra); olabels_free(extra); } Index: ometric.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpctl/ometric.h,v retrieving revision 1.3 diff -u -p -r1.3 ometric.h --- ometric.h 1 Dec 2022 09:14:40 -0000 1.3 +++ ometric.h 6 Dec 2022 10:53:12 -0000 @@ -41,9 +41,13 @@ int ometric_output_all(FILE *); /* functions to set gauge and counter metrics */ void ometric_set_int(struct ometric *, uint64_t, struct olabels *); void ometric_set_float(struct ometric *, double, struct olabels *); +void ometric_set_timeval(struct ometric *, const struct timeval *, + struct olabels *); void ometric_set_info(struct ometric *, const char **, const char **, struct olabels *); void ometric_set_state(struct ometric *, const char *, struct olabels *); void ometric_set_int_with_labels(struct ometric *, uint64_t, const char **, const char **, struct olabels *); +void ometric_set_timeval_with_labels(struct ometric *, struct timeval *, + const char **, const char **, struct olabels *); #define OKV(...) (const char *[]){ __VA_ARGS__, NULL } Index: output_ometric.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpctl/output_ometric.c,v retrieving revision 1.6 diff -u -p -r1.6 output_ometric.c --- output_ometric.c 1 Dec 2022 09:16:43 -0000 1.6 +++ output_ometric.c 6 Dec 2022 10:55:02 -0000 @@ -319,15 +319,11 @@ static void ometric_tail(void) { struct timeval elapsed_time; - double scrape; gettimeofday(&end_time, NULL); timersub(&end_time, &start_time, &elapsed_time); - scrape = (double)elapsed_time.tv_sec + - (double)elapsed_time.tv_usec / 1000000; - - ometric_set_float(bgpd_scrape_time, scrape, NULL); + ometric_set_timeval(bgpd_scrape_time, &elapsed_time, NULL); ometric_output_all(stdout); ometric_free_all();