예산의 커스텀 작업(Custom Actions)

예산의 커스텀 작업(Custom Actions)

지출 임계값에 도달하면 저장 프로시저를 자동으로 호출하도록 예산을 구성할 수 있어요. 이를 통해 웨어하우스 일시 중단, 커스텀 알림 전송, 지출 이벤트를 테이블에 기록하는 것 같은 크레딧 소비에 대응한 자동화 작업을 수행할 수 있어요. 커스텀 작업은 소비가 예산 한도를 초과할 것으로 예상될 때 Snowflake가 보내는 알림을 대체하지 않아요.

출처: Snowflake 문서

본문

커스텀 작업을 정의할 때 예상(projected) 크레딧 소비에 기반해 호출할지 실제(actual) 크레딧 소비에 기반해 호출할지 지정한 다음 임계값을 설정해요. 예상 또는 실제 소비가 임계값에 도달하면 저장 프로시저가 실행돼요.

저장 프로시저 요구사항

커스텀 작업이 호출하는 저장 프로시저는 다음 요구사항을 충족해야 해요.

이 요구사항을 충족하는 저장 프로시저를 만든 후에는 프로시저와 그 상위 데이터베이스/스키마에 대한 USAGE 권한을 SNOWFLAKE 애플리케이션에 부여해야 해요. 예를 들어 저장 프로시저의 정규화된 이름이 code_db.sch1.alert_team이면 다음 명령을 실행해요.

GRANT USAGE ON DATABASE code_db TO APPLICATION SNOWFLAKE;
GRANT USAGE ON SCHEMA code_db.sch1 TO APPLICATION SNOWFLAKE;
GRANT USAGE ON PROCEDURE code_db.sch1.alert_team(STRING, NUMBER) TO APPLICATION SNOWFLAKE;

참고(Note): 커스텀 작업에 추가한 후 저장 프로시저를 업데이트하면 프로시저에 대한 USAGE 권한을 SNOWFLAKE 애플리케이션에 다시 부여해야 해요.

예산에 커스텀 작업 추가

계정 예산 또는 커스텀 예산에 여러 커스텀 작업을 추가할 수 있지만, 같은 예산에 10개를 초과해 추가할 수는 없어요. 커스텀 작업은 다음 구성 요소로 이루어져요.

  • 저장 프로시저(Stored procedure): 호출할 프로시저에 대한 참조
  • 인자(Arguments): 저장 프로시저에 전달할 인자의 배열
  • 임계값(Threshold): 커스텀 작업을 트리거하는 예산 한도의 백분율(예: 75%)
  • 트리거 유형(Trigger type): 예상 소비 또는 실제 소비 중 무엇을 기준으로 커스텀 작업이 트리거되는지

예산에 커스텀 작업을 추가하려면 예산 인스턴스에서 ADD_CUSTOM_ACTION 메서드를 호출해요. 예를 들어 다음 코드는 지출이 예산 한도의 75%를 초과할 것으로 예상될 때 send_email_notification 저장 프로시저를 호출하는 커스텀 작업을 추가해요.

CALL budget_db.sch1.my_budget!ADD_CUSTOM_ACTION(
  SYSTEM$REFERENCE('PROCEDURE', 'code_db.sch1.alert_team(string, string, string)'),
  ARRAY_CONSTRUCT('[email protected]', 'Budget Alert', 'Spending at 75% of budget limit'),
  'PROJECTED',
  75);

커스텀 작업이 호출하는 저장 프로시저 생성까지 포함한 종단 간 예시는 확장 예시를 참고해요.

예산에서 커스텀 작업 제거

예산에서 커스텀 작업을 제거하려면 예산 인스턴스에서 REMOVE_CUSTOM_ACTIONS 메서드를 호출해요. 이 메서드를 사용해 다음을 할 수 있어요.

  • 예산에서 모든 커스텀 작업 제거. 예를 들어:
CALL budget_db.sch1.my_budget!REMOVE_CUSTOM_ACTIONS();
  • 지정된 임계값을 가진 모든 커스텀 작업 제거. 예를 들어 소비가 75%에 도달하면 트리거되는 모든 커스텀 작업을 제거하려면 다음 명령을 실행해요.
CALL budget_db.sch1.my_budget!REMOVE_CUSTOM_ACTIONS(75);
  • 예산에서 지정된 커스텀 작업 제거. 예를 들어 소비가 75%에 도달할 때 my_sp 저장 프로시저를 호출하는 커스텀 작업을 제거하려면 다음 명령을 실행해요.
CALL budget_db.sch1.my_budget!REMOVE_CUSTOM_ACTIONS(75, 'code_db.sch1.my_sp');

팁(Tip): 특정 작업을 제거하는 경우 GET_CUSTOM_ACTIONS 메서드가 반환하는 정규화된 프로시저 이름을 사용해요.

확장 예시

다음 예시는 커스텀 작업이 호출하는 저장 프로시저를 작성하고, 프로시저에 필요한 권한을 부여한 뒤, 커스텀 작업을 예산에 추가하는 방법을 보여줘요.

  1. 모든 요구사항에 부합하는 저장 프로시저를 만든다.
CREATE OR REPLACE PROCEDURE code_db.sch1.alert_team(
 integration_name string,
 email_list string,
 email_subject string,
 email_content string)
RETURNS STRING
LANGUAGE JAVASCRIPT
EXECUTE AS OWNER
AS
$$
 var sql_command = "CALL SYSTEM$SEND_EMAIL('" + INTEGRATION_NAME + "', " +
                                         "'" +  EMAIL_LIST + "', " +
                                         "'" + EMAIL_SUBJECT + "'," +
                                         "'" + EMAIL_CONTENT + "'" + ");";
 var statement1 = snowflake.createStatement({sqlText: sql_command});
 statement1.execute();
 return "alert sent";
$$;
  1. SNOWFLAKE 애플리케이션에 저장 프로시저에 대한 권한을 부여한다.
GRANT USAGE ON DATABASE code_db TO APPLICATION SNOWFLAKE;
GRANT USAGE ON SCHEMA code_db.sch1 TO APPLICATION SNOWFLAKE;
GRANT USAGE ON PROCEDURE code_db.sch1.alert_team(STRING, STRING, STRING, STRING)
  TO APPLICATION SNOWFLAKE;
  1. 소비가 예산 지출 한도의 90%에 도달할 때 트리거되도록 커스텀 작업을 예산에 추가한다.
CALL budget_db.sch1.my_budget!ADD_CUSTOM_ACTION(
  SYSTEM$REFERENCE('PROCEDURE', 'code_db.sch1.alert_team(string, string, string, string)'),
  ARRAY_CONSTRUCT('my_int', '[email protected]', 'Budget Alert', 'Spending at 90% of budget limit'),
  'ACTUAL',
  90);

커스텀 작업 문제 해결

커스텀 작업이 예상대로 작동하지 않으면 다음 방법으로 문제를 진단해요.

커스텀 작업 실행 모니터링

Snowflake는 커스텀 작업을 실행하기 위해 태스크를 사용해요. 이 태스크는 BUDGET_CUSTOM_ACTION_TRIGGER_AT_% 명명 규칙을 따라요. 예산 인스턴스의 모든 커스텀 작업 태스크 실행 상태를 확인하려면 다음 쿼리를 실행해요.

SELECT th.*, ci.name AS budget_name
  FROM SNOWFLAKE.ACCOUNT_USAGE.TASK_HISTORY th
  JOIN SNOWFLAKE.ACCOUNT_USAGE.CLASS_INSTANCES ci
    ON th.instance_id = ci.id
  WHERE ci.class_name = 'BUDGET'
    AND th.name ILIKE 'BUDGET_CUSTOM_ACTION_TRIGGER_AT_%'
    AND ci.name = '<budget_name>'
  ORDER BY th.completed_time DESC
  LIMIT 10;

작업 트리거 이력 보기

특정 예산에서 일정 기간 동안 트리거된 커스텀 작업을 보려면 다음 쿼리를 실행해요.

SELECT th.*, ci.name as budget_name
  FROM SNOWFLAKE.ACCOUNT_USAGE.TASK_HISTORY th
  JOIN SNOWFLAKE.ACCOUNT_USAGE.CLASS_INSTANCES ci
    ON th.instance_id = ci.id
  WHERE ci.class_name = 'BUDGET'
    AND th.name ILIKE 'BUDGET_CUSTOM_ACTION_TRIGGER_AT_%'
    AND ci.name = '<budget_name>'
    AND th.COMPLETED_TIME >= DATEADD('day', -7, CURRENT_TIMESTAMP())
  ORDER BY th.completed_time DESC;

특정 커스텀 작업의 트리거 이력을 확인하려면 먼저 GET_CUSTOM_ACTIONS 메서드를 호출해 작업 ID를 얻어요.

CALL <budget_name>!GET_CUSTOM_ACTIONS();

그런 다음 다음 쿼리에서 작업 ID를 사용해요.

SELECT th.*, ci.name AS budget_name
  FROM SNOWFLAKE.ACCOUNT_USAGE.TASK_HISTORY th
  JOIN SNOWFLAKE.ACCOUNT_USAGE.CLASS_INSTANCES ci
    ON th.instance_id = ci.id
  WHERE ci.class_name = 'BUDGET'
    AND th.name ILIKE 'BUDGET_CUSTOM_ACTION_TRIGGER_AT_%'
    AND th.query_text ILIKE '%<action_id>%'
    AND ci.name = '<budget_name>'
    AND th.COMPLETED_TIME >= DATEADD('day', -7, CURRENT_TIMESTAMP())
  ORDER BY th.completed_time DESC;

트리거되지 않는 작업 문제 해결

커스텀 작업이 예상 시점에 트리거되지 않으면 다음 일반적인 문제를 확인해요. 커스텀 예산이 budget_db.sch1.my_budget이라고 가정해요.

저장 프로시저 또는 권한이 변경됨

커스텀 작업이 호출하는 저장 프로시저가 여전히 유효하고 SNOWFLAKE 애플리케이션이 여전히 필요한 권한을 가지고 있는지 확인해요. CONFIRM_CUSTOM_ACTIONS_ACCESS 메서드를 호출해 저장 프로시저와 접근 제어 권한을 검증해요.

CALL budget_db.sch1.my_budget!CONFIRM_CUSTOM_ACTIONS_ACCESS();

예산이 활성화되지 않음

계정 예산에 한해 GET_CONFIG 메서드를 호출하고 is_active 필드를 확인해 예산이 활성화됐는지 확인해요.

CALL budget_db.sch1.my_budget!GET_CONFIG();

예산에 지출 한도가 없음

예산에 지출 한도가 구성되지 않으면 커스텀 작업이 트리거되지 않아요. 지출 한도를 확인해요.

CALL budget_db.sch1.my_budget!GET_SPENDING_LIMIT();

예산이 어떤 리소스도 추적하지 않음

지출 이력을 확인해 예산이 리소스를 추적하고 있는지 확인해요.

CALL budget_db.sch1.my_budget!GET_SPENDING_HISTORY();

커스텀 작업이 최근에 트리거됨

과도한 트리거를 방지하기 위해 Snowflake는 커스텀 작업의 실행 빈도를 제한해요.

  • 크레딧 소비가 지출 임계값에 도달할 것으로 예상될 때 커스텀 작업이 실행되면 저장 프로시저는 하루에 한 번 이상 호출되지 않아요.
  • 크레딧 소비가 실제 지출 한도에 도달할 때 커스텀 작업이 실행되면 저장 프로시저는 한 달에 한 번 이상 호출되지 않아요.

GET_CUSTOM_ACTIONS 메서드를 호출해 LAST_TRIGGER_ATTEMPT_TIME 필드를 확인해요.

더 알아보기 (Learn more)