Ajout d’événements facturables à un paquet d’application

Lorsque vous utilisez Custom Event Billing pour une Snowflake Native App, vous pouvez facturer des types spécifiques d’utilisation de l’application en plus des plans tarifaires existants basés sur l’utilisation. Pour mettre cela en place, vous devez effectuer deux étapes de haut niveau :

  1. Configurez votre paquet d’application pour qu’il émette des événements facturables en suivant les étapes de cette rubrique.

  2. Choisissez un plan de tarification basé sur l’utilisation avec des événements facturables pour l’annonce que vous utilisez pour publier votre Snowflake Native App auprès des consommateurs.

Cette rubrique décrit comment configurer votre paquet d’application pour qu’elle émette des événements facturables à l’aide de la fonction système SYSTEM$CREATE_BILLING_EVENT.

Vue d’ensemble de l’ajout d’événements facturables à un paquet d’application

Vous pouvez configurer votre paquet d’application pour qu’il émette des événements facturables en réponse à des événements d’utilisation spécifiques, de sorte que vous puissiez facturer les consommateurs en fonction de l’utilisation qu’ils font de votre Snowflake Native App.

Par exemple, vous pouvez ajouter un événement facturable pour facturer à un consommateur un montant spécifique pour chaque appel à une procédure stockée dans votre Snowflake Native App.

Pour ajouter des événements facturables à un paquet d’application, procédez comme suit :

  1. Créez des procédures stockées pour définir les événements d’utilisation qui déclenchent des appels à la fonction système SYSTEM$CREATE_BILLING_EVENT.

    Note

    Vous ne pouvez pas tester la sortie de la fonction système à ce stade. Cette fonction système ne peut être appelée qu’à partir d’une Snowflake Native App installée sur un compte consommateur.

  2. Ajoutez ces procédures stockées au script d’installation du paquet d’application.

Important

Snowflake prend en charge les événements facturables qui sont émis en appelant la fonction système au sein d’une procédure stockée dans l’application, comme indiqué dans les exemples de cette rubrique.

Snowflake ne prend pas en charge d’autres méthodes de calcul des frais de base pour les événements facturables, telles que les méthodes qui utilisent la sortie d’une table ou d’une fonction définie par l’utilisateur qui renvoie l’activité du consommateur ou les méthodes utilisant la télémétrie enregistrée dans un table d’événements.

Si vous ne savez pas si la mise en œuvre proposée sera prise en charge, contactez votre représentant de compte Snowflake.

Exemples d’événements facturables

Les exemples de cette section montrent comment créer des procédures stockées pour émettre des événements facturables dans le cadre de scénarios de facturation courants. Chacun de ces exemples appelle la fonction createBillingEvent définie dans Appel de la fonction SYSTEM$CREATE_BILLING_EVENT.

Appel de la fonction SYSTEM$CREATE_BILLING_EVENT

L’exemple suivant montre comment créer une fonction wrapper dans une procédure stockée pour appeler la fonction système SYSTEM$CREATE_BILLING_EVENT.

Note

Vous pouvez appeler cette fonction système dans une procédure stockée écrite en JavaScript, Python ou Java.

Cet exemple crée une procédure stockée JavaScript nommée custom_event_billing dans la base de données db_1 et le schéma public. La procédure stockée crée une fonction d’aide appelée createBillingEvent qui prend des arguments correspondant aux paramètres typés attendus par la fonction système SYSTEM$CREATE_BILLING_EVENT.

Pour plus de détails sur les paramètres et les types requis, voir 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

Les exemples de cette rubrique font appel à cette fonction d’aide.

Exemple : facturation basée sur les appels à une procédure stockée

L’exemple suivant montre comment créer une procédure stockée qui émet un événement facturable lorsqu’un consommateur appelle cette procédure stockée dans une Snowflake Native App.

Ajoutez ce code d’exemple à votre script d’installation dans la même procédure stockée que celle qui définit la fonction d’aide :

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

Cet exemple de code crée une procédure stockée qui appelle la fonction createBillingEvent pour émettre un événement facturable avec le nom de classe PROCEDURE_CALL et des frais de base de 1.0.

Note

Les types des arguments transmis à la fonction createBillingEvent doivent correspondre aux paramètres typés attendus par la fonction du système SYSTEM$CREATE_BILLING_EVENT.

Exemple : facturation basée sur les lignes consommées par une application native Snowflake

L’exemple suivant montre comment créer une procédure stockée pour émettre un événement facturable basé sur le nombre de lignes consommées dans une table du compte consommateur.

Ajoutez ce code d’exemple à votre script d’installation dans la même procédure stockée que celle qui définit la fonction d’aide :

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

Cet exemple de code crée une procédure stockée qui appelle la fonction createBillingEvent pour émettre un événement facturable avec le nom de classe ROWS_CONSUMED et des frais de base calculés de 2.5 multipliés par le nombre de lignes de la table db_1.public.t1 dans le compte consommateur.

Note

Les types des arguments transmis à la fonction createBillingEvent doivent correspondre aux paramètres typés attendus par la fonction du système SYSTEM$CREATE_BILLING_EVENT.

Exemple : facturation basée sur le nombre de lignes ingérées

L’exemple suivant montre comment créer une procédure stockée pour émettre un événement facturable en fonction du nombre de lignes ingérées dans une table.

Ajoutez ce code d’exemple à votre script d’installation dans la même procédure stockée que celle qui définit la fonction d’aide :

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

Cet exemple de code crée une procédure stockée qui appelle la fonction createBillingEvent pour émettre un événement facturable avec le nom de classe ROWS_CHANGED et un tarif de base calculé de 2.5 multiplié par le nombre de lignes ingérées dans la table db_1.target_table.

Note

Les types des arguments transmis à la fonction createBillingEvent doivent correspondre aux paramètres typés attendus par la fonction du système SYSTEM$CREATE_BILLING_EVENT.

Facturation basée sur les lignes actives mensuelles

Les lignes actives mensuelles correspondent au nombre de lignes insérées ou mises à jour pour la première fois au cours d’un mois civil. Certains fournisseurs utilisent cette métrique pour ne facturer aux consommateurs que les lignes uniques mises à jour au cours d’un mois. Vous pouvez modifier cet exemple pour compter plutôt les utilisateurs uniques, ou identifier un emplacement unique de chargement de données pour déterminer un tarif de base.

L’exemple suivant montre comment créer une procédure stockée pour déclencher un événement facturable en fonction du nombre de lignes actives mensuelles. Ajoutez ce code d’exemple à votre script d’installation dans la même procédure stockée que celle qui définit la fonction d’aide :

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

Cet exemple de code crée une procédure stockée qui détermine le nombre de lignes actives mensuelles à l’aide d’une requête de fusion pour identifier les lignes uniques. L’exemple calcule ensuite le tarif de base en utilisant la valeur de la variable monthlyActiveRows et la billing_quantity. Le tarif de base est ensuite transmis à la fonction createBillingEvent.

Note

Les types des arguments transmis à la fonction createBillingEvent doivent correspondre aux paramètres typés attendus par la fonction du système SYSTEM$CREATE_BILLING_EVENT.

Dans votre script d’installation, ajoutez cette procédure stockée après la procédure stockée qui appelle la fonction système SYSTEM$CREATE_BILLING_EVENT.

Exemple Snowpark Python : facturation basée sur les lignes consommées

Si vous voulez écrire votre procédure stockée en Snowpark Python pour facturer en fonction des lignes consommées par votre Snowflake Native App, utilisez l’exemple suivant :

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

Cet exemple de code crée une procédure stockée qui définit une méthode d’aide qui appelle la fonction système SYSTEM$CREATE_BILLING_EVENT , ainsi qu’une méthode qui appelle cette méthode d’aide, createBillingEvent, pour émettre un événement facturable avec le nom de classe ROWS_CONSUMED et des frais de base calculés en multipliant un prix de 2.5 dollars US par le nombre de lignes de la table db_1.public.t1 dans le compte consommateur.

Note

Les types des arguments transmis à la fonction createBillingEvent doivent correspondre aux paramètres typés attendus par la fonction du système SYSTEM$CREATE_BILLING_EVENT.

Test de Custom Event Billing

Pour vous assurer que vous avez correctement configuré Custom Event Billing et que les événements facturables sont émis pour les événements d’utilisation comme vous le souhaitez, procédez comme suit :

  1. Mettez à jour votre paquet d’application :

    1. Mettez à jour votre script d’installation pour inclure les procédures stockées qui émettent des événements facturables.

    2. Mettez à jour votre paquet d’application avec le nouveau script d’installation.

    3. Mettez à jour la directive de version et à la publication de votre paquet d’application.

  2. Partagez le paquet d’application avec un compte consommateur de votre organisation auquel vous avez accès :

    1. Créez une annonce privée.

    2. Ajoutez Custom Event Billing comme plan tarifaire pour l’annonce.

    3. Partagez-le avec le compte consommateur.

    4. Connectez-vous au compte consommateur à l’aide de Snowsight.

    5. Installez l”Snowflake Native App.

  3. Confirmez que les procédures stockées émettent avec succès des événements facturables.

  4. Confirmez que l’annonce est correctement établie.

Note

Lorsque vous testez Custom Event Billing, vous devez configurer une méthode de paiement mais vous ne serez pas facturé pour l’utilisation au sein de votre organisation.

Valider si les procédures stockées génèrent des événements facturables

Tout en étant connecté au compte consommateur avec lequel vous avez partagé votre annonce, appelez les procédures stockées que vous avez ajoutées à votre Snowflake Native App.

Par exemple, pour tester la procédure stockée créée pour la facturation sur la base des lignes actives mensuelles, procédez comme suit :

  1. Connectez-vous au compte consommateur dans Snowsight.

  2. Ouvrez une feuille de calcul et définissez le contexte sur db_1.public.

  3. Exécutez la instruction SQL suivante :

    CALL merge_procedure()
    
    Copy

    Si la procédure stockée renvoie Success, votre code fonctionne.

Note

Si vous exécutez ces commandes SQL dans le compte fournisseur que vous avez utilisé pour créer le paquet d’application, une erreur apparaît.

Valider le plan tarifaire de Custom Event Billing

Pour valider l’expérience consommateur d’une Snowflake Native App et confirmer que votre annonce et votre paquet d’application sont correctement configurés, vous pouvez interroger la vue MARKETPLACE_PAID_USAGE_DAILY dans le schéma DATA_SHARING_USAGE de la base de données partagée SNOWFLAKE.

Note

En raison du temps de latence dans la vue, exécutez ces requêtes au moins deux jours après avoir utilisé l”Snowflake Native App pour la première fois.

Pour confirmer que les événements facturables sont bien générés par une Snowflake Native App et une annonce, exécutez l’instruction SQL suivante sur le compte consommateur avec lequel vous avez partagé l’annonce :

Note

Remplacez les valeurs PROVIDER_ACCOUNT_NAME et PROVIDER_ORGANIZATION_NAME par celles du compte fournisseur.

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

Pour voir tous les détails associés au plan de tarification de l’annonce et valider que le plan correspond aux frais de l’application, exécutez l’instruction SQL suivante dans le compte consommateur avec lequel vous avez partagé l’annonce :

Note

Les champs précédés de pp représentent les champs spécifiés uniquement dans l’annonce comme faisant partie du plan tarifaire.

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