애플리케이션 패키지에 청구 가능한 이벤트 추가하기

Snowflake Native App 에 Custom Event Billing을 사용하면 기존의 사용량 기반 요금제 외에 특정 유형의 애플리케이션 사용량에 대해 요금을 청구할 수 있습니다. 사용자 지정 이벤트 청구를 설정하려면 다음 두 가지 상위 수준 단계를 수행해야 합니다.

  1. 이 항목의 단계에 따라 청구 가능한 이벤트를 발생시키도록 애플리케이션 패키지를 설정합니다.

  2. 컨슈머를 상대로 Snowflake Native App 을 게시하는 데 사용하는 목록에 대해 청구 가능한 이벤트가 포함된 사용량 기반 요금제를 선택합니다.

이 항목에서는 SYSTEM$CREATE_BILLING_EVENT 시스템 함수를 사용하여 청구 가능한 이벤트를 발생시키도록 애플리케이션 패키지를 설정하는 방법을 설명합니다.

애플리케이션 패키지에 청구 가능한 이벤트를 추가하는 방법의 개요

특정 사용 이벤트에 대한 응답으로 청구 가능한 이벤트를 발생시키도록 애플리케이션 패키지를 설정하여 컨슈머가 Snowflake Native App 을 사용하는 양에 따라 요금을 청구할 수 있습니다.

예를 들어 Snowflake Native App 의 저장 프로시저를 호출할 때마다 컨슈머에게 특정 금액을 청구하도록 청구 가능한 이벤트를 추가할 수 있습니다.

애플리케이션 패키지에 청구 가능한 이벤트를 추가하려면 다음을 수행하십시오.

  1. SYSTEM$CREATE_BILLING_EVENT 시스템 함수 호출을 트리거하는 사용 이벤트를 정의하는 저장 프로시저를 만듭니다.

    참고

    이 스테이지에서는 시스템 함수의 출력을 테스트할 수 없습니다. 이 시스템 함수는 컨슈머 계정에 설치된 Snowflake Native App 에서만 호출할 수 있습니다.

  2. 애플리케이션 패키지의 설정 스크립트에 해당 저장 프로시저를 추가합니다.

중요

Snowflake는 이 항목의 예제에서 설명한 대로 애플리케이션의 저장 프로시저 내에서 시스템 함수를 호출하여 발생시킨 청구 가능한 이벤트를 지원합니다.

Snowflake는 컨슈머 활동을 출력하는 테이블 함수나 사용자 정의 함수의 출력을 사용하는 방법 또는 이벤트 테이블에 기록된 원격 분석을 사용하는 방법과 같이, 청구 가능한 이벤트의 기본 요금을 계산하는 다른 방법을 지원하지 않습니다.

제안된 구현이 지원될지 잘 모르시면 Snowflake 계정 담당자에게 문의하십시오.

청구 가능한 이벤트의 예

이 섹션의 예제에서는 일반적인 청구 시나리오에 대해 청구 가능한 이벤트를 발생시키는 저장 프로시저를 만드는 방법을 보여줍니다. 이들 각 예제에서는 SYSTEM$CREATE_BILLING_EVENT 함수 호출하기 에 정의된 createBillingEvent 함수를 호출합니다.

SYSTEM$CREATE_BILLING_EVENT 함수 호출하기

다음 예에서는 저장 프로시저에 SYSTEM$CREATE_BILLING_EVENT 시스템 함수를 호출하는 래퍼 함수를 만드는 방법을 보여줍니다.

참고

JavaScript, Python 또는 Java로 작성된 저장 프로시저에서 이 시스템 함수를 호출할 수 있습니다.

이 예에서는 데이터베이스 db_1 과 스키마 publiccustom_event_billing 이라는 JavaScript 저장 프로시저를 만듭니다. 이 저장 프로시저는 SYSTEM $ CREATE_BILLING_EVENT 시스템 함수에 필요한 형식의 매개 변수에 해당하는 인자를 받는 createBillingEvent 라는 도우미 함수를 만듭니다.

매개 변수와 필요한 형식에 대한 자세한 내용은 SYSTEM$CREATE_BILLING_EVENT 섹션을 참조하십시오.

 CREATE OR REPLACE PROCEDURE db_1.public.custom_event_billing()
 RETURNS NULL
 LANGUAGE JAVASCRIPT
 AS
 $$
   /**
    * Helper method to add a billable event
    * Format timestamps as Unix timestamps in milliseconds
    */

   function createBillingEvent(className, subclassName, startTimestampVal, timestampVal, baseCharge, objects, additionalInfo) {
        try {
            var res = snowflake.createStatement({
            sqlText: `SELECT SYSTEM$CREATE_BILLING_EVENT('${className}',
                                                      '${subclassName}',
                                                      ${startTimestampVal},
                                                      ${timestampVal},
                                                      ${baseCharge},
                                                      '${objects}',
                                                      '${additionalInfo}')`
            }).execute();

            res.next();

            return res.getColumnValue(1);
        } catch(err) {
            return err.message;
        }
    }
$$;
Copy

이 항목의 예제에서는 이 도우미 함수를 호출합니다.

예: 저장 프로시저 호출을 기반으로 청구하기

다음 예에서는 컨슈머가 Snowflake Native App 에서 저장 프로시저를 호출할 때 청구 가능한 이벤트를 발생시키도록 해당 저장 프로시저를 만드는 방법을 보여줍니다.

도우미 함수를 정의하는 동일한 저장 프로시저에서 설정 스크립트에 이 예제 코드를 추가합니다.

...
  //
  // Send a billable event when a stored procedure is called.
  //
  var event_ts = Date.now();
  var billing_quantity = 1.0;
  var base_charge = billing_quantity;
  var objects = "[ \"db_1.public.procedure_1\" ]";
  var retVal = createBillingEvent("PROCEDURE_CALL", "", event_ts, event_ts, base_charge, objects, "");
  // Run the rest of the procedure ...
$$;
Copy

이 예제 코드는 청구 가능한 이벤트를 발생시키는 createBillingEvent 함수를 호출하는 저장 프로시저를 만드는데, 이벤트의 클래스 이름은 PROCEDURE_CALL 이고 기본 요금은 1.0 입니다.

참고

createBillingEvent 함수에 전달되는 인자의 형식이 SYSTEM$CREATE_BILLING_EVENT 시스템 함수에 필요한 형식의 매개 변수와 일치해야 합니다.

예: Snowflake 네이티브 앱에서 사용한 행 수를 기반으로 청구하기

다음 예에서는 컨슈머 계정의 테이블 내에서 사용된 행 수를 기반으로 청구 가능한 이벤트를 발생시키는 저장 프로시저를 만드는 방법을 보여줍니다.

도우미 함수를 정의하는 동일한 저장 프로시저에서 설정 스크립트에 이 예제 코드를 추가합니다.

...
  // Run a query and get the number of rows in the result
  var select_query = "select i from db_1.public.t1";
  res = snowflake.execute ({sqlText: select_query});
  res.next();
  //
  // Send a billable event for rows returned from the select query
  //
  var event_ts = Date.now();
  var billing_quantity = 2.5;
  var base_charge = res.getRowcount() * billing_quantity;
  var objects = "[ \"db_1.public.t1\" ]";
  createBillingEvent("ROWS_CONSUMED", "", event_ts, event_ts, base_charge, objects, "");
  // Run the rest of the procedure ...
$$;
Copy

이 예제 코드는 청구 가능한 이벤트를 발생시키는 createBillingEvent 함수를 호출하는 저장 프로시저를 만드는데, 이벤트의 클래스 이름은 ROWS_CONSUMED 이고 기본 요금은 컨슈머 계정의 db_1.public.t1 테이블에 있는 행 수에 2.5 를 곱한 값으로 계산됩니다.

참고

createBillingEvent 함수에 전달되는 인자의 형식이 SYSTEM$CREATE_BILLING_EVENT 시스템 함수에 필요한 형식의 매개 변수와 일치해야 합니다.

예: 수집된 행 수를 기반으로 청구하기

다음 예에서는 테이블로 수집된 행 수를 기반으로 청구 가능한 이벤트를 발생시키는 저장 프로시저를 만드는 방법을 보여줍니다.

도우미 함수를 정의하는 동일한 저장 프로시저에서 설정 스크립트에 이 예제 코드를 추가합니다.

...
    // Run the merge query
    var merge_query = "MERGE INTO target_table USING source_table ON target_table.i = source_table.i
        WHEN MATCHED THEN UPDATE SET target_table.j = source_table.j
        WHEN NOT MATCHED
        THEN INSERT (i, j)
        VALUES (source_table.i, source_table.j)";
    res = snowflake.execute ({sqlText: merge_query});
    res.next();
    // rows ingested = rows inserted + rows updated
    var numRowsIngested = res.getColumnValue(1) + res.getColumnValue(2);

    //
    // Send a billable event for rows changed by the merge query
    //
    var event_ts = Date.now();
    var billing_quantity = 2.5;
    var base_charge = numRowsIngested * billing_quantity;
    var objects = "[ \"db_1.public.target_table\" ]";
    createBillingEvent("ROWS_CHANGED", "", event_ts, event_ts, base_charge, objects, "");
    // Run the rest of the procedure ...
$$;
Copy

이 예제 코드는 청구 가능한 이벤트를 발생시키는 createBillingEvent 함수를 호출하는 저장 프로시저를 만드는데, 이벤트의 클래스 이름은 ROWS_CHANGED 이고 기본 요금은 db_1.target_table 테이블에서 수집된 행 수에 2.5 를 곱한 값으로 계산됩니다.

참고

createBillingEvent 함수에 전달되는 인자의 형식이 SYSTEM$CREATE_BILLING_EVENT 시스템 함수에 필요한 형식의 매개 변수와 일치해야 합니다.

월간 활성 행 수를 기반으로 청구하기

월간 활성 행 수는 달력상 한 달 이내의 범위에 처음으로 삽입되거나 업데이트된 행의 개수입니다. 일부 공급자는 이 메트릭을 사용하여 한 달에 업데이트된 고유한 행에 대해서만 컨슈머에게 요금을 청구합니다. 대신에 고유 사용자 수를 계산하거나 고유 데이터 로드 위치를 식별하여 기본 요금을 결정하도록 이 예를 수정할 수 있습니다.

다음 예에서는 월간 활성 행 수를 기반으로 청구 가능한 이벤트를 발생시키는 저장 프로시저를 만드는 방법을 보여줍니다. 도우미 함수를 정의하는 동일한 저장 프로시저에서 설정 스크립트에 이 예제 코드를 추가합니다.

...
    //
    // Get monthly active rows
    //
    var monthly_active_rows_query = "
     SELECT
         count(*)
     FROM
         source_table
     WHERE
         source_table.i not in
         (
           SELECT
             i
           FROM
             target_table
           WHERE
             updated_on >= DATE_TRUNC('MONTH', CURRENT_TIMESTAMP)
         )";
    res = snowflake.execute ({sqlText: monthly_active_rows_query});
    res.next();
    var monthlyActiveRows = parseInt(res.getColumnValue(1));
    //
    // Run the merge query and update the updated_on values for the rows
    //
    var merge_query = "
        MERGE INTO
            target_table
        USING
            source_table
        ON
            target_table.i = source_table.i
        WHEN MATCHED THEN
         UPDATE SET target_table.j = source_table.j
                    ,target_table.updated_on = current_timestamp
        WHEN NOT MATCHED THEN
            INSERT (i, j, updated_on) VALUES (source_table.i, source_table.j, current_timestamp)";
    res = snowflake.execute ({sqlText: merge_query});
    res.next();
    //
    // Emit a billable event for monthly active rows changed by the merge query
    //
    var event_ts = Date.now();
    var billing_quantity = 0.02
    var base_charge = monthlyActiveRows * billing_quantity;
    var objects = "[ \"db_1.public.target_table\" ]";
    createBillingEvent("MONTHLY_ACTIVE_ROWS", "", event_ts, event_ts, base_charge, objects, "");
    // Run the rest of the procedure ...
$$;
Copy

이 예제 코드는 고유한 행을 식별하는 병합 쿼리를 사용하여 월간 활성 행 수를 확인하는 저장 프로시저를 만듭니다. 그런 다음 monthlyActiveRows 변수의 값과 billing_quantity 를 사용하여 기본 요금을 계산합니다. 기본 요금은 createBillingEvent 함수로 전달됩니다.

참고

createBillingEvent 함수에 전달되는 인자의 형식이 SYSTEM$CREATE_BILLING_EVENT 시스템 함수에 필요한 형식의 매개 변수와 일치해야 합니다.

설정 스크립트에서 SYSTEM$CREATE_BILLING_EVENT 시스템 함수를 호출하는 저장 프로시저 뒤에 이 저장 프로시저를 추가합니다.

Snowpark Python 예제: 사용한 행 수를 기반으로 청구하기

Snowflake Native App 에서 사용한 행 수를 기반으로 청구하도록 Snowpark Python으로 저장 프로시저를 작성하려면 다음 예를 활용하십시오.

CREATE OR REPLACE PROCEDURE app_schema.billing_event_rows()
   RETURNS STRING
   LANGUAGE PYTHON
   RUNTIME_VERSION = '3.9'
   PACKAGES = ('snowflake-snowpark-python')
   HANDLER = 'run'
   EXECUTE AS OWNER
   AS $$
import time

# Helper method that calls the system function for billing
def createBillingEvent(session, class_name, subclass_name, start_timestamp, timestamp, base_charge, objects, additional_info):
   session.sql(f"SELECT SYSTEM$CREATE_BILLING_EVENT('{class_name}', '{subclass_name}', {start_timestamp}, {timestamp}, {base_charge}, '{objects}', '{additional_info}')").collect()
   return "Success"

# Handler function for the stored procedure
def run(session):
   # insert code to identify monthly active rows and calculate a charge
   try:

      # Run a query to select rows from a table
      query =  "select i from db_1.public.t1"
      res = session.sql(query).collect()

      # Define the price to charge per row
      billing_quantity = 2.5

      # Calculate the base charge based on number of rows in the result
      charge = len(res) * billing_quantity

      # Current time in Unix timestamp (epoch) time in milliseconds
      current_time_epoch = int(time.time() * 1000)

      return createBillingEvent(session, 'ROWS_CONSUMED', '', current_time_epoch, current_time_epoch, charge, '["billing_event_rows"]', '')
   except Exception as ex:
      return "Error " + ex
$$;
Copy

이 예제 코드는 청구 가능한 이벤트를 발생시키기 위해 SYSTEM $ CREATE_BILLING_EVENT 시스템 함수를 호출하는 도우미 메서드는 물론이고 그 도우미 메서드 createBillingEvent 를 호출하는 메서드도 정의하는 저장 프로시저를 만드는데, 이벤트의 클래스 이름은 ROWS_CONSUMED 이고 기본 요금은 컨슈머 계정의 db_1.public.t1 테이블에 있는 행 수에 2.5 US 달러의 가격을 곱한 값으로 계산됩니다.

참고

createBillingEvent 함수에 전달되는 인자의 형식이 SYSTEM$CREATE_BILLING_EVENT 시스템 함수에 필요한 형식의 매개 변수와 일치해야 합니다.

Custom Event Billing 테스트하기

Custom Event Billing을 올바르게 설정하고 사용 이벤트에 대해 청구 가능한 이벤트가 예상대로 발생하는지 확인하려면 다음을 수행하십시오.

  1. 애플리케이션 패키지를 업데이트합니다.

    1. 청구 가능한 이벤트를 발생시키는 저장 프로시저를 포함하도록 설정 스크립트를 업데이트합니다.

    2. 새 설정 스크립트로 애플리케이션 패키지를 업데이트합니다.

    3. 애플리케이션 패키지의 버전 및 릴리스 지시문을 업데이트합니다.

  2. 조직에서 액세스할 수 있는 컨슈머 계정과 애플리케이션 패키지를 공유합니다.

    1. 비공개 목록을 만듭니다.

    2. 목록에 대한 요금제로 Custom Event Billing 을 추가합니다.

    3. 이를 컨슈머 계정과 공유합니다.

    4. Snowsight 를 사용하여 컨슈머 계정에 로그인합니다.

    5. Snowflake Native App 을 설치합니다.

  3. 저장 프로시저가 청구 가능한 이벤트를 제대로 발생시키는지 확인합니다.

  4. 목록이 올바르게 설정되었는지 확인합니다.

참고

Custom Event Billing을 테스트할 때 결제 방법을 설정 해야 하지만, 조직 내 사용량에 대해서는 요금이 청구되지 않습니다.

저장 프로시저가 청구 가능한 이벤트를 발생시키는지 확인하기

목록을 공유한 컨슈머 계정에 로그인한 상태에서 Snowflake Native App 에 추가한 저장 프로시저를 호출합니다.

예를 들어 월간 활성 행 수를 기반으로 청구하도록 생성된 저장 프로시저를 테스트하려면 다음을 수행하십시오.

  1. Snowsight 에서 컨슈머 계정에 로그인합니다.

  2. 워크시트를 열고 컨텍스트를 db_1.public 으로 설정합니다.

  3. 다음 SQL 문을 실행합니다.

    CALL merge_procedure()
    
    Copy

    저장 프로시저가 Success 를 반환하면 코드가 제대로 작동하는 것입니다.

참고

애플리케이션 패키지를 만드는 데 사용한 공급자 계정에서 이러한 SQL 명령을 실행하면 오류가 표시됩니다.

Custom Event Billing 요금제 확인하기

Snowflake Native App 의 컨슈머 경험을 확인하고 목록과 애플리케이션 패키지가 올바로 설정되었는지 확인하려면 공유 SNOWFLAKE 데이터베이스의 DATA_SHARING_USAGE 스키마에서 MARKETPLACE_PAID_USAGE_DAILY 뷰 를 쿼리할 수 있습니다.

참고

뷰의 대기 시간을 감안해 Snowflake Native App 을 처음 사용한 지 2일 이상 지난 후에 이들 쿼리를 실행하십시오.

Snowflake Native App 과 목록에서 청구 가능한 이벤트가 제대로 생성되었는지 확인하려면 목록을 공유한 컨슈머 계정에서 다음 SQL 문을 실행하십시오.

참고

PROVIDER_ACCOUNT_NAME 및 PROVIDER_ORGANIZATION_NAME 값을 공급자 계정의 값으로 바꿉니다.

SELECT listing_global_name,
   listing_display_name,
   charge_type,
   charge
FROM SNOWFLAKE.DATA_SHARING_USAGE.MARKETPLACE_PAID_USAGE_DAILY
WHERE charge_type='MONETIZABLE_BILLING_EVENTS'
      AND PROVIDER_ACCOUNT_NAME = <account_name>
      AND PROVIDER_ORGANIZATION_NAME= <organization_name>;
Copy
+---------------------+------------------------+----------------------------+--------+
| LISTING_GLOBAL_NAME |  LISTING_DISPLAY_NAME  |        CHARGE_TYPE         | CHARGE |
+---------------------+------------------------+----------------------------+--------+
| AAAA0BBB1CC         | Snowy Mountain Listing | MONETIZABLE_BILLING_EVENTS |   18.6 |
+---------------------+------------------------+----------------------------+--------+

목록 요금제와 관련된 모든 세부 정보를 보고 요금제가 애플리케이션 요금과 일치하는지 확인하려면 목록을 공유한 컨슈머 계정에서 다음 SQL 문을 실행하십시오.

참고

앞에 pp 가 붙은 필드는 요금제의 일부로 목록에만 지정된 필드를 나타냅니다.

SELECT
    listing_display_name,
    listing_global_name,
    be.value:display_name::varchar as class_name,
    be.value:class::varchar as class,
    units,
    be.value:billing_unit::varchar as billing_unit,
    unit_price,
    charge,
    be.value:billing_quantity::float as pp_billing_quantity
FROM
    SNOWFLAKE.DATA_SHARING_USAGE.MARKETPLACE_PAID_USAGE_DAILY,
    LATERAL FLATTEN(INPUT => pricing_plan:billing_events) be
WHERE
    charge_type = 'MONETIZABLE_BILLING_EVENTS'
    AND PROVIDER_ACCOUNT_NAME = <account_name>
    AND PROVIDER_ORGANIZATION_NAME= <organization_name>;
Copy
+------------------------+---------------------+-------------+---------------+-------+--------------+------------+--------+---------------------+
|  LISTING_DISPLAY_NAME  | LISTING_GLOBAL_NAME | CLASS_NAME  |     CLASS     | UNITS | BILLING_UNIT | UNIT_PRICE | CHARGE | PP_BILLING_QUANTITY |
+------------------------+---------------------+-------------+---------------+-------+--------------+------------+--------+---------------------+
| Snowy Mountain Listing | AAAA0BBB1CC         | Active Rows | ROWS_CONSUMED |  18.6 | ROW          |          1 |   18.6 |                   1 |
+------------------------+---------------------+-------------+---------------+-------+--------------+------------+--------+---------------------+