Um painel Grafana bem projetado mostra exatamente o que está acontecendo em seu pipeline CAPTCHA - taxas de resolução, percentis de latência, tendências de equilíbrio e detalhamentos de erros. Esses modelos estão prontos para importação com o Prometheus como fonte de dados.
Layout do painel
┌───────────────────────────────────────────────┐
│ Row 1: Overview │
│ [Solve Rate %] [Balance $] [Queue Depth] [TPM]│
├───────────────────────────────────────────────┤
│ Row 2: Performance │
│ [Latency P50/P95/P99] [Solve Rate Over Time] │
├───────────────────────────────────────────────┤
│ Row 3: Errors │
│ [Error Rate %] [Error Breakdown by Type] │
├───────────────────────────────────────────────┤
│ Row 4: Workers │
│ [Active Workers] [Tasks Per Worker] │
└───────────────────────────────────────────────┘
Configuração de métricas do Prometheus
Primeiro, exponha as métricas do seu solucionador CAPTCHA:
Python — Cliente Prometheus
import os
import time
import requests
from prometheus_client import (
Counter, Histogram, Gauge, start_http_server
)
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
# Define metrics
captcha_solves = Counter(
"captcha_solves_total",
"Total CAPTCHA solve attempts",
["captcha_type", "status"]
)
captcha_latency = Histogram(
"captcha_solve_duration_seconds",
"CAPTCHA solve latency",
["captcha_type"],
buckets=[5, 10, 15, 20, 30, 45, 60, 90, 120, 180, 300]
)
captcha_balance = Gauge(
"captcha_balance_dollars",
"CaptchaAI account balance"
)
captcha_queue_depth = Gauge(
"captcha_queue_depth",
"Pending tasks in queue"
)
captcha_workers_active = Gauge(
"captcha_workers_active",
"Number of active workers"
)
session = requests.Session()
def solve_with_metrics(sitekey, pageurl, captcha_type="recaptcha_v2"):
start = time.time()
resp = session.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:
captcha_solves.labels(captcha_type, "error").inc()
return {"error": data.get("request")}
captcha_id = data["request"]
for _ in range(60):
time.sleep(5)
result = session.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
captcha_solves.labels(captcha_type, "success").inc()
captcha_latency.labels(captcha_type).observe(elapsed)
return {"solution": result["request"]}
if result.get("request") != "CAPCHA_NOT_READY":
captcha_solves.labels(captcha_type, "error").inc()
return {"error": result.get("request")}
captcha_solves.labels(captcha_type, "timeout").inc()
return {"error": "TIMEOUT"}
def update_balance():
resp = session.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "getbalance", "json": 1
})
if resp.json().get("status") == 1:
captcha_balance.set(float(resp.json()["request"]))
# Start metrics server on port 9090
start_http_server(9090)
JavaScript
const promClient = require("prom-client");
const axios = require("axios");
const API_KEY = process.env.CAPTCHAAI_API_KEY;
const register = new promClient.Registry();
const solvesTotal = new promClient.Counter({
name: "captcha_solves_total",
help: "Total CAPTCHA solve attempts",
labelNames: ["captcha_type", "status"],
registers: [register],
});
const solveLatency = new promClient.Histogram({
name: "captcha_solve_duration_seconds",
help: "CAPTCHA solve latency",
labelNames: ["captcha_type"],
buckets: [5, 10, 15, 20, 30, 45, 60, 90, 120, 180, 300],
registers: [register],
});
const balance = new promClient.Gauge({
name: "captcha_balance_dollars",
help: "CaptchaAI account balance",
registers: [register],
});
const queueDepth = new promClient.Gauge({
name: "captcha_queue_depth",
help: "Pending tasks in queue",
registers: [register],
});
async function solveWithMetrics(sitekey, pageurl, captchaType = "recaptcha_v2") {
const end = solveLatency.startTimer({ captcha_type: captchaType });
try {
const resp = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: {
key: API_KEY, method: "userrecaptcha",
googlekey: sitekey, pageurl, json: 1,
},
});
if (resp.data.status !== 1) {
solvesTotal.inc({ captcha_type: captchaType, status: "error" });
return { error: resp.data.request };
}
const captchaId = resp.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) {
end();
solvesTotal.inc({ captcha_type: captchaType, status: "success" });
return { solution: poll.data.request };
}
if (poll.data.request !== "CAPCHA_NOT_READY") {
solvesTotal.inc({ captcha_type: captchaType, status: "error" });
return { error: poll.data.request };
}
}
solvesTotal.inc({ captcha_type: captchaType, status: "timeout" });
return { error: "TIMEOUT" };
} catch (err) {
solvesTotal.inc({ captcha_type: captchaType, status: "error" });
throw err;
}
}
// 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);
Consultas do painel Grafana (PromQL)
Linha 1: estatísticas gerais
Taxa de resolução (painel de estatísticas):
sum(rate(captcha_solves_total{status="success"}[5m]))
/
sum(rate(captcha_solves_total[5m]))
* 100
Saldo (painel de medidores):
captcha_balance_dollars
Profundidade da fila (painel de estatísticas):
captcha_queue_depth
Tarefas por minuto (painel de estatísticas):
sum(rate(captcha_solves_total[5m])) * 60
Linha 2: Desempenho
Percentis de latência (série temporal):
# p50
histogram_quantile(0.50, rate(captcha_solve_duration_seconds_bucket[5m]))
# p95
histogram_quantile(0.95, rate(captcha_solve_duration_seconds_bucket[5m]))
# p99
histogram_quantile(0.99, rate(captcha_solve_duration_seconds_bucket[5m]))
Resolver taxa ao longo do tempo (série temporal):
sum(rate(captcha_solves_total{status="success"}[5m])) by (captcha_type) * 60
Linha 3: Erros
Taxa de erro (série temporal):
sum(rate(captcha_solves_total{status!="success"}[5m]))
/
sum(rate(captcha_solves_total[5m]))
* 100
Detalhamento de erros (gráfico de pizza):
sum by (status) (increase(captcha_solves_total{status!="success"}[1h]))
Linha 4: Trabalhadores
Trabalhadores Ativos (Série Temporal):
captcha_workers_active
Regras de alerta (Alerta Grafana)
# Grafana alert rules
groups:
- name: captcha-alerts
rules:
- alert: LowBalance
expr: captcha_balance_dollars < 10
for: 5m
labels:
severity: warning
annotations:
summary: "CaptchaAI balance low: {{ $value }}"
- alert: HighErrorRate
expr: |
sum(rate(captcha_solves_total{status!="success"}[5m]))
/ sum(rate(captcha_solves_total[5m]))
> 0.1
for: 5m
labels:
severity: critical
- alert: HighLatency
expr: |
histogram_quantile(0.95,
rate(captcha_solve_duration_seconds_bucket[5m])
) > 120
for: 10m
labels:
severity: warning
Solução de problemas
| Problema | Causa | Correção |
|---|---|---|
| "Sem dados" nos painéis | Prometheus não está raspando o endpoint de métricas | Verifique os alvos prometheus.yml; verificar se /metrics retorna dados |
| Percentis de latência errados | Janela rate() errada ou buckets ausentes |
Use a janela de taxas [5m]; adicione baldes mais refinados |
| Variáveis do painel não funcionam | Consulta de variável de modelo incorreta | Usar label_values(captcha_solves_total, captcha_type) |
| Alertas não disparando | Intervalo de avaliação de alerta muito longo | Defina o intervalo de avaliação para 1 minuto |
Perguntas frequentes
Posso importar esses painéis de um arquivo JSON?
Sim. Grafana suporta importação de painel JSON. Crie o painel na UI, exporte como JSON e importe-o em outras instâncias do Grafana.
Qual intervalo de raspagem do Prometheus devo usar?
15 segundos é o padrão. Para pipelines CAPTCHA com volume menor, 30 segundos funcionam bem. Não desça abaixo de 10 segundos, a menos que precise de visibilidade em tempo real.
Posso usar Grafana Cloud em vez de auto-hospedado?
Sim. Grafana Cloud oferece suporte à gravação remota do Prometheus. Envie métricas do seu Prometheus para o Grafana Cloud e use as mesmas consultas PromQL.
Artigos relacionados
- Construir painel de análise do concorrente Captchaai
- Alertas de métricas do Datadog de monitoramento Captchaai
- Construindo monitoramento do painel de uso do Captchaai
Próximas etapas
Visualize seu pipeline CAPTCHA -obtenha sua chave API CaptchaAIe configurar painéis do Grafana.
Guias relacionados:
- Monitoramento Prometheus e Grafana
- Monitoramento Datadog
- Monitoramento SLI/SLO