Diyelim ki çözüm oranınız bu sabah %98'den %90'a indi. Peki bu düşüş ne zaman başladı — dün gece mi, yoksa on gün önce mi? Anlık bir panel bu soruyu yanıtlayamaz; yalnızca zaman serisi verisi yanıtlar. Çözüm oranını, gecikmeyi ve maliyeti zaman içinde kaydettiğinizde, bir bozulmayı üretim akışınıza yansımadan önce fark edersiniz. Bu rehber, bu geçmişi Prometheus, InfluxDB ve TimescaleDB ile nasıl toplayacağınızı çalışan örneklerle gösteriyor.
Hangi metrikleri izlemelisiniz?
İzlemeye değer metrikler ikiye ayrılır: sağlayıcı kalitesini yansıtanlar (çözüm oranı, gecikme) ve bütçeyi yansıtanlar (maliyet, bakiye). Aşağıdaki tablo her birini hangi metrik tipiyle toplayacağınızı özetler.
| Metrik | Tip | Neden izlenir |
|---|---|---|
| Çözüm oranı (%) | Gauge | Sağlayıcı kalitesindeki değişiklikleri yakalar |
| Çözüm gecikmesi (ms) | Histogram | Yavaşlamaları görür, zaman aşımı eşiği belirler |
| Hata koduna göre hata oranı | Counter | Yeni beliren hata desenlerini ortaya çıkarır |
| Çözüm başına maliyet ($) | Gauge | Bütçe takibi, anormallik tespiti |
| Kuyruk derinliği | Gauge | Kapasite planlaması |
| Kullanılmadan süresi dolan token'lar | Counter | TTL ayarı için sinyal |
| API bakiyesi | Gauge | Yeniden yükleme tetiği |
Hangi zaman serisi veritabanını seçmelisiniz?
Kod yazmadan önce nereye yazacağınıza karar verin. Üç seçenek de Grafana ile sorunsuz çalışır; fark sorgu diline ve altyapınızda zaten ne bulunduğuna iner. Operasyonel izleme için Prometheus, bağımsız bir metrik deposu için InfluxDB, tanıdık SQL için TimescaleDB mantıklı bir başlangıçtır.
| Özellik | Prometheus | InfluxDB | TimescaleDB |
|---|---|---|---|
| En uygun olduğu senaryo | Operasyonel izleme | IoT / yüksek kardinaliteli metrikler | SQL tabanlı analiz |
| Sorgu dili | PromQL | Flux | SQL |
| Saklama | Yapılandırma tabanlı | Politika tabanlı | PostgreSQL saklama |
| Grafana entegrasyonu | Yerleşik | Yerleşik | Yerleşik |
| Öğrenme eğrisi | Düşük | Orta | Düşük (SQL biliyorsanız) |
| Kendi sunucunuzda barındırma | Evet | Evet | Evet (PostgreSQL uzantısı) |
Prometheus + Python ile metrik toplama (Push Gateway)
Kısa ömürlü çözüm işleri için Push Gateway en pratik yaklaşımdır: çözücünüz metriği bir aracıya iter, Prometheus oradan çeker. Böylece worker durduğunda metrik akışı kesilmez.
Çözücünüze ölçüm ekleyin
import os
import time
import requests
from prometheus_client import CollectorRegistry, Counter, Histogram, Gauge, push_to_gateway
registry = CollectorRegistry()
SOLVE_TOTAL = Counter(
"captcha_solve_total", "Total CAPTCHA solve attempts",
["type", "status"], registry=registry
)
SOLVE_LATENCY = Histogram(
"captcha_solve_latency_seconds", "CAPTCHA solve latency",
["type"], buckets=[5, 10, 15, 20, 30, 45, 60, 90, 120],
registry=registry
)
SOLVE_COST = Counter(
"captcha_solve_cost_dollars", "Total cost of CAPTCHA solves",
["type"], registry=registry
)
API_BALANCE = Gauge(
"captcha_api_balance_dollars", "CaptchaAI account balance",
registry=registry
)
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
PUSHGATEWAY = os.environ.get("PUSHGATEWAY_URL", "localhost:9091")
def solve_with_metrics(sitekey, pageurl, captcha_type="recaptcha_v2"):
start = time.time()
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1
})
data = resp.json()
if data.get("status") != 1:
SOLVE_TOTAL.labels(type=captcha_type, status="submit_error").inc()
push_metrics()
return {"error": data.get("request")}
captcha_id = data["request"]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get",
"id": captcha_id, "json": 1
}).json()
if result.get("status") == 1:
elapsed = time.time() - start
SOLVE_TOTAL.labels(type=captcha_type, status="solved").inc()
SOLVE_LATENCY.labels(type=captcha_type).observe(elapsed)
SOLVE_COST.labels(type=captcha_type).inc(0.00299)
push_metrics()
return {"solution": result["request"]}
if result.get("request") != "CAPCHA_NOT_READY":
SOLVE_TOTAL.labels(type=captcha_type, status="error").inc()
push_metrics()
return {"error": result.get("request")}
SOLVE_TOTAL.labels(type=captcha_type, status="timeout").inc()
push_metrics()
return {"error": "TIMEOUT"}
def push_metrics():
try:
push_to_gateway(PUSHGATEWAY, job="captcha_solver", registry=registry)
except Exception:
pass # Don't fail solving because metrics push failed
def update_balance():
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "getbalance"
})
try:
balance = float(resp.text)
API_BALANCE.set(balance)
push_metrics()
except ValueError:
pass
Prometheus sorguları
Trend görünürlüğünü sağlayan dört sorgu: saatlik başarı oranı, P95 gecikme, tipe göre hata oranı ve saatlik maliyet.
# Success rate over last hour
rate(captcha_solve_total{status="solved"}[1h])
/ rate(captcha_solve_total[1h]) * 100
# P95 solve latency
histogram_quantile(0.95, rate(captcha_solve_latency_seconds_bucket[1h]))
# Error rate by type
rate(captcha_solve_total{status="error"}[1h])
# Hourly cost
increase(captcha_solve_cost_dollars_total[1h])
InfluxDB + Python ile metrik yazma
Metrikleri bağımsız bir depoda tutmak isterseniz InfluxDB doğal seçenektir. Her çözümü ölçüm noktası olarak yazarsınız; etiketler filtrelemeyi, alanlar toplamayı kolaylaştırır.
Çözüm metriklerini yazın
from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS
INFLUX_URL = os.environ.get("INFLUX_URL", "http://localhost:8086")
INFLUX_TOKEN = os.environ.get("INFLUX_TOKEN", "")
INFLUX_ORG = os.environ.get("INFLUX_ORG", "captcha")
INFLUX_BUCKET = os.environ.get("INFLUX_BUCKET", "captcha_metrics")
influx_client = InfluxDBClient(url=INFLUX_URL, token=INFLUX_TOKEN, org=INFLUX_ORG)
write_api = influx_client.write_api(write_options=SYNCHRONOUS)
def record_solve_metric(captcha_type, status, elapsed_ms, cost=0.0, error=None):
point = (
Point("captcha_solve")
.tag("type", captcha_type)
.tag("status", status)
.field("elapsed_ms", elapsed_ms)
.field("cost", cost)
.field("success", 1 if status == "solved" else 0)
)
if error:
point = point.tag("error_code", error)
write_api.write(bucket=INFLUX_BUCKET, record=point)
def record_balance(balance):
point = Point("captcha_balance").field("balance", balance)
write_api.write(bucket=INFLUX_BUCKET, record=point)
InfluxDB (Flux) sorguları
Aynı üç trendi Flux ile alırsınız: saatlik pencerelerde başarı oranı, tipe göre ortalama çözüm süresi ve kümülatif maliyet.
// Success rate over last 24 hours (1-hour windows)
from(bucket: "captcha_metrics")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "captcha_solve" and r._field == "success")
|> aggregateWindow(every: 1h, fn: mean)
|> map(fn: (r) => ({r with _value: r._value * 100.0}))
|> yield(name: "success_rate")
// Average solve time by type
from(bucket: "captcha_metrics")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "captcha_solve" and r._field == "elapsed_ms" and r.status == "solved")
|> group(columns: ["type"])
|> aggregateWindow(every: 1h, fn: mean)
|> yield(name: "avg_latency")
// Cumulative cost
from(bucket: "captcha_metrics")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "captcha_solve" and r._field == "cost")
|> cumulativeSum()
|> yield(name: "cumulative_cost")
JavaScript ile Prometheus entegrasyonu
Çözüm mantığınız Node.js tarafındaysa prom-client ile aynı sayaç ve histogramları tutar, /metrics uç noktasını açıp Prometheus'un çekmesine izin verirsiniz.
const client = require("prom-client");
const axios = require("axios");
const register = new client.Registry();
const API_KEY = process.env.CAPTCHAAI_API_KEY;
const solveTotal = new client.Counter({
name: "captcha_solve_total",
help: "Total CAPTCHA solve attempts",
labelNames: ["type", "status"],
registers: [register],
});
const solveLatency = new client.Histogram({
name: "captcha_solve_latency_seconds",
help: "CAPTCHA solve latency",
labelNames: ["type"],
buckets: [5, 10, 15, 20, 30, 45, 60, 90, 120],
registers: [register],
});
async function solveWithMetrics(sitekey, pageurl, type = "recaptcha_v2") {
const start = Date.now();
const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: { key: API_KEY, method: "userrecaptcha", googlekey: sitekey, pageurl, json: 1 },
});
if (submit.data.status !== 1) {
solveTotal.inc({ type, status: "submit_error" });
return { error: submit.data.request };
}
const captchaId = submit.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const poll = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "get", id: captchaId, json: 1 },
});
if (poll.data.status === 1) {
const elapsed = (Date.now() - start) / 1000;
solveTotal.inc({ type, status: "solved" });
solveLatency.observe({ type }, elapsed);
return { solution: poll.data.request };
}
if (poll.data.request !== "CAPCHA_NOT_READY") {
solveTotal.inc({ type, status: "error" });
return { error: poll.data.request };
}
}
solveTotal.inc({ type, status: "timeout" });
return { error: "TIMEOUT" };
}
// Expose metrics endpoint
const express = require("express");
const app = express();
app.get("/metrics", async (req, res) => {
res.set("Content-Type", register.contentType);
res.end(await register.metrics());
});
app.listen(9090);
Maliyet takibi ve thread bütçesi
Zaman serisi verisinin en somut faydası maliyet görünürlüğüdür. CaptchaAI thread tabanlı çalışır: ücreti çözüm başına değil, eş zamanlı thread sayısına göre ödersiniz ve her thread sınırsız çözüm içerir. BASIC planla ($15/ay, 5 thread) sabit bir bütçeyle çalışırsınız — Türk geliştiriciler için USD'nin öngörülebilir aylık maliyeti, kur dalgalanmasına karşı gerçek bir avantajdır. captcha_solve_cost_dollars ve captcha_api_balance_dollars metriklerini izleyerek harcamanın planınızla uyumlu gittiğini ve bakiyenin ne zaman yükleme gerektireceğini erkenden görürsünüz.
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| Panelde metrik boşlukları | Push Gateway veri almıyor | Çözücü ile Push Gateway arasındaki ağ bağlantısını kontrol edin |
| Gecikme histogramı yanlış yüzdelik dilimler gösteriyor | Kova sınırları iş yüküyle örtüşmüyor | Kovaları CAPTCHA çözümü için [5, 10, 15, 20, 30, 45, 60, 90, 120] olarak ayarlayın |
| Maliyet metrikleri gerçek harcamayla tutmuyor | CAPTCHA tipine göre fiyat farkı | Maliyeti tipe göre etiketleyin; tip başına gerçek fiyatı kullanın |
| Kardinalite çok yüksek | Fazla etiket değeri | Etiketleri type, status, error_code ile sınırlayın |
Sık sorulan sorular
Anlık metriklerle zaman serisi verisi arasındaki fark nedir?
Anlık metrik size şu andaki durumu söyler: çözüm oranı şu an %90. Zaman serisi verisi ise bu değerin nasıl bir eğri izlediğini gösterir — düşüş üç gün önce mi başladı, yoksa ani bir sıçrama mı? Trend olmadan bir tek ölçümün normal mi anormal mi olduğunu bilemezsiniz.
Push Gateway olmadan Prometheus kullanabilir miyim?
Evet. Uzun ömürlü bir servis çalıştırıyorsanız /metrics uç noktasını doğrudan açıp Prometheus'un çekmesine izin verebilirsiniz — JavaScript örneğindeki yaklaşım budur. Push Gateway asıl olarak, hızlıca başlayıp biten kısa ömürlü çözüm işleri için gerekir.
Çözüm oranı düştüğünde otomatik uyarı nasıl kurarım?
Sabit eşikler yerine hareketli ortalamalara uyarı bağlayın; örneğin 1 saatlik başarı oranı %90'ın altına indiğinde ya da P95 gecikmesi 45 saniyeyi aştığında tetiklenen bir kural yazın. Hem Prometheus Alertmanager hem de InfluxDB uyarıları bunu destekler.
Çözüm başına maliyeti metriklerde nasıl doğru tutarım?
Maliyeti tek bir sabit değere gömmeyin; her metriği CAPTCHA type etiketiyle işaretleyin ve tip başına gerçek fiyatı kullanın. Böylece bir tipteki hacim artışının toplam maliyeti nasıl kaydırdığını ayrıştırabilirsiniz.
Sonraki adımlar
Çözüm performansınızın zaman içindeki eğrisini görmek istiyorsanız, ilk adım metrikleri toplamaya başlamaktır — CaptchaAI API anahtarınızı alın ve çözücünüzü yukarıdaki örneklerle donatın.
İlgili rehberler: