Émettre des événements de trace en Java

Vous pouvez utiliser la classe com.snowflake.telemetry.Telemetry de la bibliothèque de l”API de télémétrie Snowflake pour émettre des événements de trace à partir d’un gestionnaire de fonction ou de procédure écrit en Java. La classe Telemetry est incluse dans Snowflake.

Note

L’utilisation de la bibliothèque de télémétrie Snowflake ajoute d’autres bibliothèques à l’environnement d’exécution de votre fonction ou procédure. Pour plus d’informations, voir Dépendances du paquet de télémétrie Snowflake.

Pour plus d’informations sur l’inclusion de la bibliothèque de télémétrie lors de l’empaquetage de votre code avec Maven, voir Configuration de votre environnement Java et Scala pour l’utilisation de la classe de télémétrie.

Vous pouvez accéder aux données de trace stockées en exécutant une commande SELECT sur la table des événements. Pour plus d’informations, voir Affichage des données de trace.

Note

Pour les lignes directrices à garder à l’esprit lors de l’ajout d’événements de trace, voir Lignes directrices générales pour l’ajout d’événements de trace.

Pour des informations générales sur la configuration de la journalisation et la récupération des messages dans Snowflake, voir Enregistrement de messages à partir de fonctions et de procédures.

Avant de journaliser à partir d’un code, vous devez :

Ajout d’une prise en charge de l’API de télémétrie

Pour utiliser les méthodes Telemetry, vous devez mettre la bibliothèque de télémétrie Snowflake, qui est incluse dans Snowflake, à la disposition de votre code de gestionnaire.

  • Dans la clause PACKAGES de votre instruction CREATE PROCEDURE ou CREATE FUNCTION, incluez le paquet com.snowflake:telemetry. La clause PACKAGES rend l’API de télémétrie Snowflake incluse disponible pour votre code.

    Le code de l’exemple suivant utilise la clause PACKAGES pour référencer la bibliothèque de télémétrie ainsi que la bibliothèque Snowpark (qui est requise pour les procédures stockées écrites en Java - pour plus d’informations, voir Écriture de procédures stockées en Java).

    CREATE OR REPLACE PROCEDURE MYPROC(...)
      RETURNS ...
      LANGUAGE JAVA
      ...
      PACKAGES = ('com.snowflake:snowpark:latest', 'com.snowflake:telemetry:latest')
      ...
    
    Copy
  • Importez le paquet com.snowflake.telemetry dans le code de votre gestionnaire Java.

    import com.snowflake.telemetry.Telemetry;
    
    Copy

Ajout d’événements de trace

Vous pouvez ajouter des événements de trace en appelant la méthode Telemetry.addEvent et en indiquant le nom de l’événement. Il est également possible d’associer des attributs (paires clé-valeur) à un événement.

La méthode addEvent a les signatures suivantes :

public static void addEvent(String name)
public static void addEvent(String name, Attributes attributes)
Copy

Le code de l’exemple suivant ajoute un événement appelé testEvent et lui associe deux attributs : key et result.

// Adding an event without attributes.
Telemetry.addEvent("testEvent");

// Adding an event with attributes.
Attributes eventAttributes = Attributes.of(
  AttributeKey.stringKey("key"), "run",
  AttributeKey.longKey("result"), Long.valueOf(123));
Telemetry.addEvent("testEventWithAttributes", eventAttributes);
Copy

L’ajout de ces événements donne lieu à deux lignes dans la table des événements, chacune avec une valeur différente dans la colonne RECORD :

{
  "name": "testEvent"
}
Copy
{
  "name": "testEventWithAttributes"
}
Copy

La ligne d’événement testEventWithAttributes comprend les attributs suivants dans la colonne RECORD_ATTRIBUTES de la ligne :

{
  "key": "run",
  "result": 123
}
Copy

Ajout d’attributs de span

Vous pouvez définir des attributs (paires clé-valeur) associés aux spans en appelant la méthode Telemetry.setSpanAttribute.

La méthode setSpanAttribute a les signatures suivantes :

public static void setSpanAttribute(String key, boolean value)
public static void setSpanAttribute(String key, long value)
public static void setSpanAttribute(String key, double value)
public static void setSpanAttribute(String key, String value)
Copy

Pour plus de détails sur les spans, voir Comment Snowflake représente les événements de trace.

Le code de l’exemple suivant crée quatre attributs et définit leurs valeurs :

// Setting span attributes.
Telemetry.setSpanAttribute("example.boolean", true);
Telemetry.setSpanAttribute("example.long", 2L);
Telemetry.setSpanAttribute("example.double", 2.5);
Telemetry.setSpanAttribute("example.string", "testAttribute");
Copy

La définition de ces attributs se traduit par les éléments suivants dans la colonne RECORD_ATTRIBUTES de la table des événements :

{
  "example.boolean": true,
  "example.long": 2,
  "example.double": 2.5,
  "example.string": "testAttribute"
}
Copy

Ajout de spans personnalisés

Note

La prise en charge des spans personnalisés est une fonctionnalité en avant-première disponible pour tous les comptes.

Vous pouvez ajouter des spans personnalisés distincts du span par défaut créé par Snowflake. Pour plus de détails sur les spans personnalisés, voir Ajout de spans personnalisés à une trace.

Le code dans l’exemple suivant utilise l’API OpenTelemetry et l’API OpenTelemetry Context Propagation pour créer un nouveau span my.span. Il ajoute ensuite un événement avec des attributs au nouveau span. Enfin, le code termine le span pour que les données d’événement du span soient capturées dans la table d’événements. Si le code n’appelle pas la méthode Span.end, les données ne sont pas capturées dans la table des événements.

CREATE OR REPLACE FUNCTION customSpansJavaExample() RETURNS STRING
LANGUAGE JAVA
PACKAGES = ('com.snowflake:telemetry:latest')
HANDLER = 'MyJavaClass.run'
as
$$
  import com.snowflake.telemetry.Telemetry;
  import io.opentelemetry.api.common.AttributeKey;
  import io.opentelemetry.api.common.Attributes;
  import io.opentelemetry.api.GlobalOpenTelemetry;
  import io.opentelemetry.api.trace.Tracer;
  import io.opentelemetry.api.trace.Span;
  import io.opentelemetry.context.Scope;

  class MyJavaClass {
    public static String run() {
      Tracer tracer = GlobalOpenTelemetry.getTracerProvider().get("my.tracer");
      Span span = tracer.spanBuilder("my.span").startSpan();
      try (Scope scope = span.makeCurrent()) {
        // Do processing, adding events that will be captured in a my.span.

        // Add an event with attributes.
        Attributes eventAttributes = Attributes.of(
          AttributeKey.stringKey("key"), "run",
          AttributeKey.longKey("result"), Long.valueOf(123));

        span.addEvent("testEventWithAttributes", eventAttributes);
        span.setAttribute("testAttribute", "value");

      } finally {
        span.end();
      }
      return "success";
    }
  }
$$;
Copy

Exemples Java

Exemple de procédure stockée

CREATE OR REPLACE PROCEDURE do_tracing()
RETURNS STRING
LANGUAGE JAVA
RUNTIME_VERSION = '11'
PACKAGES=('com.snowflake:snowpark:latest', 'com.snowflake:telemetry:latest')
HANDLER = 'ProcedureHandler.run'
AS
$$
import com.snowflake.snowpark_java.Session;
import com.snowflake.telemetry.Telemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;

public class ProcedureHandler {

  public String run(Session session) {

    // Set span attribute.
    Telemetry.setSpanAttribute("example.proc.do_tracing", "begin");

    // Add an event without attributes.
    Telemetry.addEvent("run_method_start");

    // Add an event with attributes.
    Attributes eventAttributes = Attributes.of(
      AttributeKey.stringKey("example.method.name"), "run",
      AttributeKey.longKey("example.long"), Long.valueOf(123));
    Telemetry.addEvent("event_with_attributes", eventAttributes);

    // Set span attribute.
    Telemetry.setSpanAttribute("example.proc.do_tracing", "complete");

    return "SUCCESS";
  }
}
$$;
Copy

Exemple UDF

CREATE OR REPLACE FUNCTION add_two_numbers(A FLOAT, B FLOAT) RETURNS FLOAT
LANGUAGE JAVA
PACKAGES=('com.snowflake:telemetry:latest')
HANDLER = 'ScalarFunctionHandler.run'
AS
$$
import com.snowflake.telemetry.Telemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;

class ScalarFunctionHandler {

  public static Double run(Double d0, Double d1) {

    // Set span attribute.
    Telemetry.setSpanAttribute("example.func.add_two_numbers", "begin");

    // Add an event without attributes.
    Telemetry.addEvent("run_method_start");

    // Add an event with attributes.
    Attributes eventAttributes = Attributes.of(
      AttributeKey.stringKey("example.method.name"), "run",
      AttributeKey.longKey("example.long"), Long.valueOf(123));
    Telemetry.addEvent("event_with_attributes", eventAttributes);

    Double response = d0 == null || d1 == null ? null : (d0 + d1);

    // Set span attribute.
    Telemetry.setSpanAttribute("example.func.add_two_numbers.response", response);
    Telemetry.setSpanAttribute("example.func.add_two_numbers", "complete");

    return response;
  }
}
$$;
Copy

Exemple UDTF

CREATE OR REPLACE FUNCTION digits_of_number(x int)
RETURNS TABLE(result int)
LANGUAGE JAVA
PACKAGES=('com.snowflake:telemetry:latest')
HANDLER = 'TableFunctionHandler'
AS
$$
import com.snowflake.telemetry.Telemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import java.util.stream.Stream;

public class TableFunctionHandler {

  public TableFunctionHandler() {
    // Set span attribute.
    Telemetry.setSpanAttribute("example.func.digits_of_number", "begin");
  }

  static class OutputRow {
    public int result;

    public OutputRow(int result) {
      this.result = result;
    }
  }

  public static Class getOutputClass() {
    return OutputRow.class;
  }

  public Stream<OutputRow> process(int input) {

    // Add an event with attributes.
    Attributes eventAttributes = Attributes.of(
      AttributeKey.longKey("example.received.value"), Long.valueOf(input));
    Telemetry.addEvent("digits_of_number", eventAttributes);

    Stream.Builder<OutputRow> stream = Stream.builder();
    while (input > 0) {

      stream.add(new OutputRow(input %10));
      input /= 10;
    }

    // Set span attribute.
    Telemetry.setSpanAttribute("example.func.digits_of_number", "complete");

    return stream.build();
  }
}
$$;
Copy