// Copyright (c) The Thanos Authors.
// Licensed under the Apache License 2.0.

syntax = "proto3";
package thanos;

import "store/storepb/types.proto";
import "gogoproto/gogo.proto";
import "store/storepb/prompb/types.proto";
import "store/labelpb/types.proto";
import "google/protobuf/any.proto";

option go_package = "storepb";

option (gogoproto.sizer_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.unmarshaler_all) = true;
option (gogoproto.goproto_getters_all) = false;

// Do not generate XXX fields to reduce memory footprint and opening a door
// for zero-copy casts to/from prometheus data types.
option (gogoproto.goproto_unkeyed_all) = false;
option (gogoproto.goproto_unrecognized_all) = false;
option (gogoproto.goproto_sizecache_all) = false;

/// Store represents API against instance that stores XOR encoded values with label set metadata (e.g Prometheus metrics).
service Store {
  /// Info returns meta information about a store e.g labels that makes that store unique as well as time range that is
  /// available.
  rpc Info(InfoRequest) returns (InfoResponse);

  /// Series streams each Series (Labels and chunk/downsampling chunk) for given label matchers and time range.
  ///
  /// Series should strictly stream full series after series, optionally split by time. This means that a single frame can contain
  /// partition of the single series, but once a new series is started to be streamed it means that no more data will
  /// be sent for previous one.
  /// Series has to be sorted.
  ///
  /// There is no requirements on chunk sorting, however it is recommended to have chunk sorted by chunk min time.
  /// This heavily optimizes the resource usage on Querier / Federated Queries.
  rpc Series(SeriesRequest) returns (stream SeriesResponse);

  /// LabelNames returns all label names constrained by the given matchers.
  rpc LabelNames(LabelNamesRequest) returns (LabelNamesResponse);

  /// LabelValues returns all label values for given label name.
  rpc LabelValues(LabelValuesRequest) returns (LabelValuesResponse);
}

/// WriteableStore represents API against instance that stores XOR encoded values with label set metadata (e.g Prometheus metrics).
service WriteableStore {
  // WriteRequest allows you to write metrics to this store via remote write
  rpc RemoteWrite(WriteRequest) returns (WriteResponse) {}
}

message WriteResponse {
}

message WriteRequest {
  repeated prometheus_copy.TimeSeries timeseries = 1 [(gogoproto.nullable) = false];
  string tenant = 2;
  int64 replica = 3;
}

message InfoRequest {}

enum StoreType {
  UNKNOWN = 0;
  QUERY = 1;
  RULE = 2;
  SIDECAR = 3;
  STORE = 4;
  RECEIVE = 5;
  // DEBUG represents some debug StoreAPI components e.g. thanos tools store-api-serve.
  DEBUG = 6;
}

message InfoResponse {
  // Deprecated. Use label_sets instead.
  repeated Label labels = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/thanos-io/thanos/pkg/store/labelpb.ZLabel"];
  int64 min_time = 2;
  int64 max_time = 3;
  StoreType storeType = 4;
  // label_sets is an unsorted list of `ZLabelSet`s.
  repeated ZLabelSet label_sets = 5 [(gogoproto.nullable) = false];
}

message SeriesRequest {
  int64 min_time = 1;
  int64 max_time = 2;
  repeated LabelMatcher matchers = 3 [(gogoproto.nullable) = false];

  int64 max_resolution_window = 4;
  repeated Aggr aggregates = 5;

  // Deprecated. Use partial_response_strategy instead.
  bool partial_response_disabled = 6;

  // TODO(bwplotka): Move Thanos components to use strategy instead. Including QueryAPI.
  PartialResponseStrategy partial_response_strategy = 7;

  // skip_chunks controls whether sending chunks or not in series responses.
  bool skip_chunks = 8;

  // hints is an opaque data structure that can be used to carry additional information.
  // The content of this field and whether it's supported depends on the
  // implementation of a specific store.
  google.protobuf.Any hints = 9;

  // Query step size in milliseconds.
  // Deprecated: Use query_hints instead.
  int64 step = 10;

  // Range vector selector range in milliseconds.
  // Deprecated: Use query_hints instead.
  int64 range = 11;

  // query_hints are the hints coming from the PromQL engine when
  // requesting a storage.SeriesSet for a given expression.
  QueryHints query_hints = 12;
}

// Analogous to storage.SelectHints.
message QueryHints {
  // Query step size in milliseconds.
  int64 step_millis = 1;

  // The surrounding function or aggregation.
  Func func = 2;

  // The grouping expression
  Grouping grouping = 4;

  // Range vector selector.
  Range range = 5;
}

message Func {
  // The function or aggregation name
  string name = 1;
}

message Grouping {
  // Indicate whether it is without or by.
  bool by = 1;

  // List of label names used in the grouping.
  repeated string labels = 3;
}

message Range {
  int64 millis = 1;
}

enum Aggr {
  RAW = 0;
  COUNT = 1;
  SUM = 2;
  MIN = 3;
  MAX = 4;
  COUNTER = 5;
}

message SeriesResponse {
  oneof result {
    /// series contains 1 response series. The series labels are sorted by name.
    Series series = 1;

    /// warning is considered an information piece in place of series for warning purposes.
    /// It is used to warn store API user about suspicious cases or partial response (if enabled).
    string warning = 2;

    /// hints is an opaque data structure that can be used to carry additional information from
    /// the store. The content of this field and whether it's supported depends on the
    /// implementation of a specific store. It's also implementation specific if it's allowed that
    /// multiple SeriesResponse frames contain hints for a single Series() request and how should they
    /// be handled in such case (ie. merged vs keep the first/last one).
    google.protobuf.Any hints = 3;
  }
}

message LabelNamesRequest {
  bool partial_response_disabled = 1;

  // TODO(bwplotka): Move Thanos components to use strategy instead. Including QueryAPI.
  PartialResponseStrategy partial_response_strategy = 2;

  int64 start = 3;

  int64 end = 4;

  // hints is an opaque data structure that can be used to carry additional information.
  // The content of this field and whether it's supported depends on the
  // implementation of a specific store.
  google.protobuf.Any hints = 5;

  repeated LabelMatcher matchers = 6 [(gogoproto.nullable) = false];
}

message LabelNamesResponse {
  repeated string names = 1;
  repeated string warnings = 2;

  /// hints is an opaque data structure that can be used to carry additional information from
  /// the store. The content of this field and whether it's supported depends on the
  /// implementation of a specific store.
  google.protobuf.Any hints = 3;
}

message LabelValuesRequest {
  string label = 1;

  bool partial_response_disabled = 2;

  // TODO(bwplotka): Move Thanos components to use strategy instead. Including QueryAPI.
  PartialResponseStrategy partial_response_strategy = 3;

  int64 start = 4;

  int64 end = 5;

  // hints is an opaque data structure that can be used to carry additional information.
  // The content of this field and whether it's supported depends on the
  // implementation of a specific store.
  google.protobuf.Any hints = 6;

  repeated LabelMatcher matchers = 7 [(gogoproto.nullable) = false];
}

message LabelValuesResponse {
  repeated string values = 1;
  repeated string warnings = 2;

  /// hints is an opaque data structure that can be used to carry additional information from
  /// the store. The content of this field and whether it's supported depends on the
  /// implementation of a specific store.
  google.protobuf.Any hints = 3;
}
