Um solver de CAPTCHA que falha silenciosamente é pior do que um que falha alto: o time só percebe quando o suporte começa a receber tickets de checkout travado. A resposta é instrumentar o pipeline com Prometheus e visualizar tudo no Grafana antes que a taxa de sucesso caia sem avisar ninguém.
Este guia mostra como expor as métricas certas a partir da API da CaptchaAI, montar um exportador em Python, subir o stack com Docker Compose e configurar os três alertas que realmente importam em produção: saldo baixo, taxa de erro alta e tempo de resolução fora da curva. Se os seus workers rodam em uma região como AWS sa-east-1 (São Paulo), acompanhar o captcha_solve_duration também ajuda a separar latência de rede de lentidão real do desafio.
O que você vai montar:
- Um exportador Python que instrumenta cada chamada de resolução
- Um
prometheus.ymlapontando para esse exportador - Uma stack local com Docker Compose (solver + Prometheus + Grafana)
- Cinco consultas PromQL prontas para os painéis
- Três regras de alerta para saldo, erro e latência
Quais métricas acompanhar
As seis métricas abaixo cobrem os três tipos que o Prometheus espera: contadores para volume acumulado, medidores para o estado atual e um histograma para a distribuição do tempo de resolução. Nenhuma exige lógica customizada complexa — o exportador da próxima seção já expõe todas no formato certo.
Se você opera no plano BASIC (US$ 15/mês, 5 threads) ou ainda está validando a API antes de migrar para um plano maior,
captcha_queue_lengthecaptcha_balance_usdsão as duas métricas que evitam a maior dor de cabeça: fila crescendo porque as threads disponíveis já estão todas ocupadas, ou saldo zerando no meio de um lote grande de resolução.
| Métrica | Tipo | Objetivo |
|---|---|---|
captcha_solves_total |
Contador | Total de tentativas de resolução |
captcha_solves_success |
Contador | Soluções bem-sucedidas |
captcha_solves_errors |
Contador | Falha na resolução (por tipo de erro) |
captcha_solve_duration |
Histograma | Distribuição do tempo de resolução |
captcha_balance |
Medidor | Saldo atual da conta |
captcha_queue_length |
Medidor | Tarefas pendentes na fila |
Exportador de métricas em Python
O exportador abaixo envolve a chamada de resolução com instrumentação automática: cada tentativa incrementa captcha_solves_total, cada sucesso registra a duração no histograma, e cada falha soma ao contador de erros usando o próprio código de erro como label. O método update_balance() consulta getbalance e atualiza o medidor de saldo — chame-o em um job periódico (a cada cinco minutos já é suficiente) para não sobrecarregar a API à toa.
# 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")
Rode esse script como um processo próprio, separado do worker que resolve os CAPTCHAs — assim, uma reinicialização do solver não derruba junto o endpoint /metrics.
Configuração do Prometheus
Aponte o Prometheus para o endpoint exposto na porta 8000. Um intervalo de coleta de 10 a 15 segundos já é suficiente — raspar mais rápido do que isso satura o /metrics sem ganho real de precisão.
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: "captcha-solver"
static_configs:
- targets: ["solver-app:8000"]
scrape_interval: 10s
Stack com Docker Compose
Para subir tudo junto em um ambiente de teste, três serviços — solver, Prometheus e Grafana — já cobrem o essencial. Troque a senha padrão do Grafana (GF_SECURITY_ADMIN_PASSWORD) antes de expor a porta 3000 fora da rede interna.
# 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:
Consultas para o painel do Grafana
As cinco consultas PromQL abaixo cobrem os painéis essenciais. Comece por elas e adicione métricas específicas do seu pipeline conforme a necessidade.
Taxa de sucesso
Retorna a porcentagem de resoluções bem-sucedidas na janela de 5 minutos — o painel que qualquer stakeholder olha primeiro.
rate(captcha_solves_success[5m])
/ rate(captcha_solves_total[5m]) * 100
Tempo médio de resolução
Útil para ver tendência geral, mas sozinho esconde os outliers — combine sempre com o P95 abaixo.
rate(captcha_solve_duration_seconds_sum[5m])
/ rate(captcha_solve_duration_seconds_count[5m])
Taxa de erro por tipo
Agrupar por error_code mostra se o problema é concentrado (um único tipo de erro disparando) ou distribuído (sintoma de instabilidade geral na rede ou no proxy).
sum by (error_code) (
rate(captcha_solves_errors[5m])
)
Saldo ao longo do tempo
Um gráfico de linha simples já basta — o que importa é a inclinação da curva, não o valor absoluto em um único instante.
captcha_balance_usd
Duração de resolução (P95)
P95 importa mais do que a média porque captura os casos lentos que afetam a experiência do usuário final, mesmo quando a média parece saudável.
histogram_quantile(0.95,
rate(captcha_solve_duration_seconds_bucket[5m])
)
Esse conjunto de cinco consultas já é suficiente para o primeiro dashboard — refine os thresholds depois de observar uma semana de tráfego real.
Regras de alerta
As três regras abaixo cobrem os sintomas mais comuns em produção:
- saldo acabando antes do fim do ciclo de faturamento
- taxa de erro subindo acima do normal
- tempo de resolução degradando (P95 alto)
Ajuste os limites (< 5, > 0.1, > 60) para o perfil real do seu tráfego antes de ativar em produção.
# 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"
Conecte essas regras ao Slack, Telegram ou e-mail via Alertmanager — um aviso de saldo baixo às três da manhã vale muito mais do que descobrir a conta zerada só às nove.
Solução de problemas
Os quatro problemas abaixo cobrem praticamente todo chamado que chega sobre essa stack:
| Problema | Causa | Correção |
|---|---|---|
| Nenhuma métrica em /metrics | Servidor não iniciado | Chame start_http_server(8000) |
| Prometheus mostra "down" | Endereço de destino errado | Verifique a rede e a porta do Docker |
| Grafana não mostra dados | Prometheus não adicionado como fonte | Adicione a fonte de dados Prometheus no Grafana |
| Métricas zeradas após reiniciar | Reset de contador é esperado após restart | Use rate(), nunca o contador bruto |
Perguntas frequentes
Preciso de um plano maior para expor essas métricas?
Não. Qualquer plano, do BASIC ao VIP-3, usa os mesmos endpoints in.php/res.php e a mesma chamada getbalance — o exportador funciona igual independente do plano. O que muda é o número de threads simultâneas; em volumes maiores (ENTERPRISE ou VIP-1/2/3) vale reduzir o intervalo de scrape para acompanhar picos de fila mais de perto.
Como alertar por Slack ou e-mail em vez de só olhar o Grafana?
Adicione o Alertmanager ao stack e aponte as regras de alerta para ele. O Grafana também tem notificação nativa por canal, mas separar a avaliação (Prometheus/Alertmanager) da visualização (Grafana) evita perder um alerta só porque o painel estava fechado.
Consigo monitorar várias instâncias de worker ao mesmo tempo?
Sim. Cada worker expõe seu próprio endpoint /metrics na porta 8000; basta declarar um target por instância em prometheus.yml. As consultas PromQL já agregam automaticamente entre todas as instâncias — não é preciso somar nada manualmente.
Por quanto tempo devo guardar essas métricas?
Quinze dias de retenção local no Prometheus (o padrão de fábrica) já cobre a maioria dos casos de debugging. Para comparar tendência mês a mês, exporte para um Grafana Cloud ou um Thanos/Mimir de longo prazo — manter tudo local por muito mais tempo raramente compensa o espaço em disco.
Veja também
Observabilidade completa — monitore a CaptchaAI com Prometheus a partir de hoje.