DevOps и масштабирование

Мониторинг CaptchaAI с помощью New Relic: интеграция APM

New Relic APM обеспечивает сквозную видимость решения CAPTCHA — от отправки API до доставки решения. Отслеживайте задержку транзакций, разбивку ошибок и пользовательские события, которые напрямую связаны с состоянием вашего конвейера решения.

Что контролировать

[Submit Task] → [Wait for Solution] → [Apply Token]
     ↓                  ↓                   ↓
  Submit latency    Poll duration       Token usage
  API errors        Timeout rate        Success rate

Python — инструментарий New Relic Custom

import os
import time
import requests
import newrelic.agent

API_KEY = os.environ["CAPTCHAAI_API_KEY"]
session = requests.Session()


@newrelic.agent.background_task(name="captcha_solve", group="CaptchaAI")
def solve_captcha(sitekey, pageurl, captcha_type="recaptcha_v2"):
    """Solve a CAPTCHA with full New Relic instrumentation."""
    # Add custom attributes for filtering
    newrelic.agent.add_custom_attributes([
        ("captcha_type", captcha_type),
        ("target_url", pageurl),
    ])

    # Submit phase
    submit_result = _submit_task(sitekey, pageurl, captcha_type)
    if "error" in submit_result:
        newrelic.agent.record_custom_event("CaptchaSolveError", {
            "error": submit_result["error"],
            "phase": "submit",
            "captcha_type": captcha_type,
        })
        return submit_result

    # Poll phase
    captcha_id = submit_result["captcha_id"]
    poll_result = _poll_result(captcha_id, captcha_type)

    # Record solve event
    event_data = {
        "captcha_type": captcha_type,
        "captcha_id": captcha_id,
        "success": "solution" in poll_result,
    }
    if "solution" in poll_result:
        event_data["solve_time"] = poll_result.get("elapsed", 0)
        newrelic.agent.record_custom_event("CaptchaSolveSuccess", event_data)
    else:
        event_data["error"] = poll_result.get("error", "unknown")
        newrelic.agent.record_custom_event("CaptchaSolveError", event_data)

    return poll_result


@newrelic.agent.function_trace(name="captcha_submit")
def _submit_task(sitekey, pageurl, captcha_type):
    payload = {
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": 1
    }
    resp = session.post("https://ocr.captchaai.com/in.php", data=payload)
    data = resp.json()

    newrelic.agent.add_custom_attributes([
        ("submit_status", data.get("status")),
    ])

    if data.get("status") != 1:
        return {"error": data.get("request")}
    return {"captcha_id": data["request"]}


@newrelic.agent.function_trace(name="captcha_poll")
def _poll_result(captcha_id, captcha_type):
    start = time.time()
    poll_count = 0

    for _ in range(60):
        time.sleep(5)
        poll_count += 1
        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
            newrelic.agent.add_custom_attributes([
                ("poll_count", poll_count),
                ("solve_time_seconds", round(elapsed, 2)),
            ])
            return {"solution": result["request"], "elapsed": elapsed}

        if result.get("request") != "CAPCHA_NOT_READY":
            return {"error": result.get("request")}

    return {"error": "TIMEOUT"}


def report_balance():
    """Record balance as a custom event."""
    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"])
        newrelic.agent.record_custom_event("CaptchaBalance", {
            "balance": balance,
            "low": balance < 10,
        })
        return balance
    return None

Новая конфигурация агента Relic

# newrelic.ini
[newrelic]
app_name = CaptchaAI Pipeline
license_key = YOUR_NEW_RELIC_LICENSE_KEY
monitor_mode = true
log_level = info
transaction_tracer.enabled = true
transaction_tracer.transaction_threshold = 5.0
custom_insights_events.enabled = true
custom_insights_events.max_samples_stored = 5000

JavaScript — интеграция New Relic

const newrelic = require("newrelic");
const axios = require("axios");

const API_KEY = process.env.CAPTCHAAI_API_KEY;

async function solveCaptchaWithNewRelic(sitekey, pageurl, captchaType = "recaptcha_v2") {
  return newrelic.startBackgroundTransaction(
    "CaptchaSolve",
    "CaptchaAI",
    async () => {
      const transaction = newrelic.getTransaction();
      newrelic.addCustomAttributes({
        captchaType,
        targetUrl: pageurl,
      });

      const startTime = Date.now();

      try {
        // Submit
        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) {
          newrelic.recordCustomEvent("CaptchaSolveError", {
            error: submitResp.data.request,
            phase: "submit",
            captchaType,
          });
          transaction.end();
          return { error: submitResp.data.request };
        }

        const captchaId = submitResp.data.request;
        newrelic.addCustomAttributes({ captchaId });

        // Poll
        let pollCount = 0;
        for (let i = 0; i < 60; i++) {
          await new Promise((r) => setTimeout(r, 5000));
          pollCount++;

          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) {
            const elapsed = (Date.now() - startTime) / 1000;
            newrelic.recordCustomEvent("CaptchaSolveSuccess", {
              captchaType,
              solveTime: elapsed,
              pollCount,
            });
            newrelic.addCustomAttributes({
              solveTime: elapsed,
              pollCount,
            });
            transaction.end();
            return { solution: pollResp.data.request, elapsed };
          }

          if (pollResp.data.request !== "CAPCHA_NOT_READY") {
            newrelic.recordCustomEvent("CaptchaSolveError", {
              error: pollResp.data.request,
              phase: "poll",
              captchaType,
            });
            transaction.end();
            return { error: pollResp.data.request };
          }
        }

        newrelic.recordCustomEvent("CaptchaSolveError", {
          error: "TIMEOUT",
          phase: "poll",
          captchaType,
          pollCount,
        });
        transaction.end();
        return { error: "TIMEOUT" };
      } catch (err) {
        newrelic.noticeError(err);
        transaction.end();
        throw err;
      }
    }
  );
}

// Balance monitoring
async function monitorBalance() {
  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);
      newrelic.recordCustomEvent("CaptchaBalance", { balance });
    }
  } catch (err) {
    newrelic.noticeError(err);
  }
}

setInterval(monitorBalance, 60000);

module.exports = { solveCaptchaWithNewRelic };

Запросы панели мониторинга NRQL

Создайте панель управления New Relic с помощью этих запросов NRQL:

-- Solve success rate (last hour)
SELECT percentage(count(*), WHERE success = true)
FROM CaptchaSolveSuccess, CaptchaSolveError
SINCE 1 hour ago

-- Average solve time by CAPTCHA type
SELECT average(solveTime)
FROM CaptchaSolveSuccess
FACET captchaType
SINCE 1 hour ago TIMESERIES

-- Error breakdown
SELECT count(*)
FROM CaptchaSolveError
FACET error
SINCE 1 hour ago

-- P95 solve latency
SELECT percentile(solveTime, 95)
FROM CaptchaSolveSuccess
SINCE 1 hour ago TIMESERIES

-- Balance over time
SELECT latest(balance)
FROM CaptchaBalance
SINCE 24 hours ago TIMESERIES 5 minutes

-- Tasks per minute
SELECT rate(count(*), 1 minute)
FROM CaptchaSolveSuccess, CaptchaSolveError
SINCE 1 hour ago TIMESERIES

Политика оповещений

Тревога Условие NRQL Порог
Низкая скорость решения SELECT percentage(count(*), WHERE success = true) < 85% в течение 5 мин.
Высокая задержка SELECT percentile(solveTime, 95) FROM CaptchaSolveSuccess > 120 с в течение 10 мин.
Низкий баланс SELECT latest(balance) FROM CaptchaBalance < 10 долларов США
Пик ошибок SELECT count(*) FROM CaptchaSolveError > 50 за 5 минут

Поиск неисправностей

| Проблема | Причина | Исправить |


Следующие шаги

  • CaptchaAI Quickstart: ваше первое решение CAPTCHA за 5 минут
  • Как решить reCAPTCHA v2 через API: пошаговое руководство
  • Как решить Cloudflare Turnstile через API
  • Как решить GeeTest v3 с помощью API
Комментарии для этой статьи отключены.