private void collectData(int numRrdStepIterations) throws Exception { String rrdFilename = jmxCollector.getRrdPath(); rrdDb = new RrdDb(rrdFilename); Header header = rrdDb.getHeader(); // Wait for "n" iterations of RRDB's sample rate, then see if MBean value was collected LOGGER.debug("Sleeping for " + (header.getStep() * numRrdStepIterations) + " seconds"); Thread.sleep((header.getStep() * numRrdStepIterations) * 1000); // LOGGER.debug(rrdDb.dump()); long endTime = Calendar.getInstance().getTimeInMillis() / 1000; // +1 because the fetch gets data for times inclusively, e.g., // endTime=12345, so startTime=12345-4=12341, // then fetch data for timestamps 12341, 12342, 12343, 12344, 12345 (which is 5 values) long startTime = endTime - numRrdStepIterations + 1; LOGGER.debug("startTime = " + startTime + ", endTime = " + endTime); FetchRequest fetchRequest = rrdDb.createFetchRequest(ConsolFun.TOTAL, startTime, endTime); FetchData fetchData = fetchRequest.fetchData(); double[] values = fetchData.getValues(dataSourceName); assertThat(values.length, is(numRrdStepIterations)); logFetchData(fetchData, "TOTAL"); fetchRequest = rrdDb.createFetchRequest(ConsolFun.AVERAGE, startTime, endTime); fetchData = fetchRequest.fetchData(); values = fetchData.getValues(dataSourceName); assertThat(values.length, is(numRrdStepIterations)); logFetchData(fetchData, "AVERAGE"); fetchRequest = rrdDb.createFetchRequest(ConsolFun.MIN, startTime, endTime); fetchData = fetchRequest.fetchData(); values = fetchData.getValues(dataSourceName); assertThat(values.length, is(numRrdStepIterations)); logFetchData(fetchData, "MIN"); fetchRequest = rrdDb.createFetchRequest(ConsolFun.MAX, startTime, endTime); fetchData = fetchRequest.fetchData(); values = fetchData.getValues(dataSourceName); assertThat(values.length, is(numRrdStepIterations)); logFetchData(fetchData, "MAX"); }
private Map<Long, ArrayList<String>> addRrdData( Map<Long, ArrayList<String>> data, String itemName, ConsolFun consilidationFunction, Date timeBegin, Date timeEnd, long resolution) throws IOException { RrdDb rrdDb = new RrdDb(RRD_FOLDER + File.separator + itemName + ".rrd"); FetchRequest fetchRequest = rrdDb.createFetchRequest( consilidationFunction, Util.getTimestamp(timeBegin), Util.getTimestamp(timeEnd), resolution); FetchData fetchData = fetchRequest.fetchData(); // logger.info(fetchData.toString()); long[] timestamps = fetchData.getTimestamps(); double[][] values = fetchData.getValues(); logger.debug( "RRD fetch returned '{}' rows and '{}' columns", fetchData.getRowCount(), fetchData.getColumnCount()); for (int row = 0; row < fetchData.getRowCount(); row++) { // change to microseconds long time = timestamps[row] * 1000; if (!data.containsKey(time)) { data.put(time, new ArrayList<String>()); } ArrayList<String> vals = data.get(time); int indexOffset = vals.size(); for (int dsIndex = 0; dsIndex < fetchData.getColumnCount(); dsIndex++) { vals.add(dsIndex + indexOffset, formatDouble(values[dsIndex][row], "null", true)); } } rrdDb.close(); return data; }
/** * Retrieves the RRD stored data for the specified metric over the specified time range. * * @param rrdFilename the name of the RRD file containing the metric's data * @param startTime start time, in seconds since Unix epoch, to fetch metric's data * @param endTime end time, in seconds since Unix epoch, to fetch metric's data * @return domain object containing the metric's sampled data, which consists of the timestamps * and their associated values, and the total count of the sampled data * @throws IOException * @throws MetricsGraphException */ private MetricData getMetricData(String rrdFilename, long startTime, long endTime) throws IOException, MetricsGraphException { LOGGER.trace("ENTERING: getMetricData"); // Create RRD DB in read-only mode for the specified RRD file RrdDb rrdDb = new RrdDb(rrdFilename, true); // Extract the data source (should always only be one data source per RRD file - otherwise we // have a problem) if (rrdDb.getDsCount() != 1) { throw new MetricsGraphException( "Only one data source per RRD file is supported - RRD file " + rrdFilename + " has " + rrdDb.getDsCount() + " data sources."); } // The step (sample) interval that determines how often RRD collects the metric's data long rrdStep = rrdDb.getRrdDef().getStep(); // Retrieve the RRD file's data source type (COUNTER or GAUGE) to determine how (later) // to store the metric's data for presentation. DsType dataSourceType = rrdDb.getDatasource(0).getType(); // Fetch the metric's data from the RRD file for the specified time range FetchRequest fetchRequest = rrdDb.createFetchRequest(ConsolFun.TOTAL, startTime, endTime); FetchData fetchData = fetchRequest.fetchData(); long[] timestamps = fetchData.getTimestamps(); double[] values = fetchData.getValues(0); // Done retrieving data from the RRD database - close it, otherwise no one else will // be able to access it later. rrdDb.close(); // The lists of the metric's timestamps and their associated values that have non-"NaN" values List<Long> validTimestamps = new ArrayList<Long>(); List<Double> validValues = new ArrayList<Double>(); long totalCount = 0; MetricData metricData = new MetricData(); if (dataSourceType == DsType.COUNTER) { // Counters are for constantly incrementing data, hence they can // have a summation of their totals metricData.setHasTotalCount(true); for (int i = 0; i < timestamps.length; i++) { // Filter out the RRD values that have not yet been sampled (they will // have been set to NaN as a placeholder when the RRD file was created) if (!Double.toString(values[i]).equals("NaN")) { // RRD averages the collected samples over the step interval. // To "undo" this averaging and get the actual count, need to // multiply the sampled data value by the RRD step interval. double nonAveragedValue = (double) (values[i] * rrdStep); validTimestamps.add(timestamps[i]); validValues.add(nonAveragedValue); totalCount += (long) nonAveragedValue; } } } else if (dataSourceType == DsType.GAUGE) { // Gauges are for data that waxes and wanes, hence no total count metricData.setHasTotalCount(false); for (int i = 0; i < timestamps.length; i++) { // Filter out the RRD values that have not yet been sampled (they will // have been set to NaN as a placeholder when the RRD file was created) if (!Double.toString(values[i]).equals("NaN")) { validTimestamps.add(timestamps[i]); validValues.add(values[i]); } } } metricData.setTimestamps(validTimestamps); metricData.setValues(validValues); metricData.setTotalCount(totalCount); LOGGER.trace("EXITING: getMetricData"); return metricData; }