/* * Copyright (c) 2015 Spotify AB. * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.spotify.heroic.metric; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.spotify.heroic.aggregation.AggregationCombiner; import com.spotify.heroic.common.DateRange; import com.spotify.heroic.common.OptionalLimit; import eu.toolchain.async.Collector; import java.util.ArrayList; import java.util.Collections; import java.util.List; import lombok.Data; @Data public class QueryResult { /** * The range in which all result groups metric's should be contained in. */ private final DateRange range; /** * Groups of results. * <p> * Failed groups are omitted from here, {@link #errors} for these. */ private final List<ShardedResultGroup> groups; /** * Errors that happened during the query. */ private final List<RequestError> errors; /** * Query trace, if available. */ private final QueryTrace trace; private final ResultLimits limits; private final long preAggregationSampleSize; /** * Collect result parts into a complete result. * * @param range The range which the result represents. * @return A complete QueryResult. */ public static Collector<QueryResultPart, QueryResult> collectParts( final QueryTrace.Identifier what, final DateRange range, final AggregationCombiner combiner, final OptionalLimit groupLimit ) { final QueryTrace.NamedWatch w = QueryTrace.watch(what); return parts -> { final List<List<ShardedResultGroup>> all = new ArrayList<>(); final List<RequestError> errors = new ArrayList<>(); final ImmutableList.Builder<QueryTrace> queryTraces = ImmutableList.builder(); final ImmutableSet.Builder<ResultLimit> limits = ImmutableSet.builder(); long preAggregationSampleSize = 0; for (final QueryResultPart part : parts) { errors.addAll(part.getErrors()); queryTraces.add(part.getQueryTrace()); limits.addAll(part.getLimits().getLimits()); preAggregationSampleSize += part.getPreAggregationSampleSize(); if (part.isEmpty()) { continue; } all.add(part.getGroups()); } final List<ShardedResultGroup> groups = combiner.combine(all); final QueryTrace trace = w.end(queryTraces.build()); if (groupLimit.isGreaterOrEqual(groups.size())) { limits.add(ResultLimit.GROUP); } return new QueryResult(range, groupLimit.limitList(groups), errors, trace, new ResultLimits(limits.build()), preAggregationSampleSize); }; } public static QueryResult error(DateRange range, String errorMessage, QueryTrace trace) { return new QueryResult(range, Collections.emptyList(), Collections.singletonList(QueryError.fromMessage(errorMessage)), trace, ResultLimits.of(), 0); } }