stat: cleanup average logging
[fio.git] / stat.c
diff --git a/stat.c b/stat.c
index 818756dd8537d3385995ae817a7815f57c0c3008..73fd9f9eabc8182bc365293948aba08640b467db 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -1086,8 +1086,34 @@ static void show_thread_status_terse_v3_v4(struct thread_stat *ts,
        log_buf(out, "\n");
 }
 
+void json_add_job_opts(struct json_object *root, const char *name,
+                      struct flist_head *opt_list, bool num_jobs)
+{
+       struct json_object *dir_object;
+       struct flist_head *entry;
+       struct print_option *p;
+
+       if (flist_empty(opt_list))
+               return;
+
+       dir_object = json_create_object();
+       json_object_add_value_object(root, name, dir_object);
+
+       flist_for_each(entry, opt_list) {
+               const char *pos = "";
+
+               p = flist_entry(entry, struct print_option, list);
+               if (!num_jobs && !strcmp(p->name, "numjobs"))
+                       continue;
+               if (p->value)
+                       pos = p->value;
+               json_object_add_value_string(dir_object, p->name, pos);
+       }
+}
+
 static struct json_object *show_thread_status_json(struct thread_stat *ts,
-                                   struct group_run_stats *rs)
+                                                  struct group_run_stats *rs,
+                                                  struct flist_head *opt_list)
 {
        struct json_object *root, *tmp;
        struct jobs_eta *je;
@@ -1104,12 +1130,15 @@ static struct json_object *show_thread_status_json(struct thread_stat *ts,
        json_object_add_value_int(root, "error", ts->error);
 
        /* ETA Info */
-       je = get_jobs_eta(1, &size);
+       je = get_jobs_eta(true, &size);
        if (je) {
                json_object_add_value_int(root, "eta", je->eta_sec);
                json_object_add_value_int(root, "elapsed", je->elapsed_sec);
        }
 
+       if (opt_list)
+               json_add_job_opts(root, "job options", opt_list, true);
+
        add_ddir_status_json(ts, rs, DDIR_READ, root);
        add_ddir_status_json(ts, rs, DDIR_WRITE, root);
        add_ddir_status_json(ts, rs, DDIR_TRIM, root);
@@ -1239,6 +1268,7 @@ static void show_thread_status_terse(struct thread_stat *ts,
 
 struct json_object *show_thread_status(struct thread_stat *ts,
                                       struct group_run_stats *rs,
+                                      struct flist_head *opt_list,
                                       struct buf_output *out)
 {
        struct json_object *ret = NULL;
@@ -1246,7 +1276,7 @@ struct json_object *show_thread_status(struct thread_stat *ts,
        if (output_format & FIO_OUTPUT_TERSE)
                show_thread_status_terse(ts, rs,  out);
        if (output_format & FIO_OUTPUT_JSON)
-               ret = show_thread_status_json(ts, rs);
+               ret = show_thread_status_json(ts, rs, opt_list);
        if (output_format & FIO_OUTPUT_NORMAL)
                show_thread_status_normal(ts, rs,  out);
 
@@ -1427,6 +1457,7 @@ void __show_run_stats(void)
        struct json_object *root = NULL;
        struct json_array *array = NULL;
        struct buf_output output[FIO_OUTPUT_NR];
+       struct flist_head **opt_lists;
 
        runstats = malloc(sizeof(struct group_run_stats) * (groupid + 1));
 
@@ -1452,9 +1483,12 @@ void __show_run_stats(void)
        }
 
        threadstats = malloc(nr_ts * sizeof(struct thread_stat));
+       opt_lists = malloc(nr_ts * sizeof(struct flist_head *));
 
-       for (i = 0; i < nr_ts; i++)
+       for (i = 0; i < nr_ts; i++) {
                init_thread_stat(&threadstats[i]);
+               opt_lists[i] = NULL;
+       }
 
        j = 0;
        last_ts = -1;
@@ -1473,6 +1507,7 @@ void __show_run_stats(void)
                ts->clat_percentiles = td->o.clat_percentiles;
                ts->percentile_precision = td->o.percentile_precision;
                memcpy(ts->percentile_list, td->o.percentile_list, sizeof(td->o.percentile_list));
+               opt_lists[j] = &td->opt_list;
 
                idx++;
                ts->members++;
@@ -1596,6 +1631,7 @@ void __show_run_stats(void)
        if (output_format & FIO_OUTPUT_NORMAL)
                log_buf(&output[__FIO_OUTPUT_NORMAL], "\n");
        if (output_format & FIO_OUTPUT_JSON) {
+               struct thread_data *global;
                char time_buf[32];
                time_t time_p;
 
@@ -1608,21 +1644,27 @@ void __show_run_stats(void)
                json_object_add_value_string(root, "fio version", fio_version_string);
                json_object_add_value_int(root, "timestamp", time_p);
                json_object_add_value_string(root, "time", time_buf);
+               global = get_global_options();
+               json_add_job_opts(root, "global options", &global->opt_list, false);
                array = json_create_array();
                json_object_add_value_array(root, "jobs", array);
        }
 
+       if (is_backend)
+               fio_server_send_job_options(&get_global_options()->opt_list, -1U);
+
        for (i = 0; i < nr_ts; i++) {
                ts = &threadstats[i];
                rs = &runstats[ts->groupid];
 
-               if (is_backend)
+               if (is_backend) {
+                       fio_server_send_job_options(opt_lists[i], i);
                        fio_server_send_ts(ts, rs);
-               else {
+               else {
                        if (output_format & FIO_OUTPUT_TERSE)
                                show_thread_status_terse(ts, rs, &output[__FIO_OUTPUT_TERSE]);
                        if (output_format & FIO_OUTPUT_JSON) {
-                               struct json_object *tmp = show_thread_status_json(ts, rs);
+                               struct json_object *tmp = show_thread_status_json(ts, rs, opt_lists[i]);
                                json_array_add_value_object(array, tmp);
                        }
                        if (output_format & FIO_OUTPUT_NORMAL)
@@ -1665,6 +1707,7 @@ void __show_run_stats(void)
        log_info_flush();
        free(runstats);
        free(threadstats);
+       free(opt_lists);
 }
 
 void show_run_stats(void)
@@ -1687,19 +1730,19 @@ void __show_running_run_stats(void)
        fio_gettime(&tv, NULL);
 
        for_each_td(td, i) {
-               rt[i] = mtime_since(&td->start, &tv);
-               if (td_read(td) && td->io_bytes[DDIR_READ])
-                       td->ts.runtime[DDIR_READ] += rt[i];
-               if (td_write(td) && td->io_bytes[DDIR_WRITE])
-                       td->ts.runtime[DDIR_WRITE] += rt[i];
-               if (td_trim(td) && td->io_bytes[DDIR_TRIM])
-                       td->ts.runtime[DDIR_TRIM] += rt[i];
-
                td->update_rusage = 1;
                td->ts.io_bytes[DDIR_READ] = td->io_bytes[DDIR_READ];
                td->ts.io_bytes[DDIR_WRITE] = td->io_bytes[DDIR_WRITE];
                td->ts.io_bytes[DDIR_TRIM] = td->io_bytes[DDIR_TRIM];
                td->ts.total_run_time = mtime_since(&td->epoch, &tv);
+
+               rt[i] = mtime_since(&td->start, &tv);
+               if (td_read(td) && td->ts.io_bytes[DDIR_READ])
+                       td->ts.runtime[DDIR_READ] += rt[i];
+               if (td_write(td) && td->ts.io_bytes[DDIR_WRITE])
+                       td->ts.runtime[DDIR_WRITE] += rt[i];
+               if (td_trim(td) && td->ts.io_bytes[DDIR_TRIM])
+                       td->ts.runtime[DDIR_TRIM] += rt[i];
        }
 
        for_each_td(td, i) {
@@ -1715,11 +1758,11 @@ void __show_running_run_stats(void)
        __show_run_stats();
 
        for_each_td(td, i) {
-               if (td_read(td) && td->io_bytes[DDIR_READ])
+               if (td_read(td) && td->ts.io_bytes[DDIR_READ])
                        td->ts.runtime[DDIR_READ] -= rt[i];
-               if (td_write(td) && td->io_bytes[DDIR_WRITE])
+               if (td_write(td) && td->ts.io_bytes[DDIR_WRITE])
                        td->ts.runtime[DDIR_WRITE] -= rt[i];
-               if (td_trim(td) && td->io_bytes[DDIR_TRIM])
+               if (td_trim(td) && td->ts.io_bytes[DDIR_TRIM])
                        td->ts.runtime[DDIR_TRIM] -= rt[i];
        }
 
@@ -1899,35 +1942,30 @@ void reset_io_stats(struct thread_data *td)
        }
 }
 
-static void _add_stat_to_log(struct io_log *iolog, unsigned long elapsed)
+static void __add_stat_to_log(struct io_log *iolog, enum fio_ddir ddir,
+                             unsigned long elapsed)
 {
        /*
         * Note an entry in the log. Use the mean from the logged samples,
         * making sure to properly round up. Only write a log entry if we
         * had actual samples done.
         */
-       if (iolog->avg_window[DDIR_READ].samples) {
-               unsigned long mr;
+       if (iolog->avg_window[ddir].samples) {
+               unsigned long val;
 
-               mr = iolog->avg_window[DDIR_READ].mean.u.f + 0.50;
-               __add_log_sample(iolog, mr, DDIR_READ, 0, elapsed, 0);
+               val = iolog->avg_window[ddir].mean.u.f + 0.50;
+               __add_log_sample(iolog, val, ddir, 0, elapsed, 0);
        }
-       if (iolog->avg_window[DDIR_WRITE].samples) {
-               unsigned long mw;
 
-               mw = iolog->avg_window[DDIR_WRITE].mean.u.f + 0.50;
-               __add_log_sample(iolog, mw, DDIR_WRITE, 0, elapsed, 0);
-       }
-       if (iolog->avg_window[DDIR_TRIM].samples) {
-               unsigned long mw;
+       reset_io_stat(&iolog->avg_window[ddir]);
+}
 
-               mw = iolog->avg_window[DDIR_TRIM].mean.u.f + 0.50;
-               __add_log_sample(iolog, mw, DDIR_TRIM, 0, elapsed, 0);
-       }
+static void _add_stat_to_log(struct io_log *iolog, unsigned long elapsed)
+{
+       int ddir;
 
-       reset_io_stat(&iolog->avg_window[DDIR_READ]);
-       reset_io_stat(&iolog->avg_window[DDIR_WRITE]);
-       reset_io_stat(&iolog->avg_window[DDIR_TRIM]);
+       for (ddir = 0; ddir < DDIR_RWDIR_CNT; ddir++)
+               __add_stat_to_log(iolog, ddir, elapsed);
 }
 
 static void add_log_sample(struct thread_data *td, struct io_log *iolog,