From 6b4fde56c629c6f7d7cb1bfe5fe82657a18cda33 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Fri, 16 May 2014 12:06:52 -0500 Subject: [PATCH] rrd_fetch: improve resolution-related parameters The interface now accepts scaled durations (e.g., 5m) for the resolution. A new option automatically performs the start time alignment discussed in the documentation. --- doc/rrdfetch.pod | 38 +++++++++++++++++++++++++++----------- src/rrd_fetch.c | 28 ++++++++++++++++++---------- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/doc/rrdfetch.pod b/doc/rrdfetch.pod index 29f91bc4..47f06098 100644 --- a/doc/rrdfetch.pod +++ b/doc/rrdfetch.pod @@ -33,8 +33,11 @@ want to fetch (AVERAGE,MIN,MAX,LAST) =item B<--resolution>|B<-r> I (default is the highest resolution) the interval you want the values to have (seconds per -value). B will try to match your request, but it will return -data even if no absolute match is possible. B See note below. +value). +An L may be used +(e.g. C<5m> instead of C<300> seconds). +B will try to match your request, but it will return +data even if no absolute match is possible. See L. =item B<--start>|B<-s> I (default end-1day) @@ -49,6 +52,14 @@ the end of the time series in seconds since epoch. See also AT-STYLE TIME SPECIFICATION section for a detailed explanation of how to specify the end time. +=item B<--align-start>|B<-a> + +Automatically adjust the start time down to be aligned with the +resolution. The end-time is adjusted by the same amount. This avoids +the need for external calculations described in L, though if a specific RRA is desired this will not ensure +the start and end fall within its bounds. + =item B<--daemon> I
Address of the L daemon. If specified, a C command is sent @@ -73,13 +84,14 @@ In order to get RRDtool to fetch anything other than the finest resolution RRA B the start and end time must be specified on boundaries that are multiples of the desired resolution. Consider the following example: - rrdtool create subdata.rrd -s 10 DS:ds0:GAUGE:300:0:U \ - RRA:AVERAGE:0.5:30:3600 \ - RRA:AVERAGE:0.5:90:1200 \ - RRA:AVERAGE:0.5:360:1200 \ - RRA:MAX:0.5:360:1200 \ - RRA:AVERAGE:0.5:8640:600 \ - RRA:MAX:0.5:8640:600 + rrdtool create subdata.rrd -s 10 \ + DS:ds0:GAUGE:5m:0:U \ + RRA:AVERAGE:0.5:5m:300h \ + RRA:AVERAGE:0.5:15m:300h \ + RRA:AVERAGE:0.5:1h:50d \ + RRA:MAX:0.5:1h:50d \ + RRA:AVERAGE:0.5:1d:600d \ + RRA:MAX:0.5:1d:600d This RRD collects data every 10 seconds and stores its averages over 5 minutes, 15 minutes, 1 hour, and 1 day, as well as the maxima for 1 hour @@ -88,7 +100,7 @@ and 1 day. Consider now that you want to fetch the 15 minute average data for the last hour. You might try - rrdtool fetch subdata.rrd AVERAGE -r 900 -s -1h + rrdtool fetch subdata.rrd AVERAGE -r 15m -s -1h However, this will almost always result in a time series that is B in the 15 minute RRA. Therefore, the highest resolution RRA, @@ -101,7 +113,7 @@ Hence, make sure that =item 1. -both start and end time are a multiple of 900 +both start and end time are a multiple of 900 (C<15m>) =item 2. @@ -128,6 +140,10 @@ Or in Perl: system "rrdtool fetch subdata.rrd AVERAGE \ -r $rrdres -e @{[int($ctime/$rrdres)*$rrdres]} -s e-1h"' +Or using the B<--align-start> flag: + + rrdtool fetch subdata.rrd AVERAGE -a -r 15m -s -1h + =head2 AT-STYLE TIME SPECIFICATION diff --git a/src/rrd_fetch.c b/src/rrd_fetch.c index d5e88a88..af74a2f6 100644 --- a/src/rrd_fetch.c +++ b/src/rrd_fetch.c @@ -70,18 +70,20 @@ int rrd_fetch( char ***ds_namv, /* names of data sources */ rrd_value_t **data) { /* two dimensional array containing the data */ - long step_tmp = 1; + unsigned long step_tmp = 1; time_t start_tmp = 0, end_tmp = 0; const char *cf; char *opt_daemon = NULL; + int align_start = 0; int status; rrd_time_value_t start_tv, end_tv; - char *parsetime_error = NULL; + const char *parsetime_error = NULL; struct option long_options[] = { {"resolution", required_argument, 0, 'r'}, {"start", required_argument, 0, 's'}, {"end", required_argument, 0, 'e'}, + {"align-start", optional_argument, 0, 'a'}, {"daemon", required_argument, 0, 'd'}, {0, 0, 0, 0} }; @@ -97,7 +99,7 @@ int rrd_fetch( int option_index = 0; int opt; - opt = getopt_long(argc, argv, "r:s:e:d:", long_options, &option_index); + opt = getopt_long(argc, argv, "ar:s:e:d:", long_options, &option_index); if (opt == EOF) break; @@ -115,8 +117,14 @@ int rrd_fetch( return -1; } break; + case 'a': + align_start = 1; + break; case 'r': - step_tmp = atol(optarg); + if ((parsetime_error = rrd_scaled_duration(optarg, 1, &step_tmp))) { + rrd_set_error("resolution: %s", parsetime_error); + return -1; + } break; case 'd': @@ -141,12 +149,17 @@ int rrd_fetch( return -1; } - if (start_tmp < 3600 * 24 * 365 * 10) { rrd_set_error("the first entry to fetch should be after 1980"); return (-1); } + if (align_start) { + time_t delta = (start_tmp % step_tmp); + start_tmp -= delta; + end_tmp -= delta; + } + if (end_tmp < start_tmp) { rrd_set_error("start (%ld) should be less than end (%ld)", start_tmp, end_tmp); @@ -155,11 +168,6 @@ int rrd_fetch( *start = start_tmp; *end = end_tmp; - - if (step_tmp < 1) { - rrd_set_error("step must be >= 1 second"); - return -1; - } *step = step_tmp; if (optind + 1 >= argc) { -- 2.47.2