Çözüm oranınızın düştüğünü müşteri şikayetinden önce görmek istiyorsanız cevap tek satır: metrikleri Prometheus'a yazın, Grafana'da izleyin ve eşik aşıldığında uyarı alın. Panelsiz bir çözücü sorunu ancak istekler düşünce fark eder — bu da saatlerce sessiz kayıp demektir.
İstanbul'da teslim tarihine yetişen bir otomasyon geliştiricisi için, birçok worker aynı anda çözüm yaparken hangi türün yavaşladığını ve bakiyenin ne zaman biteceğini görmek şarttır.
Neyi neden izlemeliyiz?
Bir çözücünün sağlığı şu beş metrikte özetlenir:
| Metrik | Tür | Amaç |
|---|---|---|
captcha_solves_total |
Sayaç | Toplam çözüm denemeleri |
captcha_solves_success |
Sayaç | Başarılı çözümler |
captcha_solves_errors |
Sayaç | Başarısız çözümler (hata türüne göre) |
captcha_solve_duration |
Histogram | Çözüm süresinin dağılımı |
captcha_balance |
Ölçer | Cari hesap bakiyesi |
captcha_queue_length |
Ölçer | Kuyrukta bekleyen görevler |
Bu altı metrik birlikte iki soruyu yanıtlar: sistem şu anda sağlıklı mı ve yakında bozulacak mı? captcha_solves_success / captcha_solves_total oranı anlık başarıyı verir; captcha_solves_errors etiketli dökümü kök nedeni işaret eder. captcha_solve_duration histogramı yavaşlamayı ortalamada gizlenmeden gösterir, captcha_balance ise boru hattı bakiye bitince sessizce durmadan önce sizi uyarır.
Pratikte panelinizi şu üç soruya göre kurun:
- Başarı oranı düşüyor mu? —
success/totaloranı. - Yavaşlama tek bir türde mi toplanıyor? —
duration,methodetiketiyle. - Bakiye ne zaman bitecek? —
balanceeğilimi.
Python ile metrik toplayıcı
Çözücünüzü prometheus_client ile sarmalayın; her çağrı denemeyi, sonucu ve süreyi kaydeder ve /metrics uç noktası bunları yayınlar.
# metrics.py
import time
import requests
from prometheus_client import (
Counter, Histogram, Gauge, start_http_server,
)
# Define metrics
SOLVES_TOTAL = Counter(
"captcha_solves_total",
"Total CAPTCHA solve attempts",
["method"],
)
SOLVES_SUCCESS = Counter(
"captcha_solves_success",
"Successful CAPTCHA solves",
["method"],
)
SOLVES_ERRORS = Counter(
"captcha_solves_errors",
"Failed CAPTCHA solves",
["method", "error_code"],
)
SOLVE_DURATION = Histogram(
"captcha_solve_duration_seconds",
"CAPTCHA solve duration in seconds",
["method"],
buckets=[5, 10, 15, 20, 30, 45, 60, 90, 120],
)
BALANCE = Gauge(
"captcha_balance_usd",
"Current CaptchaAI account balance in USD",
)
QUEUE_LENGTH = Gauge(
"captcha_queue_length",
"Number of pending CAPTCHA tasks",
)
class InstrumentedSolver:
"""Solver with Prometheus metric instrumentation."""
def __init__(self, api_key):
self.api_key = api_key
self.base = "https://ocr.captchaai.com"
def solve(self, method, **params):
"""Solve CAPTCHA with metric collection."""
SOLVES_TOTAL.labels(method=method).inc()
start = time.time()
try:
token = self._do_solve(method, params)
duration = time.time() - start
SOLVES_SUCCESS.labels(method=method).inc()
SOLVE_DURATION.labels(method=method).observe(duration)
return token
except Exception as e:
error_code = str(e)[:30]
SOLVES_ERRORS.labels(
method=method, error_code=error_code,
).inc()
raise
def update_balance(self):
"""Fetch and update balance metric."""
resp = requests.get(f"{self.base}/res.php", params={
"key": self.api_key,
"action": "getbalance",
"json": 1,
}, timeout=15)
balance = float(resp.json()["request"])
BALANCE.set(balance)
return balance
def _do_solve(self, method, params, timeout=120):
data = {"key": self.api_key, "method": method, "json": 1}
data.update(params)
resp = requests.post(
f"{self.base}/in.php", data=data, timeout=30,
)
result = resp.json()
if result.get("status") != 1:
raise RuntimeError(result.get("request"))
task_id = result["request"]
start = time.time()
while time.time() - start < timeout:
time.sleep(5)
resp = requests.get(f"{self.base}/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1,
}, timeout=15)
data = resp.json()
if data["request"] != "CAPCHA_NOT_READY":
if data.get("status") == 1:
return data["request"]
raise RuntimeError(data["request"])
raise TimeoutError("Solve timeout")
# Start metrics server on port 8000
start_http_server(8000)
print("Metrics server running on :8000/metrics")
method etiketi türleri ayrı süzmenizi sağlar. update_balance çağrısını her çözümde değil, ayrı bir zamanlayıcıda (örneğin 60 saniyede bir) çalıştırın; aksi halde gereksiz istek üretirsiniz. Sunucu ayağa kalktığında /metrics uç noktası tüm sayaç ve ölçerleri Prometheus'un kazıyabileceği düz metin biçiminde yayınlar.
Toplayıcı üç Prometheus aracını birlikte kullanır:
- Counter — yalnızca artan sayaçlar (
solves_total,solves_success,solves_errors). - Histogram — çözüm süresini önceden tanımlı bucket'lara dağıtır (
solve_duration). - Gauge — anlık, iki yönde değişebilen değerler (
balance,queue_length).
Prometheus'u yapılandırma
Çözücünüzü Prometheus'a hedef olarak tanıtın; 10 saniyelik kazıma aralığı gerçek zamanlı bir panel için yeterli.
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: "captcha-solver"
static_configs:
- targets: ["solver-app:8000"]
scrape_interval: 10s
Birden fazla çözücünüz varsa her birini ayrı bir targets girdisi olarak ekleyin; Prometheus hepsini aynı iş altında toplar. Yapılandırırken iki noktaya dikkat edin:
scrape_intervaldeğerini ortalama çözüm sürenizden kısa tutun, yoksa kısa dalgalanmaları kaçırırsınız.- Hedef adresi Compose servis adıyla verin (
solver-app:8000), sabit IP ile değil.
Docker Compose ile yığını ayağa kaldırma
Çözücü, Prometheus ve Grafana'yı tek dosyada bağlayın.
# docker-compose.yml
version: "3.8"
services:
solver:
build: .
environment:
- CAPTCHAAI_KEY=${CAPTCHAAI_KEY}
ports:
- "8000:8000"
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
volumes:
grafana-data:
docker compose up -d komutundan sonra Prometheus 9090, Grafana ise 3000 portunda hazır olur. Grafana'ya ilk girişte veri kaynağı olarak http://prometheus:9090 adresini tanımlayın — servis adları Compose ağı içinde otomatik çözülür, ayrıca IP girmenize gerek yoktur.
Grafana panelleri ve PromQL sorguları
Dört panelle başlayın: başarı oranı, ortalama süre, hata dökümü ve bakiye. Sayaçlar yeniden başlatmada sıfırlandığı için oranları rate() ile hesaplayın.
Her panel farklı bir soruyu yanıtlar:
- Başarı oranı — sistemin genel sağlık göstergesi.
- Ortalama ve P95 süre — gecikme eğilimi ve en kötü durum.
- Türe göre hata — sorunun kök nedeni.
- Bakiye — yaklaşan kesinti riski.
Başarı oranı (PromQL)
rate(captcha_solves_success[5m])
/ rate(captcha_solves_total[5m]) * 100
Ortalama çözüm süresi
rate(captcha_solve_duration_seconds_sum[5m])
/ rate(captcha_solve_duration_seconds_count[5m])
Türe göre hata oranı
sum by (error_code) (
rate(captcha_solves_errors[5m])
)
Zaman içinde bakiye
captcha_balance_usd
P95 çözüm süresi
histogram_quantile(0.95,
rate(captcha_solve_duration_seconds_bucket[5m])
)
P95, kullanıcıların gerçekte deneyimlediği en kötü durumu ortalamadan daha dürüst yansıtır; SLA eşiklerinizi ortalama süreye değil P95'e göre belirleyin.
Uyarı kuralları
Panele sürekli bakmayın; eşikleri tanımlayın, sorun oluştuğunda uyarı gelsin.
# alert_rules.yml
groups:
- name: captcha-alerts
rules:
- alert: LowBalance
expr: captcha_balance_usd < 5
for: 5m
labels:
severity: warning
annotations:
summary: "CaptchaAI balance below $5"
- alert: HighErrorRate
expr: |
rate(captcha_solves_errors[5m])
/ rate(captcha_solves_total[5m]) > 0.1
for: 10m
labels:
severity: critical
annotations:
summary: "CAPTCHA error rate above 10%"
- alert: SlowSolveTime
expr: |
histogram_quantile(0.95,
rate(captcha_solve_duration_seconds_bucket[5m])
) > 60
for: 15m
labels:
severity: warning
annotations:
summary: "P95 solve time exceeds 60s"
Uyarıları Alertmanager üzerinden Slack veya e-postaya yönlendirin. Örnekteki üç kural farklı sağlık boyutunu kapsar:
LowBalance— kesintiyi önlemek için finansal eşik.HighErrorRate— 5 dakikalık pencerede hata oranı %10'u aşarsa kritik uyarı.SlowSolveTime— P95 süre 60 saniyeyi geçerse performans uyarısı.
Her kuraldaki for süresi anlık dalgalanmaların yanlış alarm üretmesini engeller — hata oranı için 10 dakika, yavaş çözüm için 15 dakika makul başlangıç değerleridir.
Üretimde bakiye ve maliyeti izleme
CaptchaAI planları USD üzerinden ücretlendirilir — BASIC ($15/ay, 5 thread) en düşük kademedir — bu yüzden TL kurundaki dalgalanma aylık plan maliyetinizi değiştirmez. Ama bakiyeniz bittiğinde çözümler sessizce durur; captcha_balance_usd ölçerini ayrı bir Grafana paneline koyun ve düşük bakiye uyarısını tahmini değil gerçek saatlik harcama hızınıza göre ayarlayın. İstanbul saatiyle (Europe/Istanbul) gece yarısı gibi düşük trafikli pencerelerde bakiyeyi elle yüklüyorsanız, eşiği bir sonraki dolum zamanına kadar rahat yetecek biçimde seçin ki iş akışınız hafta sonu ortasında durmasın.
Ölçeklerken kuyruk derinliğini izleme
captcha_queue_length ölçeri, worker'larınızın gelen yükü karşılayıp karşılamadığını gösterir. Kuyruk sürekli büyüyorsa daha fazla thread veya worker devreye almanız gerekir. Panelde şu üç durumu ayırt edin:
- Kuyruk uzunluğu düzenli artıyorsa kapasite yetersizdir.
- P95 süre artarken kuyruk sabitse darboğaz çözüm tarafındadır.
- İkisi de düşükse mevcut kurulum yükü rahat karşılıyordur.
Bu paneli başarı oranının hemen yanına koyun; kapasite darboğazını gerçek bir başarı düşüşünden en hızlı böyle ayırt edersiniz.
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| /metrics'de ölçüm yok | Sunucu başlatılmadı | start_http_server(8000)'i çağırın |
| Prometheus "down" gösteriyor | Yanlış hedef adres | Docker ağını ve portu kontrol edin |
| Grafana veri göstermiyor | Prometheus kaynak olarak eklenmedi | Grafana'ya Prometheus veri kaynağı ekleyin |
| Yeniden başlatmada ölçümler sıfırlanıyor | Sayaç sıfırlanması beklenen davranış | Ham sayaç yerine rate() kullanın |
Sık sorulan sorular
Çözüm oranı metriği ne sıklıkta güncellenir?
Kazıma aralığı kadar sık — örnekte her 10 saniyede bir, yani panel neredeyse gerçek zamanlı. prometheus_client işlem başına 1 ms'nin altında yük ekler; sık kazımanın anlamlı maliyeti yoktur.
Başarı oranı düştüğünde önce neye bakmalıyım?
Türe göre hata oranı paneline. error_code etiketi, sorunun tek bir türde mi yoksa tüm isteklerde mi olduğunu hemen gösterir. Ardından P95 süresine bakın.
Düşük bakiye uyarısını hangi eşiğe ayarlamalıyım?
Ortalama saatlik harcamanızın iki-üç katına. Örnekteki < 5 USD küçük iş yükleri için makuldür; yoğun boru hatlarında eşiği yükseltin.
Aynı kurulumu birden fazla worker ile kullanabilir miyim?
Evet. Her worker kendi /metrics uç noktasını yayınlar; Prometheus tüm hedefleri kazır ve Grafana örnekler arası otomatik toplar.
Histogram bucket'larını nasıl seçmeliyim?
Beklenen çözüm süresi aralığınızı kapsayacak biçimde. Örnekteki 5, 10, 15, 20, 30, 45, 60, 90, 120 saniyelik değerler çoğu tür için iyi bir başlangıçtır; çözümleriniz sürekli tek bir bucket'ta toplanıyorsa aralığı daraltın ki P95 anlamlı kalsın.
Üretime almadan önce kısa kontrol listesi
Kurulumu canlıya taşımadan önce şunları doğrulayın:
/metricsuç noktası çözücü konteynerinde erişilebilir.- Prometheus hedefi
updurumda ve son kazıma güncel. - Grafana'da başarı oranı, süre, hata ve bakiye panelleri veri gösteriyor.
- Üç uyarı kuralı da yüklendi ve bildirim kanalı test edildi.
- Düşük bakiye eşiği gerçek harcama hızınıza göre ayarlandı.
İlgili rehberler
Çözüm oranınızı bugün Prometheus'la izlemeye başlayın — CaptchaAI panelinizi bağlayın.