syntax = "proto3";

import "collections.proto";

package qdrant;
option csharp_namespace = "Qdrant.Client.Grpc";

message GetTelemetryRequest {
  // The level of detail needed
  uint32 details_level = 1;
  // If present, select these collections
  CollectionsSelector collections_selector = 2;
  // Timeout in secs for the request
  uint64 timeout = 3;
}

message CollectionsSelector {
  repeated string only_collections = 1;
}

message GetTelemetryResponse {
  PeerTelemetry result = 1;
  double time = 2;
}

message PeerTelemetry {
  reserved 1; // id
  AppTelemetry app = 2; // app
  // Mapping from collection name to its telemetry
  map<string, CollectionTelemetry> collections = 3;
  // Telemetry about the cluster and peers
  ClusterTelemetry cluster = 4;
  reserved 5; // requests
  reserved 6; // memory
  reserved 7; // hardware
}

message AppTelemetry {
    // Name of service
    string name = 1;
    // Qdrant version
    string version = 2;
    // Last startup timestamp in seconds
    int64 startup = 3;
}

message CollectionTelemetry {
  // Name of the collection
  string id = 1;
  // init_time_ms
  reserved 2;
  // config
  reserved 3;
  // Shards information
  repeated ReplicaSetTelemetry shards = 4;
  // Shard (replica) transfers in progress
  repeated ShardTransferTelemetry transfers = 5;
  // Resharding(s) in progress
  repeated ReshardingTelemetry resharding = 6;
  // Tasks that clean points after completing a resharding sequence
  map<uint32, ShardCleanStatusTelemetry> shard_clean_tasks = 7;
}

message ShardTransferTelemetry {
  // Local shard id
  uint32 shard_id = 1;
  // Target shard ID if different than source shard ID.
  // Used exclusively with `ReshardingStreamRecords` transfer method.
  optional uint32 to_shard_id = 2;
  // From peer id
  uint64 from = 3;
  // To peer id
  uint64 to = 4;
  // If `true` transfer is a synchronization of replicas;
  // If `false` transfer is a moving of a shard from one peer to another.
  bool sync = 5;
  // Method of transferring points
  optional ShardTransferMethod method = 6;
  // Freeform string. Typically reports progress
  string comment = 7;
}

message ReshardingTelemetry {
  string uuid = 1;
  uint32 shard_id = 2;
  uint64 peer_id = 3;
  optional ShardKey shard_key = 4;
  ReshardingDirection direction = 5;
  ReshardingStage stage = 6;
}

enum ReshardingStage {
  MIGRATING_POINTS = 0;
  READ_HASH_RING_COMMITTED = 1;
  WRITE_HASH_RING_COMMITTED = 2;
}

message ShardCleanStatusTelemetry {
  oneof variant {
    Started started = 1;
    Progress progress = 2;
    Failed failed = 3;
    Cancelled cancelled = 4;
    Done done = 5;
  }

  message Started {
    // Marker message
  }

  message Progress {
    uint64 deleted_points = 1;
  }

  message Failed {
    string reason = 1;
  }

  message Cancelled {
    // Marker message
  }

  message Done {
    // Marker message
  }
}

message ReplicaSetTelemetry {
  // Shard ID
  uint32 id = 1;
  // Optional shard key for custom sharding
  optional ShardKey key = 2;
  // Local shard information
  LocalShardTelemetry local = 3;
  // Remote shards
  repeated RemoteShardTelemetry remote = 4;
  map<uint64, ReplicaState> replica_states = 5;
  // Snapshot operations telemetry
  optional PartialSnapshotTelemetry partial_snapshot = 6;
}

message LocalShardTelemetry {
  // Optimization status
  optional ShardStatus status = 3;
  // Total optimized points
  uint64 total_optimized_points = 4;
  // Estimated vectors size in bytes
  optional uint64 vectors_size_bytes = 5;
  // Estimated payloads size in bytes
  optional uint64 payloads_size_bytes = 6;
  // Approximate number of points
  optional uint64 num_points = 7;
  // Approximate number of vectors
  optional uint64 num_vectors = 8;
  // Approximate number of vectors by vector name
  map<string, uint64> num_vectors_by_name = 9;
  // segments
  reserved 10;
  // optimizations
  reserved 11;
  // Number of vectors excluded from search if `indexed_only` is used
  map<string, uint64> indexed_only_excluded_vectors = 12;
}

enum ShardStatus {
    // Shard is completely ready for requests
    GREEN = 0;
    // Shard is available, but some segments are under optimization
    YELLOW = 1;
    // Shard is available, but some segments are pending optimization
    GREY = 2;
    // Something is not OK:
    // - some operations failed and was not recovered
    RED = 3;
}

message RemoteShardTelemetry {
    uint32 shard_id = 1;
    uint64 peer_id = 2;
}

message PartialSnapshotTelemetry {
  // Number of ongoing snapshot creation requests
  uint64 ongoing_create_snapshot_requests = 1;
  // Whether the shard is recovering
  bool is_recovering = 2;
  // Last successful recovery timestamp
  uint64 recovery_timestamp = 3;
}

message ClusterTelemetry {
  ClusterStatusTelemetry status = 1;
  reserved 2; // config
  map<uint64, PeerInfo> peers = 3;
  reserved 4; // peer_metadata
  reserved 5; // metadata
}

message ClusterStatusTelemetry {
  uint32 num_peers = 1;
  uint64 term = 2;
  uint64 commit = 3;
  uint64 pending_operations = 4;
  optional StateRole role = 5;
  bool is_voter = 6;
  optional uint64 peer_id = 7;
  ConsensusThreadStatus consensus_thread_status = 8;
}

message ConsensusThreadStatus {
  oneof status {
    Working working = 1;
    Stopped stopped = 2;
    StoppedWithErr stopped_with_err = 3;
  }
  message Working {
    // Unix timestamp in milliseconds
    int64 last_update_ms = 1;
  }

  message Stopped {
    // Marker message for stopped state
  }

  message StoppedWithErr {
    string err = 1;
  }
}

message PeerInfo {
  string uri = 1;
}

enum StateRole {
  FOLLOWER = 0;
  CANDIDATE = 1;
  LEADER = 2;
  PRE_CANDIDATE = 3;
}
