From 7da738b69a40714f8ab8a3723b5875f5ec38a44d Mon Sep 17 00:00:00 2001 From: Sebastien Godard Date: Fri, 11 Nov 2011 16:01:37 +0100 Subject: [PATCH] New output format added to sadf: JSON. JSON (JavaScript Object Notation) is a lightweight data interchange format (less verbose than XML). sadf can now display sar's data in JSON using a new switch (-j). --- Makefile.in | 8 +- activity.c | 37 + format.c | 16 +- json_stats.c | 2068 ++++++++++++++++++++++++++++++++++++++++++++++++++ json_stats.h | 91 +++ sa.h | 7 + sadf.c | 77 +- sadf.h | 16 +- sadf_misc.c | 216 ++++++ xml_stats.c | 108 +-- xml_stats.h | 4 +- 11 files changed, 2576 insertions(+), 72 deletions(-) create mode 100644 json_stats.c create mode 100644 json_stats.h diff --git a/Makefile.in b/Makefile.in index b8e36d1..d1ea853 100644 --- a/Makefile.in +++ b/Makefile.in @@ -170,7 +170,7 @@ act_sadc.o: activity.c sa.h rd_stats.h rd_sensors.h act_sar.o: activity.c sa.h pr_stats.h $(CC) -o $@ -c $(CFLAGS) -DSOURCE_SAR $(DFLAGS) $< -act_sadf.o: activity.c sa.h rndr_stats.h xml_stats.h +act_sadf.o: activity.c sa.h rndr_stats.h xml_stats.h json_stats.h $(CC) -o $@ -c $(CFLAGS) -DSOURCE_SADF $(DFLAGS) $< rd_stats.o: rd_stats.c common.h rd_stats.h ioconf.h sysconfig.h @@ -183,6 +183,8 @@ rndr_stats.o: rndr_stats.c sa.h ioconf.h sysconfig.h rndr_stats.h xml_stats.o: xml_stats.c sa.h sadf.h ioconf.h sysconfig.h xml_stats.h +json_stats.o: json_stats.c sa.h sadf.h ioconf.h sysconfig.h json_stats.h + sa_wrap.o: sa_wrap.c sa.h rd_stats.h rd_sensors.h format.o: format.c sadf.h @@ -207,9 +209,9 @@ sar.o: sar.c sa.h version.h common.h ioconf.h pr_stats.h sysconfig.h sar: sar.o act_sar.o sa_common.o pr_stats.o libsyscom.a -sadf.o: sadf.c sadf.h version.h sa.h common.h ioconf.h sysconfig.h rndr_stats.h xml_stats.h +sadf.o: sadf.c sadf.h version.h sa.h common.h ioconf.h sysconfig.h -sadf: sadf.o act_sadf.o format.o sadf_misc.o rndr_stats.o xml_stats.o sa_common.o libsyscom.a +sadf: sadf.o act_sadf.o format.o sadf_misc.o rndr_stats.o xml_stats.o json_stats.o sa_common.o libsyscom.a iostat.o: iostat.c iostat.h version.h common.h ioconf.h sysconfig.h rd_stats.h diff --git a/activity.c b/activity.c index 31baf6b..32c1e46 100644 --- a/activity.c +++ b/activity.c @@ -33,6 +33,7 @@ #ifdef SOURCE_SADF #include "rndr_stats.h" #include "xml_stats.h" +#include "json_stats.h" #endif /* @@ -83,6 +84,7 @@ struct activity cpu_act = { #ifdef SOURCE_SADF .f_render = render_cpu_stats, .f_xml_print = xml_print_cpu_stats, + .f_json_print = json_print_cpu_stats, .hdr_line = "CPU;%user;%nice;%system;%iowait;%steal;%idle|" "CPU;%usr;%nice;%sys;%iowait;%steal;%irq;%soft;%guest;%idle", .name = "A_CPU", @@ -114,6 +116,7 @@ struct activity pcsw_act = { #ifdef SOURCE_SADF .f_render = render_pcsw_stats, .f_xml_print = xml_print_pcsw_stats, + .f_json_print = json_print_pcsw_stats, .hdr_line = "proc/s;cswch/s", .name = "A_PCSW", #endif @@ -144,6 +147,7 @@ struct activity irq_act = { #ifdef SOURCE_SADF .f_render = render_irq_stats, .f_xml_print = xml_print_irq_stats, + .f_json_print = json_print_irq_stats, .hdr_line = "INTR;intr/s", .name = "A_IRQ", #endif @@ -174,6 +178,7 @@ struct activity swap_act = { #ifdef SOURCE_SADF .f_render = render_swap_stats, .f_xml_print = xml_print_swap_stats, + .f_json_print = json_print_swap_stats, .hdr_line = "pswpin/s;pswpout/s", .name = "A_SWAP", #endif @@ -204,6 +209,7 @@ struct activity paging_act = { #ifdef SOURCE_SADF .f_render = render_paging_stats, .f_xml_print = xml_print_paging_stats, + .f_json_print = json_print_paging_stats, .hdr_line = "pgpgin/s;pgpgout/s;fault/s;majflt/s;" "pgfree/s;pgscank/s;pgscand/s;pgsteal/s;%vmeff", .name = "A_PAGE", @@ -235,6 +241,7 @@ struct activity io_act = { #ifdef SOURCE_SADF .f_render = render_io_stats, .f_xml_print = xml_print_io_stats, + .f_json_print = json_print_io_stats, .hdr_line = "tps;rtps;wtps;bread/s;bwrtn/s", .name = "A_IO", #endif @@ -265,6 +272,7 @@ struct activity memory_act = { #ifdef SOURCE_SADF .f_render = render_memory_stats, .f_xml_print = xml_print_memory_stats, + .f_json_print = json_print_memory_stats, .hdr_line = "frmpg/s;bufpg/s;campg/s|" "kbmemfree;kbmemused;%memused;kbbuffers;kbcached;kbcommit;%commit;kbactive;kbinact|" "kbswpfree;kbswpused;%swpused;kbswpcad;%swpcad", @@ -297,6 +305,7 @@ struct activity ktables_act = { #ifdef SOURCE_SADF .f_render = render_ktables_stats, .f_xml_print = xml_print_ktables_stats, + .f_json_print = json_print_ktables_stats, .hdr_line = "dentunusd;file-nr;inode-nr;pty-nr", .name = "A_KTABLES", #endif @@ -327,6 +336,7 @@ struct activity queue_act = { #ifdef SOURCE_SADF .f_render = render_queue_stats, .f_xml_print = xml_print_queue_stats, + .f_json_print = json_print_queue_stats, .hdr_line = "runq-sz;plist-sz;ldavg-1;ldavg-5;ldavg-15;blocked", .name = "A_QUEUE", #endif @@ -357,6 +367,7 @@ struct activity serial_act = { #ifdef SOURCE_SADF .f_render = render_serial_stats, .f_xml_print = xml_print_serial_stats, + .f_json_print = json_print_serial_stats, .hdr_line = "TTY;rcvin/s;txmtin/s;framerr/s;prtyerr/s;brk/s;ovrun/s", .name = "A_SERIAL", #endif @@ -387,6 +398,7 @@ struct activity disk_act = { #ifdef SOURCE_SADF .f_render = render_disk_stats, .f_xml_print = xml_print_disk_stats, + .f_json_print = json_print_disk_stats, .hdr_line = "DEV;tps;rd_sec/s;wr_sec/s;avgrq-sz;avgqu-sz;await;svctm;%util", .name = "A_DISK", #endif @@ -417,6 +429,7 @@ struct activity net_dev_act = { #ifdef SOURCE_SADF .f_render = render_net_dev_stats, .f_xml_print = xml_print_net_dev_stats, + .f_json_print = json_print_net_dev_stats, .hdr_line = "IFACE;rxpck/s;txpck/s;rxkB/s;txkB/s;rxcmp/s;txcmp/s;rxmcst/s", .name = "A_NET_DEV", #endif @@ -447,6 +460,7 @@ struct activity net_edev_act = { #ifdef SOURCE_SADF .f_render = render_net_edev_stats, .f_xml_print = xml_print_net_edev_stats, + .f_json_print = json_print_net_edev_stats, .hdr_line = "IFACE;rxerr/s;txerr/s;coll/s;rxdrop/s;txdrop/s;" "txcarr/s;rxfram/s;rxfifo/s;txfifo/s", .name = "A_NET_EDEV", @@ -478,6 +492,7 @@ struct activity net_nfs_act = { #ifdef SOURCE_SADF .f_render = render_net_nfs_stats, .f_xml_print = xml_print_net_nfs_stats, + .f_json_print = json_print_net_nfs_stats, .hdr_line = "call/s;retrans/s;read/s;write/s;access/s;getatt/s", .name = "A_NET_NFS", #endif @@ -508,6 +523,7 @@ struct activity net_nfsd_act = { #ifdef SOURCE_SADF .f_render = render_net_nfsd_stats, .f_xml_print = xml_print_net_nfsd_stats, + .f_json_print = json_print_net_nfsd_stats, .hdr_line = "scall/s;badcall/s;packet/s;udp/s;tcp/s;hit/s;miss/s;" "sread/s;swrite/s;saccess/s;sgetatt/s", .name = "A_NET_NFSD", @@ -539,6 +555,7 @@ struct activity net_sock_act = { #ifdef SOURCE_SADF .f_render = render_net_sock_stats, .f_xml_print = xml_print_net_sock_stats, + .f_json_print = json_print_net_sock_stats, .hdr_line = "totsck;tcpsck;udpsck;rawsck;ip-frag;tcp-tw", .name = "A_NET_SOCK", #endif @@ -569,6 +586,7 @@ struct activity net_ip_act = { #ifdef SOURCE_SADF .f_render = render_net_ip_stats, .f_xml_print = xml_print_net_ip_stats, + .f_json_print = json_print_net_ip_stats, .hdr_line = "irec/s;fwddgm/s;idel/s;orq/s;asmrq/s;asmok/s;fragok/s;fragcrt/s", .name = "A_NET_IP", #endif @@ -599,6 +617,7 @@ struct activity net_eip_act = { #ifdef SOURCE_SADF .f_render = render_net_eip_stats, .f_xml_print = xml_print_net_eip_stats, + .f_json_print = json_print_net_eip_stats, .hdr_line = "ihdrerr/s;iadrerr/s;iukwnpr/s;idisc/s;odisc/s;onort/s;asmf/s;fragf/s", .name = "A_NET_EIP", #endif @@ -629,6 +648,7 @@ struct activity net_icmp_act = { #ifdef SOURCE_SADF .f_render = render_net_icmp_stats, .f_xml_print = xml_print_net_icmp_stats, + .f_json_print = json_print_net_icmp_stats, .hdr_line = "imsg/s;omsg/s;iech/s;iechr/s;oech/s;oechr/s;itm/s;itmr/s;otm/s;" "otmr/s;iadrmk/s;iadrmkr/s;oadrmk/s;oadrmkr/s", .name = "A_NET_ICMP", @@ -660,6 +680,7 @@ struct activity net_eicmp_act = { #ifdef SOURCE_SADF .f_render = render_net_eicmp_stats, .f_xml_print = xml_print_net_eicmp_stats, + .f_json_print = json_print_net_eicmp_stats, .hdr_line = "ierr/s;oerr/s;idstunr/s;odstunr/s;itmex/s;otmex/s;" "iparmpb/s;oparmpb/s;isrcq/s;osrcq/s;iredir/s;oredir/s", .name = "A_NET_EICMP", @@ -691,6 +712,7 @@ struct activity net_tcp_act = { #ifdef SOURCE_SADF .f_render = render_net_tcp_stats, .f_xml_print = xml_print_net_tcp_stats, + .f_json_print = json_print_net_tcp_stats, .hdr_line = "active/s;passive/s;iseg/s;oseg/s", .name = "A_NET_TCP", #endif @@ -721,6 +743,7 @@ struct activity net_etcp_act = { #ifdef SOURCE_SADF .f_render = render_net_etcp_stats, .f_xml_print = xml_print_net_etcp_stats, + .f_json_print = json_print_net_etcp_stats, .hdr_line = "atmptf/s;estres/s;retrans/s;isegerr/s;orsts/s", .name = "A_NET_ETCP", #endif @@ -751,6 +774,7 @@ struct activity net_udp_act = { #ifdef SOURCE_SADF .f_render = render_net_udp_stats, .f_xml_print = xml_print_net_udp_stats, + .f_json_print = json_print_net_udp_stats, .hdr_line = "idgm/s;odgm/s;noport/s;idgmerr/s", .name = "A_NET_UDP", #endif @@ -781,6 +805,7 @@ struct activity net_sock6_act = { #ifdef SOURCE_SADF .f_render = render_net_sock6_stats, .f_xml_print = xml_print_net_sock6_stats, + .f_json_print = json_print_net_sock6_stats, .hdr_line = "tcp6sck;udp6sck;raw6sck;ip6-frag", .name = "A_NET_SOCK6", #endif @@ -811,6 +836,7 @@ struct activity net_ip6_act = { #ifdef SOURCE_SADF .f_render = render_net_ip6_stats, .f_xml_print = xml_print_net_ip6_stats, + .f_json_print = json_print_net_ip6_stats, .hdr_line = "irec6/s;fwddgm6/s;idel6/s;orq6/s;asmrq6/s;asmok6/s;" "imcpck6/s;omcpck6/s;fragok6/s;fragcr6/s", .name = "A_NET_IP6", @@ -842,6 +868,7 @@ struct activity net_eip6_act = { #ifdef SOURCE_SADF .f_render = render_net_eip6_stats, .f_xml_print = xml_print_net_eip6_stats, + .f_json_print = json_print_net_eip6_stats, .hdr_line = "ihdrer6/s;iadrer6/s;iukwnp6/s;i2big6/s;idisc6/s;odisc6/s;" "inort6/s;onort6/s;asmf6/s;fragf6/s;itrpck6/s", .name = "A_NET_EIP6", @@ -873,6 +900,7 @@ struct activity net_icmp6_act = { #ifdef SOURCE_SADF .f_render = render_net_icmp6_stats, .f_xml_print = xml_print_net_icmp6_stats, + .f_json_print = json_print_net_icmp6_stats, .hdr_line = "imsg6/s;omsg6/s;iech6/s;iechr6/s;oechr6/s;igmbq6/s;igmbr6/s;ogmbr6/s;" "igmbrd6/s;ogmbrd6/s;irtsol6/s;ortsol6/s;irtad6/s;inbsol6/s;onbsol6/s;" "inbad6/s;onbad6/s", @@ -905,6 +933,7 @@ struct activity net_eicmp6_act = { #ifdef SOURCE_SADF .f_render = render_net_eicmp6_stats, .f_xml_print = xml_print_net_eicmp6_stats, + .f_json_print = json_print_net_eicmp6_stats, .hdr_line = "ierr6/s;idtunr6/s;odtunr6/s;itmex6/s;otmex6/s;" "iprmpb6/s;oprmpb6/s;iredir6/s;oredir6/s;ipck2b6/s;opck2b6/s", .name = "A_NET_EICMP6", @@ -936,6 +965,7 @@ struct activity net_udp6_act = { #ifdef SOURCE_SADF .f_render = render_net_udp6_stats, .f_xml_print = xml_print_net_udp6_stats, + .f_json_print = json_print_net_udp6_stats, .hdr_line = "idgm6/s;odgm6/s;noport6/s;idgmer6/s", .name = "A_NET_UDP6", #endif @@ -966,6 +996,7 @@ struct activity pwr_cpufreq_act = { #ifdef SOURCE_SADF .f_render = render_pwr_cpufreq_stats, .f_xml_print = xml_print_pwr_cpufreq_stats, + .f_json_print = json_print_pwr_cpufreq_stats, .hdr_line = "CPU;MHz", .name = "A_PWR_CPUFREQ", #endif @@ -996,6 +1027,7 @@ struct activity pwr_fan_act = { #ifdef SOURCE_SADF .f_render = render_pwr_fan_stats, .f_xml_print = xml_print_pwr_fan_stats, + .f_json_print = json_print_pwr_fan_stats, .hdr_line = "FAN;DEVICE;rpm;drpm", .name = "A_PWR_FAN", #endif @@ -1026,6 +1058,7 @@ struct activity pwr_temp_act = { #ifdef SOURCE_SADF .f_render = render_pwr_temp_stats, .f_xml_print = xml_print_pwr_temp_stats, + .f_json_print = json_print_pwr_temp_stats, .hdr_line = "TEMP;DEVICE;degC;%temp", .name = "A_PWR_TEMP", #endif @@ -1056,6 +1089,7 @@ struct activity pwr_in_act = { #ifdef SOURCE_SADF .f_render = render_pwr_in_stats, .f_xml_print = xml_print_pwr_in_stats, + .f_json_print = json_print_pwr_in_stats, .hdr_line = "IN;DEVICE;inV;%in", .name = "A_PWR_IN", #endif @@ -1086,6 +1120,7 @@ struct activity huge_act = { #ifdef SOURCE_SADF .f_render = render_huge_stats, .f_xml_print = xml_print_huge_stats, + .f_json_print = json_print_huge_stats, .hdr_line = "kbhugfree;kbhugused;%hugused", .name = "A_HUGE", #endif @@ -1116,6 +1151,7 @@ struct activity pwr_wghfreq_act = { #ifdef SOURCE_SADF .f_render = render_pwr_wghfreq_stats, .f_xml_print = xml_print_pwr_wghfreq_stats, + .f_json_print = json_print_pwr_wghfreq_stats, .hdr_line = "CPU;wghMHz", .name = "A_PWR_WGHFREQ", #endif @@ -1146,6 +1182,7 @@ struct activity pwr_usb_act = { #ifdef SOURCE_SADF .f_render = render_pwr_usb_stats, .f_xml_print = xml_print_pwr_usb_stats, + .f_json_print = json_print_pwr_usb_stats, .hdr_line = "manufact;product;BUS;idvendor;idprod;maxpower", .name = "A_PWR_USB", #endif diff --git a/format.c b/format.c index 07c2d98..15b4dd2 100644 --- a/format.c +++ b/format.c @@ -81,6 +81,19 @@ struct report_format xml_fmt = { .f_comment = print_xml_comment }; +/* + * JSON output. + */ +struct report_format json_fmt = { + .id = F_JSON_OUTPUT, + .options = FO_HEADER_ONLY + FO_TRUE_TIME, + .f_header = print_json_header, + .f_statistics = print_json_statistics, + .f_timestamp = print_json_timestamp, + .f_restart = print_json_restart, + .f_comment = print_json_comment +}; + /* * Array of output formats. */ @@ -88,5 +101,6 @@ struct report_format *fmt[NR_FMT] = { &hdr_fmt, &db_fmt, &ppc_fmt, - &xml_fmt + &xml_fmt, + &json_fmt }; diff --git a/json_stats.c b/json_stats.c new file mode 100644 index 0000000..3acd18f --- /dev/null +++ b/json_stats.c @@ -0,0 +1,2068 @@ +/* + * json_stats.c: Funtions used by sadf to display statistics in JSON format. + * (C) 1999-2011 by Sebastien GODARD (sysstat orange.fr) + * + *************************************************************************** + * This program is free software; you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; either version 2 of the License, or (at your * + * option) any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + *************************************************************************** + */ + +#include +#include +#include + +#include "sa.h" +#include "sadf.h" +#include "ioconf.h" +#include "json_stats.h" + +#ifdef USE_NLS +#include +#include +#define _(string) gettext(string) +#else +#define _(string) (string) +#endif + +extern unsigned int flags; +extern unsigned int dm_major; + +/* + *************************************************************************** + * Open or close "network" markup. + * + * IN: + * @tab Number of tabulations. + * @action Open or close action. + *************************************************************************** + */ +void json_markup_network(int tab, int action) +{ + static int markup_state = CLOSE_JSON_MARKUP; + + if (action == markup_state) + return; + markup_state = action; + + if (action == OPEN_JSON_MARKUP) { + /* Open markup */ + xprintf(tab, "\"network\": {"); + } + else { + /* Close markup */ + printf("\n"); + xprintf0(tab, "}"); + } +} + +/* + *************************************************************************** + * Open or close "power-management" markup. + * + * IN: + * @tab Number of tabulations. + * @action Open or close action. + *************************************************************************** + */ +void json_markup_power_management(int tab, int action) +{ + static int markup_state = CLOSE_JSON_MARKUP; + + if (action == markup_state) + return; + markup_state = action; + + if (action == OPEN_JSON_MARKUP) { + /* Open markup */ + xprintf(tab, "\"power-management\": {"); + } + else { + /* Close markup */ + printf("\n"); + xprintf0(tab, "}"); + } +} + +/* + *************************************************************************** + * Display CPU statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @g_itv Interval of time in jiffies mutliplied by the number of + * processors. + *************************************************************************** + */ +__print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab, + unsigned long long g_itv) +{ + int i, cpu_offline; + int sep = FALSE; + struct stats_cpu *scc, *scp; + char cpuno[8]; + + if (DISPLAY_CPU_DEF(a->opt_flags)) { + xprintf(tab++, "\"cpu-load\": ["); + } + else if (DISPLAY_CPU_ALL(a->opt_flags)) { + xprintf(tab++, "\"cpu-load-all\": ["); + } + + for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) { + + scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize); + scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize); + + /* Should current CPU (including CPU "all") be displayed? */ + if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) { + + /* Yes: Display current CPU stats */ + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + if (!i) { + /* This is CPU "all" */ + strcpy(cpuno, "all"); + } + else { + sprintf(cpuno, "%d", i - 1); + + /* + * If the CPU is offline then it is omited from /proc/stat: + * All the fields couldn't have been read and the sum of them is zero. + * (Remember that guest time is already included in user mode.) + */ + if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys + + scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal + + scc->cpu_hardirq + scc->cpu_softirq) == 0) { + /* + * Set current struct fields (which have been set to zero) + * to values from previous iteration. Hence their values won't + * jump from zero when the CPU comes back online. + */ + *scc = *scp; + + g_itv = 0; + cpu_offline = TRUE; + } + else { + /* + * Recalculate interval for current proc. + * If result is 0 then current CPU is a tickless one. + */ + g_itv = get_per_cpu_interval(scc, scp); + cpu_offline = FALSE; + } + + if (!g_itv) { + /* Current CPU is offline or tickless */ + if (DISPLAY_CPU_DEF(a->opt_flags)) { + xprintf0(tab, "{\"cpu\": \"%d\", " + "\"user\": %.2f, " + "\"nice\": %.2f, " + "\"system\": %.2f, " + "\"iowait\": %.2f, " + "\"steal\": %.2f, " + "\"idle\": %.2f}", + i - 1, 0.0, 0.0, 0.0, 0.0, 0.0, + cpu_offline ? 0.0 : 100.0); + } + else if (DISPLAY_CPU_ALL(a->opt_flags)) { + xprintf0(tab, "{\"cpu\": \"%d\", " + "\"usr\": %.2f, " + "\"nice\": %.2f, " + "\"sys\": %.2f, " + "\"iowait\": %.2f, " + "\"steal\": %.2f, " + "\"irq\": %.2f, " + "\"soft\": %.2f, " + "\"guest\": %.2f, " + "\"idle\": %.2f}", + i - 1, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + cpu_offline ? 0.0 : 100.0); + } + continue; + } + } + + if (DISPLAY_CPU_DEF(a->opt_flags)) { + xprintf0(tab, "{\"cpu\": \"%s\", " + "\"user\": %.2f, " + "\"nice\": %.2f, " + "\"system\": %.2f, " + "\"iowait\": %.2f, " + "\"steal\": %.2f, " + "\"idle\": %.2f}", + cpuno, + ll_sp_value(scp->cpu_user, scc->cpu_user, g_itv), + ll_sp_value(scp->cpu_nice, scc->cpu_nice, g_itv), + ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq, + scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq, + g_itv), + ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv), + ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv), + scc->cpu_idle < scp->cpu_idle ? + 0.0 : + ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv)); + } + else if (DISPLAY_CPU_ALL(a->opt_flags)) { + xprintf0(tab, "{\"cpu\": \"%s\", " + "\"usr\": %.2f, " + "\"nice\": %.2f, " + "\"sys\": %.2f, " + "\"iowait\": %.2f, " + "\"steal\": %.2f, " + "\"irq\": %.2f, " + "\"soft\": %.2f, " + "\"guest\": %.2f, " + "\"idle\": %.2f}", + cpuno, + (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ? + 0.0 : + ll_sp_value(scp->cpu_user - scp->cpu_guest, + scc->cpu_user - scc->cpu_guest, g_itv), + ll_sp_value(scp->cpu_nice, scc->cpu_nice, g_itv), + ll_sp_value(scp->cpu_sys, scc->cpu_sys, g_itv), + ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv), + ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv), + ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, g_itv), + ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, g_itv), + ll_sp_value(scp->cpu_guest, scc->cpu_guest, g_itv), + scc->cpu_idle < scp->cpu_idle ? + 0.0 : + ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv)); + } + } + } + + printf("\n"); + xprintf0(--tab, "]"); +} + +/* + *************************************************************************** + * Display task creation and context switch statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_pcsw_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_pcsw + *spc = (struct stats_pcsw *) a->buf[curr], + *spp = (struct stats_pcsw *) a->buf[!curr]; + + /* proc/s and cswch/s */ + xprintf0(tab, "\"process-and-context-switch\": {" + "\"proc\": %.2f, " + "\"cswch\": %.2f}", + S_VALUE(spp->processes, spc->processes, itv), + ll_s_value(spp->context_switch, spc->context_switch, itv)); +} + +/* + *************************************************************************** + * Display interrupts statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_irq_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i; + struct stats_irq *sic, *sip; + int sep = FALSE; + char irqno[8]; + + xprintf(tab++, "\"interrupts\": ["); + + for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) { + + sic = (struct stats_irq *) ((char *) a->buf[curr] + i * a->msize); + sip = (struct stats_irq *) ((char *) a->buf[!curr] + i * a->msize); + + /* Should current interrupt (including int "sum") be displayed? */ + if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) { + + /* Yes: Display it */ + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + if (!i) { + /* This is interrupt "sum" */ + strcpy(irqno, "sum"); + } + else { + sprintf(irqno, "%d", i - 1); + } + + xprintf0(tab, "{\"intr\": \"%s\", " + "\"value\": %.2f}", + irqno, + ll_s_value(sip->irq_nr, sic->irq_nr, itv)); + } + } + + printf("\n"); + xprintf0(--tab, "]"); +} + +/* + *************************************************************************** + * Display swapping statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_swap_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_swap + *ssc = (struct stats_swap *) a->buf[curr], + *ssp = (struct stats_swap *) a->buf[!curr]; + + xprintf0(tab, "\"swap-pages\": {" + "\"pswpin\": %.2f, " + "\"pswpout\": %.2f}", + S_VALUE(ssp->pswpin, ssc->pswpin, itv), + S_VALUE(ssp->pswpout, ssc->pswpout, itv)); +} + +/* + *************************************************************************** + * Display paging statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_paging_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_paging + *spc = (struct stats_paging *) a->buf[curr], + *spp = (struct stats_paging *) a->buf[!curr]; + + xprintf0(tab, "\"paging\": {" + "\"pgpgin\": %.2f, " + "\"pgpgout\": %.2f, " + "\"fault\": %.2f, " + "\"majflt\": %.2f, " + "\"pgfree\": %.2f, " + "\"pgscank\": %.2f, " + "\"pgscand\": %.2f, " + "\"pgsteal\": %.2f, " + "\"vmeff-percent\": %.2f}", + S_VALUE(spp->pgpgin, spc->pgpgin, itv), + S_VALUE(spp->pgpgout, spc->pgpgout, itv), + S_VALUE(spp->pgfault, spc->pgfault, itv), + S_VALUE(spp->pgmajfault, spc->pgmajfault, itv), + S_VALUE(spp->pgfree, spc->pgfree, itv), + S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv), + S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv), + S_VALUE(spp->pgsteal, spc->pgsteal, itv), + (spc->pgscan_kswapd + spc->pgscan_direct - + spp->pgscan_kswapd - spp->pgscan_direct) ? + SP_VALUE(spp->pgsteal, spc->pgsteal, + spc->pgscan_kswapd + spc->pgscan_direct - + spp->pgscan_kswapd - spp->pgscan_direct) : 0.0); +} + +/* + *************************************************************************** + * Display I/O and transfer rate statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_io_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_io + *sic = (struct stats_io *) a->buf[curr], + *sip = (struct stats_io *) a->buf[!curr]; + + xprintf0(tab, "\"io\": {" + "\"tps\": %.2f, " + "\"io-reads\": {" + "\"rtps\": %.2f, " + "\"bread\": %.2f}, " + "\"io-writes\": {" + "\"wtps\": %.2f, " + "\"bwrtn\": %.2f}}", + S_VALUE(sip->dk_drive, sic->dk_drive, itv), + S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv), + S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv), + S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv), + S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv)); +} + +/* + *************************************************************************** + * Display memory statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_memory_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_memory + *smc = (struct stats_memory *) a->buf[curr], + *smp = (struct stats_memory *) a->buf[!curr]; + int sep = FALSE; + + xprintf0(tab, "\"memory\": {"); + + if (DISPLAY_MEM_AMT(a->opt_flags)) { + + sep = TRUE; + + printf("\"memfree\": %lu, " + "\"memused\": %lu, " + "\"memused-percent\": %.2f, " + "\"buffers\": %lu, " + "\"cached\": %lu, " + "\"commit\": %lu, " + "\"commit-percent\": %.2f, " + "\"active\": %lu, " + "\"inactive\": %lu", + smc->frmkb, + smc->tlmkb - smc->frmkb, + smc->tlmkb ? + SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : + 0.0, + smc->bufkb, + smc->camkb, + smc->comkb, + (smc->tlmkb + smc->tlskb) ? + SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : + 0.0, + smc->activekb, + smc->inactkb); + } + + if (DISPLAY_SWAP(a->opt_flags)) { + + if (sep) { + printf(", "); + } + sep = TRUE; + + printf("\"swpfree\": %lu, " + "\"swpused\": %lu, " + "\"swpused-percent\": %.2f, " + "\"swpcad\": %lu, " + "\"swpcad-percent\": %.2f", + smc->frskb, + smc->tlskb - smc->frskb, + smc->tlskb ? + SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : + 0.0, + smc->caskb, + (smc->tlskb - smc->frskb) ? + SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : + 0.0); + } + + if (DISPLAY_MEMORY(a->opt_flags)) { + + if (sep) { + printf(", "); + } + + printf("\"frmpg\": %.2f, " + "\"bufpg\": %.2f, " + "\"campg\": %.2f", + S_VALUE((double) KB_TO_PG(smp->frmkb), + (double) KB_TO_PG(smc->frmkb), itv), + S_VALUE((double) KB_TO_PG(smp->bufkb), + (double) KB_TO_PG(smc->bufkb), itv), + S_VALUE((double) KB_TO_PG(smp->camkb), + (double) KB_TO_PG(smc->camkb), itv)); + } + + printf("}"); +} + +/* + *************************************************************************** + * Display kernel tables statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_ktables_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_ktables + *skc = (struct stats_ktables *) a->buf[curr]; + + xprintf0(tab, "\"kernel\": {" + "\"dentunusd\": %u, " + "\"file-nr\": %u, " + "\"inode-nr\": %u, " + "\"pty-nr\": %u}", + skc->dentry_stat, + skc->file_used, + skc->inode_used, + skc->pty_nr); +} + +/* + *************************************************************************** + * Display queue and load statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_queue_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_queue + *sqc = (struct stats_queue *) a->buf[curr]; + + xprintf0(tab, "\"queue\": {" + "\"runq-sz\": %lu, " + "\"plist-sz\": %u, " + "\"ldavg-1\": %.2f, " + "\"ldavg-5\": %.2f, " + "\"ldavg-15\": %.2f, " + "\"blocked\": %lu}", + sqc->nr_running, + sqc->nr_threads, + (double) sqc->load_avg_1 / 100, + (double) sqc->load_avg_5 / 100, + (double) sqc->load_avg_15 / 100, + sqc->procs_blocked); +} + +/* + *************************************************************************** + * Display serial lines statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_serial_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i; + struct stats_serial *ssc, *ssp; + int sep = FALSE; + + xprintf(tab++, "\"serial\": ["); + + for (i = 0; i < a->nr; i++) { + + ssc = (struct stats_serial *) ((char *) a->buf[curr] + i * a->msize); + ssp = (struct stats_serial *) ((char *) a->buf[!curr] + i * a->msize); + + if (ssc->line == 0) + continue; + + if (ssc->line == ssp->line) { + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + xprintf0(tab, "{\"line\": %d, " + "\"rcvin\": %.2f, " + "\"xmtin\": %.2f, " + "\"framerr\": %.2f, " + "\"prtyerr\": %.2f, " + "\"brk\": %.2f, " + "\"ovrun\": %.2f}", + ssc->line - 1, + S_VALUE(ssp->rx, ssc->rx, itv), + S_VALUE(ssp->tx, ssc->tx, itv), + S_VALUE(ssp->frame, ssc->frame, itv), + S_VALUE(ssp->parity, ssc->parity, itv), + S_VALUE(ssp->brk, ssc->brk, itv), + S_VALUE(ssp->overrun, ssc->overrun, itv)); + } + } + + printf("\n"); + xprintf0(--tab, "]"); +} + +/* + *************************************************************************** + * Display disks statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_disk_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i, j; + struct stats_disk *sdc, *sdp; + struct ext_disk_stats xds; + int sep = FALSE; + char *dev_name; + + xprintf(tab++, "\"disk\": ["); + + for (i = 0; i < a->nr; i++) { + + sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize); + + if (!(sdc->major + sdc->minor)) + continue; + + j = check_disk_reg(a, curr, !curr, i); + sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize); + + /* Compute extended statistics values */ + compute_ext_disk_stats(sdc, sdp, itv, &xds); + + dev_name = NULL; + + if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) { + dev_name = transform_devmapname(sdc->major, sdc->minor); + } + + if (!dev_name) { + dev_name = get_devname(sdc->major, sdc->minor, + USE_PRETTY_OPTION(flags)); + } + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + xprintf0(tab, "{\"disk-device\": \"%s\", " + "\"tps\": %.2f, " + "\"rd_sec\": %.2f, " + "\"wr_sec\": %.2f, " + "\"avgrq-sz\": %.2f, " + "\"avgqu-sz\": %.2f, " + "\"await\": %.2f, " + "\"svctm\": %.2f, " + "\"util-percent\": %.2f}", + /* Confusion possible here between index and minor numbers */ + dev_name, + S_VALUE(sdp->nr_ios, sdc->nr_ios, itv), + ll_s_value(sdp->rd_sect, sdc->rd_sect, itv), + ll_s_value(sdp->wr_sect, sdc->wr_sect, itv), + /* See iostat for explanations */ + xds.arqsz, + S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0, + xds.await, + xds.svctm, + xds.util / 10.0); + } + + printf("\n"); + xprintf0(--tab, "]"); +} + +/* + *************************************************************************** + * Display network interfaces statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_dev_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i, j; + struct stats_net_dev *sndc, *sndp; + int sep = FALSE; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf(tab++, "\"net-dev\": ["); + + for (i = 0; i < a->nr; i++) { + + sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize); + + if (!strcmp(sndc->interface, "")) + continue; + + j = check_net_dev_reg(a, curr, !curr, i); + sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize); + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + xprintf0(tab, "{\"iface\": \"%s\", " + "\"rxpck\": %.2f, " + "\"txpck\": %.2f, " + "\"rxkB\": %.2f, " + "\"txkB\": %.2f, " + "\"rxcmp\": %.2f, " + "\"txcmp\": %.2f, " + "\"rxmcst\": %.2f}", + sndc->interface, + S_VALUE(sndp->rx_packets, sndc->rx_packets, itv), + S_VALUE(sndp->tx_packets, sndc->tx_packets, itv), + S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv) / 1024, + S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv) / 1024, + S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv), + S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv), + S_VALUE(sndp->multicast, sndc->multicast, itv)); + } + + printf("\n"); + xprintf0(--tab, "]"); + + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display network interfaces error statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_edev_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i, j; + struct stats_net_edev *snedc, *snedp; + int sep = FALSE; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf(tab++, "\"net-edev\": ["); + + for (i = 0; i < a->nr; i++) { + + snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize); + + if (!strcmp(snedc->interface, "")) + continue; + + j = check_net_edev_reg(a, curr, !curr, i); + snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize); + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + xprintf0(tab, "{\"iface\": \"%s\", " + "\"rxerr\": %.2f, " + "\"txerr\": %.2f, " + "\"coll\": %.2f, " + "\"rxdrop\": %.2f, " + "\"txdrop\": %.2f, " + "\"txcarr\": %.2f, " + "\"rxfram\": %.2f, " + "\"rxfifo\": %.2f, " + "\"txfifo\": %.2f}", + snedc->interface, + S_VALUE(snedp->rx_errors, snedc->rx_errors, itv), + S_VALUE(snedp->tx_errors, snedc->tx_errors, itv), + S_VALUE(snedp->collisions, snedc->collisions, itv), + S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv), + S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv), + S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv), + S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv), + S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv), + S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv)); + } + + printf("\n"); + xprintf0(--tab, "]"); + + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display NFS client statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_nfs_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_nfs + *snnc = (struct stats_net_nfs *) a->buf[curr], + *snnp = (struct stats_net_nfs *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-nfs\": {" + "\"call\": %.2f, " + "\"retrans\": %.2f, " + "\"read\": %.2f, " + "\"write\": %.2f, " + "\"access\": %.2f, " + "\"getatt\": %.2f}", + S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv), + S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv), + S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv), + S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv), + S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv), + S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display NFS server statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_nfsd_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_nfsd + *snndc = (struct stats_net_nfsd *) a->buf[curr], + *snndp = (struct stats_net_nfsd *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-nfsd\": {" + "\"scall\": %.2f, " + "\"badcall\": %.2f, " + "\"packet\": %.2f, " + "\"udp\": %.2f, " + "\"tcp\": %.2f, " + "\"hit\": %.2f, " + "\"miss\": %.2f, " + "\"sread\": %.2f, " + "\"swrite\": %.2f, " + "\"saccess\": %.2f, " + "\"sgetatt\": %.2f}", + S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv), + S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv), + S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv), + S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv), + S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv), + S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv), + S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv), + S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv), + S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv), + S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv), + S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display network socket statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_sock_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_sock + *snsc = (struct stats_net_sock *) a->buf[curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-sock\": {" + "\"totsck\": %u, " + "\"tcpsck\": %u, " + "\"udpsck\": %u, " + "\"rawsck\": %u, " + "\"ip-frag\": %u, " + "\"tcp-tw\": %u}", + snsc->sock_inuse, + snsc->tcp_inuse, + snsc->udp_inuse, + snsc->raw_inuse, + snsc->frag_inuse, + snsc->tcp_tw); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display IP network statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_ip_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_ip + *snic = (struct stats_net_ip *) a->buf[curr], + *snip = (struct stats_net_ip *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-ip\": {" + "\"irec\": %.2f, " + "\"fwddgm\": %.2f, " + "\"idel\": %.2f, " + "\"orq\": %.2f, " + "\"asmrq\": %.2f, " + "\"asmok\": %.2f, " + "\"fragok\": %.2f, " + "\"fragcrt\": %.2f}", + S_VALUE(snip->InReceives, snic->InReceives, itv), + S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv), + S_VALUE(snip->InDelivers, snic->InDelivers, itv), + S_VALUE(snip->OutRequests, snic->OutRequests, itv), + S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv), + S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv), + S_VALUE(snip->FragOKs, snic->FragOKs, itv), + S_VALUE(snip->FragCreates, snic->FragCreates, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display IP network error statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_eip_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_eip + *sneic = (struct stats_net_eip *) a->buf[curr], + *sneip = (struct stats_net_eip *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-eip\": {" + "\"ihdrerr\": %.2f, " + "\"iadrerr\": %.2f, " + "\"iukwnpr\": %.2f, " + "\"idisc\": %.2f, " + "\"odisc\": %.2f, " + "\"onort\": %.2f, " + "\"asmf\": %.2f, " + "\"fragf\": %.2f}", + S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv), + S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv), + S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv), + S_VALUE(sneip->InDiscards, sneic->InDiscards, itv), + S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv), + S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv), + S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv), + S_VALUE(sneip->FragFails, sneic->FragFails, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display ICMP network statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_icmp_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_icmp + *snic = (struct stats_net_icmp *) a->buf[curr], + *snip = (struct stats_net_icmp *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-icmp\": {" + "\"imsg\": %.2f, " + "\"omsg\": %.2f, " + "\"iech\": %.2f, " + "\"iechr\": %.2f, " + "\"oech\": %.2f, " + "\"oechr\": %.2f, " + "\"itm\": %.2f, " + "\"itmr\": %.2f, " + "\"otm\": %.2f, " + "\"otmr\": %.2f, " + "\"iadrmk\": %.2f, " + "\"iadrmkr\": %.2f, " + "\"oadrmk\": %.2f, " + "\"oadrmkr\": %.2f}", + S_VALUE(snip->InMsgs, snic->InMsgs, itv), + S_VALUE(snip->OutMsgs, snic->OutMsgs, itv), + S_VALUE(snip->InEchos, snic->InEchos, itv), + S_VALUE(snip->InEchoReps, snic->InEchoReps, itv), + S_VALUE(snip->OutEchos, snic->OutEchos, itv), + S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv), + S_VALUE(snip->InTimestamps, snic->InTimestamps, itv), + S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv), + S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv), + S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv), + S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv), + S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv), + S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv), + S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display ICMP error message statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_eicmp_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_eicmp + *sneic = (struct stats_net_eicmp *) a->buf[curr], + *sneip = (struct stats_net_eicmp *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-eicmp\": {" + "\"ierr\": %.2f, " + "\"oerr\": %.2f, " + "\"idstunr\": %.2f, " + "\"odstunr\": %.2f, " + "\"itmex\": %.2f, " + "\"otmex\": %.2f, " + "\"iparmpb\": %.2f, " + "\"oparmpb\": %.2f, " + "\"isrcq\": %.2f, " + "\"osrcq\": %.2f, " + "\"iredir\": %.2f, " + "\"oredir\": %.2f}", + S_VALUE(sneip->InErrors, sneic->InErrors, itv), + S_VALUE(sneip->OutErrors, sneic->OutErrors, itv), + S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv), + S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv), + S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv), + S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv), + S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv), + S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv), + S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv), + S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv), + S_VALUE(sneip->InRedirects, sneic->InRedirects, itv), + S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display TCP network statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_tcp_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_tcp + *sntc = (struct stats_net_tcp *) a->buf[curr], + *sntp = (struct stats_net_tcp *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-tcp\": {" + "\"active\": %.2f, " + "\"passive\": %.2f, " + "\"iseg\": %.2f, " + "\"oseg\": %.2f}", + S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv), + S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv), + S_VALUE(sntp->InSegs, sntc->InSegs, itv), + S_VALUE(sntp->OutSegs, sntc->OutSegs, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display TCP network error statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in XML output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_etcp_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_etcp + *snetc = (struct stats_net_etcp *) a->buf[curr], + *snetp = (struct stats_net_etcp *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-etcp\": {" + "\"atmptf\": %.2f, " + "\"estres\": %.2f, " + "\"retrans\": %.2f, " + "\"isegerr\": %.2f, " + "\"orsts\": %.2f}", + S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv), + S_VALUE(snetp->EstabResets, snetc->EstabResets, itv), + S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv), + S_VALUE(snetp->InErrs, snetc->InErrs, itv), + S_VALUE(snetp->OutRsts, snetc->OutRsts, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display UDP network statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_udp_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_udp + *snuc = (struct stats_net_udp *) a->buf[curr], + *snup = (struct stats_net_udp *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-udp\": {" + "\"idgm\": %.2f, " + "\"odgm\": %.2f, " + "\"noport\": %.2f, " + "\"idgmerr\": %.2f}", + S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv), + S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv), + S_VALUE(snup->NoPorts, snuc->NoPorts, itv), + S_VALUE(snup->InErrors, snuc->InErrors, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display IPv6 network socket statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_sock6_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_sock6 + *snsc = (struct stats_net_sock6 *) a->buf[curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-sock6\": {" + "\"tcp6sck\": %u, " + "\"udp6sck\": %u, " + "\"raw6sck\": %u, " + "\"ip6-frag\": %u}", + snsc->tcp6_inuse, + snsc->udp6_inuse, + snsc->raw6_inuse, + snsc->frag6_inuse); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display IPv6 network statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_ip6_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_ip6 + *snic = (struct stats_net_ip6 *) a->buf[curr], + *snip = (struct stats_net_ip6 *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-ip6\": {" + "\"irec6\": %.2f, " + "\"fwddgm6\": %.2f, " + "\"idel6\": %.2f, " + "\"orq6\": %.2f, " + "\"asmrq6\": %.2f, " + "\"asmok6\": %.2f, " + "\"imcpck6\": %.2f, " + "\"omcpck6\": %.2f, " + "\"fragok6\": %.2f, " + "\"fragcr6\": %.2f}", + S_VALUE(snip->InReceives6, snic->InReceives6, itv), + S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv), + S_VALUE(snip->InDelivers6, snic->InDelivers6, itv), + S_VALUE(snip->OutRequests6, snic->OutRequests6, itv), + S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv), + S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv), + S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv), + S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv), + S_VALUE(snip->FragOKs6, snic->FragOKs6, itv), + S_VALUE(snip->FragCreates6, snic->FragCreates6, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display IPv6 network error statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_eip6_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_eip6 + *sneic = (struct stats_net_eip6 *) a->buf[curr], + *sneip = (struct stats_net_eip6 *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-eip6\": {" + "\"ihdrer6\": %.2f, " + "\"iadrer6\": %.2f, " + "\"iukwnp6\": %.2f, " + "\"i2big6\": %.2f, " + "\"idisc6\": %.2f, " + "\"odisc6\": %.2f, " + "\"inort6\": %.2f, " + "\"onort6\": %.2f, " + "\"asmf6\": %.2f, " + "\"fragf6\": %.2f, " + "\"itrpck6\": %.2f}", + S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv), + S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv), + S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv), + S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv), + S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv), + S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv), + S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv), + S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv), + S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv), + S_VALUE(sneip->FragFails6, sneic->FragFails6, itv), + S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display ICMPv6 network statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_icmp6_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_icmp6 + *snic = (struct stats_net_icmp6 *) a->buf[curr], + *snip = (struct stats_net_icmp6 *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-icmp6\": {" + "\"imsg6\": %.2f, " + "\"omsg6\": %.2f, " + "\"iech6\": %.2f, " + "\"iechr6\": %.2f, " + "\"oechr6\": %.2f, " + "\"igmbq6\": %.2f, " + "\"igmbr6\": %.2f, " + "\"ogmbr6\": %.2f, " + "\"igmbrd6\": %.2f, " + "\"ogmbrd6\": %.2f, " + "\"irtsol6\": %.2f, " + "\"ortsol6\": %.2f, " + "\"irtad6\": %.2f, " + "\"inbsol6\": %.2f, " + "\"onbsol6\": %.2f, " + "\"inbad6\": %.2f, " + "\"onbad6\": %.2f}", + S_VALUE(snip->InMsgs6, snic->InMsgs6, itv), + S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv), + S_VALUE(snip->InEchos6, snic->InEchos6, itv), + S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv), + S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv), + S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv), + S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv), + S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv), + S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv), + S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv), + S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv), + S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv), + S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv), + S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv), + S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv), + S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv), + S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display ICMPv6 error message statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_eicmp6_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_eicmp6 + *sneic = (struct stats_net_eicmp6 *) a->buf[curr], + *sneip = (struct stats_net_eicmp6 *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-eicmp6\": {" + "\"ierr6\": %.2f, " + "\"idtunr6\": %.2f, " + "\"odtunr6\": %.2f, " + "\"itmex6\": %.2f, " + "\"otmex6\": %.2f, " + "\"iprmpb6\": %.2f, " + "\"oprmpb6\": %.2f, " + "\"iredir6\": %.2f, " + "\"oredir6\": %.2f, " + "\"ipck2b6\": %.2f, " + "\"opck2b6\": %.2f}", + S_VALUE(sneip->InErrors6, sneic->InErrors6, itv), + S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv), + S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv), + S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv), + S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv), + S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv), + S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv), + S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv), + S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv), + S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv), + S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display UDPv6 network statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_net_udp6_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_net_udp6 + *snuc = (struct stats_net_udp6 *) a->buf[curr], + *snup = (struct stats_net_udp6 *) a->buf[!curr]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_network(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf0(tab, "\"net-udp6\": {" + "\"idgm6\": %.2f, " + "\"odgm6\": %.2f, " + "\"noport6\": %.2f, " + "\"idgmer6\": %.2f}", + S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv), + S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv), + S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv), + S_VALUE(snup->InErrors6, snuc->InErrors6, itv)); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_network(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display CPU frequency statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_pwr_cpufreq_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i; + struct stats_pwr_cpufreq *spc; + int sep = FALSE; + char cpuno[8]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_power_management(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf(tab++, "\"cpu-frequency\": ["); + + for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) { + + spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize); + + /* Should current CPU (including CPU "all") be displayed? */ + if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) { + + /* Yes: Display it */ + if (!i) { + /* This is CPU "all" */ + strcpy(cpuno, "all"); + } + else { + sprintf(cpuno, "%d", i - 1); + } + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + xprintf0(tab, "{\"number\": \"%s\", " + "\"frequency\": %.2f}", + cpuno, + ((double) spc->cpufreq) / 100); + } + } + + printf("\n"); + xprintf0(--tab, "]"); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_power_management(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display fan statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_pwr_fan_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i; + struct stats_pwr_fan *spc; + int sep = FALSE; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_power_management(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf(tab++, "\"fan-speed\": ["); + + for (i = 0; i < a->nr; i++) { + spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize); + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + xprintf0(tab, "{\"number\": %d, " + "\"rpm\": %llu, " + "\"drpm\": %llu, " + "\"device\": \"%s\"}", + i + 1, + (unsigned long long) spc->rpm, + (unsigned long long) (spc->rpm - spc->rpm_min), + spc->device); + } + + printf("\n"); + xprintf0(--tab, "]"); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_power_management(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display temperature statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_pwr_temp_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i; + struct stats_pwr_temp *spc; + int sep = FALSE; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_power_management(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf(tab++, "\"temperature\": ["); + + for (i = 0; i < a->nr; i++) { + spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize); + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + xprintf0(tab, "{\"number\": %d, " + "\"degC\": %.2f, " + "\"percent-temp\": %.2f, " + "\"device\": \"%s\"}", + i + 1, + spc->temp, + (spc->temp_max - spc->temp_min) ? + (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 : + 0.0, + spc->device); + } + + printf("\n"); + xprintf0(--tab, "]"); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_power_management(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display voltage inputs statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_pwr_in_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i; + struct stats_pwr_in *spc; + int sep = FALSE; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_power_management(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf(tab++, "\"voltage-input\": ["); + + for (i = 0; i < a->nr; i++) { + spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize); + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + xprintf0(tab, "{\"number\": %d, " + "\"inV\": %.2f, " + "\"percent-in\": %.2f, " + "\"device\": \"%s\"}", + i, + spc->in, + (spc->in_max - spc->in_min) ? + (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 : + 0.0, + spc->device); + } + + printf("\n"); + xprintf0(--tab, "]"); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_power_management(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display huge pages statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_huge_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + struct stats_huge + *smc = (struct stats_huge *) a->buf[curr]; + + xprintf0(tab, "\"hugepages\": {" + "\"hugfree\": %lu, " + "\"hugused\": %lu, " + "\"hugused-percent\": %.2f}", + smc->frhkb, + smc->tlhkb - smc->frhkb, + smc->tlhkb ? + SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : + 0.0); +} + +/* + *************************************************************************** + * Display weighted CPU frequency statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_pwr_wghfreq_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i, k; + struct stats_pwr_wghfreq *spc, *spp, *spc_k, *spp_k; + unsigned long long tis, tisfreq; + int sep = FALSE; + char cpuno[8]; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_power_management(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf(tab++, "\"cpu-weighted-frequency\": ["); + + for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) { + + spc = (struct stats_pwr_wghfreq *) ((char *) a->buf[curr] + i * a->msize * a->nr2); + spp = (struct stats_pwr_wghfreq *) ((char *) a->buf[!curr] + i * a->msize * a->nr2); + + /* Should current CPU (including CPU "all") be displayed? */ + if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) { + + /* Yes... */ + tisfreq = 0; + tis = 0; + + for (k = 0; k < a->nr2; k++) { + + spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize); + if (!spc_k->freq) + break; + spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize); + + tisfreq += (spc_k->freq / 1000) * + (spc_k->time_in_state - spp_k->time_in_state); + tis += (spc_k->time_in_state - spp_k->time_in_state); + } + + if (!i) { + /* This is CPU "all" */ + strcpy(cpuno, "all"); + } + else { + sprintf(cpuno, "%d", i - 1); + } + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + xprintf0(tab, "{\"number\": \"%s\", " + "\"weighted-frequency\": %.2f}", + cpuno, + tis ? ((double) tisfreq) / tis : 0.0); + } + } + + printf("\n"); + xprintf0(--tab, "]"); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_power_management(tab, CLOSE_JSON_MARKUP); + } +} + +/* + *************************************************************************** + * Display USB devices statistics in JSON. + * + * IN: + * @a Activity structure with statistics. + * @curr Index in array for current sample statistics. + * @tab Indentation in output. + * @itv Interval of time in jiffies. + *************************************************************************** + */ +__print_funct_t json_print_pwr_usb_stats(struct activity *a, int curr, int tab, + unsigned long long itv) +{ + int i; + struct stats_pwr_usb *suc; + int sep = FALSE; + + if (!IS_SELECTED(a->options) || (a->nr <= 0)) + goto close_json_markup; + + json_markup_power_management(tab, OPEN_JSON_MARKUP); + tab++; + + xprintf(tab++, "\"usb-devices\": ["); + + for (i = 0; i < a->nr; i++) { + suc = (struct stats_pwr_usb *) ((char *) a->buf[curr] + i * a->msize); + + if (!suc->bus_nr) + /* Bus#0 doesn't exist: We are at the end of the list */ + break; + + if (sep) { + printf(",\n"); + } + sep = TRUE; + + xprintf0(tab, "{\"bus_number\": %d, " + "\"idvendor\": \"%x\", " + "\"idprod\": \"%x\", " + "\"maxpower\": %u, " + "\"manufact\": \"%s\", " + "\"product\": \"%s\"}", + suc->bus_nr, + suc->vendor_id, + suc->product_id, + suc->bmaxpower << 1, + suc->manufacturer, + suc->product); + } + + printf("\n"); + xprintf0(--tab, "]"); + tab--; + +close_json_markup: + if (CLOSE_MARKUP(a->options)) { + json_markup_power_management(tab, CLOSE_JSON_MARKUP); + } +} diff --git a/json_stats.h b/json_stats.h new file mode 100644 index 0000000..9f80445 --- /dev/null +++ b/json_stats.h @@ -0,0 +1,91 @@ +/* + * json_stats.h: Include file used to display system statistics in JSON format. + * (C) 1999-2011 by Sebastien Godard (sysstat orange.fr) + */ + +#ifndef _JSON_STATS_H +#define _JSON_STATS_H + +#include "common.h" + +/* + *************************************************************************** + * Prototypes for functions used to display system statistics in JSON. + *************************************************************************** + */ + +/* Functions used to display statistics in XML */ +extern __print_funct_t json_print_cpu_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_pcsw_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_irq_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_swap_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_paging_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_io_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_memory_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_ktables_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_queue_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_serial_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_disk_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_dev_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_edev_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_nfs_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_nfsd_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_sock_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_ip_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_eip_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_icmp_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_eicmp_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_tcp_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_etcp_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_udp_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_sock6_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_ip6_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_eip6_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_icmp6_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_eicmp6_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_net_udp6_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_pwr_cpufreq_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_pwr_fan_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_pwr_temp_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_pwr_in_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_huge_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_pwr_wghfreq_stats + (struct activity *, int, int, unsigned long long); +extern __print_funct_t json_print_pwr_usb_stats + (struct activity *, int, int, unsigned long long); + +#endif /* _XML_STATS_H */ diff --git a/sa.h b/sa.h index df1957e..f4ebe6f 100644 --- a/sa.h +++ b/sa.h @@ -217,6 +217,9 @@ #define CLOSE_XML_MARKUP 0 #define OPEN_XML_MARKUP 1 +#define CLOSE_JSON_MARKUP 0 +#define OPEN_JSON_MARKUP 1 + #define COUNT_ACTIVITIES 0 #define COUNT_OUTPUTS 1 @@ -362,6 +365,10 @@ struct activity { * This function is used by sadf to display activity statistics in XML. */ __print_funct_t (*f_xml_print) (struct activity *, int, int, unsigned long long); + /* + * This function is used by sadf to display activity statistics in JSON. + */ + __print_funct_t (*f_json_print) (struct activity *, int, int, unsigned long long); /* * Header string displayed by sadf -d/-D. */ diff --git a/sadf.c b/sadf.c index 348dfa3..1bc607c 100644 --- a/sadf.c +++ b/sadf.c @@ -32,8 +32,6 @@ #include "sa.h" #include "common.h" #include "ioconf.h" -#include "rndr_stats.h" -#include "xml_stats.h" #ifdef USE_NLS # include @@ -89,7 +87,7 @@ void usage(char *progname) progname); fprintf(stderr, _("Options are:\n" - "[ -d | -p | -x ] [ -C ] [ -H ] [ -h ] [ -T ] [ -t ] [ -V ]\n" + "[ -d | -j | -p | -x ] [ -C ] [ -H ] [ -h ] [ -T ] [ -t ] [ -V ]\n" "[ -P { [,...] | ALL } ] [ -s [ ] ] [ -e [ ] ]\n" "[ -- ]\n")); exit(1); @@ -275,7 +273,31 @@ void prtab(int nr_tab) /* *************************************************************************** - * printf() function modified for textual (XML-like) display. + * printf() function modified for textual (XML-like) display. Don't print a + * CR at the end of the line. + * + * IN: + * @nr_tab Number of tabs to print. + * @fmtf printf() format. + *************************************************************************** + */ +void xprintf0(int nr_tab, const char *fmtf, ...) +{ + static char buf[1024]; + va_list args; + + va_start(args, fmtf); + vsnprintf(buf, sizeof(buf), fmtf, args); + va_end(args); + + prtab(nr_tab); + printf("%s", buf); +} + +/* + *************************************************************************** + * printf() function modified for textual (XML-like) display. Print a CR + * at the end of the line. * * IN: * @nr_tab Number of tabs to print. @@ -681,16 +703,38 @@ int write_textual_stats(int curr, int use_tm_start, int use_tm_end, int reset, (*fmt[f_position]->f_timestamp)(&tab, F_BEGIN, cur_date, cur_time, !PRINT_TRUE_TIME(flags), dt); } - tab++; + if (format == F_XML_OUTPUT) { + tab++; + } /* Display textual statistics */ for (i = 0; i < NR_ACT; i++) { /* This code is not generic at all...! */ - if (CLOSE_MARKUP(act[i]->options) || - (IS_SELECTED(act[i]->options) && (act[i]->nr > 0))) { - (*act[i]->f_xml_print)(act[i], curr, tab, - NEED_GLOBAL_ITV(act[i]->options) ? g_itv : itv); + if (format == F_JSON_OUTPUT) { + /* JSON output */ + if (CLOSE_MARKUP(act[i]->options) || + (IS_SELECTED(act[i]->options) && (act[i]->nr > 0))) { + + if (IS_SELECTED(act[i]->options) && (act[i]->nr > 0)) { + printf(","); + + if (*fmt[f_position]->f_timestamp) { + (*fmt[f_position]->f_timestamp)(&tab, F_MAIN, cur_date, cur_time, + !PRINT_TRUE_TIME(flags), dt); + } + } + (*act[i]->f_json_print)(act[i], curr, tab, NEED_GLOBAL_ITV(act[i]->options) ? + g_itv : itv); + } + } + else { + /* XML output */ + if (CLOSE_MARKUP(act[i]->options) || + (IS_SELECTED(act[i]->options) && (act[i]->nr > 0))) { + (*act[i]->f_xml_print)(act[i], curr, tab, NEED_GLOBAL_ITV(act[i]->options) ? + g_itv : itv); + } } } @@ -858,7 +902,7 @@ void rw_curr_act_stats(int ifd, off_t fpos, int *curr, long *cnt, int *eosaf, /* *************************************************************************** - * Display activities for for textual (XML-like) formats. + * Display activities for textual (XML-like) formats. * * IN: * @ifd File descriptor of input file. @@ -951,6 +995,10 @@ void textual_display_loop(int ifd, struct file_activity *file_actlst, char *dfil read_file_stat_bunch(act, curr, ifd, file_hdr.sa_nr_act, file_actlst); + if (*fmt[f_position]->f_statistics) { + (*fmt[f_position]->f_statistics)(&tab, F_MAIN); + } + /* next is set to 1 when we were close enough to desired interval */ next = write_textual_stats(curr, tm_start.use, tm_end.use, reset, &cnt, tab, cpu_nr, rectime, loctime); @@ -1390,7 +1438,7 @@ int main(int argc, char **argv) case 'C': flags |= S_F_COMMENT; break; - + case 'd': if (format) { usage(argv[0]); @@ -1406,6 +1454,13 @@ int main(int argc, char **argv) flags |= S_F_HDR_ONLY; break; + case 'j': + if (format) { + usage(argv[0]); + } + format = F_JSON_OUTPUT; + break; + case 'p': if (format) { usage(argv[0]); diff --git a/sadf.h b/sadf.h index be7e82b..8987ce5 100644 --- a/sadf.h +++ b/sadf.h @@ -23,13 +23,14 @@ */ /* Number of output formats */ -#define NR_FMT 4 +#define NR_FMT 5 /* Output formats */ #define F_DB_OUTPUT 1 #define F_HEADER_OUTPUT 2 #define F_PPC_OUTPUT 3 #define F_XML_OUTPUT 4 +#define F_JSON_OUTPUT 5 /* *************************************************************************** @@ -178,6 +179,8 @@ struct report_format { extern void xprintf(int, const char *, ...); +extern void + xprintf0(int, const char *, ...); /* * Prototypes used to display restart messages @@ -188,6 +191,8 @@ __printf_funct_t print_ppc_restart(int *, int, char *, char *, int, struct file_header *); __printf_funct_t print_xml_restart(int *, int, char *, char *, int, struct file_header *); +__printf_funct_t + print_json_restart(int *, int, char *, char *, int, struct file_header *); /* * Prototypes used to display comments @@ -198,18 +203,24 @@ __printf_funct_t print_ppc_comment(int *, int, char *, char *, int, char *, struct file_header *); __printf_funct_t print_xml_comment(int *, int, char *, char *, int, char *, struct file_header *); +__printf_funct_t + print_json_comment(int *, int, char *, char *, int, char *, struct file_header *); /* * Prototypes used to display the statistics part of the report */ __printf_funct_t print_xml_statistics(int *, int); +__printf_funct_t + print_json_statistics(int *, int); /* * Prototypes used to display the timestamp part of the report */ __printf_funct_t print_xml_timestamp(int *, int, char *, char *, int, unsigned long long); +__printf_funct_t + print_json_timestamp(int *, int, char *, char *, int, unsigned long long); /* * Prototypes used to display the report header @@ -217,6 +228,9 @@ __printf_funct_t __printf_funct_t print_xml_header(int *, int, char *, struct file_magic *, struct file_header *, __nr_t, struct activity * [], unsigned int []); +__printf_funct_t + print_json_header(int *, int, char *, struct file_magic *, struct file_header *, + __nr_t, struct activity * [], unsigned int []); __printf_funct_t print_hdr_header(int *, int, char *, struct file_magic *, struct file_header *, __nr_t, struct activity * [], unsigned int []); diff --git a/sadf_misc.c b/sadf_misc.c index 7b5a309..a041994 100644 --- a/sadf_misc.c +++ b/sadf_misc.c @@ -136,6 +136,50 @@ __printf_funct_t print_xml_restart(int *tab, int action, char *cur_date, } } +/* + *************************************************************************** + * Display restart messages (JSON format). + * + * IN: + * @tab Number of tabulations. + * @action Action expected from current function. + * @cur_date Date string of current restart message. + * @cur_time Time string of current restart message. + * @utc True if @cur_time is expressed in UTC. + * @file_hdr System activity file standard header (unused here). + * + * OUT: + * @tab Number of tabulations. + *************************************************************************** + */ +__printf_funct_t print_json_restart(int *tab, int action, char *cur_date, + char *cur_time, int utc, struct file_header *file_hdr) +{ + static int sep = FALSE; + + if (action & F_BEGIN) { + printf(",\n"); + xprintf((*tab)++, "\"restarts\": ["); + } + if (action & F_MAIN) { + if (sep) { + printf(",\n"); + } + xprintf((*tab)++, "{"); + xprintf(*tab, "\"boot\": {\"date\": \"%s\", \"time\": \"%s\", \"utc\": %d}", + cur_date, cur_time, utc ? 1 : 0); + xprintf0(--(*tab), "}"); + sep = TRUE; + } + if (action & F_END) { + if (sep) { + printf("\n"); + sep = FALSE; + } + xprintf0(--(*tab), "]"); + } +} + /* *************************************************************************** * Display comments (database and ppc formats). @@ -246,6 +290,54 @@ __printf_funct_t print_xml_comment(int *tab, int action, char *cur_date, } } +/* + *************************************************************************** + * Display comments (JSON format). + * + * IN: + * @tab Number of tabulations. + * @action Action expected from current function. + * @cur_date Date string of current comment. + * @cur_time Time string of current comment. + * @utc True if @cur_time is expressed in UTC. + * @comment Comment to display. + * @file_hdr System activity file standard header (unused here). + * + * OUT: + * @tab Number of tabulations. + *************************************************************************** + */ +__printf_funct_t print_json_comment(int *tab, int action, char *cur_date, + char *cur_time, int utc, char *comment, + struct file_header *file_hdr) +{ + static int sep = FALSE; + + if (action & F_BEGIN) { + printf(",\n"); + xprintf((*tab)++, "\"comments\": ["); + } + if (action & F_MAIN) { + if (sep) { + printf(",\n"); + } + xprintf((*tab)++, "{"); + xprintf(*tab, + "\"comment\": {\"date\": \"%s\", \"time\": \"%s\", " + "\"utc\": %d, \"com\": \"%s\"}", + cur_date, cur_time, utc ? 1 : 0, comment); + xprintf0(--(*tab), "}"); + sep = TRUE; + } + if (action & F_END) { + if (sep) { + printf("\n"); + sep = FALSE; + } + xprintf0(--(*tab), "]"); + } +} + /* *************************************************************************** * Display the "statistics" part of the report (XML format). @@ -268,6 +360,42 @@ __printf_funct_t print_xml_statistics(int *tab, int action) } } +/* + *************************************************************************** + * Display the "statistics" part of the report (JSON format). + * + * IN: + * @tab Number of tabulations. + * @action Action expected from current function. + * + * OUT: + * @tab Number of tabulations. + *************************************************************************** + */ +__printf_funct_t print_json_statistics(int *tab, int action) +{ + static int sep = FALSE; + + if (action & F_BEGIN) { + printf(",\n"); + xprintf((*tab)++, "\"statistics\": ["); + } + if (action & F_MAIN) { + if (sep) { + xprintf(--(*tab), "},"); + } + xprintf((*tab)++, "{"); + sep = TRUE; + } + if (action & F_END) { + if (sep) { + xprintf(--(*tab), "}"); + sep = FALSE; + } + xprintf0(--(*tab), "]"); + } +} + /* *************************************************************************** * Display the "timestamp" part of the report (XML format). @@ -296,6 +424,39 @@ __printf_funct_t print_xml_timestamp(int *tab, int action, char *cur_date, } } +/* + *************************************************************************** + * Display the "timestamp" part of the report (JSON format). + * + * IN: + * @tab Number of tabulations. + * @action Action expected from current function. + * @cur_date Date string of current comment. + * @cur_time Time string of current comment. + * @utc True if @cur_time is expressed in UTC. + * @itv Interval of time with preceding record. + * + * OUT: + * @tab Number of tabulations. + *************************************************************************** + */ +__printf_funct_t print_json_timestamp(int *tab, int action, char *cur_date, + char *cur_time, int utc, unsigned long long itv) +{ + if (action & F_BEGIN) { + xprintf0(*tab, + "\"timestamp\": {\"date\": \"%s\", \"time\": \"%s\", " + "\"utc\": %d, \"interval\": %llu}", + cur_date, cur_time, utc ? 1 : 0, itv); + } + if (action & F_MAIN) { + printf("\n"); + } + if (action & F_END) { + printf("\n"); + } +} + /* *************************************************************************** * Display the header of the report (XML format). @@ -352,6 +513,61 @@ __printf_funct_t print_xml_header(int *tab, int action, char *dfile, } } +/* + *************************************************************************** + * Display the header of the report (JSON format). + * + * IN: + * @tab Number of tabulations. + * @action Action expected from current function. + * @dfile Name of system activity data file. + * @file_magic System activity file magic header. + * @file_hdr System activity file standard header. + * @cpu_nr Number of processors for current daily data file. + * @act Array of activities (unused here). + * @id_seq Activity sequence (unused here). + * + * OUT: + * @tab Number of tabulations. + *************************************************************************** + */ +__printf_funct_t print_json_header(int *tab, int action, char *dfile, + struct file_magic *file_magic, + struct file_header *file_hdr, __nr_t cpu_nr, + struct activity *act[], unsigned int id_seq[]) +{ + struct tm rectime; + char cur_time[32]; + + if (action & F_BEGIN) { + xprintf(*tab, "{\"sysstat\": {"); + + xprintf(++(*tab), "\"sysdata-version\": %s,", + XML_DTD_VERSION); + + xprintf(*tab, "\"hosts\": ["); + xprintf(++(*tab), "{"); + xprintf(++(*tab), "\"nodename\": \"%s\",", file_hdr->sa_nodename); + xprintf(*tab, "\"sysname\": \"%s\",", file_hdr->sa_sysname); + xprintf(*tab, "\"release\": \"%s\",", file_hdr->sa_release); + + xprintf(*tab, "\"machine\": \"%s\",", file_hdr->sa_machine); + xprintf(*tab, "\"number-of-cpus\": %d,", + cpu_nr > 1 ? cpu_nr - 1 : 1); + + /* Fill file timestmap structure (rectime) */ + get_file_timestamp_struct(flags, &rectime, file_hdr); + strftime(cur_time, 32, "%Y-%m-%d", &rectime); + xprintf0(*tab, "\"file-date\": \"%s\"", cur_time); + } + if (action & F_END) { + printf("\n"); + xprintf(--(*tab), "}"); + xprintf(--(*tab), "]"); + xprintf(--(*tab), "}}"); + } +} + /* *************************************************************************** * Display data file header. diff --git a/xml_stats.c b/xml_stats.c index c8e99f7..7c9ff58 100644 --- a/xml_stats.c +++ b/xml_stats.c @@ -120,13 +120,13 @@ __print_funct_t xml_print_cpu_stats(struct activity *a, int curr, int tab, } for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) { - + scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize); scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize); /* Should current CPU (including CPU "all") be displayed? */ if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) { - + /* Yes: Display it */ if (!i) { /* This is CPU "all" */ @@ -161,7 +161,7 @@ __print_funct_t xml_print_cpu_stats(struct activity *a, int curr, int tab, g_itv = get_per_cpu_interval(scc, scp); cpu_offline = FALSE; } - + if (!g_itv) { /* Current CPU is offline or tickless */ if (DISPLAY_CPU_DEF(a->opt_flags)) { @@ -295,7 +295,7 @@ __print_funct_t xml_print_irq_stats(struct activity *a, int curr, int tab, int i; struct stats_irq *sic, *sip; char irqno[8]; - + xprintf(tab++, ""); xprintf(tab++, ""); @@ -306,7 +306,7 @@ __print_funct_t xml_print_irq_stats(struct activity *a, int curr, int tab, /* Should current interrupt (including int "sum") be displayed? */ if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) { - + /* Yes: Display it */ if (!i) { /* This is interrupt "sum" */ @@ -378,19 +378,19 @@ __print_funct_t xml_print_paging_stats(struct activity *a, int curr, int tab, "pgscand=\"%.2f\" " "pgsteal=\"%.2f\" " "vmeff-percent=\"%.2f\"/>", - S_VALUE(spp->pgpgin, spc->pgpgin, itv), - S_VALUE(spp->pgpgout, spc->pgpgout, itv), - S_VALUE(spp->pgfault, spc->pgfault, itv), - S_VALUE(spp->pgmajfault, spc->pgmajfault, itv), - S_VALUE(spp->pgfree, spc->pgfree, itv), - S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv), - S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv), - S_VALUE(spp->pgsteal, spc->pgsteal, itv), - (spc->pgscan_kswapd + spc->pgscan_direct - - spp->pgscan_kswapd - spp->pgscan_direct) ? - SP_VALUE(spp->pgsteal, spc->pgsteal, - spc->pgscan_kswapd + spc->pgscan_direct - - spp->pgscan_kswapd - spp->pgscan_direct) : 0.0); + S_VALUE(spp->pgpgin, spc->pgpgin, itv), + S_VALUE(spp->pgpgout, spc->pgpgout, itv), + S_VALUE(spp->pgfault, spc->pgfault, itv), + S_VALUE(spp->pgmajfault, spc->pgmajfault, itv), + S_VALUE(spp->pgfree, spc->pgfree, itv), + S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv), + S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv), + S_VALUE(spp->pgsteal, spc->pgsteal, itv), + (spc->pgscan_kswapd + spc->pgscan_direct - + spp->pgscan_kswapd - spp->pgscan_direct) ? + SP_VALUE(spp->pgsteal, spc->pgsteal, + spc->pgscan_kswapd + spc->pgscan_direct - + spp->pgscan_kswapd - spp->pgscan_direct) : 0.0); } /* @@ -415,15 +415,15 @@ __print_funct_t xml_print_io_stats(struct activity *a, int curr, int tab, xprintf(++tab, "%.2f", S_VALUE(sip->dk_drive, sic->dk_drive, itv)); - + xprintf(tab, "", S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv), S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv)); - + xprintf(tab, "", S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv), S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv)); - + xprintf(--tab, ""); } @@ -446,12 +446,12 @@ __print_funct_t xml_print_memory_stats(struct activity *a, int curr, int tab, *smp = (struct stats_memory *) a->buf[!curr]; xprintf(tab, ""); - + if (DISPLAY_MEM_AMT(a->opt_flags)) { xprintf(++tab, "%lu", smc->frmkb); - + xprintf(tab, "%lu", smc->tlmkb - smc->frmkb); @@ -459,10 +459,10 @@ __print_funct_t xml_print_memory_stats(struct activity *a, int curr, int tab, smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0); - + xprintf(tab, "%lu", smc->bufkb); - + xprintf(tab, "%lu", smc->camkb); @@ -476,7 +476,7 @@ __print_funct_t xml_print_memory_stats(struct activity *a, int curr, int tab, xprintf(tab, "%lu", smc->activekb); - + xprintf(tab--, "%lu", smc->inactkb); } @@ -485,10 +485,10 @@ __print_funct_t xml_print_memory_stats(struct activity *a, int curr, int tab, xprintf(++tab, "%lu", smc->frskb); - + xprintf(tab, "%lu", smc->tlskb - smc->frskb); - + xprintf(tab, "%.2f", smc->tlskb ? SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : @@ -508,11 +508,11 @@ __print_funct_t xml_print_memory_stats(struct activity *a, int curr, int tab, xprintf(++tab, "%.2f", S_VALUE((double) KB_TO_PG(smp->frmkb), (double) KB_TO_PG(smc->frmkb), itv)); - + xprintf(tab, "%.2f", S_VALUE((double) KB_TO_PG(smp->bufkb), (double) KB_TO_PG(smc->bufkb), itv)); - + xprintf(tab--, "%.2f", S_VALUE((double) KB_TO_PG(smp->camkb), (double) KB_TO_PG(smc->camkb), itv)); @@ -665,7 +665,7 @@ __print_funct_t xml_print_disk_stats(struct activity *a, int curr, int tab, /* Compute extended statistics values */ compute_ext_disk_stats(sdc, sdp, itv, &xds); - + dev_name = NULL; if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) { @@ -731,7 +731,7 @@ __print_funct_t xml_print_net_dev_stats(struct activity *a, int curr, int tab, if (!strcmp(sndc->interface, "")) continue; - + j = check_net_dev_reg(a, curr, !curr, i); sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize); @@ -789,7 +789,7 @@ __print_funct_t xml_print_net_edev_stats(struct activity *a, int curr, int tab, if (!strcmp(snedc->interface, "")) continue; - + j = check_net_edev_reg(a, curr, !curr, i); snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize); @@ -839,7 +839,7 @@ __print_funct_t xml_print_net_nfs_stats(struct activity *a, int curr, int tab, struct stats_net_nfs *snnc = (struct stats_net_nfs *) a->buf[curr], *snnp = (struct stats_net_nfs *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -938,7 +938,7 @@ __print_funct_t xml_print_net_sock_stats(struct activity *a, int curr, int tab, { struct stats_net_sock *snsc = (struct stats_net_sock *) a->buf[curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -983,7 +983,7 @@ __print_funct_t xml_print_net_ip_stats(struct activity *a, int curr, int tab, struct stats_net_ip *snic = (struct stats_net_ip *) a->buf[curr], *snip = (struct stats_net_ip *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -1032,7 +1032,7 @@ __print_funct_t xml_print_net_eip_stats(struct activity *a, int curr, int tab, struct stats_net_eip *sneic = (struct stats_net_eip *) a->buf[curr], *sneip = (struct stats_net_eip *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -1081,7 +1081,7 @@ __print_funct_t xml_print_net_icmp_stats(struct activity *a, int curr, int tab, struct stats_net_icmp *snic = (struct stats_net_icmp *) a->buf[curr], *snip = (struct stats_net_icmp *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -1142,7 +1142,7 @@ __print_funct_t xml_print_net_eicmp_stats(struct activity *a, int curr, int tab, struct stats_net_eicmp *sneic = (struct stats_net_eicmp *) a->buf[curr], *sneip = (struct stats_net_eicmp *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -1199,7 +1199,7 @@ __print_funct_t xml_print_net_tcp_stats(struct activity *a, int curr, int tab, struct stats_net_tcp *sntc = (struct stats_net_tcp *) a->buf[curr], *sntp = (struct stats_net_tcp *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -1335,10 +1335,10 @@ __print_funct_t xml_print_net_sock6_stats(struct activity *a, int curr, int tab, "udp6sck=\"%u\" " "raw6sck=\"%u\" " "ip6-frag=\"%u\"/>", - snsc->tcp6_inuse, - snsc->udp6_inuse, - snsc->raw6_inuse, - snsc->frag6_inuse); + snsc->tcp6_inuse, + snsc->udp6_inuse, + snsc->raw6_inuse, + snsc->frag6_inuse); tab--; close_xml_markup: @@ -1364,7 +1364,7 @@ __print_funct_t xml_print_net_ip6_stats(struct activity *a, int curr, int tab, struct stats_net_ip6 *snic = (struct stats_net_ip6 *) a->buf[curr], *snip = (struct stats_net_ip6 *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -1417,7 +1417,7 @@ __print_funct_t xml_print_net_eip6_stats(struct activity *a, int curr, int tab, struct stats_net_eip6 *sneic = (struct stats_net_eip6 *) a->buf[curr], *sneip = (struct stats_net_eip6 *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -1472,7 +1472,7 @@ __print_funct_t xml_print_net_icmp6_stats(struct activity *a, int curr, int tab, struct stats_net_icmp6 *snic = (struct stats_net_icmp6 *) a->buf[curr], *snip = (struct stats_net_icmp6 *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -1539,7 +1539,7 @@ __print_funct_t xml_print_net_eicmp6_stats(struct activity *a, int curr, int tab struct stats_net_eicmp6 *sneic = (struct stats_net_eicmp6 *) a->buf[curr], *sneip = (struct stats_net_eicmp6 *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -1594,7 +1594,7 @@ __print_funct_t xml_print_net_udp6_stats(struct activity *a, int curr, int tab, struct stats_net_udp6 *snuc = (struct stats_net_udp6 *) a->buf[curr], *snup = (struct stats_net_udp6 *) a->buf[!curr]; - + if (!IS_SELECTED(a->options) || (a->nr <= 0)) goto close_xml_markup; @@ -1645,9 +1645,9 @@ __print_funct_t xml_print_pwr_cpufreq_stats(struct activity *a, int curr, int ta xprintf(tab++, ""); for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) { - + spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize); - + /* Should current CPU (including CPU "all") be displayed? */ if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) { @@ -1659,14 +1659,14 @@ __print_funct_t xml_print_pwr_cpufreq_stats(struct activity *a, int curr, int ta else { sprintf(cpuno, "%d", i - 1); } - + xprintf(tab, "", cpuno, ((double) spc->cpufreq) / 100); } } - + xprintf(--tab, ""); tab--; @@ -1732,7 +1732,7 @@ close_xml_markup: *************************************************************************** */ __print_funct_t xml_print_pwr_temp_stats(struct activity *a, int curr, int tab, - unsigned long long itv) + unsigned long long itv) { int i; struct stats_pwr_temp *spc; diff --git a/xml_stats.h b/xml_stats.h index c75a812..aa435ae 100644 --- a/xml_stats.h +++ b/xml_stats.h @@ -3,8 +3,8 @@ * (C) 1999-2011 by Sebastien Godard (sysstat orange.fr) */ -#ifndef _PRF_STATS_H -#define _PRF_STATS_H +#ifndef _XML_STATS_H +#define _XML_STATS_H #include "common.h" -- 2.40.0