Konfigurieren von OpenTelemetry-Clients (OTLP) zum Senden von Daten an den Unity-Katalog

Von Bedeutung

Dieses Feature befindet sich in der Betaversion.

Zerobus Ingest enthält einen OTLP-Endpunkt (OpenTelemetry Protocol). Sie können Ablaufverfolgungen, Protokolle und Metriken direkt in Unity Catalog Delta-Tabellen übertragen, indem Sie standardmäßige OpenTelemetry-SDKs und -Sammler ohne benutzerdefinierte Bibliotheken verwenden. Diese Seite behandelt das Abrufen Ihres Endpunkts, das Erstellen von Zieltabellen, das Konfigurieren eines Dienstprinzipals und das Senden Ihrer ersten Telemetriedaten.

Holen Sie sich Ihren Zerobus-Erfassungsendpunkt und die URL des Arbeitsbereichs

Die Endpunkt-URL folgt diesem Muster:

  • Arbeitsbereichs-URL: https://<databricks-instance>.azuredatabricks.net
  • Serverendpunkt: <workspace-id>.zerobus.<region>.azuredatabricks.net

Beispiel:

  • Arbeitsbereichs-URL: https://adb-1234567890123456.12.azuredatabricks.net
  • Serverendpunkt: 1234567890123456.zerobus.eastus.azuredatabricks.net

Weitere Informationen zum Auffinden Ihrer Arbeitsbereichs-ID, URL und Region erhalten Sie unter Abrufen der Arbeitsbereichs-URL und des Zerobus-Erfassungsendpunkts.

Erstellen von Zieltabellen im Unity-Katalog

Sie müssen die Ziel-Delta-Tabellen erstellen, bevor Sie Daten senden. Jeder Signaltyp (Ablaufverfolgungen, Protokolle, Metriken) erfordert eine eigene Tabelle mit einem bestimmten Schema.

Voraussetzungen:

So richten Sie Ihre Tabellen ein:

  1. Ersetzen Sie <catalog>.<schema>.<prefix> durch Ihren Katalog, Ihr Schema und das gewünschte Tabellenpräfix.
  2. Ersetzen Sie <service-principal-uuid> durch die App-ID Ihres Dienstprinzipals (UUID). Um dies zu finden, wechseln Sie im Databricks-Arbeitsbereich zur Registerkarte "Konfigurationen" des Dienstprinzipals.
  3. Führen Sie das Skript in Databricks SQL aus.

Tabelle überspannt

Die Spans-Tabelle speichert verteilte Tracedaten, einschließlich Zeitdauer, Status und Attribute für jeden 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
);

Protokolltabelle

In der Protokolltabelle werden strukturierte Protokolldatensätze gespeichert, einschließlich Schweregrad, Inhalt und Ressourcenattributen.

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

Metriktabelle

In der Metriktabelle werden Messgeräte-, Summen- und Histogrammmessungen zusammen mit den zugehörigen Ressourcen- und Instrumentierungsbereichsattributen gespeichert.

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

Erstellen eines Dienstprinzipals und Erteilen von Berechtigungen

Richten Sie einen Dienstprinzipal mit OAuth-Anmeldeinformationen ein, und gewähren Sie ihm Zugriff auf Ihre Tabellen. Weitere Informationen zum Einrichten eines Dienstprinzipals finden Sie unter OAuth-Zugriff für Dienstprinzipal auf Azure Databricks autorisieren.

Gewähren Sie dem Dienstprinzipal Zugriff auf den Katalog, das Schema und jede Tabelle. Die Gewährung ALL PRIVILEGES reicht nicht aus. Sie müssen die Berechtigungen MODIFY und SELECT explizit für jede Tabelle gewähren.

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

Konfigurieren des Exporters

In den folgenden Beispielen wird die Zero-Code-Instrumentierung von OpenTelemetry verwendet, um Ablaufverfolgungen, Protokolle und Metriken automatisch ohne Codeänderungen an Ihre Anwendung zu sammeln und weiterzuleiten. Sie können auch andere OTLP-kompatible Exporteure verwenden, die gRPC und benutzerdefinierte Metadatenheader unterstützen.

Erforderliche Kopfzeilen

Alle OTLP-Anforderungen müssen die folgenden Metadatenheader enthalten:

  • x-databricks-zerobus-table-name: Der vollqualifizierte Unity Catalog-Tabellenname im <catalog>.<schema>.<table> Format. Jede Anforderung zielt auf eine einzelne Tabelle ab.
  • Authorization: OAuth-Bearer-Token, das aus den Dienstprinzipal-Anmeldeinformationen generiert wurde.

Informationen zum Generieren eines statischen Bearer-Token aus Ihren Dienstprinzipal-Zugangsdaten finden Sie in Authorize service principal access to Azure Databricks with OAuth. Statische Token laufen nach einer Stunde ab. Für langlaufende Anwendungen siehe OpenTelemetry Collector mit automatischer Tokenaktualisierung.

Variableneinstellung

Definieren Sie diese Variablen, bevor Sie eines der folgenden Beispiele ausführen:

Variable Beispiel
DATABRICKS_CLIENT_ID abc123-... (Dienstprinzipal-Anwendungs-ID)
DATABRICKS_CLIENT_SECRET dose1234...
WORKSPACE_URL adb-1234567890123456.12.azuredatabricks.net
WORKSPACE_ID 1234567890123456
REGION eastus
CATALOG my_catalog
SCHEMA my_schema
TABLE_PREFIX my_prefix

Sie können diese Variablen mithilfe von Bash als Umgebungsvariablen definieren. Beispiel:

export DATABRICKS_CLIENT_ID="<your-client-id>"
export DATABRICKS_CLIENT_SECRET="<your-client-secret>"

Schnellstart mit statischem Token

Im folgenden Beispiel wird für jeden Signaltyp ein statisches Bearer-Token (Traces, Logs, Metriken) verwendet. Bevor Sie dieses Beispiel ausführen, generieren Sie Token aus Ihren Dienstprinzipalanmeldeinformationen. Siehe Authorize-Dienstprinzipalzugriff auf Azure Databricks mit OAuth.

Verwenden Sie diesen Ansatz für kurzlebige oder Ad-hoc-Pipelines, bei denen die Verwaltung der Tokenaktualisierung kein Problem darstellt. Statische OAuth-Token laufen nach einer Stunde ab und eignen sich nicht für lange laufende Prozesse. Verwenden Sie für Produktionsworkloads stattdessen den OpenTelemetry Collector mit automatischer Tokenaktualisierung .

Sie müssen für jeden Signaltyp ein separates Token generieren. Ersetzen Sie in der authorization_details-Nutzlast $TABLE_NAME durch den vollständigen Tabellennamen für jedes Signal, wie z.B. ${TABLE_PREFIX}_otel_spans, ${TABLE_PREFIX}_otel_logs und ${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"

Speichern Sie die drei zurückgegebenen Zugriffstoken als TOKEN_SPANS, TOKEN_LOGS und TOKEN_METRICS, bevor Sie die Pakete für die automatische Instrumentierung installieren. Führen Sie dann Ihre Anwendung aus:

OTEL_SERVICE_NAME="my-service" \
OTEL_EXPORTER_OTLP_PROTOCOL="grpc" \
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://${WORKSPACE_ID}.zerobus.${REGION}.azuredatabricks.net:443" \
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT="https://${WORKSPACE_ID}.zerobus.${REGION}.azuredatabricks.net:443" \
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT="https://${WORKSPACE_ID}.zerobus.${REGION}.azuredatabricks.net: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

OpenTelemetry Collector mit automatischer Tokenaktualisierung

Datenbricks-OAuth-Token laufen nach einer Stunde ab. Anstatt die Tokenaktualisierung im Anwendungscode zu verwalten, stellen Sie einen OpenTelemetry Collector als Proxy zwischen Ihrer Anwendung und Zerobus Ingest bereit. Der Collector verwendet das oauth2clientauthextension, um beim Start basierend auf den Dienstprinzipalanmeldeinformationen ein Token zu erzeugen und aktualisiert es automatisch, bevor es abläuft.

Dies ist der empfohlene Ansatz für langlaufende und Produktionslasten. Im Gegensatz zum statischen Tokenansatz behandelt der Collector den OAuth-Tokenerwerb und die automatische Aktualisierung – Ihr Anwendungscode erfordert keine Änderungen.

Der Collector befindet sich zwischen Ihrer Anwendung und Zerobus Ingest. Ihre Anwendung sendet reines OTLP an den Collector localhost:4317 ohne Authentifizierung. Der Collector fügt den OAuth-Token und den Tabellenheader jeder Anforderung hinzu und leitet es an den Zerobus Ingest-Endpunkt weiter.

Sammlerkonfiguration

Erstellen Sie eine collector.yaml Datei zum Konfigurieren des Sammlers:

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}.azuredatabricks.net: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}.azuredatabricks.net: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}.azuredatabricks.net: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]

Führen Sie dann den Collector aus:

./otelcol-contrib --config collector.yaml

Instrumentieren Ihrer Anwendung

Legen Sie die erforderlichen Variablen fest, bevor Sie dieses Codebeispiel ausführen. Installieren Sie dann die Pakete für die automatische Instrumentierung , und führen Sie Ihre Anwendung aus.

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

Nächste Schritte