Configurez les clients OpenTelemetry (OTLP) pour envoyer des données à Unity Catalog
Bêta
Cette fonctionnalité est en Bêta.
Zerobus Ingest inclut un endpoint OpenTelemetry Protocol (OTLP). Vous pouvez envoyer des traces, des logs et des métriques directement dans les tables Delta Unity Catalog en utilisant les SDK et collecteurs OpenTelemetry standard, sans bibliothèques personnalisées. Cette page couvre la récupération de votre endpoint, la création de tables cibles, la configuration d'un Service Principal et l'envoi de vos premières données de télémétrie.
Obtenez votre endpoint Zerobus Ingest et votre URL de Workspace
L'URL de l'Endpoint suit ce modèle :
- URL du workspace :
https://<databricks-instance>.cloud.databricks.com - Endpoint du serveur :
<workspace-id>.zerobus.<region>.cloud.databricks.com
Par exemple :
- URL du workspace :
https://dbc-a1b2c3d4-e5f6.cloud.databricks.com - Endpoint du serveur :
1234567890123456.zerobus.us-west-2.cloud.databricks.com
Pour plus de détails sur la recherche de votre ID de workspace, URL et région, consultez Obtenez votre URL de workspace et votre endpoint Zerobus Ingest.
Créer des tables cibles dans Unity Catalog
Vous devez créer les tables Delta cibles avant d'envoyer les données. Chaque type de signal (traces, Logs, métriques) nécessite sa propre table avec un schéma spécifique.
Prérequis :
- DBR 15.3 ou version ultérieure : requis pour interroger des données de type
VARIANT. - (Facultatif) DBR 17.2 ou supérieur : requis pour le déchiquetage de variantes qui améliore les performances des query. Pour plus d'informations, consultez Utiliser le déchiquetage de variantes pour optimiser les performances
Pour configurer vos tables :
- Remplacez
<catalog>.<schema>.<prefix>par votre catalogue, votre schéma et le préfixe de nom de table souhaité. - Remplacez
<service-principal-uuid>par l'ID d'application (UUID) de votre service principal. Pour le trouver, accédez à l' tab Configurations du service principal dans votre Databricks workspace. - Exécutez le script dans Databricks SQL.
Tableau des portées
La table des spans stocke les données de trace distribuées, y compris le timing, le statut et les attributs pour chaque span.
CREATE TABLE <catalog>.<schema>.<prefix>_otel_spans (
record_id STRING,
time TIMESTAMP,
date DATE,
service_name STRING,
trace_id STRING,
span_id STRING,
trace_state STRING,
parent_span_id STRING,
flags INT,
name STRING,
kind STRING,
start_time_unix_nano LONG,
end_time_unix_nano LONG,
attributes VARIANT,
dropped_attributes_count INT,
events ARRAY<STRUCT<
time_unix_nano: LONG,
name: STRING,
attributes: VARIANT,
dropped_attributes_count: INT
>>,
dropped_events_count INT,
links ARRAY<STRUCT<
trace_id: STRING,
span_id: STRING,
trace_state: STRING,
attributes: VARIANT,
dropped_attributes_count: INT,
flags: INT
>>,
dropped_links_count INT,
status STRUCT<
message: STRING,
code: STRING
>,
resource STRUCT<
attributes: VARIANT,
dropped_attributes_count: INT
>,
resource_schema_url STRING,
instrumentation_scope STRUCT<
name: STRING,
version: STRING,
attributes: VARIANT,
dropped_attributes_count: INT
>,
span_schema_url STRING
) USING DELTA
CLUSTER BY (time, service_name, trace_id)
TBLPROPERTIES (
'otel.schemaVersion' = 'v2',
'delta.checkpointPolicy' = 'classic',
'delta.enableVariantShredding' = 'true', -- optional
'delta.feature.variantShredding-preview' = 'supported', -- optional
'delta.feature.variantType-preview' = 'supported' -- optional
);
Table des logs
La table des Logs stocke les enregistrements de logs structurés, y compris la gravité, le corps et les attributs des Ressources.
CREATE TABLE <catalog>.<schema>.<prefix>_otel_logs (
record_id STRING,
time TIMESTAMP,
date DATE,
service_name STRING,
event_name STRING,
trace_id STRING,
span_id STRING,
time_unix_nano LONG,
observed_time_unix_nano LONG,
severity_number STRING,
severity_text STRING,
body VARIANT,
attributes VARIANT,
dropped_attributes_count INT,
flags INT,
resource STRUCT<
attributes: VARIANT,
dropped_attributes_count: INT
>,
resource_schema_url STRING,
instrumentation_scope STRUCT<
name: STRING,
version: STRING,
attributes: VARIANT,
dropped_attributes_count: INT
>,
log_schema_url STRING
) USING DELTA
CLUSTER BY (time, service_name)
TBLPROPERTIES (
'otel.schemaVersion' = 'v2',
'delta.checkpointPolicy' = 'classic',
'delta.enableVariantShredding' = 'true', -- optional
'delta.feature.variantShredding-preview' = 'supported', -- optional
'delta.feature.variantType-preview' = 'supported' -- optional
);
Table des métriques
Le tableau de métriques stocke les mesures de jauge, de somme et d'histogramme, ainsi que leurs attributs de ressource et d'étendue d'instrumentation associés.
CREATE TABLE <catalog>.<schema>.<prefix>_otel_metrics (
record_id STRING,
time TIMESTAMP,
date DATE,
service_name STRING,
start_time_unix_nano LONG,
time_unix_nano LONG,
name STRING,
description STRING,
unit STRING,
metric_type STRING,
gauge STRUCT<
value: DOUBLE,
exemplars: ARRAY<STRUCT<
time_unix_nano: LONG,
value: DOUBLE,
span_id: STRING,
trace_id: STRING,
filtered_attributes: VARIANT
>>,
attributes: VARIANT,
flags: INT
>,
sum STRUCT<
value: DOUBLE,
exemplars: ARRAY<STRUCT<
time_unix_nano: LONG,
value: DOUBLE,
span_id: STRING,
trace_id: STRING,
filtered_attributes: VARIANT
>>,
attributes: VARIANT,
flags: INT,
aggregation_temporality: STRING,
is_monotonic: BOOLEAN
>,
histogram STRUCT<
count: LONG,
sum: DOUBLE,
bucket_counts: ARRAY<LONG>,
explicit_bounds: ARRAY<DOUBLE>,
exemplars: ARRAY<STRUCT<
time_unix_nano: LONG,
value: DOUBLE,
span_id: STRING,
trace_id: STRING,
filtered_attributes: VARIANT
>>,
attributes: VARIANT,
flags: INT,
min: DOUBLE,
max: DOUBLE,
aggregation_temporality: STRING
>,
exponential_histogram STRUCT<
attributes: VARIANT,
count: LONG,
sum: DOUBLE,
scale: INT,
zero_count: LONG,
positive_bucket: STRUCT<
offset: INT,
bucket_counts: ARRAY<LONG>
>,
negative_bucket: STRUCT<
offset: INT,
bucket_counts: ARRAY<LONG>
>,
flags: INT,
exemplars: ARRAY<STRUCT<
time_unix_nano: LONG,
value: DOUBLE,
span_id: STRING,
trace_id: STRING,
filtered_attributes: VARIANT
>>,
min: DOUBLE,
max: DOUBLE,
zero_threshold: DOUBLE,
aggregation_temporality: STRING
>,
summary STRUCT<
count: LONG,
sum: DOUBLE,
quantile_values: ARRAY<STRUCT<
quantile: DOUBLE,
value: DOUBLE
>>,
attributes: VARIANT,
flags: INT
>,
metadata VARIANT,
resource STRUCT<
attributes: VARIANT,
dropped_attributes_count: INT
>,
resource_schema_url STRING,
instrumentation_scope STRUCT<
name: STRING,
version: STRING,
attributes: VARIANT,
dropped_attributes_count: INT
>,
metric_schema_url STRING
) USING DELTA
CLUSTER BY (time, service_name)
TBLPROPERTIES (
'otel.schemaVersion' = 'v2',
'delta.checkpointPolicy' = 'classic',
'delta.enableVariantShredding' = 'true', -- optional
'delta.feature.variantShredding-preview' = 'supported', -- optional
'delta.feature.variantType-preview' = 'supported' -- optional
);
Créez un Service Principal et accordez des autorisations
Configurez un Service Principal avec des identifiants OAuth et accordez-lui l’accès à vos tables. Pour plus d'informations sur la configuration d'un Service Principal, consultez Autoriser l'accès du Service Principal à Databricks avec OAuth.
Accordez au Service Principal l'accès au catalogue, au schéma et à chaque table. L'octroi de ALL PRIVILEGES n'est pas suffisant. Vous devez explicitement accorder MODIFY et SELECT sur chaque table.
GRANT USE CATALOG ON CATALOG <catalog> TO `<service-principal-uuid>`;
GRANT USE SCHEMA ON SCHEMA <catalog>.<schema> TO `<service-principal-uuid>`;
GRANT MODIFY, SELECT ON TABLE <catalog>.<schema>.<prefix>_otel_spans TO `<service-principal-uuid>`;
GRANT MODIFY, SELECT ON TABLE <catalog>.<schema>.<prefix>_otel_logs TO `<service-principal-uuid>`;
GRANT MODIFY, SELECT ON TABLE <catalog>.<schema>.<prefix>_otel_metrics TO `<service-principal-uuid>`;
Configurez votre exportateur
Les exemples suivants utilisent l'instrumentation sans code OpenTelemetry pour collecter et transmettre automatiquement les traces, les logs et les métriques à Zerobus Ingest sans aucune modification de code apportée à votre application. Vous pouvez également utiliser d'autres exportateurs compatibles OTLP qui prennent en charge gRPC et les en-têtes de métadonnées personnalisés.
En-têtes requis
Toutes les requêtes OTLP doivent inclure les en-têtes de métadonnées suivants :
x-databricks-zerobus-table-name: Le nom de table Unity Catalog entièrement qualifié au format<catalog>.<schema>.<table>. Chaque requête cible une seule table.Authorization: jeton porteur OAuth généré à partir des informations d'identification du Service Principal.
Pour générer un jeton de porteur statique à partir de vos identifiants de Service Principal, consultez Autoriser l'accès de Service Principal à Databricks avec OAuth. Les jetons statiques expirent après une heure. Pour les applications de longue durée, consultez OpenTelemetry Collector avec refresh automatique du jeton.
Configuration des variables
Définissez ces variables avant d'exécuter l'un ou l'autre exemple :
Variable | Exemple |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Vous pouvez définir ces variables comme variables d'environnement à l'aide de Bash. Par exemple :
export DATABRICKS_CLIENT_ID="<your-client-id>"
export DATABRICKS_CLIENT_SECRET="<your-client-secret>"
Quick start avec un jeton statique
L'exemple suivant utilise un jeton porteur statique pour chaque type de signal (traces, logs, métriques). Avant d'exécuter cet exemple, générez des jetons à partir de vos informations d'identification de service principal. Consultez Autoriser l'accès du Service Principal à Databricks avec OAuth.
Utilisez cette approche pour les pipelines de courte durée ou ad hoc où la gestion du refresh des jetons n'est pas un problème. Les jetons OAuth statiques expirent après une heure et ne conviennent pas aux processus de longue durée. Pour les charges de travail de production, utilisez plutôt le OpenTelemetry Collector avec automatic token refresh.
Vous devez générer un jeton distinct pour chaque type de signal. Dans la charge utile authorization_details, remplacez $TABLE_NAME par le nom complet de la table pour chaque signal, tel que ${TABLE_PREFIX}_otel_spans, ${TABLE_PREFIX}_otel_logs et ${TABLE_PREFIX}_otel_metrics.
authorization_details=$(cat <<EOF
[{
"type": "unity_catalog_privileges",
"privileges": ["USE CATALOG"],
"object_type": "CATALOG",
"object_full_path": "$CATALOG"
},
{
"type": "unity_catalog_privileges",
"privileges": ["USE SCHEMA"],
"object_type": "SCHEMA",
"object_full_path": "$CATALOG.$SCHEMA"
},
{
"type": "unity_catalog_privileges",
"privileges": ["SELECT", "MODIFY"],
"object_type": "TABLE",
"object_full_path": "$CATALOG.$SCHEMA.$TABLE_NAME"
}]
EOF
)
curl -X POST \
-u "$DATABRICKS_CLIENT_ID:$DATABRICKS_CLIENT_SECRET" \
-d "grant_type=client_credentials" \
-d "scope=all-apis" \
-d "resource=api://databricks/workspaces/$WORKSPACE_ID/zerobusDirectWriteApi" \
--data-urlencode "authorization_details=$authorization_details" \
"https://$WORKSPACE_URL/oidc/v1/token"
Enregistrez les trois jetons d'accès renvoyés comme TOKEN_SPANS, TOKEN_LOGS et TOKEN_METRICS avant d'installer les packages d'auto-instrumentation. Ensuite, exécutez votre application :
OTEL_SERVICE_NAME="my-service" \
OTEL_EXPORTER_OTLP_PROTOCOL="grpc" \
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://${WORKSPACE_ID}.zerobus.${REGION}.cloud.databricks.com:443" \
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT="https://${WORKSPACE_ID}.zerobus.${REGION}.cloud.databricks.com:443" \
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT="https://${WORKSPACE_ID}.zerobus.${REGION}.cloud.databricks.com:443" \
OTEL_EXPORTER_OTLP_TRACES_HEADERS="authorization=Bearer ${TOKEN_SPANS},x-databricks-zerobus-table-name=${CATALOG}.${SCHEMA}.${TABLE_PREFIX}_otel_spans" \
OTEL_EXPORTER_OTLP_LOGS_HEADERS="authorization=Bearer ${TOKEN_LOGS},x-databricks-zerobus-table-name=${CATALOG}.${SCHEMA}.${TABLE_PREFIX}_otel_logs" \
OTEL_EXPORTER_OTLP_METRICS_HEADERS="authorization=Bearer ${TOKEN_METRICS},x-databricks-zerobus-table-name=${CATALOG}.${SCHEMA}.${TABLE_PREFIX}_otel_metrics" \
OTEL_TRACES_EXPORTER="otlp" \
OTEL_METRICS_EXPORTER="otlp" \
OTEL_LOGS_EXPORTER="otlp" \
opentelemetry-instrument python my_app.py
Collecteur OpenTelemetry avec automatic token refresh des jetons
Les jetons OAuth Databricks expirent après une heure. Plutôt que de gérer le token refresh dans le code de votre application, déployez un collecteur OpenTelemetry comme proxy entre votre application et Zerobus Ingest. Le collecteur utilise oauth2clientauthextension pour émettre un jeton à partir de vos informations d'identification de Service Principal au Startup et le refresh automatiquement avant son expiration.
Il s'agit de l'approche recommandée pour les charges de travail de longue durée et de production. Contrairement à l'approche par jeton statique, le Collecteur gère l'acquisition et le refresh des jetons OAuth automatiquement — votre code d'application ne nécessite aucune modification.
Le Collecteur se situe entre votre application et Zerobus Ingest. Votre application envoie du OTLP simple au Collecteur sur localhost:4317 sans authentification. Le Collecteur ajoute le jeton OAuth et l'en-tête de table à chaque requête et le transmet à l'endpoint Zerobus Ingest.
Configuration du collecteur
Créez un fichier collector.yaml pour configurer votre collecteur :
extensions:
oauth2client/spans:
client_id: ${env:DATABRICKS_CLIENT_ID}
client_secret: ${env:DATABRICKS_CLIENT_SECRET}
token_url: https://${env:WORKSPACE_URL}/oidc/v1/token
scopes: ['all-apis']
endpoint_params:
resource: 'api://databricks/workspaces/${env:WORKSPACE_ID}/zerobusDirectWriteApi'
authorization_details:
- '[{"type":"unity_catalog_privileges","privileges":["USE CATALOG"],"object_type":"CATALOG","object_full_path":"${env:CATALOG}"},{"type":"unity_catalog_privileges","privileges":["USE SCHEMA"],"object_type":"SCHEMA","object_full_path":"${env:CATALOG}.${env:SCHEMA}"},{"type":"unity_catalog_privileges","privileges":["SELECT","MODIFY"],"object_type":"TABLE","object_full_path":"${env:CATALOG}.${env:SCHEMA}.${env:TABLE_PREFIX}_otel_spans"}]'
oauth2client/logs:
client_id: ${env:DATABRICKS_CLIENT_ID}
client_secret: ${env:DATABRICKS_CLIENT_SECRET}
token_url: https://${env:WORKSPACE_URL}/oidc/v1/token
scopes: ['all-apis']
endpoint_params:
resource: 'api://databricks/workspaces/${env:WORKSPACE_ID}/zerobusDirectWriteApi'
authorization_details:
- '[{"type":"unity_catalog_privileges","privileges":["USE CATALOG"],"object_type":"CATALOG","object_full_path":"${env:CATALOG}"},{"type":"unity_catalog_privileges","privileges":["USE SCHEMA"],"object_type":"SCHEMA","object_full_path":"${env:CATALOG}.${env:SCHEMA}"},{"type":"unity_catalog_privileges","privileges":["SELECT","MODIFY"],"object_type":"TABLE","object_full_path":"${env:CATALOG}.${env:SCHEMA}.${env:TABLE_PREFIX}_otel_logs"}]'
oauth2client/metrics:
client_id: ${env:DATABRICKS_CLIENT_ID}
client_secret: ${env:DATABRICKS_CLIENT_SECRET}
token_url: https://${env:WORKSPACE_URL}/oidc/v1/token
scopes: ['all-apis']
endpoint_params:
resource: 'api://databricks/workspaces/${env:WORKSPACE_ID}/zerobusDirectWriteApi'
authorization_details:
- '[{"type":"unity_catalog_privileges","privileges":["USE CATALOG"],"object_type":"CATALOG","object_full_path":"${env:CATALOG}"},{"type":"unity_catalog_privileges","privileges":["USE SCHEMA"],"object_type":"SCHEMA","object_full_path":"${env:CATALOG}.${env:SCHEMA}"},{"type":"unity_catalog_privileges","privileges":["SELECT","MODIFY"],"object_type":"TABLE","object_full_path":"${env:CATALOG}.${env:SCHEMA}.${env:TABLE_PREFIX}_otel_metrics"}]'
exporters:
otlp/spans:
endpoint: ${env:WORKSPACE_ID}.zerobus.${env:REGION}.cloud.databricks.com:443
auth:
authenticator: oauth2client/spans
headers:
x-databricks-zerobus-table-name: '${env:CATALOG}.${env:SCHEMA}.${env:TABLE_PREFIX}_otel_spans'
otlp/logs:
endpoint: ${env:WORKSPACE_ID}.zerobus.${env:REGION}.cloud.databricks.com:443
auth:
authenticator: oauth2client/logs
headers:
x-databricks-zerobus-table-name: '${env:CATALOG}.${env:SCHEMA}.${env:TABLE_PREFIX}_otel_logs'
otlp/metrics:
endpoint: ${env:WORKSPACE_ID}.zerobus.${env:REGION}.cloud.databricks.com:443
auth:
authenticator: oauth2client/metrics
headers:
x-databricks-zerobus-table-name: '${env:CATALOG}.${env:SCHEMA}.${env:TABLE_PREFIX}_otel_metrics'
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
processors:
batch:
timeout: 5s # adjust as needed
send_batch_size: 10 # adjust as needed
service:
extensions: [oauth2client/spans, oauth2client/logs, oauth2client/metrics]
pipelines:
traces:
receivers: [otlp] # adjust as needed
processors: [batch]
exporters: [otlp/spans]
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlp/logs]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [otlp/metrics]
Ensuite, exécutez le collecteur :
./otelcol-contrib --config collector.yaml
Instrumentez votre application
Définissez les variables requises avant d'exécuter cet exemple de code. Ensuite, installez les packages d'auto-instrumentation et exécutez votre application.
OTEL_SERVICE_NAME=my-service \
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \
OTEL_EXPORTER_OTLP_PROTOCOL=grpc \
OTEL_TRACES_EXPORTER=otlp \
OTEL_METRICS_EXPORTER=otlp \
OTEL_LOGS_EXPORTER=otlp \
opentelemetry-instrument python my_app.py
Ressources supplémentaires
- Référence de table OpenTelemetry pour Zerobus Ingest: Référence pour les schémas de table et le mappage des données.
- Interroger les données OpenTelemetry: exemples de requêtes pour explorer vos données de télétrie dans Unity Catalog.
- Gestion des erreurs d'ingestion Zerobus: Dépannage des erreurs courantes et des codes d'erreur.
- Limitations du connecteur Zerobus Ingest: examinez les limites de throughput et de rétention pour Zerobus Ingest.