All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.opentsdb.core.DownsamplingSpecification Maven / Gradle / Ivy

Go to download

OpenTSDB is a distributed, scalable Time Series Database (TSDB) written on top of HBase. OpenTSDB was written to address a common need: store, index and serve metrics collected from computer systems (network gear, operating systems, applications) at a large scale, and make this data easily accessible and graphable.

There is a newer version: 2.4.1
Show newest version
// This file is part of OpenTSDB.
// Copyright (C) 2015  The OpenTSDB Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2.1 of the License, or (at your
// option) any later version.  This program is distributed in the hope that it
// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
// General Public License for more details.  You should have received a copy
// of the GNU Lesser General Public License along with this program.  If not,
// see .
package net.opentsdb.core;

import java.util.NoSuchElementException;
import java.util.TimeZone;

import com.google.common.base.MoreObjects;
import net.opentsdb.utils.DateTime;

/**
 * Representation of a downsampling specification in a TSDB query.
 * @since 2.2
 */
public final class DownsamplingSpecification {
  /** Instance of a specification indicating no downsampling requested. */
  public static final DownsamplingSpecification NO_DOWNSAMPLER =
    new DownsamplingSpecification();

  /** Special value representing no downsampling interval given. */
  public static final long NO_INTERVAL = 0L;

  /** Special value representing no downsampling function given. */
  public static final Aggregator NO_FUNCTION = null;

  /** The default fill policy. */
  public static final FillPolicy DEFAULT_FILL_POLICY = FillPolicy.NONE;

  public static final HistogramAggregation NO_HIST_AGG = null;
  
  // Parsed downsample interval.
  private final long interval;
  
  //The string interval, e.g. 1h, 30d, etc
  private final String string_interval;
  
  // Parsed downsampler function.
  private final Aggregator function;
  
  // Parsed fill policy: whether to interpolate or to fill.
  private final FillPolicy fill_policy;
  
  // Whether or not to use the calendar for intervals
  private boolean use_calendar;
 
  // The user provided timezone for calendar alignment (defaults to UTC)
  private TimeZone timezone;

  private final HistogramAggregation hist_agg;
  
  /**
   * A specification indicating no downsampling is requested.
   */
  private DownsamplingSpecification() {
    interval = NO_INTERVAL;
    function = NO_FUNCTION;
    fill_policy = DEFAULT_FILL_POLICY;
    string_interval = null;
    use_calendar = false;
    timezone = DateTime.timezones.get(DateTime.UTC_ID);
    hist_agg = NO_HIST_AGG;
  }

  /**
   * Non-stringified, piecewise c-tor.
   * @param interval The downsampling interval, in milliseconds.
   * @param function The downsampling function.
   * @param fill_policy The policy specifying how to deal with missing data.
   * @throws IllegalArgumentException if any argument is invalid.
   * @deprecated since 2.3
   */
  public DownsamplingSpecification(final long interval,
      final Aggregator function, final FillPolicy fill_policy) {
    if (null == function) {
      throw new IllegalArgumentException("downsampling function cannot be null");
    }
    if (interval <= 0L) {
      throw new IllegalArgumentException("interval not > 0: " + interval);
    }
    if (null == fill_policy) {
      throw new IllegalArgumentException("fill policy cannot be null");
    }
    if (function == Aggregators.NONE) {
      throw new IllegalArgumentException("cannot use the NONE "
          + "aggregator for downsampling");
    }

    this.interval = interval;
    this.function = function;
    this.fill_policy = fill_policy;
    string_interval = null;
    use_calendar = false;
    timezone = DateTime.timezones.get(DateTime.UTC_ID);
    hist_agg = NO_HIST_AGG;
  }

  /**
   * C-tor for string representations.
   * The argument to this c-tor should have the following format:
   * {@code interval-function[-fill_policy]}.
   * This ctor supports the "all" flag to downsample to a single value as well
   * as units suffixed with 'c' to use the calendar for downsample alignment.
   * @param specification String representation of a downsample specifier.
   * @throws IllegalArgumentException if the specification is null or invalid.
   */
  public DownsamplingSpecification(final String specification) {
    if (null == specification) {
      throw new IllegalArgumentException("Downsampling specifier cannot be " +
        "null");
    }

    final String[] parts = specification.split("-");
    if (parts.length < 2) {
      // Too few items.
      throw new IllegalArgumentException("Invalid downsampling specifier '" +
        specification + "': must provide at least interval and function");
    } else if (parts.length > 3) {
      // Too many items.
      throw new IllegalArgumentException("Invalid downsampling specifier '" +
        specification + "': must consist of interval, function, and optional " +
        "fill policy");
    }

    // This porridge is just right.

    // INTERVAL.
    // This will throw if interval is invalid.
    if (parts[0].contains("all")) {
      interval = NO_INTERVAL;
      use_calendar = false;
      string_interval = parts[0];
    } else if (parts[0].charAt(parts[0].length() - 1) == 'c') {
      final String duration = parts[0].substring(0, parts[0].length() - 1);
      interval = DateTime.parseDuration(duration);
      string_interval = duration;
      use_calendar = true;
    } else {
      interval = DateTime.parseDuration(parts[0]);
      use_calendar = false;
      string_interval = parts[0];
    }

    if (parts[1].toLowerCase().equals("sum")) {
      hist_agg = HistogramAggregation.SUM;
    } else {
      hist_agg = null;
    }
    
    // FUNCTION.
    try {
      function = Aggregators.get(parts[1]);
    } catch (final NoSuchElementException e) {
      throw new IllegalArgumentException("No such downsampling function: " +
        parts[1]);
    }
    if (function == Aggregators.NONE) {
      throw new IllegalArgumentException("cannot use the NONE "
          + "aggregator for downsampling");
    }

    // FILL POLICY.
    if (3 == parts.length) {
      // If the user gave us three parts, then the third must be a fill
      // policy.
      fill_policy = FillPolicy.fromString(parts[2]);
      if (null == fill_policy) {
        final StringBuilder oss = new StringBuilder();
        oss.append("No such fill policy: '").append(parts[2])
           .append("': must be one of:");
        for (final FillPolicy policy : FillPolicy.values()) {
          oss.append(" ").append(policy.getName());
        }

        throw new IllegalArgumentException(oss.toString());
      }
    } else {
      // Default to linear interpolation.
      fill_policy = FillPolicy.NONE;
    }
    timezone = DateTime.timezones.get(DateTime.UTC_ID);
  }

  /** @param use_calendar Whether or not to use the calendar when downsampling 
   * @since 2.3 */
  public void setUseCalendar(final boolean use_calendar) {
    this.use_calendar = use_calendar;
  }
  
  /** @param timezone The timezone to use when downsampling on calendar 
   * boundaries.
   * @since 2.3 */
  public void setTimezone(final TimeZone timezone) {
    if (timezone == null) {
      throw new IllegalArgumentException("Timezone cannot be null");
    }
    this.timezone = timezone;
  }
  
  /**
   * Get the downsampling interval, in milliseconds.
   * @return the downsampling interval, in milliseconds.
   */
  public long getInterval() {
    return interval;
  }

  /** @return The string interval from the user (without the 'c' if given) 
   * @since 2.3 */
  public String getStringInterval() {
    return string_interval;
  }
  
  /**
   * Get the downsampling function.
   * @return the downsampling function.
   */
  public Aggregator getFunction() {
    return function;
  }

  /**
   * Get the policy specifying how to deal with missing data.
   * @return the policy specifying how to deal with missing data.
   */
  public FillPolicy getFillPolicy() {
    return fill_policy;
  }

  /** @return Whether or not to use the calendar when downsampling 
   * @since 2.3 */
  public boolean useCalendar() {
    return use_calendar;
  }
  
  /** @return The timezone to use when downsampling on calendar boundaries.
   * @since 2.3 */
  public TimeZone getTimezone() {
    return timezone;
  }
  
  public HistogramAggregation getHistogramAggregation() {
    return hist_agg;
  }
  
  @Override
  public String toString() {
    return MoreObjects.toStringHelper(this)
      .add("interval", getInterval())
      .add("function", getFunction())
      .add("fillPolicy", getFillPolicy())
      .add("stringInterval", string_interval)
      .add("useCalendar", useCalendar())
      .add("timeZone", getTimezone() != null ? getTimezone().getID() : null)
      .toString();
  }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy