É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 :
Mettre en place une table d’événements pour collecter les messages enregistrés par le code du gestionnaire.
Pour plus d’informations, voir Aperçu de la table d’événements.
Assurez-vous que le niveau de trace est défini de manière à ce que les données souhaitées soient stockées dans la table des événements.
Pour plus d’informations, voir Définition des niveaux de journalisation, des métriques et du traçage.
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') ...
Importez le paquet
com.snowflake.telemetry
dans le code de votre gestionnaire Java.import com.snowflake.telemetry.Telemetry;
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)
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);
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"
}
{
"name": "testEventWithAttributes"
}
La ligne d’événement testEventWithAttributes
comprend les attributs suivants dans la colonne RECORD_ATTRIBUTES de la ligne :
{
"key": "run",
"result": 123
}
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)
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");
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"
}
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";
}
}
$$;
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";
}
}
$$;
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;
}
}
$$;
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();
}
}
$$;