# yaml-language-server: $schema=https://schema.zeabur.app/template.json
apiVersion: zeabur.com/v1
kind: Template
metadata:
    name: Prometheus + Tempo + Grafana
spec:
    description: Monitor your applications with Prometheus, Tempo and Grafana.
    icon: https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Grafana_icon.svg/1969px-Grafana_icon.svg.png
    variables:
        - key: PUBLIC_DOMAIN
          type: DOMAIN
          name: Domain
          description: The domain name for your Grafana dashboard
    tags:
        - monitoring
        - observability
        - tracing
        - metrics
        - prometheus
        - grafana
        - tempo
    readme: "## ⚠️ Deprecation Notice: Switch to Standalone Templates\n\nThis integrated template is now **deprecated and unmaintained**. While it served as a convenient \"all-in-one\" package, its monolithic design prevents you from independently swapping or upgrading individual components.\n\nTo provide you with greater flexibility and control over your stack, Zeabur has decoupled **Prometheus**, **Tempo** and **Grafana** into separate, standalone templates. This change allows you to mix and match versions and configurations that best suit your specific infrastructure needs.\n\n### How to Replicate This Setup\n\nIf you need a comprehensive telemetry solution like this one, you can easily recreate it by following these steps:\n\n1. Deploy the **[Grafana template](https://zeabur.com/templates/MDTTQR)** by selecting the **\"Create New Project\"** option. \n2. Deploy the **[Prometheus template](https://zeabur.com/templates/XV8ADT)** and choose **\"Deploy to Existing Project\"** to add it to the same workspace.\n3. Deploy the **[Tempo template](https://zeabur.com/templates/DO7QLO)** and choose **\"Deploy to Existing Project\"** to add it to the same workspace.\n\nIt's also common to deploy them in separate projects, where you have a central Grafana instance receiving metrics (Prometheus and Tempo) from multiple projects.\n\nAlso, we highly encourage you to explore the **[Grafana template page](https://zeabur.com/templates/MDTTQR)** to discover other metrics and tracing backend solutions. By combining these independent building blocks, you can design a robust, custom observability solution tailored specifically to your goals.\n\n---\n\nMonitor your applications with Prometheus, Grafana and Tempo.\n\nThis template is based on <https://github.com/grafana/tempo/tree/main/example/docker-compose/local>, and contains:\n\n- memcached\n- tempo\n- k6-tracing\n- prometheus\n- grafana\n"
    services:
        - name: memcached
          icon: https://cdn.zeabur.com/prebuilt.svg
          template: PREBUILT
          spec:
            id: memcached
            source:
                image: memcached:1.6.39
                runAsUserID: 11211
        - name: tempo
          icon: https://grafana.com/static/assets/img/logos/grafana-tempo.svg
          dependencies:
            - memcached
          template: PREBUILT
          spec:
            id: tempo
            source:
                image: grafana/tempo:latest
                args:
                    - -config.file=/etc/tempo.yaml
            ports:
                - id: jaeger
                  port: 14268
                  type: HTTP
                - id: tempo
                  port: 3200
                  type: HTTP
                - id: tempogrpc
                  port: 9095
                  type: TCP
                - id: otlpgrpc
                  port: 4317
                  type: TCP
                - id: otlphttp
                  port: 4318
                  type: HTTP
                - id: zipkin
                  port: 9411
                  type: HTTP
            volumes:
                - id: data
                  dir: /var/tempo
            env:
                TEMPO_STORAGE_MEMCACHED_ADDRESS:
                    default: memcached:11211
                TEMPO_STORAGE_TYPE:
                    default: memcached
            configs:
                - path: /etc/tempo.yaml
                  template: |
                    stream_over_http_enabled: true
                    server:
                      http_listen_port: 3200
                      log_level: info

                    cache:
                      background:
                        writeback_goroutines: 5
                      caches:
                        - roles:
                            - frontend-search
                          memcached:
                            addresses: dns+memcached:11211

                    query_frontend:
                      mcp_server:
                        enabled: true
                      search:
                        duration_slo: 5s
                        throughput_bytes_slo: 1.073741824e+09
                        metadata_slo:
                          duration_slo: 5s
                          throughput_bytes_slo: 1.073741824e+09
                      trace_by_id:
                        duration_slo: 100ms
                      metrics:
                        max_duration: 200h # maximum duration of a metrics query, increase for local setups
                        query_backend_after: 5m
                        duration_slo: 5s
                        throughput_bytes_slo: 1.073741824e+09

                    distributor:
                      usage:
                        cost_attribution:
                          enabled: true
                      receivers: # this configuration will listen on all ports and protocols that tempo is capable of.
                        jaeger: # the receives all come from the OpenTelemetry collector.  more configuration information can
                          protocols: # be found there: https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver
                            thrift_http: #
                              endpoint: "0.0.0.0:14268" # for a production deployment you should only enable the receivers you need!
                            grpc:
                              endpoint: "0.0.0.0:14250"
                            thrift_binary:
                              endpoint: "0.0.0.0:6832"
                            thrift_compact:
                              endpoint: "0.0.0.0:6831"
                        zipkin:
                          endpoint: "0.0.0.0:9411"
                        otlp:
                          protocols:
                            grpc:
                              endpoint: "0.0.0.0:4317"
                            http:
                              endpoint: "0.0.0.0:4318"
                        opencensus:
                          endpoint: "0.0.0.0:55678"

                    ingester:
                      max_block_duration: 5m # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally

                    compactor:
                      compaction:
                        block_retention: 720h # overall Tempo trace retention. set for demo purposes

                    metrics_generator:
                      registry:
                        external_labels:
                          source: tempo
                          cluster: docker-compose
                      storage:
                        path: /var/tempo/generator/wal
                        remote_write:
                          - url: http://prometheus:9090/api/v1/write
                            send_exemplars: true
                      traces_storage:
                        path: /var/tempo/generator/traces
                      processor:
                        local_blocks:
                          filter_server_spans: false
                          flush_to_storage: true

                    storage:
                      trace:
                        backend: local # backend configuration to use
                        wal:
                          path: /var/tempo/wal # where to store the wal locally
                        local:
                          path: /var/tempo/blocks

                    overrides:
                      defaults:
                        cost_attribution:
                          dimensions:
                            service.name: "" # unscoped matches both resource and span attributes
                            span.http.target: "service_route" # span scoped attribute, also remapped to custom label in metrics.
                        metrics_generator:
                          processors: [service-graphs, span-metrics, local-blocks] # enables metrics generator
                          generate_native_histograms: both
                  permission: null
                  envsubst: null
        - name: k6-tracing
          icon: https://cdn.zeabur.com/prebuilt.svg
          dependencies:
            - tempo
          template: PREBUILT
          spec:
            id: k6-tracing
            source:
                image: ghcr.io/grafana/xk6-client-tracing:v0.0.9
        - name: prometheus
          icon: https://upload.wikimedia.org/wikipedia/commons/3/38/Prometheus_software_logo.svg
          template: PREBUILT
          spec:
            id: prometheus
            source:
                image: prom/prometheus:latest
                args:
                    - --config.file=/etc/prometheus.yaml
                    - --web.enable-remote-write-receiver
                    - --enable-feature=exemplar-storage
                    - --enable-feature=native-histograms
            ports:
                - id: web
                  port: 9090
                  type: HTTP
            volumes:
                - id: data
                  dir: /prometheus
            configs:
                - path: /etc/prometheus.yaml
                  template: |
                    global:
                      scrape_interval:     15s
                      evaluation_interval: 15s

                    scrape_configs:
                      - job_name: 'prometheus'
                        static_configs:
                          - targets: ['localhost:9090']
                      - job_name: 'tempo'
                        static_configs:
                          - targets: ['tempo:3200']
                      - job_name: 'tempo-usage-metrics'
                        metrics_path: '/usage_metrics'
                        static_configs:
                          - targets: ['tempo:3200']
                  permission: null
                  envsubst: null
        - name: grafana
          icon: https://upload.wikimedia.org/wikipedia/commons/3/3b/Grafana_icon.svg
          template: PREBUILT
          spec:
            id: grafana
            source:
                image: grafana/grafana-enterprise:12.3.0-18765596677
            ports:
                - id: web
                  port: 3000
                  type: HTTP
            volumes:
                - id: data
                  dir: /var/lib/grafana
            instructions:
                - title: Grafana Admin Username
                  content: ${GF_SECURITY_ADMIN_USER}
                - title: Grafana Admin Password
                  content: ${GF_SECURITY_ADMIN_PASSWORD}
            env:
                GF_FEATURE_TOGGLES_ENABLE:
                    default: traceqlEditor metricsSummary
                GF_INSTALL_PLUGINS:
                    default: https://storage.googleapis.com/integration-artifacts/grafana-exploretraces-app/grafana-exploretraces-app-latest.zip;grafana-traces-app
                GF_SECURITY_ADMIN_PASSWORD:
                    default: ${PASSWORD}
                GF_SECURITY_ADMIN_USER:
                    default: admin
            configs:
                - path: /etc/grafana/provisioning/datasources/datasource.yml
                  template: |
                    apiVersion: 1

                    datasources:
                    - name: Prometheus
                      type: prometheus
                      uid: prometheus
                      access: proxy
                      orgId: 1
                      url: http://prometheus:9090
                      basicAuth: false
                      isDefault: false
                      version: 1
                      editable: false
                      jsonData:
                        httpMethod: GET
                    - name: Tempo
                      type: tempo
                      access: proxy
                      orgId: 1
                      url: http://tempo:3200
                      basicAuth: false
                      isDefault: true
                      version: 1
                      editable: false
                      apiVersion: 1
                      uid: tempo
                      jsonData:
                        httpMethod: GET
                        serviceMap:
                          datasourceUid: prometheus
                        streamingEnabled:
                          search: true
                  permission: null
                  envsubst: null
          domainKey: PUBLIC_DOMAIN
