DevOps & Scaling

PagerDuty ile Özel CaptchaAI Uyarıları Oluşturma

CAPTCHA'nın sabah saat 3'te çözülmesi, saatlerce verinin kaçırılmasına neden olur. PagerDuty entegrasyonu, günlükleri incelemeden sorunu teşhis etmek ve düzeltmek için yeterli bağlamla doğru kişinin anında bilgilendirilmesini sağlar.

Uyarı Stratejisi

Şiddet Durum Çağrı Görevi Eylemi
Kritik Bakiye < 2$ Sayfa çağrı mühendisi
Kritik Bütün işçiler yere düştü Sayfa çağrı mühendisi
Yüksek 5 dakika boyunca hata oranı > %20 Acil olay yarat
Uyarı Bakiye < 10$ Düşük acil olay oluşturma
Uyarı Kuyruk derinliği > 10 dakika boyunca 100 Düşük acil olay oluşturma
Bilgi Gecikmeyi çözün p95 > 120s Mevcut olaya veya günlüğe ekle

Python – PagerDuty Olaylar API'si v2

import os
import time
import hashlib
import requests
from datetime import datetime

API_KEY = os.environ["CAPTCHAAI_API_KEY"]
PAGERDUTY_ROUTING_KEY = os.environ["PAGERDUTY_ROUTING_KEY"]

session = requests.Session()


class CaptchaPagerDuty:
    EVENTS_URL = "https://events.pagerduty.com/v2/enqueue"

    def __init__(self, routing_key):
        self.routing_key = routing_key

    def trigger(self, summary, severity="error", source="captcha-pipeline",
                details=None, dedup_key=None):
        """Trigger a new PagerDuty incident."""
        payload = {
            "routing_key": self.routing_key,
            "event_action": "trigger",
            "payload": {
                "summary": summary,
                "severity": severity,  # critical, error, warning, info
                "source": source,
                "timestamp": datetime.utcnow().isoformat() + "Z",
                "custom_details": details or {}
            }
        }

        if dedup_key:
            payload["dedup_key"] = dedup_key

        resp = requests.post(self.EVENTS_URL, json=payload, timeout=10)
        resp.raise_for_status()
        return resp.json()

    def resolve(self, dedup_key):
        """Resolve an existing incident."""
        payload = {
            "routing_key": self.routing_key,
            "event_action": "resolve",
            "dedup_key": dedup_key
        }
        resp = requests.post(self.EVENTS_URL, json=payload, timeout=10)
        resp.raise_for_status()
        return resp.json()

    def acknowledge(self, dedup_key):
        """Acknowledge an existing incident."""
        payload = {
            "routing_key": self.routing_key,
            "event_action": "acknowledge",
            "dedup_key": dedup_key
        }
        resp = requests.post(self.EVENTS_URL, json=payload, timeout=10)
        resp.raise_for_status()
        return resp.json()


pagerduty = CaptchaPagerDuty(PAGERDUTY_ROUTING_KEY)


class CaptchaMonitor:
    def __init__(self):
        self.error_window = []  # (timestamp, is_error)
        self.window_size = 300  # 5 minutes in seconds

    def record_solve(self, success):
        now = time.time()
        self.error_window.append((now, not success))
        # Prune old entries
        self.error_window = [
            (t, e) for t, e in self.error_window
            if now - t < self.window_size
        ]

    @property
    def error_rate(self):
        if not self.error_window:
            return 0.0
        errors = sum(1 for _, e in self.error_window if e)
        return errors / len(self.error_window)

    def check_balance(self):
        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:
            return None
        return float(data["request"])

    def run_checks(self):
        """Run all monitoring checks and trigger alerts."""
        # Check balance
        balance = self.check_balance()
        if balance is not None:
            if balance < 2:
                pagerduty.trigger(
                    summary=f"CaptchaAI balance critically low: ${balance:.2f}",
                    severity="critical",
                    dedup_key="captcha-balance-critical",
                    details={"balance": balance, "threshold": 2}
                )
            elif balance < 10:
                pagerduty.trigger(
                    summary=f"CaptchaAI balance low: ${balance:.2f}",
                    severity="warning",
                    dedup_key="captcha-balance-warning",
                    details={"balance": balance, "threshold": 10}
                )
            else:
                # Resolve if balance recovered
                try:
                    pagerduty.resolve("captcha-balance-critical")
                    pagerduty.resolve("captcha-balance-warning")
                except Exception:
                    pass  # No incident to resolve

        # Check error rate
        rate = self.error_rate
        if rate > 0.20:
            total = len(self.error_window)
            errors = sum(1 for _, e in self.error_window if e)
            pagerduty.trigger(
                summary=f"CaptchaAI error rate {rate:.0%} "
                        f"({errors}/{total} in 5 min)",
                severity="error",
                dedup_key="captcha-error-rate-high",
                details={
                    "error_rate": round(rate, 3),
                    "total_tasks": total,
                    "failed_tasks": errors,
                    "window_seconds": self.window_size
                }
            )
        elif rate < 0.05 and len(self.error_window) > 10:
            try:
                pagerduty.resolve("captcha-error-rate-high")
            except Exception:
                pass


monitor = CaptchaMonitor()

# After each solve:
# monitor.record_solve(success=True)

# Run checks every 60 seconds:
# while True:
#     monitor.run_checks()
#     time.sleep(60)

JavaScript – PagerDuty Entegrasyonu

const axios = require("axios");

const API_KEY = process.env.CAPTCHAAI_API_KEY;
const PD_ROUTING_KEY = process.env.PAGERDUTY_ROUTING_KEY;
const PD_EVENTS_URL = "https://events.pagerduty.com/v2/enqueue";

class PagerDutyAlerter {
  constructor(routingKey) {
    this.routingKey = routingKey;
  }

  async trigger(summary, severity = "error", details = {}, dedupKey = null) {
    const payload = {
      routing_key: this.routingKey,
      event_action: "trigger",
      payload: {
        summary,
        severity,
        source: "captcha-pipeline",
        timestamp: new Date().toISOString(),
        custom_details: details,
      },
    };
    if (dedupKey) payload.dedup_key = dedupKey;

    const resp = await axios.post(PD_EVENTS_URL, payload, { timeout: 10000 });
    return resp.data;
  }

  async resolve(dedupKey) {
    await axios.post(PD_EVENTS_URL, {
      routing_key: this.routingKey,
      event_action: "resolve",
      dedup_key: dedupKey,
    }, { timeout: 10000 });
  }
}

const alerter = new PagerDutyAlerter(PD_ROUTING_KEY);

class CaptchaHealthMonitor {
  constructor(windowMs = 300000) {
    this.results = [];
    this.windowMs = windowMs;
  }

  record(success) {
    this.results.push({ time: Date.now(), success });
    const cutoff = Date.now() - this.windowMs;
    this.results = this.results.filter((r) => r.time > cutoff);
  }

  get errorRate() {
    if (this.results.length === 0) return 0;
    const errors = this.results.filter((r) => !r.success).length;
    return errors / this.results.length;
  }

  async checkAndAlert() {
    // Balance check
    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);
        if (balance < 2) {
          await alerter.trigger(
            `CaptchaAI balance critically low: $${balance.toFixed(2)}`,
            "critical",
            { balance },
            "captcha-balance-critical"
          );
        } else if (balance < 10) {
          await alerter.trigger(
            `CaptchaAI balance low: $${balance.toFixed(2)}`,
            "warning",
            { balance },
            "captcha-balance-warning"
          );
        } else {
          await alerter.resolve("captcha-balance-critical").catch(() => {});
          await alerter.resolve("captcha-balance-warning").catch(() => {});
        }
      }
    } catch (err) {
      console.error("Balance check failed:", err.message);
    }

    // Error rate check
    const rate = this.errorRate;
    if (rate > 0.2 && this.results.length > 10) {
      await alerter.trigger(
        `CaptchaAI error rate: ${(rate * 100).toFixed(1)}%`,
        "error",
        { errorRate: rate, totalTasks: this.results.length },
        "captcha-error-rate"
      );
    } else if (rate < 0.05 && this.results.length > 10) {
      await alerter.resolve("captcha-error-rate").catch(() => {});
    }
  }
}

const monitor = new CaptchaHealthMonitor();

// Run checks every 60 seconds
setInterval(() => monitor.checkAndAlert(), 60000);

module.exports = { monitor, alerter };

PagerDuty Kurulum Kontrol Listesi

Adım Eylem
1 "CaptchaAI Pipeline" için PagerDuty'de bir hizmet oluşturun
2 Hizmete Events API v2 entegrasyonunu ekleyin
3 Yönlendirme anahtarını PAGERDUTY_ROUTING_KEY env var'a kopyalayın
4 Üst kademeye iletme politikasını ayarlayın (çağrı sırasında – ekip lideri – yönetici)
5 Bildirim kurallarını yapılandırın (anında iletme, SMS, telefon)
6 Planlı kesintiler için bakım aralıkları ekleyin

Sorun giderme

Sorun Sebep Düzeltme
Uyarı tetiklenmiyor Yanlış yönlendirme anahtarı Anahtarın hizmetin Events API entegrasyonuyla eşleştiğini doğrulayın
Yinelenen olaylar dedup_key eksik Her uyarı türü için her zaman tutarlı bir tekilleştirme anahtarı ayarlayın
Uyarı sel Tetikleyiciler arasında bekleme süresi yok PagerDuty tekilleştirme anahtarı kopyaları bastırır; bunları kullandığınızdan emin olun
Otomatik çözüm çalışmıyor Yinelenen anahtar uyumsuzluğu Çözümlemenin tetikleyiciyle tamamen aynı tekilleştirme anahtarını kullandığından emin olun

SSS

Uyarı yorgunluğunu nasıl önleyebilirim?

İlgili uyarıları tek bir olayda gruplandırmak için veri tekilleştirme anahtarlarını kullanın. Uyarı uyarılarını düşük aciliyet (sayfa yok) olarak ayarlayın. Bakiyenin 2$'ın altında olması veya tüm çalışanların çalışmaması durumunda kritik/high-urgency rezerve edin.

Bunun yerine PagerDuty'yi Datadog/New Relic ile entegre edebilir miyim?

Evet. Hem Datadog hem de New Relic yerel PagerDuty entegrasyonlarına sahiptir. Zaten metrikleri bir gözlemlenebilirlik platformuna gönderiyorsanız bunları kullanın. Doğrudan API entegrasyonu (bu kılavuz), özel kontrol istediğinizde en iyisidir.

Tetikleme, onaylama ve çözme arasındaki fark nedir?

Tetikleyici yeni bir olay yaratır. Onay bildirimleri durdurur ancak olayın açık kalmasını sağlar (birisi bunun üzerinde çalışıyor). Resolve olayı tamamen kapatır.

İlgili Makaleler

Sonraki Adımlar

CAPTCHA hattınızda sorun olduğu anda uyarı alın;CaptchaAI API anahtarıyla başlayınve PagerDuty'yi bağlayın.

İlgili kılavuzlar:

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

İlgili Yazılar

DevOps & Scaling CAPTCHA Çözme Altyapısı için Mavi-Yeşil Dağıtım
Üretimdeki Captcha AI iş akışlarına yönelik mimari kararları, işletim hususlarını ve otomasyon modellerini içeren CAPTCHA Çözme Altyapısı için Mavi-Yeşil Dağıtı...

Üretimdeki Captcha AI iş akışlarına yönelik mimari kararları, işletim hususlarını ve otomasyon modellerini içe...

Apr 27, 2026
DevOps & Scaling Azure İşlevleri + CaptchaAI: Bulut Entegrasyonu
Azure İşlevleri + Captcha AI: Bulut Entegrasyonu için Dev Ops kılavuzu, üretimdeki Captcha AI iş akışlarına yönelik mimari kararları, işletim hususlarını ve oto...

Azure İşlevleri + Captcha AI: Bulut Entegrasyonu için Dev Ops kılavuzu, üretimdeki Captcha AI iş akışlarına yö...

Apr 23, 2026
DevOps & Scaling CaptchaAI Çalışan Dağıtımı için Ansible Playbook'lar
Ansible Playbook'lar için Captcha AI Çalışan Dağıtımı için Dev Ops kılavuzu, üretimdeki Captcha AI iş akışlarına yönelik mimari kararları, işletim hususlarını v...

Ansible Playbook'lar için Captcha AI Çalışan Dağıtımı için Dev Ops kılavuzu, üretimdeki Captcha AI iş akışları...

Apr 19, 2026