Para saber si tu proceso de resolución de CAPTCHA está sano necesitas vigilar tres señales en tiempo real:
- Rendimiento — cuántas tareas se resuelven y cuántas fallan, desglosadas por tipo de error.
- Latencia — cuánto tarda cada resolución, medida en percentiles (p50, p95, p99).
- Saldo — cuánto crédito de la API te queda antes de que el pipeline se detenga.
Datadog reúne esas tres señales en un mismo panel, dispara alertas antes de que la cola se atasque o la cuenta se quede sin fondos, y te deja diagnosticar caídas sin abrir logs. Esta guía es un recorrido práctico: qué métricas emitir, cómo enviarlas con DogStatsD desde Python y Node.js, cómo armar el dashboard y qué alertas definir.
Piensa en un equipo de scraping en Ciudad de México que resuelve decenas de miles de reCAPTCHA v2 al día para el QA de su flujo de checkout. Cuando la latencia p95 se dispara o la tasa de errores sube, quieren enterarse por una alerta, no por un cliente. Y como CaptchaAI factura por thread con un costo mensual predecible en USD, vigilar el saldo evita que un pico de volumen frene el pipeline a mitad de una corrida.
Qué métricas de CaptchaAI conviene vigilar
Empieza por siete métricas: describen la salud del pipeline sin saturarte de series temporales. Cada una lleva su tipo de Datadog y la razón por la que importa. Conviene entender los tres tipos antes de instrumentar:
- Counter — acumula eventos (tareas enviadas, éxitos, errores); Datadog los suma por intervalo.
- Gauge — una foto del valor actual (saldo, cola, workers vivos) en cada reporte.
- Histogram — una distribución de la que Datadog deriva percentiles, ideal para la latencia.
| Métrica | Tipo | Por qué importa |
|---|---|---|
captcha.solve.count |
Counter | Total de tareas enviadas |
captcha.solve.success |
Counter | Resoluciones correctas |
captcha.solve.error |
Counter | Resoluciones fallidas (por tipo de error) |
captcha.solve.latency |
Histogram | Tiempo desde el envío hasta la solución |
captcha.queue.depth |
Gauge | Tareas pendientes en la cola |
captcha.balance |
Gauge | Saldo restante de la API |
captcha.worker.active |
Gauge | Procesos worker activos |
Enviar métricas desde Python con DogStatsD
El siguiente decorador envuelve tu función de resolución y emite las métricas sin ensuciar la lógica de negocio: cuenta cada envío, marca los éxitos y errores, y registra la latencia solo en el camino correcto. Los reportes de saldo, cola y workers viven en funciones aparte que puedes llamar desde un scheduler.
import os
import time
import functools
import requests
from datadog import initialize, statsd
# Initialize Datadog
initialize(
statsd_host=os.environ.get("DD_AGENT_HOST", "localhost"),
statsd_port=int(os.environ.get("DD_DOGSTATSD_PORT", "8125"))
)
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
session = requests.Session()
def track_captcha_metrics(captcha_type="recaptcha_v2"):
"""Decorator to track solve metrics."""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
tags = [f"captcha_type:{captcha_type}"]
statsd.increment("captcha.solve.count", tags=tags)
start = time.time()
try:
result = func(*args, **kwargs)
elapsed = time.time() - start
if "solution" in result:
statsd.increment("captcha.solve.success", tags=tags)
statsd.histogram("captcha.solve.latency", elapsed, tags=tags)
else:
error = result.get("error", "unknown")
statsd.increment(
"captcha.solve.error",
tags=tags + [f"error:{error}"]
)
return result
except Exception as e:
statsd.increment(
"captcha.solve.error",
tags=tags + [f"error:{type(e).__name__}"]
)
raise
return wrapper
return decorator
@track_captcha_metrics(captcha_type="recaptcha_v2")
def solve_recaptcha(sitekey, pageurl):
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:
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:
return {"solution": result["request"]}
if result.get("request") != "CAPCHA_NOT_READY":
return {"error": result.get("request")}
return {"error": "TIMEOUT"}
def report_balance():
"""Send balance as a gauge metric."""
resp = session.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "getbalance", "json": 1
})
data = resp.json()
if data.get("status") == 1:
balance = float(data["request"])
statsd.gauge("captcha.balance", balance)
return balance
return None
def report_queue_depth(depth):
"""Report current queue depth."""
statsd.gauge("captcha.queue.depth", depth)
def report_worker_count(active, total):
"""Report worker health."""
statsd.gauge("captcha.worker.active", active)
statsd.gauge("captcha.worker.total", total)
Instrumentar el pipeline en Node.js
Si tu integración corre en Node.js, hot-shots cumple el mismo papel que la librería de Datadog en Python. El prefijo captcha. y las etiquetas globales de entorno se configuran una sola vez, y a partir de ahí cada resolución reporta count, success/error y latencia con las mismas convenciones que en el ejemplo anterior.
const { StatsD } = require("hot-shots");
const axios = require("axios");
const API_KEY = process.env.CAPTCHAAI_API_KEY;
const dogstatsd = new StatsD({
host: process.env.DD_AGENT_HOST || "localhost",
port: parseInt(process.env.DD_DOGSTATSD_PORT || "8125", 10),
prefix: "captcha.",
globalTags: [`env:${process.env.NODE_ENV || "development"}`],
});
async function solveCaptchaWithMetrics(sitekey, pageurl, captchaType = "recaptcha_v2") {
const tags = [`captcha_type:${captchaType}`];
dogstatsd.increment("solve.count", 1, tags);
const startTime = Date.now();
try {
const result = await solveCaptcha(sitekey, pageurl);
const elapsed = (Date.now() - startTime) / 1000;
if (result.solution) {
dogstatsd.increment("solve.success", 1, tags);
dogstatsd.histogram("solve.latency", elapsed, tags);
} else {
dogstatsd.increment("solve.error", 1, [...tags, `error:${result.error}`]);
}
return result;
} catch (err) {
dogstatsd.increment("solve.error", 1, [...tags, `error:${err.message}`]);
throw err;
}
}
async function solveCaptcha(sitekey, pageurl) {
const submitResp = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: {
key: API_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageurl,
json: 1,
},
});
if (submitResp.data.status !== 1) {
return { error: submitResp.data.request };
}
const captchaId = submitResp.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const pollResp = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "get", id: captchaId, json: 1 },
});
if (pollResp.data.status === 1) return { solution: pollResp.data.request };
if (pollResp.data.request !== "CAPCHA_NOT_READY") {
return { error: pollResp.data.request };
}
}
return { error: "TIMEOUT" };
}
async function reportBalance() {
try {
const resp = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "getbalance", json: 1 },
});
if (resp.data.status === 1) {
const balance = parseFloat(resp.data.request);
dogstatsd.gauge("balance", balance);
return balance;
}
} catch (err) {
console.error("Balance check failed:", err.message);
}
return null;
}
// Report balance every minute
setInterval(reportBalance, 60000);
module.exports = { solveCaptchaWithMetrics, reportBalance };
Dashboard de Datadog listo para importar
Con las métricas fluyendo, arma el panel. Importa esta plantilla JSON en Datadog para levantar un dashboard de monitoreo del pipeline CAPTCHA con la tasa de resolución, los percentiles de latencia, el saldo y la profundidad de cola:
{
"title": "CaptchaAI Pipeline",
"widgets": [
{
"definition": {
"type": "timeseries",
"title": "Solve Rate (Success vs Error)",
"requests": [
{"q": "sum:captcha.solve.success{*}.as_count()"},
{"q": "sum:captcha.solve.error{*}.as_count()"}
]
}
},
{
"definition": {
"type": "timeseries",
"title": "Solve Latency (p50, p95, p99)",
"requests": [
{"q": "avg:captcha.solve.latency{*}"},
{"q": "percentile:captcha.solve.latency{*},0.95"},
{"q": "percentile:captcha.solve.latency{*},0.99"}
]
}
},
{
"definition": {
"type": "query_value",
"title": "API Balance",
"requests": [{"q": "avg:captcha.balance{*}"}]
}
},
{
"definition": {
"type": "timeseries",
"title": "Queue Depth",
"requests": [{"q": "avg:captcha.queue.depth{*}"}]
}
}
]
}
Alertas que se disparan antes de que falle el pipeline
Un dashboard te dice qué pasó; una alerta te avisa a tiempo. Define estos umbrales para que el saldo bajo, un pico de latencia o un worker caído lleguen a tu canal antes de que afecten la producción.
| Alerta | Condición | Gravedad |
|---|---|---|
| Saldo bajo | captcha.balance < 10 |
Advertencia |
| Saldo crítico | captcha.balance < 2 |
Crítica |
| Tasa de error alta | Tasa de error > 10 % en 5 minutos | Advertencia |
| Pico de latencia | Latencia p95 > 120 s durante 10 minutos | Advertencia |
| Cola atascada | Profundidad de cola > 100 y creciendo durante 5 min | Advertencia |
| Worker caído | captcha.worker.active == 0 |
Crítica |
Del umbral al monitor de Datadog
Cada fila de la tabla se traduce a un monitor. Este es el de saldo bajo, listo para crear vía la API de Datadog; replica el mismo patrón cambiando la query y el umbral para las demás alertas:
# Datadog monitor definition (API create)
- type: metric alert
name: "CaptchaAI Low Balance"
query: "avg(last_5m):avg:captcha.balance{*} < 10"
message: "CaptchaAI balance is low: {{value}}. Top up to avoid solve failures."
tags:
- team:scraping
- service:captcha
Diagnóstico de problemas comunes
Si las métricas no llegan o los gráficos salen vacíos, casi siempre es una de estas cuatro causas:
| Problema | Causa | Solución |
|---|---|---|
| Las métricas no aparecen | El agente DogStatsD no está corriendo | Revisa DD_AGENT_HOST y comprueba con docker ps que el contenedor del agente esté activo |
| Histograma de latencia vacío | No se registró ninguna resolución exitosa | Verifica que statsd.histogram() se llame en el camino de éxito |
| Faltan etiquetas | Formato de etiqueta incorrecto | Usa el formato key:value; sin espacios en las etiquetas |
| Métricas duplicadas | Varios reporters corriendo a la vez | Deja un único reporter de saldo por despliegue |
Preguntas frecuentes
¿Qué alerta debo configurar primero?
La de saldo. Un captcha.balance en cero detiene todas las resoluciones de golpe, así que la alerta de saldo bajo (< 10) es la que más incidentes evita. Después, la de tasa de error, que suele ser el primer síntoma de un problema en el flujo.
¿Cada cuánto conviene consultar el saldo de la API?
Cada minuto es un buen punto de partida, como en el ejemplo de Node.js (setInterval(reportBalance, 60000)). El saldo cambia despacio, así que sondearlo con más frecuencia solo añade llamadas a la API sin darte información nueva.
¿Sirve este monitoreo para cualquier tipo de CAPTCHA que resuelva CaptchaAI?
Sí. Las métricas se basan en el patrón de envío y sondeo, no en un tipo concreto, así que instrumentas igual reCAPTCHA v2 y v3, Cloudflare Turnstile o GeeTest v3. Basta con cambiar la etiqueta captcha_type para desglosar la latencia y los errores por tipo.
¿Puedo enviar estas métricas a Prometheus en lugar de Datadog?
Sí. El mismo enfoque de instrumentar la función de resolución aplica con un cliente de Prometheus, usando sus tipos histogram y counter; tienes el equivalente con Prometheus y Grafana enlazado más abajo, en las guías relacionadas.
Artículos relacionados
- Sistema de monitoreo de reseñas con CaptchaAI
- Bot de monitoreo de cambios de contenido con CaptchaAI
- Panel de uso de CaptchaAI
Conecta CaptchaAI a Datadog
Consigue visibilidad completa de tu pipeline CAPTCHA: empieza con una clave API de CaptchaAI y conéctala a Datadog en minutos.
Guías relacionadas: