From patchwork Tue Nov 23 21:59:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 12635529 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 234E9C433FE for ; Tue, 23 Nov 2021 22:00:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236126AbhKWWDN (ORCPT ); Tue, 23 Nov 2021 17:03:13 -0500 Received: from ex13-edg-ou-002.vmware.com ([208.91.0.190]:43361 "EHLO EX13-EDG-OU-002.vmware.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236032AbhKWWDN (ORCPT ); Tue, 23 Nov 2021 17:03:13 -0500 Received: from sc9-mailhost1.vmware.com (10.113.161.71) by EX13-EDG-OU-002.vmware.com (10.113.208.156) with Microsoft SMTP Server id 15.0.1156.6; Tue, 23 Nov 2021 14:00:00 -0800 Received: from vypre.local.home (unknown [10.21.245.90]) by sc9-mailhost1.vmware.com (Postfix) with ESMTP id DB90520176; Tue, 23 Nov 2021 14:00:03 -0800 (PST) From: Steven Rostedt To: CC: "Steven Rostedt (VMware)" Subject: [PATCH 1/3] libtracefs/sqlhist: Add -B option to use instances for histograms Date: Tue, 23 Nov 2021 16:59:56 -0500 Message-ID: <20211123215958.1091307-2-rostedt@goodmis.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211123215958.1091307-1-rostedt@goodmis.org> References: <20211123215958.1091307-1-rostedt@goodmis.org> MIME-Version: 1.0 Received-SPF: None (EX13-EDG-OU-002.vmware.com: rostedt@goodmis.org does not designate permitted sender hosts) Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (VMware)" As sqlhist can also create histograms, it should have a way to pass in an instance value that would be used to create a histogram for a given instance. Signed-off-by: Steven Rostedt (VMware) --- Documentation/libtracefs-sql.txt | 28 +++++++++++++++++++++----- Documentation/libtracefs-sqlhist.txt.1 | 5 +++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Documentation/libtracefs-sql.txt b/Documentation/libtracefs-sql.txt index 3389090..6297e9a 100644 --- a/Documentation/libtracefs-sql.txt +++ b/Documentation/libtracefs-sql.txt @@ -330,7 +330,8 @@ enum action { #define ACTIONS ((ACTION_MAX - 1)) -static int do_sql(const char *buffer, const char *name, const char *var, +static int do_sql(const char *instance_name, + const char *buffer, const char *name, const char *var, const char *trace_dir, bool execute, int action, char **save_fields) { @@ -409,15 +410,28 @@ static int do_sql(const char *buffer, const char *name, const char *var, if (execute) tracefs_synth_create(synth); } else { + struct tracefs_instance *instance = NULL; struct tracefs_hist *hist; + hist = tracefs_synth_get_start_hist(synth); if (!hist) { perror("get_start_hist"); exit(-1); } - tracefs_hist_echo_cmd(&seq, NULL, hist, 0); + if (instance_name) { + if (execute) + instance = tracefs_instance_create(instance_name); + else + instance = tracefs_instance_alloc(trace_dir, + instance_name); + if (!instance) { + perror("Failed to create instance"); + exit(-1); + } + } + tracefs_hist_echo_cmd(&seq, instance, hist, 0); if (execute) - tracefs_hist_start(NULL, hist); + tracefs_hist_start(instance, hist); } tracefs_synth_free(synth); @@ -434,6 +448,7 @@ int main (int argc, char **argv) char buf[BUFSIZ]; int buffer_size = 0; const char *file = NULL; + const char *instance = NULL; bool execute = false; char **save_fields = NULL; const char *name; @@ -446,7 +461,7 @@ int main (int argc, char **argv) int i; for (;;) { - c = getopt(argc, argv, "ht:f:en:m:c:sS:T"); + c = getopt(argc, argv, "ht:f:en:m:c:sS:TB:"); if (c == -1) break; @@ -488,6 +503,9 @@ int main (int argc, char **argv) case 'T': action |= ACTION_TRACE | ACTION_SNAPSHOT; break; + case 'B': + instance = optarg; + break; case 'n': name = optarg; break; @@ -528,7 +546,7 @@ int main (int argc, char **argv) } } - do_sql(buffer, name, var, trace_dir, execute, action, save_fields); + do_sql(instance, buffer, name, var, trace_dir, execute, action, save_fields); free(buffer); return 0; diff --git a/Documentation/libtracefs-sqlhist.txt.1 b/Documentation/libtracefs-sqlhist.txt.1 index 1e94ea4..875b250 100644 --- a/Documentation/libtracefs-sqlhist.txt.1 +++ b/Documentation/libtracefs-sqlhist.txt.1 @@ -88,6 +88,11 @@ OPTIONS Save the given fields. The fields must be fields of the "end" event given in the *SQL-select-command* +*-B* 'instance':: + For simple statements that only produce a histogram, the instance given here + will be where the histogram will be created. This is ignored for full synthetic + event creation, as sythetic events have a global affect on all tracing instances, + where as, histograms only affect a single instance. EXAMPLES -------- From patchwork Tue Nov 23 21:59:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 12635531 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1633C433EF for ; Tue, 23 Nov 2021 22:00:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237394AbhKWWDO (ORCPT ); Tue, 23 Nov 2021 17:03:14 -0500 Received: from ex13-edg-ou-001.vmware.com ([208.91.0.189]:29860 "EHLO EX13-EDG-OU-001.vmware.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233876AbhKWWDN (ORCPT ); Tue, 23 Nov 2021 17:03:13 -0500 Received: from sc9-mailhost1.vmware.com (10.113.161.71) by EX13-EDG-OU-001.vmware.com (10.113.208.155) with Microsoft SMTP Server id 15.0.1156.6; Tue, 23 Nov 2021 14:00:01 -0800 Received: from vypre.local.home (unknown [10.21.245.90]) by sc9-mailhost1.vmware.com (Postfix) with ESMTP id 8A98920256; Tue, 23 Nov 2021 14:00:04 -0800 (PST) From: Steven Rostedt To: CC: "Steven Rostedt (VMware)" Subject: [PATCH 2/3] libtracefs/Documentation: Clean up libtracefs-hist man pages Date: Tue, 23 Nov 2021 16:59:57 -0500 Message-ID: <20211123215958.1091307-3-rostedt@goodmis.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211123215958.1091307-1-rostedt@goodmis.org> References: <20211123215958.1091307-1-rostedt@goodmis.org> MIME-Version: 1.0 Received-SPF: None (EX13-EDG-OU-001.vmware.com: rostedt@goodmis.org does not designate permitted sender hosts) Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (VMware)" Include the tracefs_hist_key_type enum and the structure of tracefs_hist_axis in the man page as that is expected to be useful. It should not be expected that people must read the actual header for this information. Also add spaces between some of the functions to separate out functionality a little to make it easier to read. Also fix the missing "pass:" before "[*]axes". Signed-off-by: Steven Rostedt (VMware) --- Documentation/libtracefs-hist.txt | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Documentation/libtracefs-hist.txt b/Documentation/libtracefs-hist.txt index 31ea712..ab802cf 100644 --- a/Documentation/libtracefs-hist.txt +++ b/Documentation/libtracefs-hist.txt @@ -12,6 +12,23 @@ SYNOPSIS -- *#include * +enum tracefs_hist_key_type { + TRACEFS_HIST_KEY_NORMAL = 0, + TRACEFS_HIST_KEY_HEX, + TRACEFS_HIST_KEY_SYM, + TRACEFS_HIST_KEY_SYM_OFFSET, + TRACEFS_HIST_KEY_SYSCALL, + TRACEFS_HIST_KEY_EXECNAME, + TRACEFS_HIST_KEY_LOG, + TRACEFS_HIST_KEY_USECS, + TRACEFS_HIST_KEY_MAX +}; + +struct tracefs_hist_axis { + const char *key; + enum tracefs_hist_key_type type; +}; + struct tracefs_hist pass:[*]tracefs_hist1d_alloc(struct tracefs_tep pass:[*] tep, const char pass:[*]system, const char pass:[*]event, const char pass:[*]key, enum tracefs_hist_key_type type); @@ -21,27 +38,33 @@ struct tracefs_hist pass:[*]tracefs_hist2d_alloc(struct tracefs_tep pass:[*] tep const char pass:[*]key2, enum tracefs_hist_key_type type2)); struct tracefs_hist pass:[*]tracefs_hist_alloc(struct tracefs_tep pass:[*] tep, const char pass:[*]system, const char pass:[*]event, - struct tracefs_hist_axis [*]axes); + struct tracefs_hist_axis pass:[*]axes); void tracefs_hist_free(struct tracefs_hist pass:[*]hist); + int tracefs_hist_add_key(struct tracefs_hist pass:[*]hist, const char pass:[*]key, enum tracefs_hist_key_type type); int tracefs_hist_add_value(struct tracefs_hist pass:[*]hist, const char pass:[*]value); int tracefs_hist_add_sort_key(struct tracefs_hist pass:[*]hist, const char pass:[*]sort_key); + int tracefs_hist_set_sort_key(struct tracefs_hist pass:[*]hist, const char pass:[*]sort_key, ...); int tracefs_hist_sort_key_direction(struct tracefs_hist pass:[*]hist, const char pass:[*]sort_key, enum tracefs_hist_sort_direction dir); + int tracefs_hist_add_name(struct tracefs_hist pass:[*]hist, const char pass:[*]name); + int tracefs_hist_append_filter(struct tracefs_hist pass:[*]hist, enum tracefs_filter type, const char pass:[*]field, enum tracefs_compare compare, const char pass:[*]val); + int tracefs_hist_echo_cmd(struct trace_seq pass:[*]s, struct tracefs_instance pass:[*]instance, struct tracefs_hist pass:[*]hist, enum tracefs_hist_command command); + int tracefs_hist_command(struct tracefs_instance pass:[*]instance, struct tracefs_hist pass:[*]hist, enum tracefs_hist_command command); From patchwork Tue Nov 23 21:59:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 12635533 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 408D9C4332F for ; Tue, 23 Nov 2021 22:00:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233876AbhKWWDP (ORCPT ); Tue, 23 Nov 2021 17:03:15 -0500 Received: from ex13-edg-ou-002.vmware.com ([208.91.0.190]:2237 "EHLO EX13-EDG-OU-002.vmware.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236032AbhKWWDO (ORCPT ); Tue, 23 Nov 2021 17:03:14 -0500 Received: from sc9-mailhost1.vmware.com (10.113.161.71) by EX13-EDG-OU-002.vmware.com (10.113.208.156) with Microsoft SMTP Server id 15.0.1156.6; Tue, 23 Nov 2021 14:00:01 -0800 Received: from vypre.local.home (unknown [10.21.245.90]) by sc9-mailhost1.vmware.com (Postfix) with ESMTP id 381EE20146; Tue, 23 Nov 2021 14:00:05 -0800 (PST) From: Steven Rostedt To: CC: "Steven Rostedt (VMware)" Subject: [PATCH 3/3] libtracefs/Documentation: Modify the hist man page example Date: Tue, 23 Nov 2021 16:59:58 -0500 Message-ID: <20211123215958.1091307-4-rostedt@goodmis.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211123215958.1091307-1-rostedt@goodmis.org> References: <20211123215958.1091307-1-rostedt@goodmis.org> MIME-Version: 1.0 Received-SPF: None (EX13-EDG-OU-002.vmware.com: rostedt@goodmis.org does not designate permitted sender hosts) Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (VMware)" Update the hist man page example to allow modification of a user defined histogram type. Signed-off-by: Steven Rostedt (VMware) --- Documentation/libtracefs-hist.txt | 288 +++++++++++++++++++++++++----- 1 file changed, 242 insertions(+), 46 deletions(-) diff --git a/Documentation/libtracefs-hist.txt b/Documentation/libtracefs-hist.txt index ab802cf..c501d5a 100644 --- a/Documentation/libtracefs-hist.txt +++ b/Documentation/libtracefs-hist.txt @@ -245,6 +245,7 @@ EXAMPLE [source,c] -- #include +#include #include enum commands { @@ -256,63 +257,184 @@ enum commands { SHOW, }; -int main (int argc, char **argv, char **env) +static void parse_system_event(char *group, char **system, char **event) +{ + *system = strtok(group, "/"); + *event = strtok(NULL, "/"); + if (!*event) { + *event = *system; + *system = NULL; + } +} + +static int parse_keys(char *keys, struct tracefs_hist_axis **axes) +{ + char *sav = NULL; + char *key; + int cnt = 0; + + for (key = strtok_r(keys, ",", &sav); key; key = strtok_r(NULL, ",", &sav)) { + struct tracefs_hist_axis *ax; + char *att; + + ax = realloc(*axes, sizeof(*ax) * (cnt + 2)); + if (!ax) { + perror("Failed to allocate axes"); + exit(-1); + } + ax[cnt].key = key; + ax[cnt].type = 0; + ax[cnt + 1].key = NULL; + ax[cnt + 1].type = 0; + + *axes = ax; + + att = strchr(key, '.'); + if (att) { + *att++ = '\0'; + if (strcmp(att, "hex") == 0) + ax[cnt].type = TRACEFS_HIST_KEY_HEX; + else if (strcmp(att, "sym") == 0) + ax[cnt].type = TRACEFS_HIST_KEY_SYM; + else if (strcmp(att, "sym_offset") == 0) + ax[cnt].type = TRACEFS_HIST_KEY_SYM_OFFSET; + else if (strcmp(att, "syscall") == 0) + ax[cnt].type = TRACEFS_HIST_KEY_SYSCALL; + else if (strcmp(att, "exec") == 0) + ax[cnt].type = TRACEFS_HIST_KEY_EXECNAME; + else if (strcmp(att, "log") == 0) + ax[cnt].type = TRACEFS_HIST_KEY_LOG; + else if (strcmp(att, "usecs") == 0) + ax[cnt].type = TRACEFS_HIST_KEY_USECS; + else { + fprintf(stderr, "Undefined attribute '%s'\n", att); + fprintf(stderr," Acceptable attributes:\n"); + fprintf(stderr," hex, sym, sym_offset, syscall, exe, log, usecs\n"); + exit(-1); + } + } + cnt++; + } + return cnt; +} + +static void process_hist(enum commands cmd, const char *instance_name, + char *group, char *keys, char *vals, char *sort, + char *ascend, char *desc) { - struct tracefs_instance *instance; + struct tracefs_instance *instance = NULL; struct tracefs_hist *hist; struct tep_handle *tep; - enum commands cmd; - char *cmd_str; + struct tracefs_hist_axis *axes = NULL; + char *system; + char *event; + char *sav; + char *val; int ret; + int cnt; - if (argc < 2) { - fprintf(stderr, "usage: %s command\n", argv[0]); + if (instance_name) { + instance = tracefs_instance_create(instance_name); + if (!instance) { + fprintf(stderr, "Failed instance create\n"); + exit(-1); + } + } + + tep = tracefs_local_events(NULL); + if (!tep) { + perror("Could not read events"); exit(-1); } - cmd_str = argv[1]; + parse_system_event(group, &system, &event); - if (!strcmp(cmd_str, "start")) - cmd = START; - else if (!strcmp(cmd_str, "pause")) - cmd = PAUSE; - else if (!strcmp(cmd_str, "cont")) - cmd = CONT; - else if (!strcmp(cmd_str, "reset")) - cmd = RESET; - else if (!strcmp(cmd_str, "delete")) - cmd = DELETE; - else if (!strcmp(cmd_str, "show")) - cmd = SHOW; - else { - fprintf(stderr, "Unknown command %s\n", cmd_str); + if (cmd == SHOW) { + char *content; + content = tracefs_event_file_read(instance, system, event, + "hist", NULL); + if (!content) { + perror("Reading hist file"); + exit(-1); + } + printf("%s\n", content); + free(content); + return; + } + + if (!keys) { + fprintf(stderr, "Command needs -k option\n"); exit(-1); } - instance = tracefs_instance_create("hist_test"); - if (!instance) { - fprintf(stderr, "Failed instance create\n"); + cnt = parse_keys(keys, &axes); + if (!cnt) { + fprintf(stderr, "No keys??\n"); exit(-1); } - tep = tracefs_local_events(NULL); - hist = tracefs_hist2d_alloc(tep, "kmem", "kmalloc", - "call_site", TRACEFS_HIST_KEY_SYM, - "bytes_req", 0); + /* Show examples of hist1d and hist2d */ + switch (cnt) { + case 1: + hist = tracefs_hist1d_alloc(tep, system, event, + axes[0].key, axes[0].type); + break; + case 2: + hist = tracefs_hist2d_alloc(tep, system, event, + axes[0].key, axes[0].type, + axes[1].key, axes[1].type); + break; + default: + /* Really, 1 and 2 could use this too */ + hist = tracefs_hist_alloc(tep, system, event, axes); + } if (!hist) { fprintf(stderr, "Failed hist create\n"); exit(-1); } - ret = tracefs_hist_add_value(hist, "bytes_alloc"); - ret |= tracefs_hist_add_sort_key(hist, "bytes_req"); - ret |= tracefs_hist_add_sort_key(hist, "bytes_alloc"); + if (vals) { + sav = NULL; + for (val = strtok_r(vals, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { + ret = tracefs_hist_add_value(hist, val); + if (ret) { + fprintf(stderr, "Failed to add value %s\n", val); + exit(-1); + } + } + } - ret |= tracefs_hist_sort_key_direction(hist, "bytes_alloc", - TRACEFS_HIST_SORT_DESCENDING); - if (ret) { - fprintf(stderr, "Failed modifying histogram\n"); - exit(-1); + if (sort) { + sav = NULL; + for (val = strtok_r(sort, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { + ret = tracefs_hist_add_sort_key(hist, val); + if (ret) { + fprintf(stderr, "Failed to add sort key/val %s\n", val); + exit(-1); + } + } + } + + if (ascend) { + sav = NULL; + for (val = strtok_r(ascend, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { + ret = tracefs_hist_sort_key_direction(hist, val, TRACEFS_HIST_SORT_ASCENDING); + if (ret) { + fprintf(stderr, "Failed to add ascending key/val %s\n", val); + exit(-1); + } + } + } + + if (desc) { + sav = NULL; + for (val = strtok_r(desc, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { + ret = tracefs_hist_sort_key_direction(hist, val, TRACEFS_HIST_SORT_DESCENDING); + if (ret) { + fprintf(stderr, "Failed to add descending key/val %s\n", val); + exit(-1); + } + } } tracefs_error_clear(instance); @@ -338,22 +460,96 @@ int main (int argc, char **argv, char **env) case DELETE: ret = tracefs_hist_destroy(instance, hist); break; - case SHOW: { - char *content; - content = tracefs_event_file_read(instance, "kmem", "kmalloc", - "hist", NULL); - ret = content ? 0 : -1; - if (content) { - printf("%s\n", content); - free(content); - } + case SHOW: + /* Show was already done */ break; } - } if (ret) fprintf(stderr, "Failed: command\n"); exit(ret); } + +int main (int argc, char **argv, char **env) +{ + enum commands cmd; + char *instance = NULL; + char *cmd_str; + char *event = NULL; + char *keys = NULL; + char *vals = NULL; + char *sort = NULL; + char *desc = NULL; + char *ascend = NULL; + + if (argc < 2) { + fprintf(stderr, "usage: %s command [-B instance][-e [system/]event][-k keys][-v vals][-s sort]\n", argv[0]); + fprintf(stderr, " [-a ascending][-d descending]\n"); + exit(-1); + } + + cmd_str = argv[1]; + + if (!strcmp(cmd_str, "start")) + cmd = START; + else if (!strcmp(cmd_str, "pause")) + cmd = PAUSE; + else if (!strcmp(cmd_str, "cont")) + cmd = CONT; + else if (!strcmp(cmd_str, "reset")) + cmd = RESET; + else if (!strcmp(cmd_str, "delete")) + cmd = DELETE; + else if (!strcmp(cmd_str, "show")) + cmd = SHOW; + else { + fprintf(stderr, "Unknown command %s\n", cmd_str); + exit(-1); + } + + for (;;) { + int c; + + c = getopt(argc - 1, argv + 1, "e:k:v:B:s:d:a:"); + if (c == -1) + break; + + switch (c) { + case 'e': + event = optarg; + break; + case 'k': + keys = optarg; + break; + case 'v': + vals = optarg; + break; + case 'B': + instance = optarg; + break; + case 's': + sort = optarg; + break; + case 'd': + desc = optarg; + break; + case 'a': + ascend = optarg; + break; + } + } + if (!event) { + event = "kmem/kmalloc"; + if (!keys) + keys = "call_site.sym,bytes_req"; + if (!vals) + vals = "bytes_alloc"; + if (!sort) + sort = "bytes_req,bytes_alloc"; + if (!desc) + desc = "bytes_alloc"; + } + process_hist(cmd, instance, event, keys, vals, sort, ascend, desc); +} -- FILES