DevOps & Scaling

New Relic ile CaptchaAI İzleme: APM Entegrasyonu

Üretimdeki bir CAPTCHA çözüm hattı çoğu zaman sessizce bozulur: çözüm oranı düşer, gecikme tırmanır ya da bakiye biter — ve siz bunu ancak otomasyonunuz durduğunda fark edersiniz. New Relic APM bu kör noktayı kapatır: görev gönderiminden token teslimine kadar her fazı özel olaylarla ölçer, çözüm oranını ve P95 gecikmeyi tek bir NRQL panosunda izlersiniz. Bu rehber CaptchaAI iş akışınızı Python ve JavaScript ile enstrümante etmenin, panoları kurmanın ve doğru uyarı eşiklerini belirlemenin doğrudan yolunu gösterir.

İzlenmesi gereken üç faz

Bir CaptchaAI çözümü üç net aşamadan geçer ve her aşamanın kendi hata modu ile gecikme profili vardır. Enstrümantasyonu bu üç faza göre kurduğunuzda, bir aksama olduğunda sorunun hangi aşamada oturduğunu saniyeler içinde görürsünüz:

[Submit Task] → [Wait for Solution] → [Apply Token]
     ↓                  ↓                   ↓
  Submit latency    Poll duration       Token usage
  API errors        Timeout rate        Success rate
  • Gönderim fazı: görevin in.php'ye gönderilmesi. Burada gönderim gecikmesini ve API hata kodlarını ölçersiniz — yanlış sitekey, hatalı pageurl veya bakiye sorunları bu fazda ortaya çıkar.
  • Sorgulama fazı: sonucun res.php üzerinden periyodik sorgulanması. İzlenecek metrikler sorgulama süresi ve zaman aşımı oranıdır; asıl çözüm süresi bu pencerede geçer.
  • Token kullanımı: dönen token'ın hedef sayfada kullanılması. Burada başarı oranını ve token'ın kabul edilip edilmediğini takip edersiniz.

İpucu: captcha_id alanını hem çözüm görevine hem de onu tetikleyen web işlemine özel nitelik olarak ekleyin. Böylece NRQL'de tek bir kimlikle iki tarafı WHERE captchaId = '...' ile eşleştirebilirsiniz.

Python ile New Relic özel enstrümantasyonu

New Relic'in otomatik enstrümantasyonu HTTP çağrılarını görür ama "bu bir CAPTCHA çözümüydü, türü reCAPTCHA v2, süresi 12 saniye" gibi işe özgü bilgiyi bilmez. Bu bağlamı background_task, function_trace ve özel olaylarla siz eklersiniz. Aşağıdaki modül çözüm fonksiyonunu sarmalar; başarıyı CaptchaSolveSuccess, hatayı CaptchaSolveError olayına yazar ve report_balance ile bakiyeyi ayrı bir olay olarak kaydeder:

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

New Relic aracısı yapılandırması

Özel olayların panoya düşmesi için custom_insights_events.enabled ayarı açık olmalıdır — kapalıysa CaptchaSolveSuccess gibi olaylar hiç görünmez. transaction_threshold değeri, hangi işlemlerin ayrıntılı iz olarak saklanacağını belirler:

# 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 (Node.js) ile New Relic entegrasyonu

Node.js tarafında aynı yaklaşım startBackgroundTransaction ile kurulur. Fonksiyon çözüm görevini kendi arka plan işlemi olarak açar, axios ile gönderim ve sorgulama yapar, her fazda özel olay yazar ve monitorBalance ile bakiyeyi belirli aralıklarla raporlar:

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 };

Örnek senaryo: İstanbul'daki bir e-ticaret QA hattı

Diyelim ki İstanbul merkezli bir ekip, ödeme adımındaki reCAPTCHA v2 doğrulamasını yetkili bir QA ortamında düzenli olarak test ediyor. Testler Europe/Istanbul saat dilimine göre gece çalışıyor ve her koşuda yüzlerce çözüm üretiliyor. Buradaki en kritik iki metrik gecikme ve bakiyedir: çözüm süresi tırmanırsa gece koşusu sabaha yetişmez, bakiye biterse gönderim fazı sessizce hata döndürür.

New Relic panosuna captchaType ve saat dilimi kırılımı eklendiğinde, ekip sabah tek bakışta "dün gece hangi türde kaç çözüm, ortalama kaç saniyede tamamlandı" sorusuna yanıt alır. Maliyet tarafında CaptchaAI thread tabanlı ve aylık USD fiyatlıdır; TL kur oynaklığından etkilenmeyen öngörülebilir bir gider kalemi olması, Türkiye'deki ekipler için gerçek bir avantajdır. Düşük hacimli bir QA hattı BASIC ($15/ay, 5 thread) ile başlayabilir; report_balance olayı sayesinde bakiye eşiğin altına indiğinde uyarı tetiklenir. Kazıma senaryolarında toplanan kişisel verilerin KVKK kapsamına girdiğini unutmayın — CaptchaAI'yi yalnızca yetkili QA ve veri toplama iş akışlarında konumlandırın.

NRQL panosu sorguları

Aşağıdaki NRQL sorgularıyla çözüm oranını, tür bazında ortalama süreyi, hata dağılımını, P95 gecikmeyi ve bakiyeyi tek bir panoda toplayın:

-- 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

Panoyu ilk kez kurarken şu sırayı izleyin:

  1. Yukarıdaki sorguları New Relic'te tek tek çalıştırıp beklenen veriyi döndürdüklerini doğrulayın.
  2. Her sorguyu ayrı bir grafik olarak panoya ekleyin ve Europe/Istanbul saat dilimini seçin.
  3. Çözüm oranı ile P95 gecikmeyi en üste taşıyın; ekip sabah tek bakışta gece koşusunu görebilsin.

Uyarı politikaları ve eşikler

Eşikleri kendi taban çizginize göre belirleyin: birkaç gün veri topladıktan sonra çözüm oranınızın ve P95 gecikmenizin normal aralığını görür, uyarıları bu aralığın dışına çıkacak şekilde ayarlarsınız.

Aşağıdaki değerler makul bir başlangıç noktasıdır; üretim taban çizginize göre sıkılaştırın veya gevşetin.

Uyarı NRQL koşulu Eşik
Düşük çözüm oranı SELECT percentage(count(*), WHERE success = true) 5 dakika boyunca < %85
Yüksek gecikme SELECT percentile(solveTime, 95) FROM CaptchaSolveSuccess 10 dakika boyunca > 120 saniye
Düşük bakiye SELECT latest(balance) FROM CaptchaBalance < $10
Hata artışı SELECT count(*) FROM CaptchaSolveError 5 dakikada > 50

Sorun giderme

Enstrümantasyon kurulduğunda en sık karşılaşılan dört sorun ve pratik çözümleri:

Sorun Sebep Çözüm
Özel olaylar panoda görünmüyor custom_insights_events.enabled kapalı newrelic.ini'de etkinleştirin
İşlem izleri eksik Eşik çok yüksek transaction_threshold değerini 1,0 saniyeye düşürün
Nitelikler kısaltılıyor Değer çok uzun Özellik değerlerini 255 karakterin altında tutun
Yayına aldıktan sonra veri gelmiyor Lisans anahtarı yanlış ya da aracı başlamıyor newrelic-admin validate-config newrelic.ini ile doğrulayın

Sık sorulan sorular

Bakiyeyi neden ayrı bir özel olayla izlemeliyim?

Çünkü bakiye bitmesi bir "hata" gibi görünmez — gönderim fazı sessizce başarısız olur. CaptchaBalance olayını periyodik yazıp < $10 eşiğiyle uyarı bağladığınızda, hattınız durmadan önce haber alırsınız. Bu, üretimdeki en ucuz sigortalardan biridir.

Çözüm oranı ve gecikme uyarılarının eşiklerini nasıl belirlerim?

Sabit bir "doğru sayı" yoktur; kendi taban çizginizi ölçün. Birkaç gün veri topladıktan sonra çözüm oranınızın ve P95 gecikmenizin normal aralığını NRQL panosunda görür, uyarıyı bu aralığın hemen dışına ayarlarsınız. Başlangıç için %85 çözüm oranı ve 120 saniyelik P95 makul birer değerdir.

CaptchaAI'nin desteklemediği bir türü panoda nasıl ele almalıyım?

Bir türü göndermeden önce desteklendiğinden emin olun. CaptchaAI reCAPTCHA v2/v3, Cloudflare Turnstile ve Challenge, GeeTest v3 ile görüntü/OCR ve grid türlerini çözer; CaptchaFox (beta), Friendly Captcha (beta) ve Lemin (beta) beta aşamasındadır. hCaptcha ve FunCaptcha desteklenmez — bu türleri gönderen çağrılar CaptchaSolveError olarak düşer ve hata dağılımı panosunda görünür.

Örnek kod yalnızca Python ve JavaScript'te mi var?

Hayır. Bu rehberdeki iki dilin yanı sıra örnek paketi Node.js, PHP, Go, Java, C#, Ruby, Rust, Kotlin ve Bash sürümlerini de içerir; aynı enstrümantasyon desenini kendi yığınınıza taşıyabilirsiniz.

İlgili makaleler

Sonraki adımlar

Çözüm hattınıza uçtan uca görünürlük kazandırın: CaptchaAI API anahtarınızı alın ve New Relic'e bağlayın.

İlgili kılavuzlar:

Bu makale için yorumlar devre dışı bırakılmıştır.