diff --git a/src/disk.c b/src/disk.c index c4f9b39285..f016fff3dd 100644 --- a/src/disk.c +++ b/src/disk.c @@ -75,6 +75,12 @@ #include #endif +static char const *const device_label = "system.device"; +static char const *const direction_label = "disk.io.direction"; + +static char const *const read_direction = "read"; +static char const *const write_direction = "write"; + #if (MAC_OS_X_VERSION_MIN_REQUIRED < 120000) // Before macOS 12 Monterey #define IOMainPort IOMasterPort #endif @@ -93,25 +99,13 @@ typedef struct diskstats { /* This overflows in roughly 1361 years */ unsigned int poll_count; - derive_t read_sectors; - derive_t write_sectors; - - derive_t read_bytes; - derive_t write_bytes; - - derive_t read_ops; - derive_t write_ops; - derive_t read_time; - derive_t write_time; + counter_t read_sectors; + counter_t write_sectors; - derive_t avg_read_time; - derive_t avg_write_time; + counter_t read_bytes; + counter_t write_bytes; - derive_t io_time; - - bool has_merged; - bool has_in_progress; - bool has_io_time; + value_to_rate_state_t io_time_state; struct diskstats *next; } diskstats_t; @@ -309,13 +303,10 @@ static int disk_shutdown(void) { } /* int disk_shutdown */ #if KERNEL_LINUX -static counter_t disk_calc_time_incr(counter_t delta_time, - counter_t delta_ops) { - double interval = CDTIME_T_TO_DOUBLE(plugin_get_interval()); - double avg_time = ((double)delta_time) / ((double)delta_ops); - double avg_time_incr = interval * avg_time; - - return (counter_t)(avg_time_incr + .5); +static counter_t parse_counter(char const *s) { + char **const endptr = NULL; + int const base = 0; + return (counter_t)strtoull(s, endptr, base); } #endif @@ -382,54 +373,70 @@ static signed long long dict_get_value(CFDictionaryRef dict, const char *key) { static int disk_read(void) { metric_family_t fam_io = { .name = "system.disk.io", + .help = "Bytes read from and written to disk.", + .unit = "By", .type = METRIC_TYPE_COUNTER, }; metric_family_t fam_ops = { .name = "system.disk.operations", + .help = "Read and write operations performed by the disk. Operations are " + "reported separately even if they were merged into one operation " + "by the I/O subsystem.", + .unit = "{operation}", .type = METRIC_TYPE_COUNTER, }; - metric_family_t fam_time = { - .name = "system.disk.time", + metric_family_t fam_ops_time = { + .name = "system.disk.operation_time", + .help = "Sum of the time each operation took to complete", + .unit = "us", .type = METRIC_TYPE_COUNTER, }; metric_family_t fam_merged = { .name = "system.disk.merged", + .help = "I/O operations that were merged into reduce load on the disk.", + .unit = "{operation}", .type = METRIC_TYPE_COUNTER, }; - metric_family_t fam_disk_io_time = { - .name = "disk_io_time_total", + .name = "system.disk.io_time", + .help = "Time disk spent activated", + .unit = "us", .type = METRIC_TYPE_COUNTER, }; metric_family_t fam_disk_io_weighted_time = { - .name = "disk_io_weighted_time_total", + .name = "system.disk.weighted_io_time", + .help = "This metric is incremented at each I/O start, I/O completion, " + "or I/O merge by the number of I/Os in progress, times the " + "number of milliseconds spent doing I/O since the last update of " + "this field. This can provide an easy measure of both I/O " + "completion time and the backlog that may be accumulating.", + .unit = "ms", .type = METRIC_TYPE_COUNTER, }; metric_family_t fam_disk_pending_operations = { - .name = "disk_pending_operations", + .name = "system.disk.pending_operations", + .help = "Number of I/O operations currently in progress.", + .unit = "{operation}", .type = METRIC_TYPE_GAUGE, }; - -#if KERNEL_LINUX - metric_family_t fam_disk_utilization = { - .name = "disk_utilization", + metric_family_t fam_utilization = { + .name = "system.disk.utilization", + .help = "The ratio of time the device had one or more transactions " + "outstanding.", + .unit = "1", .type = METRIC_TYPE_GAUGE, }; -#endif metric_family_t *fams[] = { - &fam_io, - &fam_ops, - &fam_time, - &fam_merged, - - &fam_disk_io_time, - &fam_disk_io_weighted_time, - &fam_disk_pending_operations, -#if KERNEL_LINUX - &fam_disk_utilization, -#endif - NULL + &fam_io, + &fam_ops, + &fam_ops_time, + &fam_merged, + &fam_disk_io_time, + &fam_disk_io_weighted_time, + &fam_disk_pending_operations, + &fam_utilization, + NULL, }; #if HAVE_IOKIT_IOKITLIB_H @@ -441,8 +448,8 @@ static int disk_read(void) { CFStringRef tmp_cf_string_ref; kern_return_t status; - signed long long read_ops, read_byt, read_tme; - signed long long write_ops, write_byt, write_tme; + signed long long read_ops, read_byt; + signed long long write_ops, write_byt; int disk_major, disk_minor; char disk_name[DATA_MAX_NAME_LEN]; @@ -556,37 +563,37 @@ static int disk_read(void) { dict_get_value(stats_dict, kIOBlockStorageDriverStatisticsReadsKey); read_byt = dict_get_value(stats_dict, kIOBlockStorageDriverStatisticsBytesReadKey); - read_tme = dict_get_value(stats_dict, - kIOBlockStorageDriverStatisticsTotalReadTimeKey); + long long read_time_ns = dict_get_value( + stats_dict, kIOBlockStorageDriverStatisticsTotalReadTimeKey); write_ops = dict_get_value(stats_dict, kIOBlockStorageDriverStatisticsWritesKey); write_byt = dict_get_value(stats_dict, kIOBlockStorageDriverStatisticsBytesWrittenKey); - write_tme = dict_get_value( + long long write_time_ns = dict_get_value( stats_dict, kIOBlockStorageDriverStatisticsTotalWriteTimeKey); CFRelease(props_dict); IOObjectRelease(disk); /* and submit */ metric_t m = {0}; - metric_label_set(&m, "device", disk_name); + metric_label_set(&m, device_label, disk_name); if ((read_byt != -1LL) || (write_byt != -1LL)) { - metric_family_append(&fam_io, "direction", "read", + metric_family_append(&fam_io, direction_label, read_direction, (value_t){.counter = read_byt}, &m); - metric_family_append(&fam_io, "direction", "write", + metric_family_append(&fam_io, direction_label, write_direction, (value_t){.counter = write_byt}, &m); } if ((read_ops != -1LL) || (write_ops != -1LL)) { - metric_family_append(&fam_ops, "direction", "read", + metric_family_append(&fam_ops, direction_label, read_direction, (value_t){.counter = read_ops}, &m); - metric_family_append(&fam_ops, "direction", "write", + metric_family_append(&fam_ops, direction_label, write_direction, (value_t){.counter = write_ops}, &m); } - if ((read_tme != -1LL) || (write_tme != -1LL)) { - metric_family_append(&fam_time, "direction", "read", - (value_t){.counter = read_tme / 1000}, &m); - metric_family_append(&fam_time, "direction", "write", - (value_t){.counter = write_tme / 1000}, &m); + if ((read_time_ns != -1LL) || (write_time_ns != -1LL)) { + metric_family_append(&fam_ops_time, direction_label, read_direction, + (value_t){.derive = read_time_ns / 1000}, &m); + metric_family_append(&fam_ops_time, direction_label, write_direction, + (value_t){.derive = write_time_ns / 1000}, &m); } metric_reset(&m); } @@ -602,8 +609,6 @@ static int disk_read(void) { struct gident *geom_id; const char *disk_name; - long double read_time, write_time, busy_time, total_duration; - uint64_t queue_length; for (retry = 0, dirty = 1; retry < 5 && dirty == 1; retry++) { if (snap != NULL) @@ -684,50 +689,57 @@ static int disk_read(void) { continue; metric_t m = {0}; - metric_label_set(&m, "device", disk_name); + metric_label_set(&m, device_label, disk_name); if ((snap_iter->bytes[DEVSTAT_READ] != 0) || (snap_iter->bytes[DEVSTAT_WRITE] != 0)) { metric_family_append( - &fam_io, "direction", "read", + &fam_io, direction_label, read_direction, (value_t){.counter = (counter_t)snap_iter->bytes[DEVSTAT_READ]}, &m); metric_family_append( - &fam_io, "direction", "write", + &fam_io, direction_label, write_direction, (value_t){.counter = (counter_t)snap_iter->bytes[DEVSTAT_WRITE]}, &m); } if ((snap_iter->operations[DEVSTAT_READ] != 0) || (snap_iter->operations[DEVSTAT_WRITE] != 0)) { metric_family_append( - &fam_ops, "direction", "read", + &fam_ops, direction_label, read_direction, (value_t){.counter = (counter_t)snap_iter->operations[DEVSTAT_READ]}, &m); metric_family_append( - &fam_ops, "direction", "write", + &fam_ops, direction_label, write_direction, (value_t){.counter = (counter_t)snap_iter->operations[DEVSTAT_WRITE]}, &m); } - read_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_READ], NULL); - write_time = + long double read_time_s = + devstat_compute_etime(&snap_iter->duration[DEVSTAT_READ], NULL); + long double write_time_s = devstat_compute_etime(&snap_iter->duration[DEVSTAT_WRITE], NULL); - if ((read_time != 0) || (write_time != 0)) { - metric_family_append(&fam_time, "direction", "read", - (value_t){.counter = (counter_t)(read_time * 1000)}, - &m); - metric_family_append(&fam_time, "direction", "write", - (value_t){.counter = (counter_t)(write_time * 1000)}, - &m); + if ((read_time_s != 0) || (write_time_s != 0)) { + metric_family_append( + &fam_ops_time, direction_label, read_direction, + (value_t){.derive = (derive_t)(read_time_s * 1000000.0)}, &m); + metric_family_append( + &fam_ops_time, direction_label, write_direction, + (value_t){.derive = (derive_t)(write_time_s * 1000000.0)}, &m); } - if (devstat_compute_statistics(snap_iter, NULL, 1.0, DSM_TOTAL_BUSY_TIME, - &busy_time, DSM_TOTAL_DURATION, - &total_duration, DSM_QUEUE_LENGTH, - &queue_length, DSM_NONE) != 0) { + + long double busy_time = 0, utilization = 0, total_duration = 0; + uint64_t queue_length = 0; + if (devstat_compute_statistics( + snap_iter, NULL, 1.0, DSM_TOTAL_BUSY_TIME, &busy_time, DSM_BUSY_PCT, + &utilization, DSM_TOTAL_DURATION, &total_duration, DSM_QUEUE_LENGTH, + &queue_length, DSM_NONE) != 0) { WARNING("%s", devstat_errbuf); } else { - m.value.counter = (counter_t)busy_time; + m.value.counter = (counter_t)(1000000.0 * busy_time); metric_family_metric_append(&fam_disk_io_time, m); + m.value.gauge = (gauge_t)utilization; + metric_family_metric_append(&fam_utilization, m); + m.value.counter = (counter_t)total_duration; metric_family_metric_append(&fam_disk_io_weighted_time, m); @@ -745,20 +757,19 @@ static int disk_read(void) { char *fields[32]; static unsigned int poll_count = 0; - derive_t read_sectors = 0; - derive_t write_sectors = 0; + counter_t read_sectors = 0; + counter_t write_sectors = 0; - derive_t read_ops = 0; - derive_t read_merged = 0; - derive_t read_time = 0; - derive_t write_ops = 0; - derive_t write_merged = 0; - derive_t write_time = 0; + counter_t read_ops = 0; + counter_t read_merged = 0; + counter_t read_time_ms = 0; + counter_t write_ops = 0; + counter_t write_merged = 0; + counter_t write_time_ms = 0; gauge_t in_progress = NAN; - derive_t io_time = 0; - derive_t weighted_time = 0; - derive_t diff_io_time = 0; - int is_disk = 0; + counter_t io_time_ms = 0; + counter_t weighted_time = 0; + gauge_t io_time_rate_ms = NAN; // unit: ms/s diskstats_t *ds, *pre_ds; @@ -797,46 +808,37 @@ static int disk_read(void) { pre_ds->next = ds; } - is_disk = 0; if (numfields == 7) { /* Kernel 2.6, Partition */ - read_ops = atoll(fields[3]); - read_sectors = atoll(fields[4]); - write_ops = atoll(fields[5]); - write_sectors = atoll(fields[6]); + read_ops = parse_counter(fields[3]); + read_sectors = parse_counter(fields[4]); + write_ops = parse_counter(fields[5]); + write_sectors = parse_counter(fields[6]); } else { assert(numfields >= 14); - read_ops = atoll(fields[3]); - write_ops = atoll(fields[7]); + read_ops = parse_counter(fields[3]); + write_ops = parse_counter(fields[7]); - read_sectors = atoll(fields[5]); - write_sectors = atoll(fields[9]); + read_sectors = parse_counter(fields[5]); + write_sectors = parse_counter(fields[9]); - is_disk = 1; - read_merged = atoll(fields[4]); - read_time = atoll(fields[6]); - write_merged = atoll(fields[8]); - write_time = atoll(fields[10]); + read_merged = parse_counter(fields[4]); + read_time_ms = parse_counter(fields[6]); + write_merged = parse_counter(fields[8]); + write_time_ms = parse_counter(fields[10]); in_progress = atof(fields[11]); - io_time = atof(fields[12]); - weighted_time = atof(fields[13]); + io_time_ms = parse_counter(fields[12]); + weighted_time = parse_counter(fields[13]); } + /* Scale the "sectors" counters to bytes. */ { - derive_t diff_read_sectors; - derive_t diff_write_sectors; - - /* If the counter wraps around, it's only 32 bits.. */ - if (read_sectors < ds->read_sectors) - diff_read_sectors = 1 + read_sectors + (UINT_MAX - ds->read_sectors); - else - diff_read_sectors = read_sectors - ds->read_sectors; - if (write_sectors < ds->write_sectors) - diff_write_sectors = 1 + write_sectors + (UINT_MAX - ds->write_sectors); - else - diff_write_sectors = write_sectors - ds->write_sectors; + counter_t diff_read_sectors = + counter_diff(ds->read_sectors, read_sectors); + counter_t diff_write_sectors = + counter_diff(ds->write_sectors, write_sectors); ds->read_bytes += 512 * diff_read_sectors; ds->write_bytes += 512 * diff_write_sectors; @@ -844,70 +846,9 @@ static int disk_read(void) { ds->write_sectors = write_sectors; } - /* Calculate the average time an io-op needs to complete */ - if (is_disk) { - derive_t diff_read_ops; - derive_t diff_write_ops; - derive_t diff_read_time; - derive_t diff_write_time; - - if (read_ops < ds->read_ops) - diff_read_ops = 1 + read_ops + (UINT_MAX - ds->read_ops); - else - diff_read_ops = read_ops - ds->read_ops; - DEBUG("disk plugin: disk_name = %s; read_ops = %" PRIi64 "; " - "ds->read_ops = %" PRIi64 "; diff_read_ops = %" PRIi64 ";", - disk_name, read_ops, ds->read_ops, diff_read_ops); - - if (write_ops < ds->write_ops) - diff_write_ops = 1 + write_ops + (UINT_MAX - ds->write_ops); - else - diff_write_ops = write_ops - ds->write_ops; - - if (read_time < ds->read_time) - diff_read_time = 1 + read_time + (UINT_MAX - ds->read_time); - else - diff_read_time = read_time - ds->read_time; - - if (write_time < ds->write_time) - diff_write_time = 1 + write_time + (UINT_MAX - ds->write_time); - else - diff_write_time = write_time - ds->write_time; - - if (io_time < ds->io_time) - diff_io_time = 1 + io_time + (UINT_MAX - ds->io_time); - else - diff_io_time = io_time - ds->io_time; - - if (diff_read_ops != 0) - ds->avg_read_time += disk_calc_time_incr(diff_read_time, diff_read_ops); - if (diff_write_ops != 0) - ds->avg_write_time += - disk_calc_time_incr(diff_write_time, diff_write_ops); + value_to_rate(&io_time_rate_ms, (value_t){.counter = io_time_ms}, + DS_TYPE_COUNTER, cdtime(), &ds->io_time_state); - ds->read_ops = read_ops; - ds->read_time = read_time; - ds->write_ops = write_ops; - ds->write_time = write_time; - ds->io_time = io_time; - - if (read_merged || write_merged) - ds->has_merged = true; - - if (in_progress) - ds->has_in_progress = true; - - if (io_time) - ds->has_io_time = true; - - } /* if (is_disk) */ - - /* Skip first cycle for newly-added disk */ - if (ds->poll_count == 0) { - DEBUG("disk plugin: (ds->poll_count = 0) => Skipping."); - ds->poll_count = poll_count; - continue; - } ds->poll_count = poll_count; if ((read_ops == 0) && (write_ops == 0)) { @@ -936,58 +877,56 @@ static int disk_read(void) { continue; } metric_t m = {0}; - metric_label_set(&m, "device", output_name); + metric_label_set(&m, device_label, output_name); if ((ds->read_bytes != 0) || (ds->write_bytes != 0)) { - metric_family_append(&fam_io, "direction", "read", + metric_family_append(&fam_io, direction_label, read_direction, (value_t){.counter = (counter_t)ds->read_bytes}, &m); - metric_family_append(&fam_io, "direction", "write", + metric_family_append(&fam_io, direction_label, write_direction, (value_t){.counter = (counter_t)ds->write_bytes}, &m); } - if ((ds->read_ops != 0) || (ds->write_ops != 0)) { - metric_family_append(&fam_ops, "direction", "read", - (value_t){.counter = (counter_t)ds->read_ops}, &m); - metric_family_append(&fam_ops, "direction", "write", - (value_t){.counter = (counter_t)ds->write_ops}, &m); + if ((read_ops != 0) || (write_ops != 0)) { + metric_family_append(&fam_ops, direction_label, read_direction, + (value_t){.counter = (counter_t)read_ops}, &m); + metric_family_append(&fam_ops, direction_label, write_direction, + (value_t){.counter = (counter_t)write_ops}, &m); } - if ((ds->avg_read_time != 0) || (ds->avg_write_time != 0)) { - metric_family_append(&fam_time, "direction", "read", - (value_t){.counter = (counter_t)ds->avg_read_time}, - &m); - metric_family_append(&fam_time, "direction", "write", - (value_t){.counter = (counter_t)ds->avg_write_time}, - &m); + if ((read_time_ms != 0) || (write_time_ms != 0)) { + metric_family_append(&fam_ops_time, direction_label, read_direction, + (value_t){.derive = read_time_ms * 1000}, &m); + metric_family_append(&fam_ops_time, direction_label, write_direction, + (value_t){.derive = write_time_ms * 1000}, &m); } - if (is_disk) { - if (ds->has_merged) { - metric_family_append(&fam_merged, "direction", "read", - (value_t){.counter = (counter_t)read_merged}, &m); - metric_family_append(&fam_merged, "direction", "write", - (value_t){.counter = (counter_t)write_merged}, &m); - } - if (ds->has_in_progress) { - m.value.gauge = in_progress; - metric_family_metric_append(&fam_disk_pending_operations, m); - } - if (ds->has_io_time) { - m.value.counter = (counter_t)io_time; - metric_family_metric_append(&fam_disk_io_time, m); - } - m.value.counter = (counter_t)weighted_time; - metric_family_metric_append(&fam_disk_io_weighted_time, m); + if (read_merged != 0 || write_merged != 0) { + metric_family_append(&fam_merged, direction_label, read_direction, + (value_t){.counter = (counter_t)read_merged}, &m); + metric_family_append(&fam_merged, direction_label, write_direction, + (value_t){.counter = (counter_t)write_merged}, &m); + } - long interval = CDTIME_T_TO_MS(plugin_get_interval()); - if (interval == 0) { - DEBUG("disk plugin: got zero plugin interval"); - } + if (!isnan(in_progress)) { + m.value.gauge = in_progress; + metric_family_metric_append(&fam_disk_pending_operations, m); + } + + if (io_time_ms != 0) { + m.value.derive = 1000 * io_time_ms; + metric_family_metric_append(&fam_disk_io_time, m); + } - m.value.gauge = ((diff_io_time / (double)interval) * 100.0); - metric_family_metric_append(&fam_disk_utilization, m); - } /* if (is_disk) */ + if (weighted_time != 0) { + m.value.counter = weighted_time; + metric_family_metric_append(&fam_disk_io_weighted_time, m); + } + + if (!isnan(io_time_rate_ms)) { + m.value.gauge = io_time_rate_ms / 1000.0; + metric_family_metric_append(&fam_utilization, m); + } metric_reset(&m); @@ -1028,16 +967,12 @@ static int disk_read(void) { #define KIO_WOCTETS writes #define KIO_ROPS nreads #define KIO_WOPS nwrites -#define KIO_RTIME rtime -#define KIO_WTIME wtime #elif HAVE_KSTAT_IO_T_NWRITTEN && HAVE_KSTAT_IO_T_WRITES && \ HAVE_KSTAT_IO_T_WTIME #define KIO_ROCTETS nread #define KIO_WOCTETS nwritten #define KIO_ROPS reads #define KIO_WOPS writes -#define KIO_RTIME rtime -#define KIO_WTIME wtime #else #error "kstat_io_t does not have the required members" #endif @@ -1059,24 +994,31 @@ static int disk_read(void) { } metric_t m = {0}; - metric_label_set(&m, "device", ksp[i]->ks_name); + metric_label_set(&m, device_label, ksp[i]->ks_name); - metric_family_append(&fam_io, "direction", "read", + metric_family_append(&fam_io, direction_label, read_direction, (value_t){.counter = kio.KIO_ROCTETS}, &m); - metric_family_append(&fam_io, "direction", "write", + metric_family_append(&fam_io, direction_label, write_direction, (value_t){.counter = kio.KIO_WOCTETS}, &m); - metric_family_append(&fam_ops, "direction", "read", + metric_family_append(&fam_ops, direction_label, read_direction, (value_t){.counter = kio.KIO_ROPS}, &m); - metric_family_append(&fam_ops, "direction", "write", + metric_family_append(&fam_ops, direction_label, write_direction, (value_t){.counter = kio.KIO_WOPS}, &m); - if (strncmp(ksp[i]->ks_class, "disk", 4) == 0) { - /* FIXME: Convert this to microseconds if necessary */ - metric_family_append(&fam_time, "direction", "read", - (value_t){.counter = kio.KIO_RTIME}, &m); - metric_family_append(&fam_time, "direction", "write", - (value_t){.counter = kio.KIO_WTIME}, &m); + if (strncmp(ksp[i]->ks_class, "disk", strlen("disk")) == 0) { + hrtime_t run_time_ns = kio.rtime; + m.value.derive = (derive_t)(run_time_ns / 1000); + metric_family_metric_append(&fam_disk_io_time, m); + + hrtime_t weighted_io_time_ns = kio.rlentime; + m.value.derive = (derive_t)(weighted_io_time_ns / 1000000); + metric_family_metric_append(&fam_disk_io_weighted_time, m); + + uint_t ops_waiting = kio.wcnt; + uint_t ops_running = kio.rcnt; + m.value.gauge = (gauge_t)(ops_running + ops_waiting); + metric_family_metric_append(&fam_disk_pending_operations, m); } metric_reset(&m); @@ -1100,11 +1042,11 @@ static int disk_read(void) { continue; } metric_t m = {0}; - metric_label_set(&m, "device", ds->disk_name); + metric_label_set(&m, device_label, ds->disk_name); - metric_family_append(&fam_io, "direction", "read", + metric_family_append(&fam_io, direction_label, read_direction, (value_t){.counter = ds->read_bytes}, &m); - metric_family_append(&fam_io, "direction", "write", + metric_family_append(&fam_io, direction_label, write_direction, (value_t){.counter = ds->write_bytes}, &m); metric_reset(&m); @@ -1138,39 +1080,38 @@ static int disk_read(void) { if (ignorelist_match(ignorelist, stat_disk[i].name) != 0) continue; metric_t m = {0}; - metric_label_set(&m, "device", stat_disk[i].name); + metric_label_set(&m, device_label, stat_disk[i].name); - metric_family_append(&fam_io, "direction", "read", + metric_family_append(&fam_io, direction_label, read_direction, (value_t){.counter = (counter_t)(stat_disk[i].rblks * stat_disk[i].bsize)}, &m); - metric_family_append(&fam_io, "direction", "write", + metric_family_append(&fam_io, direction_label, write_direction, (value_t){.counter = (counter_t)(stat_disk[i].wblks * stat_disk[i].bsize)}, &m); - metric_family_append(&fam_ops, "direction", "read", + metric_family_append(&fam_ops, direction_label, read_direction, (value_t){.counter = (counter_t)stat_disk[i].xrate}, &m); - metric_family_append(&fam_ops, "direction", "write", + metric_family_append(&fam_ops, direction_label, write_direction, (value_t){.counter = (counter_t)(stat_disk[i].xfers - stat_disk[i].xrate)}, &m); - derive_t read_time = stat_disk[i].rserv; - read_time *= ((double)(_system_configuration.Xint) / - (double)(_system_configuration.Xfrac)) / - 1000000.0; - derive_t write_time = stat_disk[i].wserv; - write_time *= ((double)(_system_configuration.Xint) / - (double)(_system_configuration.Xfrac)) / - 1000000.0; - metric_family_append(&fam_time, "direction", "read", - (value_t){.counter = (counter_t)read_time}, &m); - metric_family_append(&fam_time, "direction", "write", - (value_t){.counter = (counter_t)} write_time, &m); + double xintfrac = ((double)_system_configuration.Xint) / + ((double)_system_configuration.Xfrac); - metric_reset(&m); + derive_t read_time_ns = stat_disk[i].rserv * _system_configuration.Xint / + _system_configuration.Xfrac; + derive_t write_time_ns = stat_disk[i].wserv * _system_configuration.Xint / + _system_configuration.Xfrac; + metric_family_append(&fam_ops_time, direction_label, read_direction, + (value_t){.derive = read_time_ns / 1000}, &m); + metric_family_append(&fam_ops_time, direction_label, write_direction, + (value_t){.derive = write_time_ns / 1000, &m); + + metric_reset(&m); } /* #endif defined(HAVE_PERFSTAT) */ #elif HAVE_SYSCTL && KERNEL_NETBSD @@ -1217,19 +1158,20 @@ static int disk_read(void) { continue; metric_t m = {0}; - metric_label_set(&m, "device", drives[i].name); + metric_label_set(&m, device_label, drives[i].name); - metric_family_append(&fam_io, "direction", "read", + metric_family_append(&fam_io, direction_label, read_direction, (value_t){.counter = drives[i].rbytes}, &m); - metric_family_append(&fam_io, "direction", "write", + metric_family_append(&fam_io, direction_label, write_direction, (value_t){.counter = drives[i].wbytes}, &m); - metric_family_append(&fam_ops, "direction", "read", + metric_family_append(&fam_ops, direction_label, read_direction, (value_t){.counter = drives[i].rxfer}, &m); - metric_family_append(&fam_ops, "direction", "write", + metric_family_append(&fam_ops, direction_label, write_direction, (value_t){.counter = drives[i].wxfer}, &m); - m.value.counter = drives[i].time_sec * 1000 + drives[i].time_usec / 1000; + m.value.derive = ((derive_t)drives[i].time_sec * 1000000) + + ((derive_t)drives[i].time_usec); metric_family_metric_append(&fam_disk_io_time, m); metric_reset(&m);