net.opentsdb.core.DownsamplingSpecification Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opentsdb Show documentation
Show all versions of opentsdb Show documentation
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.
// 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();
}
}