/*
 * 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 org.apache.druid.query;

import org.apache.druid.collections.bitmap.BitmapFactory;
import org.apache.druid.guice.annotations.ExtensionPoint;
import org.apache.druid.guice.annotations.PublicApi;
import org.apache.druid.java.util.emitter.service.ServiceEmitter;
import org.apache.druid.query.filter.Filter;
import org.apache.druid.query.search.SearchQueryMetricsFactory;

import java.util.List;

/**
 * Abstraction wrapping {@link org.apache.druid.java.util.emitter.service.ServiceMetricEvent.Builder} and allowing to
 * control what metrics are actually emitted, what dimensions do they have, etc.
 *
 *
 * Goals of QueryMetrics
 * ---------------------
 *  1. Skipping or partial filtering of particular dimensions or metrics entirely. Implementation could leave the body
 *  of the corresponding method empty, or implement random filtering like:
 *  public void reportCpuTime(long timeNs)
 *  {
 *    if (ThreadLocalRandom.current().nextDouble() < 0.1) {
 *      super.reportCpuTime(timeNs);
 *    }
 *  }
 *
 *  2. Ability to add new dimensions and metrics, possibly expensive to compute, or expensive to process (long string
 *  values, high cardinality, etc.) and not to affect existing Druid installations, by skipping (see 1.) those
 *  dimensions and metrics entirely in the default QueryMetrics implementations. Users who need those expensive
 *  dimensions and metrics, could explicitly emit them in their own QueryMetrics.
 *
 *  3. Control over the time unit, in which time metrics are emitted. By default (see {@link DefaultQueryMetrics} and
 *  it's subclasses) it's milliseconds, but if queries are fast, it could be not precise enough.
 *
 *  4. Control over the dimension and metric names.
 *
 *  Here, "control" is provided to the operator of a Druid cluster, who would exercise that control through a
 *  site-specific extension adding XxxQueryMetricsFactory impl(s).
 *
 *
 * Types of methods in this interface
 * ----------------------------------
 *  1. Methods, pulling some dimensions from the query object. These methods are used to populate the metric before the
 *  query is run. These methods accept a single `QueryType query` parameter. {@link #query(Query)} calls all methods
 *  of this type, hence pulling all available information from the query object as dimensions.
 *
 *  2. Methods for setting dimensions, which become known in the process of the query execution or after the query is
 *  completed.
 *
 *  3. Methods to register metrics to be emitted later in bulk via {@link #emit(ServiceEmitter)}. These methods
 *  return this QueryMetrics object back for chaining. Names of these methods start with "report" prefix.
 *
 *
 * Implementors expectations
 * -------------------------
 * QueryMetrics is expected to be changed often, in every Druid release (including "patch" releases). Users who create
 * their custom implementations of QueryMetrics should be ready to fix the code of their QueryMetrics (implement new
 * methods) when they update Druid. Broken builds of custom extensions, containing custom QueryMetrics is the way to
 * notify users that Druid core "wants" to emit new dimension or metric, and the user handles them manually: if the new
 * dimension or metric is useful and not very expensive to process and store then emit, skip (see above Goals, 1.)
 * otherwise.
 *
 * <p>Despite this interface is annotated as {@link ExtensionPoint} and some of it's methods as {@link PublicApi}, it
 * may be changed in breaking ways even in minor releases.
 *
 * <p>If implementors of custom QueryMetrics don't want to fix builds on every Druid release (e. g. if they want to add
 * a single dimension to emitted events and don't want to alter other dimensions and emitted metrics), they could
 * inherit their custom QueryMetrics from {@link DefaultQueryMetrics} or query-specific default implementation class,
 * such as {@link org.apache.druid.query.topn.DefaultTopNQueryMetrics}. Those classes are guaranteed to stay around and
 * implement new methods, added to the QueryMetrics interface (or a query-specific subinterface). However, there is no
 * 100% guarantee of compatibility, because methods could not only be added to QueryMetrics, existing methods could also
 * be changed or removed.
 *
 * <p>QueryMetrics is designed for use from a single thread, implementations shouldn't care about thread-safety.
 *
 *
 * Adding new methods to QueryMetrics
 * ----------------------------------
 * 1. When adding a new method for setting a dimension, which could be pulled from the query object, always make them
 * accept a single `QueryType query` parameter, letting the implementations to do all the work of carving the dimension
 * value out of the query object.
 *
 * 2. When adding a new method for setting a dimension, which becomes known in the process of the query execution or
 * after the query is completed, design it so that as little work as possible is done for preparing arguments for this
 * method, and as much work as possible is done in the implementations of this method, if they decide to actually emit
 * this dimension.
 *
 * 3. When adding a new method for registering metrics, make it to accept the metric value in the smallest reasonable
 * unit (i. e. nanoseconds for time metrics, bytes for metrics of data size, etc.), allowing the implementations of
 * this method to round the value up to more coarse-grained units, if they don't need the maximum precision.
 *
 *
 * Making subinterfaces of QueryMetrics for emitting custom dimensions and/or metrics for specific query types
 * -----------------------------------------------------------------------------------------------------------
 * If a query type (e. g. {@link org.apache.druid.query.metadata.metadata.SegmentMetadataQuery} (it's runners) needs to
 * emit custom dimensions and/or metrics which doesn't make sense for all other query types, the following steps should
 * be executed:
 *
 *  1. Create `interface SegmentMetadataQueryMetrics extends QueryMetrics` (here and below "SegmentMetadata" is the
 *  query type) with additional methods (see "Adding new methods" section above).
 *
 *  2. Create `class DefaultSegmentMetadataQueryMetrics implements SegmentMetadataQueryMetrics`. This class should
 *  implement extra methods from SegmentMetadataQueryMetrics interfaces with empty bodies, AND DELEGATE ALL OTHER
 *  METHODS TO A QueryMetrics OBJECT, provided as a sole parameter in DefaultSegmentMetadataQueryMetrics constructor.
 *
 *  NOTE: query(), dataSource(), queryType(), interval(), hasFilters(), duration(), queryId(), sqlQueryId(), and
 *  context() methods or any "pre-query-execution-time" methods should either have a empty body or throw exception.
 *
 *  3. Create `interface SegmentMetadataQueryMetricsFactory` with a single method
 *  `SegmentMetadataQueryMetrics makeMetrics(SegmentMetadataQuery query);`.
 *
 *  4. Create `class DefaultSegmentMetadataQueryMetricsFactory implements SegmentMetadataQueryMetricsFactory`,
 *  which accepts {@link GenericQueryMetricsFactory} as injected constructor parameter, and implements makeMetrics() as
 *  `return new DefaultSegmentMetadataQueryMetrics(genericQueryMetricsFactory.makeMetrics(query));`
 *
 *  5. Inject and use SegmentMetadataQueryMetricsFactory instead of {@link GenericQueryMetricsFactory} in
 *  {@link org.apache.druid.query.metadata.SegmentMetadataQueryQueryToolChest}.
 *
 *  6. Establish injection of SegmentMetadataQueryMetricsFactory using config and provider method in
 *  QueryToolChestModule (see how it is done in QueryToolChestModule) for existing query types
 *  with custom metrics, e. g. {@link SearchQueryMetricsFactory}), if the query type
 *  belongs to the core druid-processing, e. g. SegmentMetadataQuery. If the query type defined in an extension, you
 *  can specify `binder.bind(ScanQueryMetricsFactory.class).to(DefaultScanQueryMetricsFactory.class)` in the extension's
 *  Guice module, if the query type is defined in an extension, e. g. ScanQuery. Or establish similar configuration,
 *  as for the core query types.
 *
 * This complex procedure is needed to ensure custom {@link GenericQueryMetricsFactory} specified by users still works
 * for the query type when query type decides to create their custom QueryMetrics subclass.
 *
 * {@link org.apache.druid.query.topn.TopNQueryMetrics}, {@link org.apache.druid.query.groupby.GroupByQueryMetrics}, and
 * {@link org.apache.druid.query.timeseries.TimeseriesQueryMetrics} are implemented differently, because they are
 * introduced at the same time as the whole QueryMetrics abstraction and their default implementations have to actually
 * emit more dimensions than the default generic QueryMetrics. So those subinterfaces shouldn't be taken as direct
 * examples for following the plan specified above.
 *
 * Refer {@link SearchQueryMetricsFactory} as an implementation example of this procedure.
 *
 * @param <QueryType>
 */
@ExtensionPoint
public interface QueryMetrics<QueryType extends Query<?>>
{

  /**
   * Pulls all information from the query object into dimensions of future metrics.
   */
  void query(QueryType query);

  /**
   * Sets {@link Query#getDataSource()} of the given query as dimension.
   */
  @PublicApi
  void dataSource(QueryType query);

  /**
   * Sets {@link Query#getType()} of the given query as dimension.
   */
  @PublicApi
  void queryType(QueryType query);

  /**
   * Sets {@link Query#getIntervals()} of the given query as dimension.
   */
  @PublicApi
  void interval(QueryType query);

  /**
   * Sets {@link Query#hasFilters()} of the given query as dimension.
   */
  @PublicApi
  void hasFilters(QueryType query);

  /**
   * Sets {@link Query#getDuration()} of the given query as dimension.
   */
  @PublicApi
  void duration(QueryType query);

  /**
   * Sets {@link Query#getId()} of the given query as dimension.
   */
  @PublicApi
  void queryId(QueryType query);

  /**
   * Sets {@link Query#getSubQueryId()} of the given query as dimension.
   */
  @PublicApi
  void subQueryId(QueryType query);

  /**
   * Sets {@link Query#getSqlQueryId()} of the given query as dimension
   */
  @PublicApi
  void sqlQueryId(QueryType query);

  /**
   * Sets {@link Query#getContext()} of the given query as dimension.
   */
  @PublicApi
  void context(QueryType query);

  void server(String host);

  void remoteAddress(String remoteAddress);

  void status(String status);

  void success(boolean success);

  void segment(String segmentIdentifier);

  void preFilters(List<Filter> preFilters);

  void postFilters(List<Filter> postFilters);

  /**
   * Sets identity of the requester for a query. See {@code AuthenticationResult}.
   */
  void identity(String identity);

  /**
   * Sets whether or not a segment scan has been vectorized. Generally expected to only be attached to segment-level
   * metrics, since at whole-query level we might have a mix of vectorized and non-vectorized segment scans.
   */
  void vectorized(boolean vectorized);

  /**
   * Sets broker merge parallelism, if parallel merges are enabled. This will only appear in broker level metrics. This
   * value is identical to the {@link #reportParallelMergeParallelism} metric value, but optionally also available as a
   * dimension.
   */
  void parallelMergeParallelism(int parallelism);

  /**
   * Creates a {@link BitmapResultFactory} which may record some information along bitmap construction from {@link
   * #preFilters(List)}. The returned BitmapResultFactory may add some dimensions to this QueryMetrics from it's {@link
   * BitmapResultFactory#toImmutableBitmap(Object)} method. See {@link BitmapResultFactory} Javadoc for more
   * information.
   */
  BitmapResultFactory<?> makeBitmapResultFactory(BitmapFactory factory);

  /**
   * Registers "query time" metric.
   */
  QueryMetrics<QueryType> reportQueryTime(long timeNs);

  /**
   * Registers "query bytes" metric.
   */
  QueryMetrics<QueryType> reportQueryBytes(long byteCount);

  /**
   * Registeres "segments queried count" metric.
   */
  QueryMetrics<QueryType> reportQueriedSegmentCount(long segmentCount);

  /**
   * Registers "wait time" metric.
   */
  QueryMetrics<QueryType> reportWaitTime(long timeNs);

  /**
   * Registers "segment time" metric.
   */
  QueryMetrics<QueryType> reportSegmentTime(long timeNs);

  /**
   * Registers "segmentAndCache time" metric.
   */
  QueryMetrics<QueryType> reportSegmentAndCacheTime(long timeNs);

  /**
   * Registers "cpu time" metric.
   */
  QueryMetrics<QueryType> reportCpuTime(long timeNs);

  /**
   * Registers "time to first byte" metric.
   */
  QueryMetrics<QueryType> reportNodeTimeToFirstByte(long timeNs);

  /**
   * Registers "time that channel is unreadable (backpressure)" metric.
   */
  QueryMetrics<QueryType> reportBackPressureTime(long timeNs);

  /**
   * Registers "node time" metric.
   */
  QueryMetrics<QueryType> reportNodeTime(long timeNs);

  /**
   * Registers "node bytes" metric.
   */
  QueryMetrics<QueryType> reportNodeBytes(long byteCount);

  /**
   * Reports the time spent constructing bitmap from {@link #preFilters(List)} of the query. Not reported, if there are
   * no preFilters.
   */
  QueryMetrics<QueryType> reportBitmapConstructionTime(long timeNs);

  /**
   * Reports the total number of rows in the processed segment.
   */
  QueryMetrics<QueryType> reportSegmentRows(long numRows);

  /**
   * Reports the number of rows to scan in the segment after applying {@link #preFilters(List)}. If the are no
   * preFilters, this metric is equal to {@link #reportSegmentRows(long)}.
   */
  QueryMetrics<QueryType> reportPreFilteredRows(long numRows);

  /**
   * Reports number of parallel tasks the broker used to process the query during parallel merge. This value is
   * identical to the {@link #parallelMergeParallelism} dimension value, but optionally also available as a metric.
   */
  QueryMetrics<QueryType> reportParallelMergeParallelism(int parallelism);

  /**
   * Reports total number of input sequences processed by the broker during parallel merge.
   */
  QueryMetrics<QueryType> reportParallelMergeInputSequences(long numSequences);

  /**
   * Reports total number of input rows processed by the broker during parallel merge.
   */
  QueryMetrics<QueryType> reportParallelMergeInputRows(long numRows);

  /**
   * Reports broker total number of output rows after merging and combining input sequences (should be less than or
   * equal to the value supplied to {@link #reportParallelMergeInputRows}.
   */
  QueryMetrics<QueryType> reportParallelMergeOutputRows(long numRows);

  /**
   * Reports broker total number of fork join pool tasks required to complete query
   */
  QueryMetrics<QueryType> reportParallelMergeTaskCount(long numTasks);

  /**
   * Reports broker total CPU time in nanoseconds where fork join merge combine tasks were doing work
   */
  QueryMetrics<QueryType> reportParallelMergeTotalCpuTime(long timeNs);

  /**
   * Emits all metrics, registered since the last {@code emit()} call on this QueryMetrics object.
   */
  void emit(ServiceEmitter emitter);
}
