LIBTRACECMD(3)

πŸ’… LIBTRACECMD(3) β€” the time-stamp page, bestie edition

okay so this is from the libtracefs manual, page LIBTRACECMD(3), and we're about to get so comfy with time stamps from trace files. grab a matcha, this is gonna be good πŸ“


✨ NAME ✨

tracecmd_get_first_ts, tracecmd_add_ts_offset, tracecmd_get_tsc2nsec β€” literally the trio that handles time stamps from a trace file πŸ’–


🌸 SYNOPSIS 🌸

#include <trace-cmd.h>

unsigned long long tracecmd_get_first_ts(struct tracecmd_input *handle);
void tracecmd_add_ts_offset(struct tracecmd_input *handle, long long offset);
int tracecmd_get_tsc2nsec(struct tracecmd_input *handle, int *mult, int pass[*]shift, unsigned long long *offset);

(yes, pass[*]shift is exactly how it's written, don't come for me, I copy character for character πŸ‘‘)


πŸ¦‹ DESCRIPTION πŸ¦‹

This little set of APIs is your go-to for reading tracing data out of a trace file that was opened with tracecmd_open()(3), tracecmd_open_fd()(3) or tracecmd_open_head()(3). Three openers, three vibes, one friend group 🫢

  • tracecmd_get_first_ts() β€” returns the time stamp of the first record in the handle. that's it. that's the whole function. iconic minimalism πŸ’…
  • tracecmd_add_ts_offset() β€” adds an offset to each of the records in the handle that represents a trace file. lowkey the main character of this page, because it's what lets you associate two different tracing files by their offset. the classic example: a trace file from a host and a trace file from a guest that were not synchronized when created 😭 now you can line them up. slay.
  • tracecmd_get_tsc2nsec β€” returns the calculation values that convert the raw timestamp into nanoseconds ✨ The parameters are pointers to the storage to save the values, or NULL to ignore them. So: the multiplier gets saved in mult, the shift value gets saved in shift, and the offset value gets saved in offset β€” but only if the corresponding parameters aren't NULL, k? no cap, passing NULL is a totally valid "not me caring about that one" move πŸ™ˆ

⭐ RETURN VALUE ⭐

  • tracecmd_get_first_ts() β€” returns the timestamp of the first record in a trace file for the given handle. straightforward, we love her 🌈
  • tracecmd_get_tsc2nsec() β€” returns 0 if the tracing clock supports the shift values, and -1 otherwise.
πŸ’€ Heads up bestie, this is the important twist: if the trace file has the TSC2NSEC option, the values returned in the parameters may still be valid even if the function itself returns -1. The return value only notes whether the values will be used in the calculations of the given clock. So don't panic-close the file when you see -1, read the fine print first πŸŽ€

πŸ”₯ EXAMPLE πŸ”₯

here's the whole thing, verbatim, because she's a queen and she deserves to be shown in full:

#include <stdlib.h>
#include <trace-cmd.h>

static int print_events(struct tracecmd_input *handle, struct tep_record *record, int cpu, void *data)
{
        static struct trace_seq seq;
        struct tep_handle *tep = tracecmd_get_tep(handle);
        const char *file = tracecmd_get_private(handle);

        if (!seq.buffer)
                trace_seq_init(&seq);

        trace_seq_reset(&seq);
        trace_seq_printf(&seq, "%s: ", file);
        tep_print_event(tep, &seq, record, "%6.1000d [%03d] %s-%d %s: %s\n",
                        TEP_PRINT_TIME, TEP_PRINT_CPU, TEP_PRINT_COMM, TEP_PRINT_PID,
                        TEP_PRINT_NAME, TEP_PRINT_INFO);
        trace_seq_terminate(&seq);
        trace_seq_do_printf(&seq);
        return 0;
}

int main(int argc, char **argv)
{
        struct tracecmd_input **handles = NULL;
        unsigned long long ts, first_ts = 0;
        unsigned long long offset;
        int multi;
        int shift;
        int nr_handles = 0;
        int ret;
        int i;

        if (argc < 2) {
                printf("usage: %s trace.dat [trace.dat ...]\n", argv[0]);
                exit(-1);
        }

        for (i = 1; i < argc; i++) {
                handles = realloc(handles, sizeof(*handles) * (nr_handles + 1));
                if (!handles)
                        exit(-1);
                handles[nr_handles] = tracecmd_open(argv[i], 0);
                if (!handles[nr_handles])
                        exit(-1);

                ret = tracecmd_get_tsc2nsec(handles[nr_handles], &multi, &shift, &offset);
                if (!ret)
                        printf(" %s has tsc2nsec calculations of mult:%d shift:%d offset:%lld\n",
                                argv[i], multi, shift, offset);
                tracecmd_set_private(handles[nr_handles], argv[i]);
                ts = tracecmd_get_first_ts(handles[nr_handles]);
                if (!first_ts || ts < first_ts)
                        first_ts = ts;
                nr_handles++;
        }

        /* Set the time stamp to start at the first record found */
        for (i = 0; i < nr_handles; i++)
                tracecmd_add_ts_offset(handles[i], -first_ts);

        tracecmd_iterate_events_multi(handles, nr_handles, print_events, NULL);

        for (i = 0; i < nr_handles; i++)
                tracecmd_close(handles[i]);
        free(handles);
}

the way this just opens every trace file you hand it, asks for the tsc2nsec math, grabs the earliest first timestamp across all of them, then shifts everything so the whole party starts at the same moment β€” that's the offset trick doing its thing 🧚 and then it iterates all the events together through print_events. periodt.


πŸŽ€ FILES πŸŽ€

  • trace-cmd.h β€” the header file to include in order to have access to the library APIs. don't forget it, or nothing works and you'll be sad 😭
  • -ltracecmd β€” the linker switch to add when building a program that uses the library. yes, that one goes in your build flags, not your source file πŸ’…

🌟 SEE ALSO 🌟

libtracefs(3), libtraceevent(3), trace-cmd(1) trace-cmd.dat(5)

the whole friend group, go say hi πŸ’–


πŸ‘‘ AUTHOR πŸ‘‘

  • Steven Rostedt <rostedt@goodmis.org>
  • Tzvetomir Stoyanov <tz.stoyanov@gmail.com>

πŸ™ˆ REPORTING BUGS πŸ™ˆ

Report bugs to <linux-trace-devel@vger.kernel.org>. found a bug? tell the mailing list, not your group chat (well, tell the group chat too, but tell the list first fr fr)


πŸ’œ LICENSE πŸ’œ

libtracecmd is Free Software licensed under the GNU LGPL 2.1.


🌈 RESOURCES 🌈

https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ β€” the source, go scroll, it's giving open source excellence ✨


πŸ’– COPYING πŸ’–

Copyright (C) 2020 VMware, Inc. Free use of this software is granted under the terms of the GNU Public License (GPL).


πŸ“ NOTES πŸ“

  1. rostedt@goodmis.org β€” mailto:rostedt@goodmis.org
  2. tz.stoyanov@gmail.com β€” mailto:tz.stoyanov@gmail.com
  3. linux-trace-devel@vger.kernel.org β€” mailto:linux-trace-devel@vger.kernel.org

okay that's the whole page, bestie, you're officially caught up πŸ’…πŸ«Ά this was libtracefs, dated 03/09/2026, page LIBTRACECMD(3) β€” now go add some offsets and make those host and guest traces line up like the synchronized queens they are βœ¨πŸ‘‘

πŸ“¦ where this page comes from