---
title: "경고 규칙 API"
description: "Alpacon 지표 경고 규칙을 위한 REST API 레퍼런스. CPU, 메모리, 디스크, 네트워크 지표를 감시하는 규칙을 만들고, 방향·지속 시간·복귀 임계값·데이터 없음 감지 시간·알림 수신 대상을 설정하고, 장치 하나로 좁힐 수 있습니다."
---

> Full documentation index: https://docs.alpacax.com/llms.ko.txt

# 경고 규칙 API

**엔드포인트**: `/api/metrics/alert-rules/`

경고 규칙은 에이전트가 이미 보낸 데이터를 사용해 서버의 지표를 감시하다가 값이 설정한 방향으로 임계값을 지나면 경고를 발생시킵니다. 규칙은 Alpacon이 자체 일정에 따라 약 1분마다 평가합니다. 규칙이 발생하고 해제되는 방식은 [메트릭 알림](/use/servers/monitor/#메트릭-알림)을 참고하세요.

기본으로 생성되는 디스크 사용률 규칙(모든 서버가 플랜과 관계없이 갖는 규칙)을 포함해, 모든 동작에 워크스페이스의 Metrics 확장 기능이 켜져 있어야 합니다. 그 규칙은 확장 기능이 꺼진 워크스페이스에서도 계속 평가되며, 다만 그 상태를 이 API로는 확인할 수 없습니다.

## 규칙 수정 및 삭제 권한

워크스페이스 관리자는 모든 규칙을 수정하거나 삭제할 수 있습니다. 역할에 워크스페이스 전체 범위의 `alert_rule:update`(`PUT`/`PATCH`용) 또는 `alert_rule:delete` 권한이 있는 사용자도 마찬가지입니다. 기본 제공 `operator` 역할은 두 권한을 모두 가지며, `member` 역할은 둘 다 갖지 않습니다. 규칙을 만들었다고 해서 작성자에게 그 규칙에 대한 별도 권한이 생기지는 않습니다.

이 역할과 별개로, 관리자는 워크스페이스 전체 역할을 바꾸지 않고도 특정 사용자, 그룹, 또는 서비스 토큰의 Application에 규칙 하나만 수정하고 삭제할 권한을 줄 수 있습니다. 이 권한은 RBAC 역할 API를 통해 해당 규칙에 명시적으로 `alert_rule:maintainer` 바인딩을 부여하는 방식으로 설정하며, 콘솔의 역할 선택 화면은 아직 권한 범위를 규칙 하나로 좁히지 못합니다. 서비스 토큰은 이런 바인딩이 있어야만 규칙에 접근할 수 있고, Application이 가진 워크스페이스 전체 역할은 `operator`라도 그것만으로는 규칙에 접근하지 못합니다. 개인 API 토큰은 발급받은 사용자로 동작하므로, 그 사용자의 역할과 바인딩을 그대로 따릅니다.

Alpacon이 이 바인딩을 작성자에게 자동으로 부여하던 시기에 만들어진 규칙은 그때 작성자에게 준 바인딩을 여전히 가지고 있을 수 있으며, Alpacon이 이런 옛 바인딩을 정리할 때까지 그 작성자는 계속 규칙을 수정하고 삭제할 수 있습니다.

### 기본 규칙

CPU 사용률, 메모리 사용률을 비롯해 기본으로 지정된 코어 외 확장 규칙은 다른 규칙과 마찬가지로 `alert_rule:update` 권한이 있는 누구나 수정할 수 있습니다. 기본 규칙은 기본 상태로 지정된 동안에는 누가 요청하든 삭제할 수 없습니다. [경고 규칙 삭제](#경고-규칙-삭제)를 참고하세요.

### 핵심 디스크 사용률 규칙

모든 워크스페이스에는 Metrics 확장 기능이 켜져 있는지와 관계없이 항상 동작하는 기본 디스크 사용률 규칙(`is_default: true`, 대상 `disk-usage`)이 있습니다. 다음은 워크스페이스 관리자만 할 수 있습니다.

- `PUT` 또는 `PATCH`로 이 규칙을 수정
- 장치와 관계없이 `is_default: true`이고 대상이 `disk-usage`인 규칙을 새로 만들거나, 기존 규칙을 그렇게 바꾸는 것
- 이 규칙에 대한 [서버 오버라이드](/reference/api/metrics/rule-overrides/)를 생성·수정·삭제하거나, 오버라이드를 이 규칙으로 옮기거나 이 규칙에서 다른 규칙으로 옮기는 것
- 서버 API의 규칙 분리(detach-rule) 액션이나 `rules`에서 이 규칙을 뺀 서버 수정을 통해 서버에서 이 규칙을 분리하는 것

`operator`, 이 규칙에 대한 바인딩을 가진 주체, 모든 서비스 토큰을 포함해 그 밖의 누구든 403 `metrics_alert_rule_core_admin_only`를 받습니다. 이 규칙을 서버에 다시 붙이는 것은 이 제한을 받지 않으며, 이 규칙을 이미 읽을 수 있는 사람이라면 [수신자](#수신자-미리보기)나 [평가](#평가-미리보기) 미리보기도 그대로 쓸 수 있습니다.

  
    ## 경고 규칙 목록 조회

    경고 규칙 목록을 페이지네이션하여 가져옵니다.

    ### 요청

    ```http
    GET /api/metrics/alert-rules/
    ```

    ### 쿼리 파라미터

    | 파라미터 | 타입 | 설명 |
    |-----------|------|-------------|
    | `name` | string | 규칙 이름으로 필터링 |
    | `target` | string | 대상 지표로 필터링 |
    | `threshold` | number | 임계값으로 필터링 |
    | `operator` | string | 방향으로 필터링 (`gte` 또는 `lte`) |
    | `device` | string | 장치로 필터링 |
    | `severity` | string | 심각도로 필터링 (`critical`, `warning`, `info`) |
    | `is_default` | boolean | 기본 규칙 여부로 필터링 |
    | `server` | string (UUID) | 이 서버에 붙은 규칙만 조회 |
    | `exclude_server` | string (UUID) | 이 서버에 붙지 않은 규칙만 조회 |
    | `search` | string | 이름, 대상, 기본 규칙 여부로 검색 |
    | `ordering` | string | 정렬 순서. 기본값: `-added_at` |
    | `page` | integer | 페이지 번호 |
    | `page_size` | integer | 페이지당 결과 수 (기본값: 15, 최대: 100) |

    ### 응답

    ```json
    {
      "count": 2,
      "next": null,
      "previous": null,
      "results": [
        {
          "id": "3f1c9b2e-6a4d-4e8f-9b1a-2c3d4e5f6a7b",
          "name": "Core disk usage",
          "target": "disk-usage",
          "threshold": 80,
          "operator": "gte",
          "duration_s": 0,
          "recovery_threshold": 78,
          "no_data_after_s": null,
          "device": "",
          "severity": "warning",
          "notify_email": "all",
          "notify_slack_channel": true,
          "is_default": true
        },
        {
          "id": "8c4d6e2a-1b3f-4a5c-8d9e-0f1a2b3c4d5e",
          "name": "Sustained high CPU",
          "target": "cpu-usage",
          "threshold": 80,
          "operator": "gte",
          "duration_s": 300,
          "recovery_threshold": 70,
          "no_data_after_s": 600,
          "device": "",
          "severity": "critical",
          "notify_email": "admins",
          "notify_slack_channel": false,
          "is_default": false
        }
      ]
    }
    ```

    필요한 스코프: [`alert_rule:read`](/reference/scopes/#alert_rule-read)

    ### 예시

    ```bash
    curl -X GET "https://your-workspace.ap1.alpacon.io/api/metrics/alert-rules/?target=cpu-usage" \
      -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\""
    ```
  

  
    ## 경고 규칙 생성

    새 경고 규칙을 만듭니다.

    ### 요청

    ```http
    POST /api/metrics/alert-rules/
    ```

    ### 요청 본문

    ```json
    {
      "name": "Sustained high CPU",
      "target": "cpu-usage",
      "threshold": 80,
      "operator": "gte",
      "duration_s": 300,
      "recovery_threshold": 70,
      "no_data_after_s": 600,
      "severity": "critical",
      "notify_email": "admins",
      "notify_slack_channel": false
    }
    ```

    ### 요청 파라미터

    | 필드 | 타입 | 필수 | 설명 |
    |------|------|------|------|
    | `name` | string | Yes | 규칙 이름. 워크스페이스 내에서 유일해야 함 |
    | `target` | string | Yes | 감시할 지표: `cpu-usage`, `memory-usage`, `disk-usage`, `peak-read-bps`, `peak-write-bps`, `avg-read-bps`, `avg-write-bps`, `peak-input-pps`, `peak-input-bps`, `peak-output-pps`, `peak-output-bps`, `avg-input-pps`, `avg-input-bps`, `avg-output-pps`, `avg-output-bps` |
    | `threshold` | number | Yes | 경고를 발생시키는 값 |
    | `operator` | string | No | `gte`: 임계값 이상일 때 발생(기본값). `lte`: 임계값 이하일 때 발생 |
    | `duration_s` | integer | No | 경고가 발생하기까지 조건이 유지되어야 하는 시간(초). 기본값 `0`이면 조건을 만족하는 첫 샘플에서 바로 발생. 0보다 크게 설정할 때는 대상의 수집 주기 2회분 이상이어야 하며, 그보다 짧으면 `metrics_alert_rule_duration_too_short`로 거부됨 |
    | `recovery_threshold` | number | No | 경고가 해제되기 위해 지표가 돌아와야 하는 값. 선택한 `operator`에서 회복하는 쪽에 있어야 함(`gte`라면 `threshold`보다 낮게, `lte`라면 `threshold`보다 높게). 비워 두면 `threshold` 자체가 해제 기준이 됨 |
    | `no_data_after_s` | integer | No | 이 시간(초) 동안 샘플이 도착하지 않으면 별도의 경고를 발생시킴. 이 대상의 수집 간격 이상, 86400(24시간) 이하여야 함. 비워 두면 이 기능을 사용하지 않음 |
    | `device` | string | No | 규칙을 디스크나 네트워크 인터페이스 하나로 제한. 장치 단위로 측정되는 대상(`disk-usage`와 위 디스크 I/O·네트워크 대상들)에만 설정 가능하며, 서버 전체를 대상으로 하는 `cpu-usage`, `memory-usage`에는 거부됨 |
    | `severity` | string | No | 발생하는 경고의 심각도: `critical`, `warning`, `info` 중 하나. 기본값 `warning`. 심각도가 어떤 채널까지 작동할지를 결정함: `critical`만 `notify_email`에 따라 메일을 보낼 수 있고, `critical`과 `warning`은 `notify_slack_channel`에 따라 Slack에 게시할 수 있으며, `info`는 둘 다 보내지 않음. 심각도와 관계없이 콘솔과 벨에는 그대로 기록되고, 그 규칙 이벤트를 구독하는 웹훅에는 그대로 전달되며, 열려 있는 동안에는 시간별 [열린 알림 다이제스트](/reference/notifications/#미해결-알림-요약)에도 포함됨 |
    | `notify_email` | string | No | 경고 메일을 받을 대상. 이미 서버를 볼 수 있는 사람 중에서 고름: `all`(기본값, 서버를 볼 수 있는 모든 사람), `admins`(워크스페이스 관리자만), `group_members`(서버 그룹 멤버와 소유자), `none`(개별 경고 메일 안 보냄). `notify_slack_channel`과 독립적으로 동작하며, 별도로 발송되는 [열린 알림 다이제스트](/reference/notifications/#미해결-알림-요약)에는 영향을 주지 않음. `critical` 심각도 규칙에만 적용되며, `warning`이나 `info` 규칙은 이 값과 관계없이 메일을 보내지 않음 |
    | `notify_slack_channel` | boolean | No | 발생과 해제를 워크스페이스에 연결된 Slack 채널에 게시할지 여부. 기본값 `true`. `notify_email`과 독립적으로 동작. `critical`과 `warning` 심각도에 적용되며, `info` 규칙은 이 값과 관계없이 아무것도 게시하지 않음 |
    | `is_default` | boolean | No | 이후 등록되는 모든 서버에 자동으로 붙는 규칙인지 여부. 대상과 장치 조합당 기본 규칙은 하나만 가능 |

    `notify_email`과 `notify_slack_channel`은 로그인한 워크스페이스 멤버만 설정할 수 있습니다. 애플리케이션이나 서비스 토큰이 이 두 필드 중 하나라도 요청에 담으면, 규칙에 이미 설정된 값과 같은 값을 보내는 경우라도 `metrics_alert_rule_destination_not_allowed`로 거부됩니다.

    규칙을 만들었다고 해서 작성자에게 그 규칙에 대한 별도 권한이 생기지는 않습니다. [규칙 수정 및 삭제 권한](#규칙-수정-및-삭제-권한)을 참고하세요. 새 규칙이 `is_default: true`이고 대상이 `disk-usage`로 남는 생성 요청은 호출자가 워크스페이스 관리자가 아니면 `metrics_alert_rule_core_admin_only`로 거부됩니다. [핵심 디스크 사용률 규칙](#핵심-디스크-사용률-규칙)을 참고하세요.

    ### 응답

    ```json
    {
      "id": "8c4d6e2a-1b3f-4a5c-8d9e-0f1a2b3c4d5e",
      "name": "Sustained high CPU",
      "target": "cpu-usage",
      "threshold": 80,
      "operator": "gte",
      "duration_s": 300,
      "recovery_threshold": 70,
      "no_data_after_s": 600,
      "device": "",
      "severity": "critical",
      "notify_email": "admins",
      "notify_slack_channel": false,
      "is_default": false
    }
    ```

    필요한 스코프: [`alert_rule:create`](/reference/scopes/#alert_rule-create)

    ### 예시

    ```bash
    curl -X POST "https://your-workspace.ap1.alpacon.io/api/metrics/alert-rules/" \
      -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\"" \
      -H "Content-Type: application/json" \
      -d '{"name": "Sustained high CPU", "target": "cpu-usage", "threshold": 80, "duration_s": 300}'
    ```
  

  
    ## 경고 규칙 상세 조회

    특정 경고 규칙을 ID로 조회합니다.

    ### 요청

    ```http
    GET /api/metrics/alert-rules/{rule_id}/
    ```

    ### 경로 파라미터

    | 파라미터 | 타입 | 설명 |
    |----------|------|------|
    | `rule_id` | string (UUID) | 조회할 경고 규칙의 ID |

    ### 응답

    ```json
    {
      "id": "8c4d6e2a-1b3f-4a5c-8d9e-0f1a2b3c4d5e",
      "name": "Sustained high CPU",
      "target": "cpu-usage",
      "threshold": 80,
      "operator": "gte",
      "duration_s": 300,
      "recovery_threshold": 70,
      "no_data_after_s": 600,
      "device": "",
      "severity": "critical",
      "notify_email": "admins",
      "notify_slack_channel": false,
      "is_default": false
    }
    ```

    필요한 스코프: [`alert_rule:read`](/reference/scopes/#alert_rule-read)

    ### 예시

    ```bash
    curl -X GET "https://your-workspace.ap1.alpacon.io/api/metrics/alert-rules/8c4d6e2a-1b3f-4a5c-8d9e-0f1a2b3c4d5e/" \
      -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\""
    ```
  

  
    ## 수신자 미리보기

    경고 규칙이 실제로 발생하기 전에, 그 규칙이 누구에게 알림을 보낼지 개수로만(이름 없이) 미리 확인합니다.

    ### 요청

    ```http
    GET /api/metrics/alert-rules/{rule_id}/recipients/
    ```

    ### 경로 파라미터

    | 파라미터 | 타입 | 설명 |
    |----------|------|------|
    | `rule_id` | string (UUID) | 조회할 경고 규칙의 ID |

    ### 응답

    ```json
    {
      "email": {
        "mode": "group_members",
        "count": 7,
        "reasons": { "admins": 0, "group_members": 6, "owner": 1 }
      },
      "slack_channel": { "enabled": true, "connected": true },
      "event_subscriptions": 2
    }
    ```

    | 필드 | 설명 |
    |------|------|
    | `email.mode` | 규칙의 `notify_email` 값을 그대로 돌려줌 |
    | `email.count` | 이 규칙의 이메일 수신 대상이 실제로 닿을 사람 수. 규칙이 붙어 있고 실제로 발생시킬 수 있는 서버 중 내가 볼 수 있는 서버만 대상으로 셈. `notify_email`이 `none`이면 항상 0이고, 심각도가 `warning`이나 `info`인 규칙도 `notify_email` 값과 관계없이 항상 0(직접 메일을 보내는 것은 `critical` 규칙뿐) |
    | `email.reasons` | 그 사람들이 각 근거를 몇 명씩 갖는지. `admins`는 워크스페이스 관리자, `group_members`는 그 서버들이 속한 그룹의 멤버, `owner`는 그 서버들의 소유자 중 자기 서버에 아직 접근할 수 있는 사람(규칙을 만든 사람이 아님). 근거는 겹칠 수 있음(워크스페이스 관리자이면서 그룹 멤버일 수 있음). 따라서 셋을 더해도 `count`와 같지 않을 수 있음 |
    | `slack_channel.enabled` | 규칙의 `notify_slack_channel` 값을 그대로 돌려줌 |
    | `slack_channel.connected` | 이 워크스페이스에 알림을 게시할 수 있는 Slack 설치가 있는지 여부. 심각도가 `info`인 규칙은 두 값과 관계없이 아무것도 게시하지 않음 |
    | `event_subscriptions` | 이 규칙의 발생·해제 이벤트를 받을 살아 있는 이벤트 구독 수. 위에서 센 서버를 대상으로 하는 구독과 워크스페이스 전체 대상 구독을 합친 개수. 개수만 알려주며, `notify_email`이나 `notify_slack_channel` 설정과는 무관함 |

    응답 어디에도 사용자 이름, 이메일, ID는 나타나지 않습니다.

    규칙에 붙은 서버가 전부 내가 볼 수 없는 서버라면 `404`를 반환합니다. 규칙 자체를 볼 수 없을 때와 같은 응답입니다. 반면 아직 어떤 서버에도 붙지 않은 규칙은 `404`가 아니라 0을 반환합니다. 막 만들어 아직 서버에 붙이지 않은 상태가 그 모양이며, 거기서 `404`를 반환하면 저장이 실패한 것처럼 보이기 때문입니다.

    필요한 스코프: [`alert_rule:read`](/reference/scopes/#alert_rule-read)

    ### 예시

    ```bash
    curl -X GET "https://your-workspace.ap1.alpacon.io/api/metrics/alert-rules/8c4d6e2a-1b3f-4a5c-8d9e-0f1a2b3c4d5e/recipients/" \
      -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\""
    ```
  

  
    ## 평가 미리보기

    규칙을 저장하지 않고 최근 realtime 샘플에 재생해서, 그 규칙이 언제 발생하고 해제됐을지 확인합니다. 발생과 해제 판정은 워크스페이스의 실제 규칙을 평가하는 것과 같은 평가기가 내리며, 이 API는 그 판정에 샘플을 재생해서 넣어 줄 뿐입니다.

    ### 요청

    ```http
    POST /api/metrics/alert-rules/preview/
    ```

    ### 요청 본문

    ```json
    {
      "rule": {"target": "cpu-usage", "operator": "gte", "threshold": 80,
               "duration_s": 300, "recovery_threshold": 75, "no_data_after_s": null,
               "device": "", "severity": "warning",
               "notify_email": "all", "notify_slack_channel": true},
      "rule_id": "8c4d6e2a-1b3f-4a5c-8d9e-0f1a2b3c4d5e",
      "servers": ["3f0e2b1c-5d6a-4e7f-8a9b-0c1d2e3f4a5b"],
      "window_s": 3600
    }
    ```

    ### 요청 파라미터

    | 필드 | 타입 | 필수 | 설명 |
    |------|------|------|------|
    | `rule` | object | Yes | 규칙 본문. [경고 규칙 생성](#경고-규칙-생성)과 같은 필드에서 `name`, `is_default`는 뺌(보내도 무시됨). `rule_id`를 함께 보낼 때도 항상 필수입니다: 이때는 바꿔 볼 필드만 채우면 되고 나머지는 그 규칙의 값을 쓰며, 아무것도 바꾸지 않는다면 `{}`를 보내면 됩니다 |
    | `rule_id` | string (UUID) | No | 미리보기 대상으로 삼을 기존 규칙. 이 규칙의 [서버 오버라이드](/reference/api/metrics/rule-overrides/)가 적용되고, 붙어 있는 서버가 `servers`의 기본값이 됨 |
    | `servers` | array of string (UUID) | `rule_id`가 없으면 필수 | 재생할 서버. 최대 20대 |
    | `window_s` | integer | No | 얼마나 과거까지 재생할지(초). 기본값 `86400`(24시간), 최소 `60`, 최대 `604800`(7일, realtime 샘플을 보관하는 기간만큼) |

    `rule_id`나 `servers` 중 적어도 하나는 있어야 합니다.

    위 필드 외에 상한이 두 개 더 있습니다. 서버는 최대 20대이고, 서버 수 × `window_s`는 5 × 604800초를 넘을 수 없습니다. 20대면 창은 약 1.75일로 줄고, 7일 전체를 쓰면 서버는 5대로 줄어듭니다. 별도로 재생이 읽거나 판정하는 샘플 행은 300,000행을 넘을 수 없으며, 디스크나 인터페이스가 많은 서버라면 서버 상한보다 먼저 이 상한에 걸릴 수 있습니다. `rule_id`만 보내면 `servers`는 그 규칙이 붙어 있는 서버로 기본값이 정해지는데, 그 기본 서버 목록이 20대를 넘으면 20대 상한에 걸려 거부되므로 이때는 `servers`를 직접 지정해야 합니다.

    규칙을 저장할 때와 같은 [수신 대상 제한](#경고-규칙-생성)이 여기에도 적용됩니다: 본문에 `notify_email`이나 `notify_slack_channel`을 담아 보내면 애플리케이션이나 서비스 토큰은 `metrics_alert_rule_destination_not_allowed`로 거부됩니다.

    ### 응답

    ```json
    {
      "window": {"start": "2026-09-01T11:00:00Z", "end": "2026-09-01T12:00:00Z"},
      "sample_interval_s": 60,
      "summary": {"episodes": 1, "would_interrupt": 1, "open_at_end": 0, "longest_s": 240},
      "servers": [
        {"server": "3f0e2b1c-5d6a-4e7f-8a9b-0c1d2e3f4a5b", "device": "", "samples": 60,
         "episodes": [
           {"condition": "threshold", "raised_at": "2026-09-01T11:50:00Z",
            "resolved_at": "2026-09-01T11:54:00Z", "peak": 91.2, "outlived_hold": true,
            "would_interrupt": true}
         ]}
      ],
      "recipients": {
        "email": {"mode": "all", "count": 3,
                  "reasons": {"admins": 1, "group_members": 2, "owner": 1}},
        "slack_channel": {"enabled": true, "connected": false},
        "event_subscriptions": 0
      },
      "not_reproduced": ["tick_jitter", "state_before_window"]
    }
    ```

    | 필드 | 설명 |
    |------|------|
    | `window.start` / `window.end` | 재생한 구간. `end`는 요청이 실행된 시각, `start`는 그보다 `window_s`초 앞 |
    | `sample_interval_s` | 재생이 판정하는 틱 간격, `60` |
    | `summary.episodes` | 응답에 담긴 모든 서버·장치를 통틀어 발생한 에피소드 수 |
    | `summary.would_interrupt` | `would_interrupt`가 `true`인 에피소드 수. 즉 hold(약 2분)를 넘겨 열려 있었고, 규칙의 심각도와 수신 대상 설정으로 라우팅했을 때 이메일이나 Slack까지 가는 에피소드 수(실제 평가기가 쓰는 것과 같은 판정). 규칙의 심각도와 수신 대상이 어느 채널로도 가지 않는다면 에피소드와 무관하게 `0` |
    | `summary.open_at_end` | `window.end` 시점에 아직 열려 있는 에피소드 수 |
    | `summary.longest_s` | 가장 오래 지속된 에피소드의 길이(초). `window.end`에도 열려 있는 에피소드는 그 시점까지의 길이로 잼 |
    | `servers[]` | 재생한 (서버, 장치) 조합마다 한 행. 호스트 전체 대상(`cpu-usage`, `memory-usage`)은 `device: ""` 한 행, 장치를 지정한 규칙은 그 장치 한 행, 장치를 지정하지 않은 장치 단위 대상은 구간 안에서 샘플을 보낸 장치마다 한 행. 관리 대상이 아니거나, 커미션되지 않았거나, 자신의 오버라이드로 제외된 서버는 아예 빠짐 |
    | `servers[].episodes[].condition` | `threshold` 또는 `no_data` |
    | `servers[].episodes[].raised_at` / `resolved_at` | 에피소드가 열리고 닫힌 시각. `window.end`까지 열려 있으면 `resolved_at`은 `null` |
    | `servers[].episodes[].peak` | 발생 판정이 읽은 가장 오래된 샘플부터 해제까지(열려 있으면 `window.end`까지)의 최고값(`lte` 규칙이면 최저값). `no_data` 에피소드는 `null` |
    | `servers[].episodes[].outlived_hold` | 이 에피소드가 실제 이메일·Slack 발송을 막는 약 2분의 hold를 넘겨 열려 있었는지 |
    | `servers[].episodes[].would_interrupt` | 이 에피소드가 hold를 넘겨 열려 있었고, 규칙의 심각도와 수신 대상 설정이 이메일이나 Slack처럼 인터럽트를 보내는 채널로 라우팅하는지. `outlived_hold: true`를 전제로 하며, hold를 넘겼더라도 규칙의 심각도와 수신 대상으로 아무것도 보내지 않는다면 여전히 `false` |
    | `recipients` | [수신자 미리보기](#수신자-미리보기)와 같은 모양이며, 실제로 재생한 서버를 대상으로 계산함 |
    | `not_reproduced` | 이 재생이 실제 평가기와 달라지는 지점 중 이 응답에 해당하는 것: `tick_jitter`(실제 틱은 분 경계에서 몇 초 어긋날 수 있지만 이 재생은 정확히 분 단위로 가정함), `state_before_window`(`window.start` 이전의 상태를 알 수 없어 구간이 시작될 때 이미 열려 있던 에피소드는 놓침), `maintenance_window_no_data`(규칙에 `no_data_after_s`가 있을 때만 표시되며 점검 시간대 자체의 데이터 없음 처리는 재생하지 않음), `core_scope_current`(기본으로 제공되는 코어 디스크 사용률 규칙에만 표시되며 어느 볼륨이 "코어"인지는 틱마다가 아니라 `window.end` 기준으로 한 번만 정함) |

    없는 `rule_id`, 또는 붙어 있는 서버가 전부 내가 볼 수 없는 서버라면 `404`를 반환합니다. `servers`에 내가 볼 수 없거나 존재하지 않는 서버가 있으면 `server_not_found` 코드와 함께 `400`을 반환합니다. `rule_id`로 남의 규칙을 미리보는 것은 막지 않습니다. 저장하지 않는 읽기이기 때문이며, [활동 로그](/use/audit/governance/activity-log/)에도 남지 않습니다.

    필요한 스코프: [`alert_rule:read`](/reference/scopes/#alert_rule-read)

    ### 예시

    ```bash
    curl -X POST "https://your-workspace.ap1.alpacon.io/api/metrics/alert-rules/preview/" \
      -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\"" \
      -H "Content-Type: application/json" \
      -d '{"rule": {"target": "cpu-usage", "threshold": 80, "duration_s": 300}, "servers": ["3f0e2b1c-5d6a-4e7f-8a9b-0c1d2e3f4a5b"]}'
    ```
  

  
    ## 경고 규칙 수정

    기존 경고 규칙을 수정합니다. `PATCH`를 통한 부분 업데이트를 지원합니다.

    ### 요청

    ```http
    PATCH /api/metrics/alert-rules/{rule_id}/
    ```

    ### 경로 파라미터

    | 파라미터 | 타입 | 설명 |
    |----------|------|------|
    | `rule_id` | string (UUID) | 수정할 경고 규칙의 ID |

    ### 요청 본문

    ```json
    {
      "threshold": 85,
      "recovery_threshold": 75
    }
    ```

    ### 요청 파라미터

    [경고 규칙 생성](#경고-규칙-생성)과 같은 필드이며, 모두 선택 사항입니다. `operator`나 `threshold`를 바꾸면 이 규칙 자체의 복귀 임계값이나 [서버 오버라이드](/reference/api/metrics/rule-overrides/)의 복귀 임계값이 바뀐 값의 잘못된 쪽에 남게 될 경우, 그 수정은 거부됩니다.

    특정 규칙에 접근해 수정할 수 있는 주체는 정해져 있습니다. [규칙 수정 및 삭제 권한](#규칙-수정-및-삭제-권한)을 참고하세요. 핵심 디스크 사용률 규칙은 워크스페이스 관리자의 `PUT`/`PATCH`만 허용하며, 그 밖의 호출자는 `metrics_alert_rule_core_admin_only`를 받습니다.

    ### 응답

    수정된 필드를 포함한 전체 경고 규칙 객체를 반환합니다 ([경고 규칙 상세 조회](#경고-규칙-상세-조회)와 같은 스키마).

    필요한 스코프: [`alert_rule:update`](/reference/scopes/#alert_rule-update)

    ### 예시

    ```bash
    curl -X PATCH "https://your-workspace.ap1.alpacon.io/api/metrics/alert-rules/8c4d6e2a-1b3f-4a5c-8d9e-0f1a2b3c4d5e/" \
      -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\"" \
      -H "Content-Type: application/json" \
      -d '{"threshold": 85, "recovery_threshold": 75}'
    ```
  

  
    ## 경고 규칙 삭제

    경고 규칙을 삭제합니다. 기본 규칙(`is_default: true`)은 기본 상태로 지정된 채로는 삭제할 수 없습니다. 먼저 `is_default`를 해제하세요.

    특정 규칙에 접근해 삭제할 수 있는 주체는 정해져 있습니다. [규칙 수정 및 삭제 권한](#규칙-수정-및-삭제-권한)을 참고하세요.

    ### 요청

    ```http
    DELETE /api/metrics/alert-rules/{rule_id}/
    ```

    ### 경로 파라미터

    | 파라미터 | 타입 | 설명 |
    |----------|------|------|
    | `rule_id` | string (UUID) | 삭제할 경고 규칙의 ID |

    ### 응답

    ```http
    204 No Content
    ```

    필요한 스코프: [`alert_rule:delete`](/reference/scopes/#alert_rule-delete)

    ### 예시

    ```bash
    curl -X DELETE "https://your-workspace.ap1.alpacon.io/api/metrics/alert-rules/8c4d6e2a-1b3f-4a5c-8d9e-0f1a2b3c4d5e/" \
      -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\""
    ```
  

## 오류 코드

| 상태 | 오류 코드 | 설명 |
|------|----------|------|
| 400 | `metrics_alert_rule_exists` | 이 대상과 장치 조합에 이미 기본 규칙이 있음 |
| 400 | `metrics_alert_rule_recovery_threshold_invalid` | `recovery_threshold`가 `threshold`의 회복하는 쪽에 있지 않음 |
| 400 | `metrics_alert_rule_override_recovery_threshold_invalid` | `operator`, `threshold`, `recovery_threshold`를 수정하면 어떤 서버 [오버라이드](/reference/api/metrics/rule-overrides/)의 회복 임계값이 발동하는 쪽에 남게 됨 |
| 400 | `metrics_alert_rule_duration_too_short` | `duration_s`가 0보다 크지만 이 대상의 수집 주기 2회분보다 짧음 |
| 400 | `metrics_alert_rule_override_duration_too_short` | `target`을 수정하면 어떤 서버 오버라이드의 양수 `duration_s`가 새 대상의 하한(수집 주기 2회분)보다 짧아짐 |
| 400 | `metrics_alert_rule_no_data_window_too_short` | `no_data_after_s`가 이 대상의 수집 간격보다 짧음 |
| 400 | `metrics_alert_rule_no_data_window_too_long` | `no_data_after_s`가 86400초(24시간)보다 김 |
| 400 | `metrics_alert_rule_device_not_supported` | 서버 전체를 대상으로 하는 지표(`cpu-usage`, `memory-usage`)에 `device`를 지정함 |
| 400 | `metrics_alert_rule_cannot_be_deleted` | `is_default`가 `true`인 규칙을 삭제하려고 함 |
| 400 | `metrics_alert_rule_destination_not_allowed` | 로그인한 워크스페이스 멤버가 아니라 애플리케이션이나 서비스 토큰이 `notify_email` 또는 `notify_slack_channel`을 설정하려고 함 |
| 400 | `server_not_found` | [평가 미리보기](#평가-미리보기)의 `servers`에 볼 수 없거나 존재하지 않는 서버를 지정함 |
| 400 | `metrics_alert_rule_preview_window_too_long` | [평가 미리보기](#평가-미리보기)의 `window_s`가 604800초(7일)보다 김 |
| 400 | `metrics_alert_rule_preview_too_many_servers` | [평가 미리보기](#평가-미리보기)에 서버를 20대 넘게 지정했거나, 서버 수 × `window_s`가 5 × 604800을 넘음 |
| 400 | `metrics_alert_rule_preview_too_many_samples` | [평가 미리보기](#평가-미리보기)가 읽거나 판정해야 할 샘플 행이 300,000행을 넘음 |
| 400 | `metrics_alert_rule_preview_servers_required` | [평가 미리보기](#평가-미리보기)에 `rule_id`와 `servers` 둘 다 없음 |
| 401 | `UNAUTHORIZED` | 유효하지 않거나 누락된 인증 정보 |
| 403 | `metrics_alert_rule_core_admin_only` | 워크스페이스 관리자가 아닌 주체가 핵심 디스크 사용률 규칙을 수정하려고 했거나, 규칙을 만들거나 대상을 바꿔 이 규칙으로 만들려고 함 |
| 403 | `FORBIDDEN` | 권한 부족, 또는 이 워크스페이스에서 Metrics 확장 기능이 꺼져 있음 |
| 404 | `NOT_FOUND` | 경고 규칙을 찾을 수 없음 |

규칙 자체의 값이 문제라면 먼저 확인되어 위의 오버라이드가 아닌 코드로 거부됩니다. 두 오버라이드 코드는 규칙에 달린 모든 오버라이드를 다 판정한 뒤에 거부되며, `field_errors`는 영향을 받은 오버라이드마다 `overrides.<서버 id>.recovery_threshold` 또는 `overrides.<서버 id>.duration_s` 경로를 씁니다. 한 서버가 둘 다에 걸리면 두 경로가 함께 실립니다. 호출자가 해당 서버를 볼 수 없으면 `overrides.*` 경로 없이 같은 코드의 `non_field_errors`만 담깁니다. [규칙 오버라이드 API](/reference/api/metrics/rule-overrides/)로 오버라이드를 직접 고칠 때의 오류 코드는 바뀌지 않습니다.

Source: https://docs.alpacax.com/ko/reference/api/metrics/rules/
