Skip to content
isdnetworks
Go back

알림을 줄였더니 다음 건이 묻혔다

cron 배치 실패 알림이 하루에 수십 통씩 오고 내용이 다 같아서 아무도 보지 않았다. 그래서 한 시간에 한 통만 나가게 바꿨다. 그 뒤로 실패를 며칠 늦게 알게 됐다.

Table of contents

Open Table of contents

원인 — 억제 조건이 너무 넓었다

이렇게 만들었다.

$last = $this->cache->get('last_alert_time');

if ($last && (time() - $last) < 3600) {
    return;   // 한 시간 안에 보낸 적 있으면 안 보냄
}

sendAlert($message);
$this->cache->save('last_alert_time', time(), 7200);

마지막으로 보낸 시각을 memcached 키 하나에 담고 TTL 을 한 시간으로 줬다. 그 키가 하나라서 종류를 가리지 않았고 어떤 알림이든 한 시간에 한 통이 됐다.

상품 동기화 실패로 한 통이 나가면 그 뒤 한 시간 동안 결제 배치 실패가 묻힌다. 같은 알림을 줄이려던 것인데 다른 알림까지 줄인 것이다. 줄이는 대상을 정하지 않은 것이 원인이었다.

억제 단위를 나눴다

키 이름에 알림 종류를 넣었다.

$key = 'last_alert:' . $type;   // 'last_alert:sync', 'last_alert:payment'

$last = $this->cache->get($key);
if ($last && (time() - $last) < 3600) {
    return;
}

sendAlert($message);
$this->cache->save($key, time(), 7200);

$type 이 키에 들어가니 같은 종류만 그 TTL 안에서 억제되고 다른 종류는 그대로 나간다. 대상 번호까지 넣으면 더 좁게 나눌 수도 있었다.

$key = 'last_alert:' . $type . ':' . $targetId;

다만 너무 좁히면 억제를 안 하는 것과 결과가 같아진다. 같은 대상에서 계속 나는 실패는 다시 수십 통이 된다. 어느 단위로 나눌지가 이 작업의 판단이었다.

억제된 건수를 함께 보냈다

억제하면 그 사이에 몇 번 있었는지 알 수 없다. 그래서 안 보낸 횟수를 세어 두고 다음 알림에 붙였다.

$cnt = (int)$this->cache->get($key . ':count');

if ($last && (time() - $last) < 3600) {
    $this->cache->save($key . ':count', $cnt + 1, 7200);
    return;
}

$extra = $cnt > 0 ? " (지난 1시간 동안 {$cnt}건 더 발생)" : '';
sendAlert($message . $extra);
$this->cache->save($key . ':count', 0, 7200);

받는 알림은 이렇게 된다.

[배치실패] 상품 동기화 실패 (지난 1시간 동안 47건 더 발생)

여기서 한 번 걸렸다. Memcached::increment() 에 초기값을 주려면 OPT_BINARY_PROTOCOL 이 켜져 있어야 하고 아니면 인자 오류가 난다. 그래서 add() 로 먼저 만들고 increment() 를 부르는 쪽으로 했다.

한 건 실패한 것과 47건 실패한 것은 다른 상황이다. 숫자가 없으면 둘이 같은 알림으로 보인다. 이 한 줄이 대응 순서를 바꿨다.

비교 — 억제하지 않는 알림

알림 종류를 나눠 보니 억제해도 되는 것과 아닌 것이 갈렸다.

종류억제
배치 실패1시간
조회 지연1시간
결제 처리 실패안 함
데이터베이스 접속 실패안 함

돈이 걸린 것과 전체가 멈추는 것은 memcached 를 아예 안 보고 매번 보내게 뒀다. 시끄러워도 그게 맞았다. 억제는 여러 번 와도 대응이 같은 것에만 걸었다.

복구됐을 때도 알리게 했다.

if ($nowOk && $this->cache->get('failing:' . $type)) {
    sendAlert("[복구] {$type} 정상화");
    $this->cache->delete('failing:' . $type);
}

복구 알림이 있으면 실패 알림을 받고도 기다려 볼 수 있다. 없으면 매번 들어가서 봐야 한다.

알림을 보내는 코드 자체가 죽으면 아무 알림이 없고 그러면 정상으로 보인다. 그래서 cron 으로 하루 한 번 정상 신호를 보내게 했다.

[일일점검] 배치 5종 정상, 어제 실패 3건

이게 안 오면 감시 자체가 멈춘 것이다. 아무 소식이 없는 것을 정상으로 읽으면 안 되고 정상일 때도 소식이 있어야 둘이 구분된다.

수신자도 설정 파일에 목록으로 뒀다. 한 사람 메일로만 가면 그 사람이 휴가일 때 아무도 못 보고 코드에 박아 두면 사람이 바뀔 때마다 배포한다.

정리


Share this post on:

Previous Post
몰아 보내면 막힌다
Next Post
한 곳에서만 깨지던 글자