Tutoriales

Datos de series de tiempo para CAPTCHA Resuelve tendencias de rendimiento

Las métricas de un momento dado le indican lo que está sucediendo ahora. Los datos de series de tiempo le indican qué cambió, cuándo cambió y si algo tiende a convertirse en un problema. Realice un seguimiento de las tasas de resolución de CAPTCHA, la latencia y el costo a lo largo del tiempo para detectar la degradación antes de que afecte su canalización.

Qué rastrear

Métrica Tipo ¿Por qué?
Tasa de resolución (%) Calibre Detectar cambios en la calidad del proveedor
Resolver latencia (ms) histograma Detecte desaceleraciones, planifique tiempos de espera
Tasa de error por código Contador Identificar patrones de error emergentes
Costo por resolución ($) Calibre Seguimiento de presupuesto, detección de anomalías.
Profundidad de la cola Calibre Planificación de capacidad
Los tokens expiraron antes de su uso. Contador Señal de sintonización TTL
Saldo API Calibre Gatillo de recarga

Prometeo + Python (Push Gateway)

Instrumente su solucionador

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

Consultas de Prometeo

# 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

Escribir métricas de resolució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)

Consultas de InfluxDB (flujo)

// 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")

Implementación de 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);

Comparación de bases de datos

Característica Prometeo InflujoDB Escala de tiempoDB
Lo mejor para Monitoreo operativo IoT/métricas de alta cardinalidad Análisis basado en SQL
Lenguaje de consulta PromQL flujo SQL
Retención Basado en configuración Basado en políticas Retención de PostgreSQL
Integración de Grafana Nativo Nativo Nativo
Curva de aprendizaje Bajo Medio Bajo (si conoce SQL)
Autohospedado si si Sí (extensión PostgreSQL)

Solución de problemas

Problema causa Solución
Brechas de métricas en el panel La puerta de enlace push no recibe datos Verifique la red entre el solucionador y la puerta de enlace push
El histograma de latencia muestra percentiles incorrectos Los límites del segmento no coinciden con la carga de trabajo Ajustar cubos: [5, 10, 15, 20, 30, 45, 60, 90, 120] para resolver CAPTCHA
Las métricas de costos no coinciden con el gasto real Diferentes precios por tipo CAPTCHA Costo de etiqueta por tipo; utilizar precios reales por tipo
Demasiada cardinalidad Demasiados valores de etiqueta Limitar etiquetas a type, status, error_code

Preguntas frecuentes

¿Qué base de datos de series temporales debo utilizar?

Prometheus si ya lo tiene para monitoreo de infraestructura, simplemente agregue métricas CAPTCHA. InfluxDB si desea un almacén de métricas independiente. TimescaleDB si desea consultas SQL sobre datos de series temporales.

¿Cuánto tiempo debo conservar las métricas CAPTCHA?

Mantenga datos de alta resolución (por segundo) durante 7 días, agregados (por hora) durante 90 días y resúmenes diarios de forma indefinida. Esto equilibra el costo de almacenamiento con la visibilidad de las tendencias.

¿Puedo detectar la degradación de la tasa de resolución automáticamente?

Sí. Establezca alertas en promedios móviles, por ejemplo, alerta cuando la tasa de éxito de 1 hora cae por debajo del 90 % o cuando la latencia P95 supera los 45 segundos. Tanto las alertas de Prometheus Alertmanager como las de InfluxDB lo admiten.

Próximos pasos

Realice un seguimiento de su rendimiento de resolución de CAPTCHA a lo largo del tiempo.obtenga su clave API CaptchaAIy comenzar a recopilar métricas.

Guías relacionadas:

Los comentarios están deshabilitados para este artículo.