Skip to content
This repository has been archived by the owner on Mar 27, 2021. It is now read-only.

Commit

Permalink
merged in master
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Kingswell committed Feb 4, 2021
2 parents 03e58e4 + d7dde9e commit 5b8da86
Show file tree
Hide file tree
Showing 27 changed files with 466 additions and 296 deletions.
2 changes: 1 addition & 1 deletion docs/_layouts/api-endpoint.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ <h4>Example Request</h4>
<h4>Example Curl</h4>
<pre><code class="language-bash">
{%- capture headers %}
{%- unless page.empty %}-H "X-Client-Id: my_app_name" -H "Content-Type: application/json"
{%- unless page.empty %}-H "Content-Type: application/json"
{%
endunless %}
{%- endcapture %}
Expand Down
3 changes: 3 additions & 0 deletions docs/content/_endpoints/post-query-batch.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ response_fields:
purpose: Responses to each query run.
---
This accepts a JSON document where all keys are expected to map up to a Query.
<p></p>
<em>Note that the <code>x-client-id: my_app_name</code>
header must be supplied since anonymous requests are not permitted.</em>
38 changes: 37 additions & 1 deletion docs/content/_endpoints/post-query-metrics.md
Original file line number Diff line number Diff line change
@@ -1 +1,37 @@

---
method: POST
endpoint: /query/metrics
help: Query for metrics
description: Query and aggregate metrics.
fields:
- name: range
required: true
type_name: QueryDateRange
purpose: 'The range in time for which to query'
- name: filter
type_name: Filter
- name: aggregation
type_name: Aggregation
purpose: Aggregation to use when down-sampling.
- name: features
type_json: '[&lt;string&gt;, ...]'
purpose: |
Enable or disable a feature on a per-query basis.
See <a href="docs/config#features">Features Configuration</a> for more details.
response_fields:
- name: 'range'
type_json: '{start: &lt;number&gt;, end: &lt;number&gt;}'
purpose: 'The range in time for which to query'
- name: 'errors'
type_name: 'RequestError'
purpose: 'Potential errors returned either from different shards or for specific time series. The presence of an error does not cause the entire query to fail, instead it is up to the client to use this information to decide if the response is reliable enough.'
- name: 'result'
type_name: 'ShardedResultGroup'
type_array: true
purpose: 'An array of result groups.'
- name: 'statistics'
type_name: 'Statistics'
purpose: 'Statistics about the current query. This field should be inspected for errors which will have caused the result to be inconsistent.'
---
<em>Note that the <code>x-client-id: my_app_name</code>
header must be supplied since anonymous requests are not permitted.</em>
5 changes: 2 additions & 3 deletions heroic-component/src/main/java/com/spotify/heroic/Query.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ import java.util.*

data class Query(
val aggregation: Optional<Aggregation>,
val source: Optional<MetricType>,
val metricType: Optional<MetricType>, // points or distribution points for testing
val range: Optional<QueryDateRange>,
val filter: Optional<Filter>,
val options: Optional<QueryOptions>,
// set of experimental features to enable
val features: Optional<FeatureSet>
val features: Optional<FeatureSet> // set of experimental features to enable
)
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@
import org.slf4j.LoggerFactory;

public class QueryBuilder {
private Optional<MetricType> source = Optional.empty();
private Optional<Map<String, String>> tags = Optional.empty();
private Optional<String> key = Optional.empty();
private Optional<Filter> filter = Optional.empty();
private Optional<QueryDateRange> range = Optional.empty();
private Optional<MetricType> metricType = Optional.empty();
private Optional<Aggregation> aggregation = Optional.empty();
private Optional<QueryOptions> options = Optional.empty();
private Optional<JsonNode> clientContext = Optional.empty();
Expand Down Expand Up @@ -97,6 +97,15 @@ public QueryBuilder filter(final Optional<Filter> filter) {
return this;
}

/**
* Specify a metricType to use, if none are specified it will be determined in CoreQueryManager.
*/
public QueryBuilder metricType(final Optional<MetricType> metricType) {
checkNotNull(metricType, "metricType must not be null");
this.metricType = pickOptional(this.metricType, metricType);
return this;
}

/**
* Specify an aggregation to use.
*/
Expand All @@ -106,11 +115,6 @@ public QueryBuilder aggregation(final Optional<Aggregation> aggregation) {
return this;
}

public QueryBuilder source(Optional<MetricType> source) {
this.source = source;
return this;
}

public QueryBuilder options(final Optional<QueryOptions> options) {
checkNotNull(options, "options");
this.options = pickOptional(this.options, options);
Expand Down Expand Up @@ -146,7 +150,7 @@ public QueryBuilder features(final Optional<FeatureSet> features) {
}

public Query build() {
return new Query(aggregation, source, range, legacyFilter(), options, features);
return new Query(aggregation, metricType, range, legacyFilter(), options, features);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import java.util.*
data class QueryExpression(
@JvmField val context: Context,
val select: Optional<Expression>,
val source: Optional<MetricType>,
val metricType: Optional<MetricType>,
val range: Optional<RangeExpression>,
val filter: Optional<Filter>,
val with: Map<String, Expression>,
Expand All @@ -41,7 +41,7 @@ data class QueryExpression(
QueryExpression(
context,
select.map { it.eval(scope) },
source,
metricType,
range.map { it.eval(scope) },
filter,
Expression.evalMap(with, scope),
Expand All @@ -52,6 +52,6 @@ data class QueryExpression(
return visitor.visitQuery(this)
}

override fun toRepr() = """{select: $select source: $source,
override fun toRepr() = """{select: $select metricType: $metricType,
range: $range, filter: $filter, with: $with, as: $asExpression}""".trimIndent()
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ data class FetchData(
}

data class Request(
val type: MetricType,
val metricType: MetricType,
val series: Series,
val range: DateRange,
val options: QueryOptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,44 +158,45 @@ static Summary create(
public abstract static class Request {
@JsonCreator
public static Request create(
@JsonProperty("source") MetricType source,
@JsonProperty("filter") Filter filter,
@JsonProperty("range") DateRange range,
@JsonProperty("aggregation") AggregationInstance aggregation,
@JsonProperty("metricType") MetricType metricType,
@JsonProperty("options") QueryOptions options,
@JsonProperty("context") QueryContext context,
@JsonProperty("features") Features features
) {
return new AutoValue_FullQuery_Request(
source, filter, range, aggregation, options, context, features);
filter, range, aggregation, metricType, options, context, features);
}

@JsonProperty
public abstract MetricType source();

@JsonProperty
public abstract Filter filter();
@JsonProperty
public abstract DateRange range();
@JsonProperty
public abstract AggregationInstance aggregation();
@JsonProperty
public abstract MetricType metricType();
@JsonProperty
public abstract QueryOptions options();
@JsonProperty
public abstract QueryContext context();
@JsonProperty
public abstract Features features();

public Summary summarize() {
return Summary.create(source(), filter(), range(), aggregation(), options());
return Summary.create(filter(), range(), aggregation(), metricType(), options());
}

public void hashTo(final ObjectHasher hasher) {
hasher.putObject(getClass(), () -> {
hasher.putField("source", source(), hasher.enumValue());
hasher.putField("filter", filter(), hasher.with(Filter::hashTo));
hasher.putField("range", range(), hasher.with(DateRange::hashTo));
hasher.putField("aggregation", aggregation(),
hasher.with(AggregationInstance::hashTo));
hasher.putField("metricType", metricType(), hasher.enumValue());
hasher.putField("options", options(), hasher.with(QueryOptions::hashTo));
hasher.putField("features", features(), hasher.with(Features::hashTo));
});
Expand All @@ -205,25 +206,25 @@ public void hashTo(final ObjectHasher hasher) {
public abstract static class Summary {
@JsonCreator
public static Summary create(
@JsonProperty("source") MetricType source,
@JsonProperty("filter") Filter filter,
@JsonProperty("range") DateRange range,
@JsonProperty("aggregation") AggregationInstance aggregation,
@JsonProperty("metricType") MetricType metricType,
@JsonProperty("options") QueryOptions options
) {
return new AutoValue_FullQuery_Request_Summary(
source, filter, range, aggregation, options);
filter, range, aggregation, metricType, options);
}

@JsonProperty
abstract MetricType source();
@JsonProperty
abstract Filter filter();
@JsonProperty
abstract DateRange range();
@JsonProperty
abstract AggregationInstance aggregation();
@JsonProperty
abstract MetricType metricType();
@JsonProperty
abstract QueryOptions options();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ public abstract class QueryMetrics {
public static QueryMetrics create(
Optional<String> query,
Optional<Aggregation> aggregation,
Optional<String> source,
Optional<MetricType> metricType,
Optional<QueryDateRange> range,
Optional<Filter> filter,
Optional<QueryOptions> options,
Optional<JsonNode> clientContext
) {
return legacyCreate(query, aggregation, source, range, filter, options, clientContext,
return legacyCreate(query, aggregation, metricType, range, filter, options, clientContext,
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), false);
}
Expand All @@ -60,7 +60,7 @@ public static QueryMetrics create(
public static QueryMetrics legacyCreate(
@JsonProperty("query") Optional<String> query,
@JsonProperty("aggregation") Optional<Aggregation> aggregation,
@JsonProperty("source") Optional<String> source,
@JsonProperty("metricType") Optional<MetricType> metricType,
@JsonProperty("range") Optional<QueryDateRange> range,
@JsonProperty("filter") Optional<Filter> filter,
@JsonProperty("options") Optional<QueryOptions> options,
Expand All @@ -75,18 +75,17 @@ public static QueryMetrics legacyCreate(

final Optional<Aggregation> legitAggregation = firstPresent(aggregation,
aggregators.filter(c -> !c.isEmpty()).map(Chain::fromList));
final Optional<MetricType> sourceMetric = source.flatMap(MetricType::fromIdentifier);

return new AutoValue_QueryMetrics(query, legitAggregation, sourceMetric, range, filter,
return new AutoValue_QueryMetrics(query, legitAggregation, metricType, range, filter,
options, clientContext, key, tags, features);
}

@JsonProperty("query")
public abstract Optional<String> query();
@JsonProperty("aggregation")
public abstract Optional<Aggregation> aggregation();
@JsonProperty("source")
public abstract Optional<MetricType> source();
@JsonProperty("metricType")
public abstract Optional<MetricType> metricType();
@JsonProperty("range")
public abstract Optional<QueryDateRange> range();
@JsonProperty("filter")
Expand All @@ -111,7 +110,7 @@ public QueryBuilder toQueryBuilder(final Function<String, QueryBuilder> stringTo
.filter(filter())
.range(range())
.aggregation(aggregation())
.source(source())
.metricType(metricType())
.options(options())
.clientContext(clientContext());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void testAccessors() {
final QueryExpression e = build();

assertEquals(select, e.getSelect());
assertEquals(source, e.getSource());
assertEquals(source, e.getMetricType());
assertEquals(range, e.getRange());
assertEquals(filter, e.getFilter());
assertEquals(with, e.getWith());
Expand Down
1 change: 1 addition & 0 deletions heroic-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ dependencies {
// Default usage tracking module. Normally different module dependencies are handled in
// heroic-dist, but defaults need to be accessible in heroic-core.
implementation project(':heroic-usage-tracking-google-analytics')
implementation project(':heroic-aggregation-simple')

testImplementation project(':heroic-test')
testImplementation project(path: ':heroic-component', configuration: 'testRuntime')
Expand Down
Loading

0 comments on commit 5b8da86

Please sign in to comment.