预算的自定义操作

您可以将预算配置为在达到支出阈值时自动调用存储过程。这使您可以采取自动操作来响应 credit 使用量,例如暂停仓库、发送自定义警报或将支出事件记录到表中。自定义操作不会取代预计使用量超过预算限制时 Snowflake 发送的 通知

定义自定义操作时,您可以指定它是根据 预计 credit 使用量还是 实际 credit 使用量来调用存储过程,然后设置阈值。当预计或实际使用量达到阈值时,将执行存储过程。

存储过程要求

自定义操作调用的存储过程必须满足以下要求:

创建符合这些要求的存储过程后,必须向 SNOWFLAKE 应用程序授予对过程及其父数据库/架构的 USAGE 权限。例如,如果存储过程的完全限定名称是 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;

备注

如果在将存储过程添加到自定义操作后更新存储过程,则必须重新授予 SNOWFLAKE 应用程序对该过程的 USAGE 权限。

向预算添加自定义操作

您可以向账户预算或自定义预算添加多个自定义操作,但向同一预算添加的自定义操作不能超过 10 个。自定义操作由以下组件组成:

  • 存储过程:对要调用的过程的引用。

  • Argument:要传递给存储过程的实参数组。

  • 阈值:触发自定义操作的预算限制百分比(例如 75%)。

  • 触发类型:自定义操作是根据预计使用量还是实际使用量触发。

要向预算添加自定义操作,请对预算实例调用 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('admin@example.com', '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');
    

    小技巧

    如果要移除特定操作,请使用 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";
    $$;
    
  2. 将对该存储过程的权限授予 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;
    
  3. 将自定义操作添加到预算中,以便在使用量达到预算支出限额的 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', 'admin@example.com', '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 会限制自定义操作的执行频率:

  • 如果在 credit 使用量预计达到支出阈值时运行自定义操作,则存储过程每天调用的次数不会超过一次。

  • 如果自定义操作在 credit 使用量达到实际支出限额时运行,则存储过程每月调用次数不会超过一次。

通过调用 GET_CUSTOM_ACTIONS 方法检查 LAST_TRIGGER_ATTEMPT_TIME 字段。