Como adicionar eventos faturáveis a um aplicativo

Quando você usa o Custom Event Billing para um aplicativo, pode cobrar por tipos específicos de uso do aplicativo, além dos planos de preços baseados em uso existentes. Para configurá-lo, você deve executar duas etapas de alto nível:

  1. Configure seu aplicativo para emitir eventos faturáveis seguindo as etapas deste tópico.

  2. Selecione um plano de preços baseado em uso com eventos faturáveis para a listagem que você usa para publicar seu aplicativo para os consumidores.

Este tópico descreve como configurar seu aplicativo para emitir eventos faturáveis usando a função do sistema SYSTEM$CREATE_BILLING_EVENT.

Visão geral da adição de eventos faturáveis a um aplicativo

Você pode configurar seu aplicativo para emitir eventos faturáveis em resposta a eventos de uso específicos para que possa cobrar dos consumidores com base no quanto eles usam seu aplicativo.

Por exemplo, você pode adicionar um evento faturável para cobrar de um consumidor um valor específico para cada chamada de um procedimento armazenado em seu aplicativo.

Para adicionar eventos faturáveis ao seu aplicativo, faça o seguinte:

  1. Crie procedimentos armazenados para definir quais eventos de uso acionam chamadas para a função do sistema SYSTEM$CREATE_BILLING_EVENT.

    Nota

    Você não pode testar a saída da função do sistema neste estágio. Esta função do sistema só pode ser chamada a partir de um aplicativo instalado em uma conta de consumidor.

  2. Adicione esses procedimentos armazenados ao script de configuração de seu aplicativo.

Importante

O Snowflake oferece suporte a eventos faturáveis que são emitidos chamando a função do sistema em um procedimento armazenado no aplicativo, conforme descrito pelos exemplos neste tópico.

O Snowflake não oferece suporte a outros métodos de cálculo da cobrança básica para eventos faturáveis, como métodos que usam a saída de uma tabela ou função definida pelo usuário que gera atividade do consumidor ou métodos que usam telemetria registrada em uma tabela de eventos.

Se você não tiver certeza se uma implementação proposta terá suporte, entre em contato com seu representante da conta Snowflake.

Exemplos de eventos faturáveis

Os exemplos nesta seção mostram como criar procedimentos armazenados para emitir eventos faturáveis para cenários de cobrança comuns. Cada um desses exemplos chama a função createBillingEvent definida em Chamada da função SYSTEM$CREATE_BILLING_EVENT.

Chamada da função SYSTEM$CREATE_BILLING_EVENT

O exemplo a seguir mostra como criar uma função wrapper em um procedimento armazenado para chamar a função do sistema SYSTEM$CREATE_BILLING_EVENT.

Nota

Você pode chamar essa função do sistema em um procedimento armazenado escrito em JavaScript, Python ou Java.

Este exemplo cria um procedimento armazenado JavaScript chamado custom_event_billing no banco de dados db_1 e esquema public. O procedimento armazenado cria uma função auxiliar chamada createBillingEvent que recebe argumentos que correspondem aos parâmetros digitados esperados pela função do sistema SYSTEM$CREATE_BILLING_EVENT.

Para obter mais detalhes sobre os parâmetros e os tipos necessários, consulte 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
    */

   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

Os exemplos neste tópico chamam essa função auxiliar.

Exemplo: cobrança baseada em chamadas para um procedimento armazenado

O exemplo a seguir mostra como criar um procedimento armazenado para emitir um evento faturável quando um consumidor chama esse procedimento armazenado em um aplicativo.

Adicione este código de exemplo ao seu script de configuração no mesmo procedimento armazenado que define a função auxiliar:

...
  //
  // 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

Este código de exemplo cria um procedimento armazenado que chama a função createBillingEvent para emitir um evento faturável com o nome da classe PROCEDURE_CALL e uma cobrança básica de 1.0.

Nota

Os tipos de argumentos passados para a função createBillingEvent deve corresponder aos parâmetros digitados esperados pela função do sistema SYSTEM$CREATE_BILLING_EVENT.

Exemplo: faturamento baseado em linhas consumidas por um aplicativo

O exemplo a seguir mostra como criar um procedimento armazenado para emitir um evento faturável com base no número de linhas consumidas em uma tabela na conta do consumidor.

Adicione este código de exemplo ao seu script de configuração no mesmo procedimento armazenado que define a função auxiliar:

...
  // 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

Este código de exemplo cria um procedimento armazenado que chama o createBillingEvent função para emitir um evento faturável com o nome da classe ROWS_CONSUMED e uma cobrança base calculada de 2.5 multiplicado pelo número de linhas no db_1.public.t1 tabela na conta do consumidor.

Nota

Os tipos de argumentos passados para a função createBillingEvent deve corresponder aos parâmetros digitados esperados pela função do sistema SYSTEM$CREATE_BILLING_EVENT.

Exemplo: cobrança com base no número de linhas ingeridas

O exemplo a seguir mostra como criar um procedimento armazenado para emitir um evento faturável com base no número de linhas ingeridas em uma tabela.

Adicione este código de exemplo ao seu script de configuração no mesmo procedimento armazenado que define a função auxiliar:

...
    // 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

Este código de exemplo cria um procedimento armazenado que chama a função createBillingEvent para emitir um evento faturável com o nome da classe ROWS_CHANGED e uma cobrança base calculada de 2.5 multiplicado pelo número de linhas ingeridas na tabela db_1.target_table.

Nota

Os tipos de argumentos passados para a função createBillingEvent deve corresponder aos parâmetros digitados esperados pela função do sistema SYSTEM$CREATE_BILLING_EVENT.

Faturamento baseado em linhas ativas mensais

As linhas ativas mensais são o número de linhas inseridas ou atualizadas pela primeira vez em um mês de calendário. Alguns provedores usam essa métrica para cobrar apenas dos consumidores por linhas exclusivas atualizadas em um mês. Você pode modificar este exemplo para contar usuários exclusivos ou identificar um local de carregamento de dados exclusivo para determinar uma cobrança básica.

O exemplo a seguir mostra como criar um procedimento armazenado para emitir um evento faturável com base no número de linhas ativas mensais. Adicione este código de exemplo ao seu script de configuração no mesmo procedimento armazenado que define a função auxiliar:

...
    //
    // 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

Este código de exemplo cria um procedimento armazenado que determina o número de linhas ativas mensais usando uma consulta de mesclagem para identificar linhas exclusivas. O exemplo então calcula a cobrança base usando o valor da variável monthlyActiveRows e o billing_quantity. A cobrança básica é então passada para a função createBillingEvent.

Nota

Os tipos de argumentos passados para a função createBillingEvent deve corresponder aos parâmetros digitados esperados pela função do sistema SYSTEM$CREATE_BILLING_EVENT.

Em seu script de configuração, adicione este procedimento armazenado após o procedimento armazenado que chama a função do sistema SYSTEM$CREATE_BILLING_EVENT.

Exemplo do Snowpark Python: cobrança baseada em linhas consumidas

Se você deseja escrever seu procedimento armazenado no Snowpark Python para faturar com base nas linhas consumidas pelo seu aplicativo, use o seguinte exemplo:

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
      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

Este código de exemplo cria um procedimento armazenado que define um método auxiliar que chama o SYSTEM$CREATE_BILLING_EVENT função do sistema, bem como um método que chama esse método auxiliar, createBillingEvent, para emitir um evento faturável com o nome da classe ROWS_CONSUMED e uma taxa básica calculada multiplicando um preço de 2.5 US dólares pelo número de linhas no db_1.public.t1 tabela na conta do consumidor.

Nota

Os tipos de argumentos passados para a função createBillingEvent deve corresponder aos parâmetros digitados esperados pela função do sistema SYSTEM$CREATE_BILLING_EVENT.

Como testar o Custom Event Billing

Para certificar-se de que você configurou o Custom Event Billing corretamente e de que os eventos faturáveis sejam emitidos para eventos de uso conforme o esperado, faça o seguinte:

  1. Atualize seu pacote de aplicativo:

    1. Atualize seu script de configuração para incluir os procedimentos armazenados que emitam eventos faturáveis.

    2. Atualize seu pacote de aplicativo com o novo script de configuração.

    3. Atualize a versão e a diretriz de versão para seu pacote de aplicativo.

  2. Compartilhe o pacote de aplicativo com uma conta de consumidor em sua organização à qual você tenha acesso para:

    1. Criar uma listagem privada.

    2. Adicionar Custom Event Billing como o plano de preços para a listagem.

    3. Compartilhe com a conta do consumidor.

    4. Entre na conta do consumidor usando Snowsight.

    5. Instale o aplicativo.

  3. Confirme se os procedimentos armazenados emitem com sucesso eventos faturáveis.

  4. Confirme se a listagem está configurada corretamente.

Nota

Ao testar o Custom Event Billing, você deve configurar o Stripe mas você não será cobrado pelo uso em sua organização.

Validação se os procedimentos armazenados podem emitir eventos faturáveis

Enquanto estiver conectado à conta do consumidor com a qual você compartilhou seu aplicativo, chame os procedimentos armazenados que você adicionou ao seu aplicativo.

Por exemplo, para testar o procedimento armazenado criado para cobrança baseada em linhas ativas mensais, faça o seguinte:

  1. Entre na conta do consumidor em Snowsight.

  2. Abra uma planilha e defina o contexto para db_1.public.

  3. Execute a seguinte instrução SQL:

    CALL merge_procedure()
    
    Copy

    Se o procedimento armazenado retornar Success, seu código está funcionando.

Nota

Se você executar estes comandos SQL na conta do provedor que você usou para desenvolver o aplicativo, você verá um erro.

Validação do plano de preços do Custom Event Billing

Para validar a experiência do consumidor de seu aplicativo e confirmar que sua listagem e aplicativo estão configurados corretamente, você pode consultar a exibição MARKETPLACE_PAID_USAGE_DAILY no esquema DATA_SHARING_USAGE do banco de dados SNOWFLAKE compartilhado.

Nota

Devido à latência na exibição, execute essas consultas pelo menos dois dias após o primeiro uso do aplicativo.

Para confirmar se os eventos faturáveis foram gerados com êxito por seu aplicativo e listagem, execute a seguinte instrução SQL na conta do consumidor com a qual você compartilhou seu aplicativo:

Nota

Substitua os valores PROVIDER_ACCOUNT_NAME e PROVIDER_ORGANIZATION_NAME pelos da conta do provedor.

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 |
+---------------------+------------------------+----------------------------+--------+

Para ver todos os detalhes associados ao plano de preços da listagem e validar se o plano corresponde às cobranças do aplicativo, execute a seguinte instrução SQL na conta do consumidor com a qual você compartilhou seu aplicativo:

Nota

Os campos anexados com pp representam campos especificados apenas na listagem como parte do plano de preços.

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 |
+------------------------+---------------------+-------------+---------------+-------+--------------+------------+--------+---------------------+