# Example ITRS Analytics configuration for AWS EC2 handling 250k Obcerv entities and 100k metrics/sec, and 20k OpenTelemetry
# spans/sec (pre-sampling).
#
# Nodes:
# - (2) m5.8xlarge (32 CPU, 128GiB Memory) for Timescale
# - (7) c5.4xlarge (16 CPU, 32GiB Memory) for all other workloads
#
# The resource requests for Timescale total 48 cores and 360GiB memory.
# The resource requests for the other workloads total ~72 cores and ~170GiB memory.
# These totals include Linkerd resources.
#
# Disk requirements:
# - Timescale:
#   - 4 x 2 TiB timeseries data disk for each replica (x2)
#   - 200 GiB data disk for each replica (x2)
#   - 300 GiB WAL disk for each replica (x2)
# - Kafka broker: 400 GiB for each replica (x3)
# - Kafka controller: 1 GiB for each replica (x3)
# - ClickHouse Keeper: 2 GiB for each replica (x3)
# - ClickHouse Traces: 90 GiB for each replica (x2)
# - ClickHouse Traces:
# - Loki: 30 GiB
# - etcd: 1 GiB for each replica (x3)
# - Downsampled Metrics:
#   - Raw: 5 GiB for each replica (x4)
#   - Bucketed: 5 GiB for each replica (x4)
#
# The configuration references a default storage class named `gp3` which uses EBS gp3 volumes. This storage class should
# be configured with the default minimum gp3 settings of 3000 IOPS and 125 MiB/s throughput.
#
# The configuration also references a storage class named `gp3-timescale` which uses EBS gp3 volumes, but with
# higher provisioned performance for the WAL volumes. This storage class should be configured with 5000 IOPS and
# 200 MiB/s throughput.
#
# You can create these classes or change the config to use classes of your own, but they should be similar in performance.
#
# This configuration is based upon a certain number of Obcerv entities, average metrics per entity, and
# average metrics collection interval. The following function can be used to figure out what type of load to expect:
#
# metrics/sec = (Obcerv entities * metrics/entity) / average metrics collection interval
#
# In this example configuration, we have the following:
#
# 100,000 metrics/sec = (250,000 Obcerv entities * 4 metrics/entity) / 10 seconds average metrics collection interval
#
# NOTE: Ingestion, storage, and retrieval of OpenTelemetry spans is a beta feature.
#
# Additionally, the configuration is based upon a certain number of OpenTelemetry spans per second that are sampled
# based upon the following rules:
# - Error traces are always sampled
# - Target sampling probability per endpoint (corresponds to the name of the root span) is 0.01
# - Target sampling rate / second / endpoint (corresponds to the name of the root span) is 0.5
# - Root span duration outlier quantile is 0.95. The durations of all root spans are tracked and used to make guesses about
#   abnormally long spans
#

defaultStorageClass: "gp3"
apps:
  externalHostname: "obcerv.mydomain.internal"
  ingress:
    annotations:
      kubernetes.io/ingress.class: "nginx"
      nginx.org/mergeable-ingress-type: "master"
ingestion:
  externalHostname: "obcerv-ingestion.mydomain.internal"
  replicas: 3
  ingress:
    annotations:
      kubernetes.io/ingress.class: "nginx"
      nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
  resources:
    requests:
      memory: "512Mi"
      cpu: "500m"
    limits:
      memory: "768Mi"
      cpu: "1"
  traces:
    jvmOpts: "-XX:InitialRAMPercentage=65 -XX:MaxRAMPercentage=65 -XX:MaxDirectMemorySize=200M"
    resources:
      requests:
        memory: "4Gi"
        cpu: "3"
      limits:
        memory: "8Gi"
        cpu: "4"
mesh:
  resourcesHot:
    config.linkerd.io/proxy-cpu-request: "80m"
    config.linkerd.io/proxy-cpu-limit: "1"
    config.linkerd.io/proxy-memory-request: "48Mi"
    config.linkerd.io/proxy-memory-limit: "192Mi"
iam:
  ingress:
    annotations:
      kubernetes.io/ingress.class: "nginx"
      nginx.org/mergeable-ingress-type: "minion"
kafka:
  replicas: 3
  diskSize: "400Gi"
  resources:
    requests:
      memory: "12Gi"
      cpu: "3"
    limits:
      memory: "12Gi"
      cpu: "5"
  controller:
    replicas: 3
timescale:
  sharedBuffersPercentage: 40
  bgwLruMaxPages: 8000
  walBuffers: 64000
  clusterSize: 2
  dataDiskSize: "200Gi"
  timeseriesDiskCount: 4
  timeseriesDiskSize: "2Ti"
  walDiskSize: "300Gi"
  walStorageClass: "gp3-timescale"
  maxLocksPerTransaction: 10000
  resources:
    requests:
      memory: "116Gi"
      cpu: "16"
    limits:
      memory: "116Gi"
      cpu: "16"
  nodeSelector:
    instancegroup: timescale-nodes
  tolerations:
  - key: dedicated
    operator: Equal
    value: timescale-nodes
    effect: NoSchedule
  retention:
    metrics:
      chunkSize: 8h
      retention: 30d
    metrics_5m:
      chunkSize: 1d
      retention: 90d
    metrics_1h:
      chunkSize: 5d
      retention: 180d
    metrics_1d:
      chunkSize: 20d
      retention: 1y
    statuses:
      chunkSize: 7d
      retention: 1y
    signal_details:
      chunkSize: 1d
      retention: 30d
loki:
  diskSize: "30Gi"
  ingestionBurstSize: 12
  ingestionRateLimit: 8
  resources:
    requests:
      memory: "1Gi"
      cpu: "500m"
    limits:
      memory: "1Gi"
      cpu: "1"
sinkd:
  timeseriesCacheMaxSize: 3000000
  evCacheMaxSize: 3000000
  replicas: 3
  rawReplicas: 5
  jvmOpts: "-Xms1536M -Xmx1536M -XX:MaxDirectMemorySize=100M"
  rawJvmOpts: "-Xms1024M -Xmx1536M"
  resources:
    requests:
      memory: "2Gi"
      cpu: "250m"
    limits:
      memory: "3Gi"
      cpu: "3"
  rawResources:
    requests:
      memory: "1536Mi"
      cpu: "500m"
    limits:
      memory: "3Gi"
      cpu: "3"
  metrics:
    consumerProperties:
      max.partition.fetch.bytes: 1048576
      max.poll.records: 50000
  dsMetrics:
    consumerProperties:
      max.partition.fetch.bytes: 1048576
  loki:
    consumerProperties:
      max.partition.fetch.bytes: 1048576
  entities:
    consumerProperties:
      max.partition.fetch.bytes: 1048576
      max.poll.records: 75000
  signals:
    consumerProperties:
      max.partition.fetch.bytes: 1048576
  traces:
    consumerProperties:
      max.poll.records: 20000
    resources:
      requests:
        memory: "756Mi"
        cpu: "100m"
      limits:
        memory: "1800Mi"
        cpu: "1"
platformd:
  replicas: 2
  resources:
    requests:
      memory: "1536Mi"
      cpu: "1"
    limits:
      memory: "2Gi"
      cpu: "2250m"
dpd:
  replicas: 2
  jvmOpts: "-Xmx5500M"
  maxEntitySerdeCacheEntries: 75000
  entitiesInMemoryCacheSizeMb: 256
  consumerProperties:
    max.poll.records: 10000
    fetch.min.bytes: 524288
  metricsMultiplexer:
    maxFilterResultCacheSize: 2000000
    maxConcurrentOps: 1000
    localParallelism: 12
  selfMonitoringThresholds:
    entities_partition_lag_warn: 100000
    entities_partition_lag_critical: 500000
    metrics_partition_lag_warn: 1000000
    metrics_partition_lag_critical: 5000000
  resources:
    requests:
      memory: "6Gi"
      cpu: "3"
    limits:
      memory: "8Gi"
      cpu: "6500m"
downsampledMetricsStream:
  replicas: 4
  bucketedReplicas: 4
  consumerProperties:
    fetch.min.bytes: 524288
    max.partition.fetch.bytes: 1048576
    max.poll.records: 10000
  resources:
    requests:
      memory: "3Gi"
      cpu: "1"
    limits:
      memory: "3Gi"
      cpu: "4"
  bucketedConsumerProperties:
    fetch.min.bytes: 524288
    max.partition.fetch.bytes: 1048576
    max.poll.records: 10000
  bucketedResources:
    requests:
      memory: "3Gi"
      cpu: "1"
    limits:
      memory: "6Gi"
      cpu: "4"
  rocksdb:
    raw:
      indexAndFilterRatio: 0.5
      memoryMib: 500
      writeBufferMib: 16
      writeBufferRatio: 0.25
    bucketed:
      indexAndFilterRatio: 0.5
      memoryMib: 200
      writeBufferMib: 16
      writeBufferRatio: 0.25
entityStream:
  intermediate:
    storedEntitiesCacheSize: 10000
    jvmOpts: "-XX:MaxRAMPercentage=25"
    replicas: 4
    consumerProperties:
      max.partition.fetch.bytes: 1048576
    resources:
      requests:
        memory: "1536Mi"
        cpu: "750m"
      limits:
        memory: "2Gi"
        cpu: "2"
    rocksdb:
      memoryMib: 300
  final:
    replicas: 6
    storedEntitiesCacheSize: 10000
    consumerProperties:
      max.partition.fetch.bytes: 1048576
    resources:
      requests:
        memory: "1536Mi"
        cpu: "1"
      limits:
        memory: "2560Mi"
        cpu: "2"
signalsStream:
  consumerProperties:
    max.partition.fetch.bytes: 1048576
  resources:
    requests:
      memory: "830Mi"
      cpu: "150m"
    limits:
      memory: "1536Mi"
      cpu: "1200m"
etcd:
  replicas: 3
collection:
  daemonSet:
    tolerations:
    # must match the tainted Timescale nodes setting
    - key: dedicated
      operator: Equal
      value: timescale-nodes
      effect: NoSchedule
latestMetricsService:
  replicas: 4
  resources:
    limits:
      cpu: "2"
      memory: "4Gi"
    requests:
      cpu: "500m"
      memory: "1Gi"
clickhouse:
  traces:
    replicas: 2
    diskSize: "90Gi"
    resources:
      limits:
        cpu: "4"
        memory: "14Gi"
      requests:
        cpu: "4"
        memory: "14Gi"
  keeper:
    replicas: 3
postgres:
  clusterSize: 2