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
- İstemci Captcha Boru Hatları Oluşturma Captchaai
- Sorumlu Otomasyon Oluşturma Captchaai
- Captchaai İzleme Datadog Metrik Uyarıları
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: