tracefs_synth_create(3) — Linux manual page

NAME | SYNOPSIS | DESCRIPTION | RETURN VALUE | ERRORS | EXAMPLE | FILES | SEE ALSO | AUTHOR | REPORTING BUGS | LICENSE | RESOURCES | COPYING | NOTES | COLOPHON

LIBTRACEFS(3)               libtracefs Manual              LIBTRACEFS(3)

NAME         top

       tracefs_synth_create, tracefs_synth_destroy,
       tracefs_synth_complete, tracefs_synth_trace,
       tracefs_synth_snapshot, tracefs_synth_save,
       tracefs_synth_set_instance,  - Creation of synthetic events

SYNOPSIS         top

       #include <tracefs.h>

       int tracefs_synth_create(struct tracefs_synth *synth);
       int tracefs_synth_destroy(struct tracefs_synth *synth);
       bool tracefs_synth_complete(struct tracefs_synth *synth);

       int tracefs_synth_set_instance(struct tracefs_synth *synth, struct tracefs_instance *instance);
       int tracefs_synth_trace(struct tracefs_synth *synth,
                               enum tracefs_synth_handler type, const char *var);
       int tracefs_synth_snapshot(struct tracefs_synth *synth,
                                  enum tracefs_synth_handler type, const char *var);
       int tracefs_synth_save(struct tracefs_synth *synth,
                              enum tracefs_synth_handler type, const char *var,
                              char **save_fields);

DESCRIPTION         top

       Synthetic events are dynamic events that are created by matching
       two other events which triggers a synthetic event. One event is
       the starting event which some field is recorded, and when the
       second event is executed, if it has a field (or fields) that
       matches the starting event’s field (or fields) then it will
       trigger the synthetic event. The field values other than the
       matching fields may be passed from the starting event to the end
       event to perform calculations on, or to simply pass as a
       parameter to the synthetic event.

       One common use case is to set "sched_waking" as the starting
       event. This event is triggered when a process is awoken. Then set
       "sched_switch" as the ending event. This event is triggered when
       a new task is scheduled on the CPU. By setting the "common_pid"
       of both events as the matching fields, the time between the two
       events is considered the wake up latency of that process. Use
       TRACEFS_TIMESTAMP as a field for both events to calculate the
       delta in nanoseconds, or use TRACEFS_TIMESTAMP_USECS as the
       compare fields for both events to calculate the delta in
       microseconds. This is used as the example below.

       tracefs_synth_create() creates the synthetic event in the system.
       By default, the histogram triggers are created in the top trace
       instance, as any synthetic event can be used globally across all
       instances. In case an application wants to keep the histogram
       triggers out of the top level instance, it can use
       tracefs_synth_set_instance() to have the histograms used for
       creating the synthetic event in an instance other than the top
       level. A synthetic event descriptor must be created with
       tracefs_synth_alloc(3) before this can be used to create it on
       the system.

       tracefs_synth_destroy() destroys the synthetic event. It will
       attempt to stop the running of it in its instance (top by
       default), but if its running in another instance this may fail as
       busy.

       tracefs_synth_complete() returns true if the synthetic event
       synth has both a starting and ending event.

       tracefs_synth_trace() Instead of doing just a trace on matching
       of the start and end events, do the type handler where
       TRACEFS_SYNTH_HANDLE_MAX will do a trace when the given variable
       var hits a new max for the matching keys. Or
       TRACEFS_SYNTH_HANDLE_CHANGE for when the var changes. var must be
       one of the name elements used in tracefs_synth_add_end_field(3).

       tracefs_synth_snapshot() When the given variable var is either a
       new max if handler is TRACEFS_SYNTH_HANDLE_MAX or simply changed
       if TRACEFS_SYNTH_HANDLE_CHANGE then take a "snapshot" of the
       buffer. The snapshot moves the normal "trace" buffer into a
       "snapshot" buffer, that can be accessed via the "snapshot" file
       in the top level tracefs directory, or one of the instances. var
       changes. var must be one of the name elements used in
       tracefs_synth_add_end_field(3).

       tracefs_synth_save() When the given variable var is either a new
       max if handler is TRACEFS_SYNTH_HANDLE_MAX or simpy changed if
       TRACEFS_SYNTH_HANDLE_CHANGE then save the given save_fields list.
       The fields will be stored in the histogram "hist" file of the
       event that can be retrieved with tracefs_event_file_read(3). var
       must be one of the name elements used in
       tracefs_synth_add_end_field(3).

       tracefs_synth_set_instance() Set the trace instance, where the
       histogram triggers that create the synthetic event will be
       created. By default, the top instance is used. This API must be
       called before the call to tracefs_synth_create(), in order to use
       the new instance when creating the event. Note, that even if the
       synthetic event is created in an instance, it is still visible by
       all other instances including the top level. That is, other
       instances can enable the created synthetic event and have it
       traced in the buffers that belong to the instance that enabled
       it.

RETURN VALUE         top

       All functions return zero on success or -1 on error.

ERRORS         top

       The following errors are for all the above calls:

       EPERM Not run as root user when required.

       EINVAL Either a parameter is not valid (NULL when it should not
       be) or a field that is not compatible for calculations.

       ENODEV An event or one of its fields is not found.

       EBADE The fields of the start and end events are not compatible
       for either matching or comparing.

       ENOMEM not enough memory is available.

       And more errors may have happened from the system calls to the
       system.

EXAMPLE         top

       See tracefs_sql(3) for a more indepth use of some of this code.

           #include <stdlib.h>
           #include <tracefs.h>

           #define start_event "sched_waking"
           #define start_field "pid"

           #define end_event "sched_switch"
           #define end_field "next_pid"

           #define match_name "pid"

           static struct tracefs_synth *synth;

           static void make_event(void)
           {
                   struct tep_handle *tep;

                   /* Load all events from the system */
                   tep = tracefs_local_events(NULL);

                   /* Initialize the synthetic event */
                   synth = tracefs_synth_alloc(tep, "wakeup_lat",
                                               NULL, start_event,
                                               NULL, end_event,
                                               start_field, end_field,
                                               match_name);

                   /* The tep is no longer needed */
                   tep_free(tep);

                   /* Save the "prio" field as "prio" from the start event */
                   tracefs_synth_add_start_field(synth, "prio", NULL);

                   /* Save the "next_comm" as "comm" from the end event */
                   tracefs_synth_add_end_field(synth, "next_comm", "comm");

                   /* Save the "prev_prio" as "prev_prio" from the end event */
                   tracefs_synth_add_end_field(synth, "prev_prio", NULL);

                   /*
                    * Take a microsecond time difference between end and start
                    * and record as "delta"
                    */
                   tracefs_synth_add_compare_field(synth, TRACEFS_TIMESTAMP_USECS,
                                                   TRACEFS_TIMESTAMP_USECS,
                                                   TRACEFS_SYNTH_DELTA_END, "delta");

                   /* Only record if start event "prio" is less than 100 */
                   tracefs_synth_append_start_filter(synth, TRACEFS_FILTER_COMPARE,
                                                     "prio", TRACEFS_COMPARE_LT, "100");

                   /*
                    * Only record if end event "next_prio" is less than 50
                    * or the previous task's prio was not greater than or equal to 100.
                    *   next_prio < 50 || !(prev_prio >= 100)
                    */
                   tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE,
                                                   "next_prio", TRACEFS_COMPARE_LT, "50");
                   tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OR, NULL, 0, NULL);
                   tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_NOT, NULL, 0, NULL);
                   tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OPEN_PAREN, NULL, 0, NULL);
                   tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE,
                                                   "prev_prio", TRACEFS_COMPARE_GE, "100");
                   /*
                    * Note, the above only added: "next_prio < 50 || !(prev_prio >= 100"
                    * That's because, when the synth is executed, the remaining close parenthesis
                    * will be added. That is, the string will end up being:
                    * "next_prio < 50 || !(prev_prio >= 100)" when one of tracefs_sync_create()
                    * or tracefs_sync_echo_cmd() is run.
                    */
           }

           /* Display how to create the synthetic event */
           static void show_event(void)
           {
                   struct trace_seq s;

                   trace_seq_init(&s);

                   tracefs_synth_echo_cmd(&s, synth);
                   trace_seq_terminate(&s);
                   trace_seq_do_printf(&s);
                   trace_seq_destroy(&s);
           }

           int main (int argc, char **argv)
           {
                   make_event();

                   if (argc > 1) {
                           if (!strcmp(argv[1], "create")) {
                                   /* Create the synthetic event */
                                   tracefs_synth_create(synth);
                           } else if (!strcmp(argv[1], "delete")) {
                                   /* Delete the synthetic event */
                                   tracefs_synth_destroy(synth);
                           } else {
                                   printf("usage: %s [create|delete]\n", argv[0]);
                                   exit(-1);
                           }
                   } else
                           show_event();

                   tracefs_synth_free(synth);

                   return 0;
           }

FILES         top

           tracefs.h
                   Header file to include in order to have access to the library APIs.
           -ltracefs
                   Linker switch to add when building a program that uses the library.

SEE ALSO         top

       libtracefs(3), libtraceevent(3), trace-cmd(1),
       tracefs_hist_alloc(3), tracefs_hist_alloc_2d(3),
       tracefs_hist_alloc_nd(3), tracefs_hist_free(3),
       tracefs_hist_add_key(3), tracefs_hist_add_value(3),
       tracefs_hist_add_name(3), tracefs_hist_start(3),
       tracefs_hist_destory(3), tracefs_hist_add_sort_key(3),
       tracefs_hist_sort_key_direction(3), tracefs_synth_alloc(3),
       tracefs_synth_add_match_field(3),
       tracefs_synth_add_compare_field(3),
       tracefs_synth_add_start_field(3), tracefs_synth_add_end_field(3),
       tracefs_synth_append_start_filter(3),
       tracefs_synth_append_end_filter(3), tracefs_synth_free(3),
       tracefs_synth_echo_cmd(3), tracefs_synth_get_start_hist(3),
       tracefs_synth_get_name(3), tracefs_synth_raw_fmt(3),
       tracefs_synth_show_event(3), tracefs_synth_show_start_hist(3),
       tracefs_synth_show_end_hist(3), tracefs_synth_get_event(3),

AUTHOR         top

           Steven Rostedt <[email protected][1]>
           Tzvetomir Stoyanov <[email protected][2]>
           sameeruddin shaik <[email protected][3]>

REPORTING BUGS         top

       Report bugs to <[email protected][4]>

LICENSE         top

       libtracefs is Free Software licensed under the GNU LGPL 2.1

RESOURCES         top

       https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ 

COPYING         top

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

NOTES         top

        1. [email protected]
           mailto:[email protected]

        2. [email protected]
           mailto:[email protected]

        3. [email protected]
           mailto:[email protected]

        4. [email protected]
           mailto:[email protected]

COLOPHON         top

       This page is part of the libtracefs (Linux kernel trace file
       system library) project.  Information about the project can be
       found at ⟨https://www.trace-cmd.org/⟩.  If you have a bug report
       for this manual page, see ⟨https://www.trace-cmd.org/⟩.  This
       page was obtained from the project's upstream Git repository
       ⟨https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git⟩ on
       2024-06-14.  (At that time, the date of the most recent commit
       that was found in the repository was 2024-05-17.)  If you
       discover any rendering problems in this HTML version of the page,
       or you believe there is a better or more up-to-date source for
       the page, or you have corrections or improvements to the
       information in this COLOPHON (which is not part of the original
       manual page), send a mail to [email protected]

libtracefs 1.7.0               12/22/2023                  LIBTRACEFS(3)

Pages that refer to this page: tracefs_sql(3)tracefs_synth_alloc(3)tracefs_synth_echo_cmd(3)