예제 #1
0
 /**
  * The 'closes' the rrd file. This is where the actual work of writing the RRD files takes place.
  * The passed in rrd is actually an rrd command string containing updates. This method executes
  * this command.
  *
  * @param rrd a {@link java.lang.StringBuffer} object.
  * @throws java.lang.Exception if any.
  */
 @Override
 public void closeFile(StringBuffer rrd) throws Exception {
   String command = rrd.toString();
   String[] results = Interface.launch(command);
   if (results[0] != null) {
     throw new Exception(results[0]);
   }
 }
예제 #2
0
  /**
   * Creates a the rrd file from the rrdDefinition. Since this definition is really just the create
   * command string it just executes it.
   *
   * @param createCommand a {@link java.lang.String} object.
   * @throws java.lang.Exception if any.
   */
  @Override
  public void createFile(CreateCommand createCommand, Map<String, String> attributeMappings)
      throws Exception {
    if (createCommand == null) {
      LOG.debug("createRRD: skipping RRD file");
      return;
    }
    LOG.debug("Executing: rrdtool {}", createCommand.toString());
    Interface.launch(createCommand.toString());

    String filenameWithoutExtension = createCommand.filename.replace(RrdUtils.getExtension(), "");
    int lastIndexOfSeparator = filenameWithoutExtension.lastIndexOf(File.separator);

    RrdUtils.createMetaDataFile(
        filenameWithoutExtension.substring(0, lastIndexOfSeparator),
        filenameWithoutExtension.substring(lastIndexOfSeparator),
        attributeMappings);
  }
예제 #3
0
  /** {@inheritDoc} */
  @Override
  public Double fetchLastValueInRange(String rrdFile, String ds, int interval, int range)
      throws NumberFormatException, RrdException {
    // Generate rrd_fetch() command through jrrd JNI interface in order to
    // retrieve
    // LAST pdp for the datasource stored in the specified RRD file
    //
    // String array returned from launch() native method format:
    // String[0] - If success is null, otherwise contains reason for failure
    // String[1] - All data source names contained in the RRD (space
    // delimited)
    // String[2]...String[n] - RRD fetch data in the following format:
    // <timestamp> <value1> <value2> ... <valueX> where X is
    // the total number of data sources
    //
    // NOTE: Specifying start time of 'now-<interval>' and
    // end time of 'now-<interval>' where <interval> is the
    // configured thresholding interval (and should be the
    // same as the RRD step size) in order to guarantee that
    // we don't get a 'NaN' value from the fetch command. This
    // is necessary because the collection is being done by collectd
    // and there is nothing keeping us in sync.
    //
    // interval argument is in milliseconds so must convert to seconds
    //

    // TODO: Combine fetchLastValueInRange and fetchLastValue

    long now = System.currentTimeMillis();
    long latestUpdateTime = (now - (now % interval)) / 1000L;
    long earliestUpdateTime = ((now - (now % interval)) - range) / 1000L;

    LOG.debug("fetchInRange: fetching data from {} to {}", earliestUpdateTime, latestUpdateTime);

    String fetchCmd =
        "fetch " + rrdFile + " AVERAGE -s " + earliestUpdateTime + " -e " + latestUpdateTime;

    String[] fetchStrings = Interface.launch(fetchCmd);

    // Sanity check the returned string array
    if (fetchStrings == null) {
      LOG.error(
          "fetchInRange: Unexpected error issuing RRD 'fetch' command, no error text available.");
      return null;
    }

    // Check error string at index 0, will be null if 'fetch' was successful
    if (fetchStrings[0] != null) {
      LOG.error("fetchInRange: RRD database 'fetch' failed, reason: {}", fetchStrings[0]);
      return null;
    }

    // Sanity check
    if (fetchStrings[1] == null || fetchStrings[2] == null) {
      LOG.error("fetchInRange: RRD database 'fetch' failed, no data retrieved.");
      return null;
    }

    int numFetched = fetchStrings.length;

    LOG.debug("fetchInRange: got {} strings from RRD", numFetched);

    // String at index 1 contains the RRDs datasource names
    //
    String[] dsNames = fetchStrings[1].split("\\s");
    int dsIndex = 0;
    for (int i = 0; i < dsNames.length; i++) {
      if (dsNames[i].equals(ds)) dsIndex = i;
    }
    String dsName = dsNames[dsIndex].trim();

    Double dsValue;

    // Back through the RRD output until I get something interesting

    for (int i = fetchStrings.length - 2; i > 1; i--) {
      String[] dsValues = fetchStrings[i].split("\\s");
      if (dsValues[dsIndex].trim().equalsIgnoreCase("nan")) {
        LOG.debug("fetchInRange: Got a NaN value - continuing back in time");
      } else {
        try {
          dsValue = new Double(dsValues[dsIndex].trim());
          LOG.debug("fetchInRange: fetch successful: {}= {}", dsName, dsValue);
          return dsValue;
        } catch (NumberFormatException nfe) {
          LOG.warn(
              "fetchInRange: Unable to convert fetched value ({}) to Double for data source {}",
              dsValues[dsIndex].trim(),
              dsName);
          throw nfe;
        }
      }
    }

    return null;
  }
예제 #4
0
  /** {@inheritDoc} */
  @Override
  public Double fetchLastValue(
      String rrdFile, String ds, String consolidationFunction, int interval) {
    /*
     * Generate rrd_fetch() command through jrrd JNI interface in order to
     * retrieve LAST pdp for the datasource stored in the specified RRD
     * file.
     *
     * String array returned from launch() native method format:
     *      String[0] - If success is null, otherwise contains reason
     *                  for failure
     *      String[1] - All data source names contained in the RRD (space
     *                  delimited)
     *      String[2 ... n] - RRD fetch data in the following format:
     *                      <timestamp> <value1> <value2> ... <valueX>
     *                  X is the total number of data sources.
     *
     * NOTE: Specifying start time of 'now-<interval>' and end time of
     * 'now-<interval>' where <interval> is the configured thresholding
     * interval (and should be the same as the RRD step size) in order to
     * guarantee that we don't get a 'NaN' value from the fetch command.
     * This is necessary because the collection is being done by collectd at
     * effectively random times and there is nothing keeping us in sync.
     *
     * interval argument is in milliseconds so must convert to seconds
     */

    // TODO: Combine fetchLastValueInRange and fetchLastValue
    String fetchCmd =
        "fetch "
            + rrdFile
            + " "
            + consolidationFunction
            + " -s now-"
            + interval / 1000
            + " -e now-"
            + interval / 1000;

    LOG.debug("fetch: Issuing RRD command: {}", fetchCmd);

    String[] fetchStrings = Interface.launch(fetchCmd);

    // Sanity check the returned string array
    if (fetchStrings == null) {
      LOG.error("fetch: Unexpected error issuing RRD 'fetch' command, no error text available.");
      return null;
    }

    // Check error string at index 0, will be null if 'fetch' was successful
    if (fetchStrings[0] != null) {
      LOG.error("fetch: RRD database 'fetch' failed, reason: {}", fetchStrings[0]);
      return null;
    }

    // Sanity check
    if (fetchStrings[1] == null || fetchStrings[2] == null) {
      LOG.error("fetch: RRD database 'fetch' failed, no data retrieved.");
      return null;
    }

    // String at index 1 contains the RRDs datasource names
    //
    String[] dsNames = fetchStrings[1].split("\\s");
    int dsIndex = 0;
    for (int i = 0; i < dsNames.length; i++) {
      if (dsNames[i].equals(ds)) dsIndex = i;
    }
    String dsName = dsNames[dsIndex].trim();

    // String at index 2 contains fetched values for the current time
    // Convert value string into a Double
    //
    String[] dsValues = fetchStrings[2].split("\\s");
    Double dsValue = null;
    if (dsValues[dsIndex].trim().equalsIgnoreCase("nan")) {
      dsValue = new Double(Double.NaN);
    } else {
      try {
        dsValue = new Double(dsValues[dsIndex].trim());
      } catch (NumberFormatException nfe) {
        LOG.warn(
            "fetch: Unable to convert fetched value ({}) to Double for data source {}",
            dsValues[dsIndex].trim(),
            dsName);
        throw nfe;
      }
    }

    LOG.debug("fetch: fetch successful: {}={}", dsName, dsValue);

    return dsValue;
  }