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

net.opentsdb.query.pojo.Query 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.query.pojo;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.common.base.Objects;

import net.opentsdb.utils.JSON;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Pojo builder class used for serdes of the expression query
 * @since 2.3
 */
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonDeserialize(builder = Query.Builder.class)
public class Query extends Validatable {
  /** An optional name for the query */
  private String name;
  
  /** The timespan component of the query */
  private Timespan time;
  
  /** A list of filters */
  private List filters;
  
  /** A list of metrics */
  private List metrics;
  
  /** A list of expressions */
  private List expressions;
  
  /** A list of outputs */
  private List outputs;

  /**
   * Default ctor
   * @param builder The builder to pull values from
   */
  public Query(Builder builder) {
    this.name = builder.name;
    this.time = builder.time;
    this.filters = builder.filters;
    this.metrics = builder.metrics;
    this.expressions = builder.expressions;
    this.outputs = builder.outputs;
  }

  /** @return an optional name for the query */
  public String getName() {
    return name;
  }

  /** @return the timespan component of the query */
  public Timespan getTime() {
    return time;
  }

  /** @return a list of filters */
  public List getFilters() {
    return filters;
  }

  /** @return a list of metrics */
  public List getMetrics() {
    return metrics;
  }

  /** @return a list of expressions */
  public List getExpressions() {
    return expressions;
  }

  /** @return a list of outputs */
  public List getOutputs() {
    return outputs;
  }

  /** @return A new builder for the query */
  public static Builder Builder() {
    return new Builder();
  }
  
  /** Validates the query
   * @throws IllegalArgumentException if one or more parameters were invalid
   */
  public void validate() {
    if (time == null) {
      throw new IllegalArgumentException("missing time");
    }

    validatePOJO(time, "time");

    if (metrics == null || metrics.isEmpty()) {
      throw new IllegalArgumentException("missing or empty metrics");
    }

    final Set variable_ids = new HashSet();
    for (Metric metric : metrics) {
      if (variable_ids.contains(metric.getId())) {
        throw new IllegalArgumentException("duplicated metric id: "
            + metric.getId());
      }
      variable_ids.add(metric.getId());
    }

    final Set filter_ids = new HashSet();

    for (Filter filter : filters) {
      if (filter_ids.contains(filter.getId())) {
        throw new IllegalArgumentException("duplicated filter id: "
            + filter.getId());
      }
      filter_ids.add(filter.getId());
    }
    
    for (Expression expression : expressions) {
      if (variable_ids.contains(expression.getId())) {
        throw new IllegalArgumentException("Duplicated variable or expression id: "
            + expression.getId());
      }
      variable_ids.add(expression.getId());
    }

    validateCollection(metrics, "metric");

    if (filters != null) {
      validateCollection(filters, "filter");
    }

    if (expressions != null) {
      validateCollection(expressions, "expression");
    }

    validateFilters();
    
    if (expressions != null) {
      validateCollection(expressions, "expression");
      for (final Expression exp : expressions) {
        if (exp.getVariables() == null) {
          throw new IllegalArgumentException("No variables found for an "
              + "expression?! " + JSON.serializeToString(exp));
        }
        
        for (final String var : exp.getVariables()) {
          if (!variable_ids.contains(var)) {
            throw new IllegalArgumentException("Expression [" + exp.getExpr() 
              + "] was missing input " + var);
          }
        }
      }
    }
  }

  /** Validates the filters, making sure each metric has a filter
   * @throws IllegalArgumentException if one or more parameters were invalid
   */
  private void validateFilters() {
    Set ids = new HashSet();
    for (Filter filter : filters) {
      ids.add(filter.getId());
    }

    for(Metric metric : metrics) {
      if (metric.getFilter() != null && 
          !metric.getFilter().isEmpty() && 
          !ids.contains(metric.getFilter())) {
        throw new IllegalArgumentException(
            String.format("unrecognized filter id %s in metric %s",
                metric.getFilter(), metric.getId()));
      }
    }
  }
  
  /**
   * Makes sure the ID has only letters and characters
   * @param id The ID to parse
   * @throws IllegalArgumentException if the ID is invalid
   */
  public static void validateId(final String id) {
    if (id == null || id.isEmpty()) {
      throw new IllegalArgumentException("The ID cannot be null or empty");
    }
    for (int i = 0; i < id.length(); i++) {
      final char c = id.charAt(i);
      if (!(Character.isLetterOrDigit(c))) {
        throw new IllegalArgumentException("Invalid id (\"" + id + 
            "\"): illegal character: " + c);
      }
    }
    if (id.length() == 1) {
      if (Character.isDigit(id.charAt(0))) {
        throw new IllegalArgumentException("The ID cannot be an integer");
      }
    }
  }

  @Override
  public boolean equals(Object o) {
    if (this == o)
      return true;
    if (o == null || getClass() != o.getClass())
      return false;

    Query query = (Query) o;

    return Objects.equal(query.expressions, expressions)
        && Objects.equal(query.filters, filters)
        && Objects.equal(query.metrics, metrics)
        && Objects.equal(query.name, name)
        && Objects.equal(query.outputs, outputs)
        && Objects.equal(query.time, time);
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(name, time, filters, metrics, expressions, outputs);
  }

  /**
   * A builder for the query component of a query
   */
  @JsonIgnoreProperties(ignoreUnknown = true)
  @JsonPOJOBuilder(buildMethodName = "build", withPrefix = "")
  public static final class Builder {
    @JsonProperty
    private String name;
    @JsonProperty
    private Timespan time;
    @JsonProperty
    private List filters;
    @JsonProperty
    private List metrics;
    @JsonProperty
    private List expressions;
    @JsonProperty
    private List outputs;

    public Builder() { }

    public Builder setName(final String name) {
      this.name = name;
      return this;
    }

    public Builder setTime(final Timespan time) {
      this.time = time;
      return this;
    }

    public Builder setFilters(final List filters) {
      this.filters = filters;
      return this;
    }

    public Builder setMetrics(final List metrics) {
      this.metrics = metrics;
      return this;
    }

    public Builder setExpressions(final List expressions) {
      this.expressions = expressions;
      return this;
    }

    public Builder setOutputs(final List outputs) {
      this.outputs = outputs;
      return this;
    }

    public Query build() {
      return new Query(this);
    }
  }
  
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy