# İzleme

> QueryProxy'yi Prometheus ile scrape edin, örnek Grafana dashboard'unu içe aktarın; queryproxy:doctor ve zamanlayıcıyla sorunları kullanıcılarınızdan önce görün.

- Dokümantasyon: Kılavuzlar
- Güncelleme: 2026-10-25
- Kaynak: https://queryproxy.com/tr/docs/izleme/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
QueryProxy'nin sağlıklı olduğunu size söylemesinin üç yolu var: bir Prometheus
endpoint'i, örnek bir Grafana dashboard'u ve `queryproxy:doctor` komutu.
Endpoint siz açana kadar kapalıdır.

## `/metrics` endpoint'i

`GET /metrics` Prometheus metin formatını döndürür. Aşağıdakilerden biri
ayarlanana kadar `404` yanıtı verir; ayarlandıktan sonra bir scrape'i, doğru
bearer token'ı taşıyorsa **ya da** izinli bir adresten geliyorsa geçirir:

| Değişken | Anlamı |
| :-- | :-- |
| `QUERYPROXY_METRICS_TOKEN` | Scrape'ler için bearer token. 24 ya da daha fazla rastgele karakter kullanın: `openssl rand -hex 24`. `QUERYPROXY_METRICS_TOKEN_FILE` onu bir dosyadan okur |
| `QUERYPROXY_METRICS_ALLOWED_IPS` | Token olmadan scrape edebilecek, virgülle ayrılmış adresler ya da CIDR aralıkları |

Birini ya da ikisini birden ayarlayın. Diğer her şey `401` alır. Route web
oturumunun dışında çalışır: cookie ya da CSRF yok.

Token dışında bir scrape'in kabul edilip edilmeyeceğini iki şey belirler:

- **İstemci adresi** `TRUSTED_PROXIES` kurallarını izler. Bir ters vekilin
  arkasında, vekil listelenmediği sürece allowlist vekilin adresini görür.
  `TRUSTED_PROXIES=*` değerini asla vermeyin: bu durumda herhangi bir istemci
  kendi `X-Forwarded-For`'unu gönderip adres allowlist'ini geçebilir.
- **`Host` başlığı** `APP_URL`'in host'u ya da `TRUSTED_HOSTS` içindeki bir ad
  olmalıdır; aksi halde istek `400` ile reddedilir. Kullanıcıların eriştiği adı
  scrape edin.

Token'ın bir dosyadan okunduğu bir Prometheus scrape yapılandırması:

```yaml
scrape_configs:
  - job_name: queryproxy
    scheme: https
    metrics_path: /metrics
    authorization:
      type: Bearer
      credentials_file: /etc/prometheus/queryproxy-metrics-token
    static_configs:
      - targets: ['queryproxy.example.com']
```

### Neleri sunar

Sayaçlar bilinen label kümeleri için 0'dan başlar; böylece `rate()` için bir
başlangıç noktası olur.

| Metrik | Tür | Label'lar | Anlamı |
| :-- | :-- | :-- | :-- |
| `queryproxy_requests_total` | counter | `kind` (`read`, `write`), `status` | Talepler; her biri bir duruma girdiğinde sayılır. `queued` sayılmaz. Stop ve cancel ikisi de `cancelled` olarak sayılır |
| `queryproxy_requests_pending` | gauge | | Karar bekleyen talepler |
| `queryproxy_approval_latency_seconds` | histogram | | Gönderimden bir onay ya da red kararına kadar geçen saniye |
| `queryproxy_execution_duration_seconds` | histogram | `driver` | Bir talebin hedef veritabanında çalıştığı saniye |
| `queryproxy_guard_rejections_total` | counter | `rule` | SQL guard'ın reddettiği ifadeler, kural ailesine göre: `where_clause`, `privilege_management`, `server_control`, `file_io`, `dynamic_sql`, `transaction_control`, `session_setting`, `unreadable_sql`, `other` |
| `queryproxy_masked_values_total` | counter | `rule` | Bir maskeleme kuralıyla değiştirilen sonuç değerleri, kural türüne göre: `column`, `regex`, `validator` |
| `queryproxy_slot_deferred_requests_total` | counter | | Her bağlantı slot'u meşgul olduğu için bekletilen talepler |
| `queryproxy_queue_depth` | gauge | `queue` | Bir kuyrukta bekleyen işler |
| `queryproxy_failed_jobs` | gauge | | Başarısız işler tablosundaki satırlar |

Label'lar asla SQL, kullanıcı adı, takım adı ya da host adı taşımaz. Maskelenen
değerlerin `rule` label'ı kuralın adı değil eşleşme türüdür; çünkü kural
adlarını her takım kendisi seçer.

Sayıların nasıl davrandığına dair notlar:

- Bir guard reddi kullanıcı eylemi başına sayılır. Bir ifadeyi doğrulayıp sonra
  aynı ifadeyi göndermek onu iki kez saydırabilir.
- Birden çok kural ailesine takılan bir red, her ailede bir kez sayılır.
- SQLite'ta sayılan her olay bir veritabanı yazmasıdır. Label'lar sınırlı
  olduğu için tablo küçük kalır.
- `/metrics`, `metric_samples` tablosuna ihtiyaç duyar. Yeni işçileri
  başlatmadan önce migration'ları çalıştırın.

### Faydalı sorgular

```text
# Requests waiting for a decision for a long time
queryproxy_requests_pending > 0

# 95th percentile approval latency over 1 hour
histogram_quantile(0.95, sum by (le) (rate(queryproxy_approval_latency_seconds_bucket[1h])))

# 95th percentile execution time per driver
histogram_quantile(0.95, sum by (le, driver) (rate(queryproxy_execution_duration_seconds_bucket[15m])))

# Failed requests per minute
sum(rate(queryproxy_requests_total{status="failed"}[5m])) * 60
```

`queryproxy_failed_jobs > 0` ve büyümeye devam eden bir `queryproxy_queue_depth`
için alarm kurun: ikisi de işçinin yetişemediği ya da çalışmadığı anlamına gelir.

## Grafana dashboard'u

Depodaki
[`docs/grafana-queryproxy.json`](https://github.com/QueryProxy/QueryProxy/blob/main/docs/grafana-queryproxy.json)
örnek bir dashboard'dur (uid `queryproxy-overview`). Grafana'nın dashboard
import özelliğiyle içe aktarın, ardından en üstteki **Data source** değişkeninden
Prometheus veri kaynağınızı seçin. Pending talepleri, başarısız işleri, kuyruk
derinliğini, duruma ve türe göre talepleri, onay gecikmesini (p50 ve p95),
driver'a göre çalışma süresini (p95), guard reddlerini, maskelenen değerleri ve
bir bağlantı slot'u için bekletilen talepleri gösterir. Bir başlangıç noktası
olarak görün; kopyalayın ve kopyayı düzenleyin.

## Doctor

`queryproxy:doctor` yapılandırmayı, veritabanını, kuyruğu, zamanlayıcıyı,
depolamayı, TLS'i ve denetim zincirini kontrol eder. Her deploy'dan sonra ve bir
pipeline içinde `--strict --json` ile çalıştırın. Her kontrol
[Sorun giderme](/tr/docs/sorun-giderme/#doctor-çıktısını-okuma) sayfasında
açıklanır.

Doctor **zamanlayıcının** çalışıp çalışmadığını söyleyebilir; çünkü zamanlayıcı
her dakika cache'e bir heartbeat yazar. Duran bir zamanlayıcı, süresi dolmuş
sonuçların temizlenmediği, hatırlatmaların gönderilmediği ve günlük denetim
checkpoint'inin çalışmadığı anlamına gelir.

## Zamanlayıcının çalıştırdıkları

| İş | Zamanlama |
| :-- | :-- |
| `results:prune` | Günlük |
| `queue:prune-failed` | Haftalık |
| `audit:checkpoint` | Günlük |
| `requests:remind` | Her 15 dakikada bir |
| Zamanlayıcı heartbeat'i | Her dakika |

## Sonraki adımlar

- [Denetim zinciri ve SIEM dışa aktarımı](/tr/docs/denetim-kaydi-ve-siem/)
- [Sorun giderme](/tr/docs/sorun-giderme/)
- [Yapılandırma](/tr/docs/yapilandirma/)
