DevOps & Scaling

CaptchaAI Metrikleri için Grafana Kontrol Paneli Şablonları

CAPTCHA çözüm kanalınız sessizce yavaşladığında bunu genellikle ilk fark eden son kullanıcı olur — siz değil. Grafana ile Prometheus'u birbirine bağladığınızda ise çözüm oranındaki her düşüşü, gecikme sıçramasını ve azalan bakiyeyi anında ekranda görürsünüz. Aşağıdaki şablonlar hazır bir dört satırlık panel düzeni, kopyala-yapıştır PromQL sorguları ve uyarı kurallarıyla gelir; veri kaynağı olarak Prometheus'la doğrudan içe aktarabilirsiniz.

Panel Düzeni: Dört Satırda Tam Görünürlük

Aşağıdaki düzen, bir bakışta karar vermeniz gereken metrikleri en üste, ayrıntılı zaman serilerini alta yerleştirir. Genel bakış satırıyla başlayın; ekibiniz alarma önce oradan bakacak.

Dört satırın her biri farklı bir soruyu yanıtlar:

  • Satır 1 — Genel bakış: "Kanal şu an sağlıklı mı?" Çözüm oranı, kalan bakiye, kuyruk derinliği ve dakika başına görev.
  • Satır 2 — Performans: "Ne kadar hızlı?" Gecikmeyi p50, p95 ve p99 yüzdelikleriyle gösterir; ortalama yerine yüzdelik kullanmak, birkaç yavaş çözümün deneyimi nasıl bozduğunu görünür kılar.
  • Satır 3 — Hatalar: Hataları türlerine göre ayırır, böylece bir zaman aşımı dalgasıyla geçersiz sitekey hatasını karıştırmazsınız.
  • Satır 4 — Worker'lar: Worker havuzunuzun kapasitesini ve iş dağılımını izler.
┌───────────────────────────────────────────────┐
│ Row 1: Overview                               │
│ [Solve Rate %] [Balance $] [Queue Depth] [TPM]│
├───────────────────────────────────────────────┤
│ Row 2: Performance                            │
│ [Latency P50/P95/P99]  [Solve Rate Over Time] │
├───────────────────────────────────────────────┤
│ Row 3: Errors                                 │
│ [Error Rate %]  [Error Breakdown by Type]      │
├───────────────────────────────────────────────┤
│ Row 4: Workers                                │
│ [Active Workers]  [Tasks Per Worker]           │
└───────────────────────────────────────────────┘

Metrikleri Prometheus'a Aktarma

Panelleri kurmadan önce CAPTCHA çözücünüzün metrikleri bir /metrics uç noktasından yayması gerekir. Aşağıdaki iki örnek şu ölçüleri Prometheus'un okuyabileceği biçimde açar:

  • captcha_solves_total — tip ve durum etiketleriyle toplam çözüm denemesi sayacı.
  • captcha_solve_duration_seconds — gecikme histogramı (yüzdelik hesabı için kovalı).
  • captcha_balance_dollars — hesap bakiyesi göstergesi.
  • captcha_queue_depth ve captcha_workers_active — kuyruk ve worker göstergeleri.

Python ile metrik toplama

import os
import time
import requests
from prometheus_client import (
    Counter, Histogram, Gauge, start_http_server
)

API_KEY = os.environ["CAPTCHAAI_API_KEY"]

# Define metrics
captcha_solves = Counter(
    "captcha_solves_total",
    "Total CAPTCHA solve attempts",
    ["captcha_type", "status"]
)
captcha_latency = Histogram(
    "captcha_solve_duration_seconds",
    "CAPTCHA solve latency",
    ["captcha_type"],
    buckets=[5, 10, 15, 20, 30, 45, 60, 90, 120, 180, 300]
)
captcha_balance = Gauge(
    "captcha_balance_dollars",
    "CaptchaAI account balance"
)
captcha_queue_depth = Gauge(
    "captcha_queue_depth",
    "Pending tasks in queue"
)
captcha_workers_active = Gauge(
    "captcha_workers_active",
    "Number of active workers"
)

session = requests.Session()


def solve_with_metrics(sitekey, pageurl, captcha_type="recaptcha_v2"):
    start = time.time()

    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:
        captcha_solves.labels(captcha_type, "error").inc()
        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:
            elapsed = time.time() - start
            captcha_solves.labels(captcha_type, "success").inc()
            captcha_latency.labels(captcha_type).observe(elapsed)
            return {"solution": result["request"]}

        if result.get("request") != "CAPCHA_NOT_READY":
            captcha_solves.labels(captcha_type, "error").inc()
            return {"error": result.get("request")}

    captcha_solves.labels(captcha_type, "timeout").inc()
    return {"error": "TIMEOUT"}


def update_balance():
    resp = session.get("https://ocr.captchaai.com/res.php", params={
        "key": API_KEY, "action": "getbalance", "json": 1
    })
    if resp.json().get("status") == 1:
        captcha_balance.set(float(resp.json()["request"]))


# Start metrics server on port 9090
start_http_server(9090)

Her çözüm denemesi başarı, hata veya zaman aşımı etiketiyle sayaca işlenir; captcha_latency histogramı ise gecikme yüzdeliklerini hesaplamanız için gereken kovaları toplar. update_balance() fonksiyonunu periyodik olarak çağırarak bakiye göstergesini güncel tutun.

Node.js ile metrik toplama

const promClient = require("prom-client");
const axios = require("axios");

const API_KEY = process.env.CAPTCHAAI_API_KEY;
const register = new promClient.Registry();

const solvesTotal = new promClient.Counter({
  name: "captcha_solves_total",
  help: "Total CAPTCHA solve attempts",
  labelNames: ["captcha_type", "status"],
  registers: [register],
});

const solveLatency = new promClient.Histogram({
  name: "captcha_solve_duration_seconds",
  help: "CAPTCHA solve latency",
  labelNames: ["captcha_type"],
  buckets: [5, 10, 15, 20, 30, 45, 60, 90, 120, 180, 300],
  registers: [register],
});

const balance = new promClient.Gauge({
  name: "captcha_balance_dollars",
  help: "CaptchaAI account balance",
  registers: [register],
});

const queueDepth = new promClient.Gauge({
  name: "captcha_queue_depth",
  help: "Pending tasks in queue",
  registers: [register],
});

async function solveWithMetrics(sitekey, pageurl, captchaType = "recaptcha_v2") {
  const end = solveLatency.startTimer({ captcha_type: captchaType });

  try {
    const resp = await axios.post("https://ocr.captchaai.com/in.php", null, {
      params: {
        key: API_KEY, method: "userrecaptcha",
        googlekey: sitekey, pageurl, json: 1,
      },
    });

    if (resp.data.status !== 1) {
      solvesTotal.inc({ captcha_type: captchaType, status: "error" });
      return { error: resp.data.request };
    }

    const captchaId = resp.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) {
        end();
        solvesTotal.inc({ captcha_type: captchaType, status: "success" });
        return { solution: poll.data.request };
      }
      if (poll.data.request !== "CAPCHA_NOT_READY") {
        solvesTotal.inc({ captcha_type: captchaType, status: "error" });
        return { error: poll.data.request };
      }
    }
    solvesTotal.inc({ captcha_type: captchaType, status: "timeout" });
    return { error: "TIMEOUT" };
  } catch (err) {
    solvesTotal.inc({ captcha_type: captchaType, status: "error" });
    throw err;
  }
}

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

İki uygulama da metrik adlarını aynı tutar (captcha_solves_total, captcha_solve_duration_seconds), bu yüzden PromQL sorguları hangi dili kullanırsanız kullanın değişmeden çalışır.

PromQL Sorguları: Panelleri Besleyin

Aşağıdaki sorgular panel düzeninin dört satırıyla birebir eşleşir. Her bloğu ilgili Grafana paneline yapıştırın; oran pencerelerini [5m] olarak bırakmanız çoğu CAPTCHA kanalı için yeterli çözünürlüğü verir.

Satır 1: Genel bakış panelleri

Çözüm oranı (Stat paneli)

sum(rate(captcha_solves_total{status="success"}[5m]))
/
sum(rate(captcha_solves_total[5m]))

* 100

Bakiye (Gauge paneli)

captcha_balance_dollars

Kuyruk derinliği (Stat paneli)

captcha_queue_depth

Dakika başına görev (Stat paneli)

sum(rate(captcha_solves_total[5m])) * 60

Satır 2: Performans

Gecikme yüzdelikleri (Zaman serisi)

# p50
histogram_quantile(0.50, rate(captcha_solve_duration_seconds_bucket[5m]))

# p95
histogram_quantile(0.95, rate(captcha_solve_duration_seconds_bucket[5m]))

# p99
histogram_quantile(0.99, rate(captcha_solve_duration_seconds_bucket[5m]))

Zaman içinde çözüm oranı (Zaman serisi)

sum(rate(captcha_solves_total{status="success"}[5m])) by (captcha_type) * 60

Satır 3: Hatalar

Hata oranı (Zaman serisi)

sum(rate(captcha_solves_total{status!="success"}[5m]))
/
sum(rate(captcha_solves_total[5m]))

* 100

Hata dağılımı (Pasta grafiği)

sum by (status) (increase(captcha_solves_total{status!="success"}[1h]))

Satır 4: Worker'lar

Aktif worker'lar (Zaman serisi)

captcha_workers_active

Uyarı Kuralları: Sorunları Erken Yakalayın

İyi bir panel yalnızca yarı çözümdür; asıl değer, siz ekrana bakmıyorken tetiklenen uyarılardadır. Aşağıdaki kurallar düşük bakiye, yükselen hata oranı ve artan gecikme için sizi uyarır. Her kuralda for alanı, uyarının tetiklenmeden önce koşulun ne kadar süre doğru kalması gerektiğini belirtir; bu sayede tek bir geçici sıçrama gece yarısı sizi uyandırmaz. Kritik ve uyarı seviyelerini ayırarak yalnızca gerçek olayların bildirim kanalınıza düşmesini sağlayın — aksi halde uyarı yorgunluğu kaçınılmazdır.

# Grafana alert rules
groups:

  - name: captcha-alerts
    rules:

      - alert: LowBalance
        expr: captcha_balance_dollars < 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CaptchaAI balance low: {{ $value }}"

      - alert: HighErrorRate
        expr: |
          sum(rate(captcha_solves_total{status!="success"}[5m]))
          / sum(rate(captcha_solves_total[5m]))
          > 0.1
        for: 5m
        labels:
          severity: critical

      - alert: HighLatency
        expr: |
          histogram_quantile(0.95,
            rate(captcha_solve_duration_seconds_bucket[5m])
          ) > 120
        for: 10m
        labels:
          severity: warning

LowBalance eşiği burada 10 dolara ayarlı. Türkiye'deki otomasyon geliştiricilerinin çoğu USD bazlı ödeme yaptığı ve TL kuru oynak olduğu için, CaptchaAI'nin thread tabanlı sabit aylık planları bütçeyi öngörülebilir kılar. Örneğin BASIC ($15/ay, 5 thread) ile başlayan bir freelance projede bakiye uyarısını 10 doların altına inmeden tetiklemek, kritik bir iş teslimi sırasında kanalın durmasını önler. Uyarı zaman damgalarını Europe/Istanbul diliminde okumak için Grafana bildirimlerinizi buna göre yapılandırın.

Sık Sorulan Sorular

Önce hangi panelleri eklemeliyim?

Genel bakış satırıyla başlayın: çözüm oranı, bakiye ve kuyruk derinliği. Bu üç metrik kanalın sağlığını tek bakışta özetler. Gecikme yüzdelikleri ve hata dağılımını ikinci adımda ekleyin.

Bu panelleri JSON dosyasından içe aktarabilir miyim?

Evet. Grafana, JSON kontrol paneli içe aktarmayı destekler. Paneli arayüzde oluşturun, JSON olarak dışa aktarın ve diğer Grafana örneklerine aynı dosyayla aktarın.

Düşük bakiye uyarısını nasıl kurarım?

Yukarıdaki LowBalance kuralını kullanın: captcha_balance_dollars göstergesi eşiğin altına indiğinde uyarı tetiklenir. Eşiği ortalama günlük harcamanızın en az iki katına ayarlayın ki yenileme için zamanınız olsun.

Grafana'da thread kullanımını izleyebilir miyim?

Doğrudan bir thread metriği yoktur, ancak dakika başına görev ve gecikme birlikte thread doygunluğunu iyi gösterir. Gecikme artarken görev hacmi sabitse, plan thread sınırınıza yaklaşıyor olabilirsiniz — bir üst plana geçmeyi değerlendirin. CaptchaAI planları thread tabanlı olduğundan, aynı anda kaç görevi paralel işleyebileceğinizi doğrudan plan belirler: BASIC 5 thread sunar, üst kademeler daha fazla eşzamanlılık verir.

Hangi Prometheus kazıma aralığını seçmeliyim?

15 saniye çoğu ekip için iyi bir başlangıçtır. Daha düşük hacimli CAPTCHA kanallarında 30 saniye gereksiz veri toplamadan yeterli çözünürlük sağlar. Gerçek zamanlı görünürlüğe ihtiyacınız olmadıkça 10 saniyenin altına inmeyin; çok sık kazıma hem Prometheus'u hem de çözücünüzün /metrics uç noktasını gereksiz yükler.

Kendi sunucum yerine Grafana Cloud kullanabilir miyim?

Evet. Grafana Cloud, Prometheus remote write desteği sunar. Metrikleri kendi Prometheus'unuzdan Grafana Cloud'a gönderir ve buradaki PromQL sorgularını hiç değiştirmeden aynen kullanabilirsiniz. Kendi kendine barındırma ile bulut arasındaki tek fark veri kaynağının konumudur; panel ve uyarı tanımları aynı kalır.

Sorun Giderme

Paneller kurulduktan sonra en sık karşılaşılan aksaklıklar ve hızlı çözümleri:

Sorun Sebep Düzeltme
Panellerde "Veri yok" Prometheus, metrik uç noktasını kazımıyor prometheus.yml hedeflerini kontrol edin; /metrics'in veri döndürdüğünü doğrulayın
Gecikme yüzdelikleri hatalı Yanlış rate() penceresi veya eksik kovalar [5m] oran penceresini kullanın; daha ince taneli kovalar ekleyin
Panel değişkenleri çalışmıyor Şablon değişkeni sorgusu hatalı label_values(captcha_solves_total, captcha_type) sorgusunu kullanın
Uyarılar tetiklenmiyor Uyarı değerlendirme aralığı çok uzun Değerlendirme aralığını 1 dakikaya çekin

İlgili Makaleler

Sonraki Adımlar

CAPTCHA kanalınızı görselleştirin — CaptchaAI API anahtarınızı alın ve Grafana panellerinizi kurun.

İlgili kılavuzlar:

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