Metrik titik waktu memberi tahu Anda apa yang terjadi saat ini. Data rangkaian waktu memberi tahu Anda apa yang berubah, kapan berubah, dan apakah sesuatu cenderung menimbulkan masalah. Lacak tingkat penyelesaian, latensi, dan biaya CAPTCHA dari waktu ke waktu untuk mengetahui degradasi sebelum berdampak pada pipeline Anda.
Apa yang Harus Dilacak
| Metrik | Ketik | Mengapa |
|---|---|---|
| Tingkat penyelesaian (%) | Pengukur | Deteksi perubahan kualitas penyedia |
| Mengatasi latensi (ms) | Histogram | Temukan perlambatan, rencanakan timeout |
| Tingkat kesalahan berdasarkan kode | Penghitung | Identifikasi pola kesalahan yang muncul |
| Biaya per penyelesaian ($) | Pengukur | Pelacakan anggaran, deteksi anomali |
| Kedalaman antrian | Pengukur | Perencanaan kapasitas |
| Token expiry sebelum digunakan | Penghitung | Sinyal penyetelan TTL |
| saldo API | Pengukur | Isi ulang pemicu |
Prometheus + Python (Gerbang Dorong)
Instrumen Pemecah Anda
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
Pertanyaan Prometheus
# 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])
MasuknyaDB + Python
Tulis Metrik Penyelesaian
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)
Kueri InfluxDB (Fluks)
// 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")
Implementasi JavaScript (Prometheus)
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);
Perbandingan Basis Data
| Fitur | Prometheus | masuknyaDB | Skala waktuDB |
|---|---|---|---|
| Terbaik untuk | Pemantauan operasional | IoT / metrik berkardinalitas tinggi | Analisis berbasis SQL |
| Bahasa kueri | PromQL | Fluks | SQL |
| Retensi | Berbasis konfigurasi | Berbasis kebijakan | Retensi PostgreSQL |
| Integrasi Grafana | Asli | Asli | Asli |
| Kurva belajar | Rendah | Sedang | Rendah (jika Anda tahu SQL) |
| Dihosting sendiri | Ya | Ya | Ya (ekstensi PostgreSQL) |
Pemecahan masalah
| Masalah | Sebab | Perbaiki |
|---|---|---|
| Kesenjangan metrik di dashboard | Gerbang dorong tidak menerima data | Periksa jaringan antara solver dan push gateway |
| Histogram latensi menunjukkan persentil yang salah | Batasan keranjang tidak sesuai dengan beban kerja | Sesuaikan keranjang: [5, 10, 15, 20, 30, 45, 60, 90, 120] untuk penyelesaian CAPTCHA |
| Metrik biaya tidak sesuai dengan pembelanjaan sebenarnya | Harga berbeda untuk setiap jenis CAPTCHA | Tandai biaya berdasarkan jenis; gunakan harga per jenis yang sebenarnya |
| Terlalu banyak kardinalitas | Terlalu banyak nilai label | Batasi label pada type, status, error_code |
Pertanyaan Umum
Basis data deret waktu manakah yang harus saya gunakan?
Prometheus jika Anda sudah memilikinya untuk pemantauan infrastruktur - cukup tambahkan metrik CAPTCHA. InfluxDB jika Anda menginginkan penyimpanan metrik mandiri. TimescaleDB jika Anda ingin kueri SQL pada data deret waktu.
Berapa lama saya harus mempertahankan metrik CAPTCHA?
Simpan data resolusi tinggi (per detik) selama 7 hari, data gabungan (per jam) selama 90 hari, dan ringkasan harian tanpa timeout. Hal ini menyeimbangkan biaya penyimpanan dengan visibilitas tren.
Bisakah saya mendeteksi penurunan tingkat penyelesaian secara otomatis?
Ya. Tetapkan peringatan pada rata-rata perputaran – misalnya, peringatan ketika tingkat keberhasilan 1 jam turun di bawah 90% atau ketika latensi P95 melebihi 45 detik. Peringatan Prometheus Alertmanager dan InfluxDB mendukung hal ini.
Langkah Selanjutnya
Lacak kinerja penyelesaian CAPTCHA Anda dari waktu ke waktu —dapatkan kunci API CaptchaAI Andadan mulai mengumpulkan metrik.
Panduan terkait:
- Templat dashboard Grafana
- Pemantauan SLI/SLO
- Sejarah CAPTCHA MongoDB