Référence de rédaction des informations personnelles identifiables (PII) à partir des traces OTel
Cette page décrit une architecture de référence pour masquer les informations personnelles identifiables (PII) des spans OpenTelemetry (OTel) stockées dans Unity Catalog. Il couvre deux flux complémentaires : le traitement par batch côté serveur et la rédaction à la lecture basée sur la vue. Les deux flux utilisent les AI Functions et les Spark Declarative Pipelines. Pour les instructions de déploiement et les assets téléchargeables, consultez Masquer les PII des traces OpenTelemetry dans Unity Catalog.
parameter
Tous les composants de cette solutions sont paramétrés pour être réutilisés dans différents environnements.
Paramètres de table
parameter | Description | Exemple |
|---|---|---|
| Catalogue Unity Catalog contenant les tables OTel brutes. |
|
| Schéma Unity Catalog contenant les tables OTel brutes. |
|
| Préfixe utilisé lors de la configuration du stockage de traces OTel. |
|
| Catalogue Unity Catalog pour les tables de sortie censurées. |
|
| Schéma Unity Catalog pour les tables de sortie expurgées. |
|
| TTL pour les données non expurgées (conformité GDPR). Définissez sur |
|
Noms de tables sources dérivés :
{source_catalog}.{source_schema}.{table_prefix}_otel_spans{source_catalog}.{source_schema}.{table_prefix}_otel_logs{source_catalog}.{source_schema}.{table_prefix}_otel_annotations
Règles de rédaction des PII
parameter | Description | Exemple |
|---|---|---|
| Liste des types de PII à masquer. |
|
| Comment masquer les PII : |
|
| Caractère utilisé pour le masquage. |
|
| Champs OTel à appliquer pour la rédaction. |
|
| Clés d’attribut à exclure du masquage (par exemple, |
|
| Modèles Regex pour les PII spécifiques à un domaine. |
|
Flux 1 : Traitement par batch côté serveur (recommandé)
Ce flux utilise Spark Declarative Pipelines pour matérialiser des tables expurgées à partir des tables OTel brutes.
Pourquoi utiliser un pipeline déclaratif
Considération | Lakeflow pipelines (table de streaming) | Notebook et job planifié |
|---|---|---|
Traitement incrémentiel | Intégré — les tables de streaming ne traitent que les nouvelles lignes. | Gestion manuelle des points de contrôle avec Structured Streaming. |
Support de fonctions IA | Intégré dans SQL. | Intégré dans SQL. |
Monitoring et alertes | Interface utilisateur du pipeline et journal des événements intégrés. | Doit être configuré séparément. |
Nouvelle tentative et gestion des échecs | Automatique. | Manuel. |
Traçabilité | Suivi automatique du lineage Unity Catalog. | Manuel. |
Compute serverless | Oui. | Oui (avec des jobs serverless). |
Surcoût opérationnel | Faible — entièrement managé. | Moyen — gérer l'état, les planifications et les alertes. |
Les LakeFlow Pipelines avec des tables de streaming sont les plus adaptés. Les étendues OTel sont en ajout uniquement, ce qui les rend idéales pour l'ingestion incrémentielle de tables de streaming. Les fonctions d'IA, telles que ai_mask, sont intégrées dans SQL, de sorte qu'un pipeline SQL est l'implémentation la plus simple.
Architecture

Mise en œuvre
Étape 1 : Verrouillez les tables brutes
Accorder l'accès aux tables brutes uniquement au service principal du pipeline et aux utilisateurs administrateurs.
-- Restrict raw table access
GRANT USE CATALOG ON CATALOG ${source_catalog} TO `pii_pipeline_sp`;
GRANT USE SCHEMA ON SCHEMA ${source_catalog}.${source_schema} TO `pii_pipeline_sp`;
GRANT SELECT ON TABLE ${source_catalog}.${source_schema}.${table_prefix}_otel_spans TO `pii_pipeline_sp`;
GRANT SELECT ON TABLE ${source_catalog}.${source_schema}.${table_prefix}_otel_logs TO `pii_pipeline_sp`;
-- Revoke broader access
REVOKE SELECT ON TABLE ${source_catalog}.${source_schema}.${table_prefix}_otel_spans FROM `data_team`;
Étape 2 : Créer le pipeline SQL
Définissez les tables de streaming expurgées dans pii_redaction_pipeline.sql.
-- =============================================================
-- Streaming Table: Redacted Spans
-- =============================================================
CREATE OR REFRESH STREAMING TABLE redacted_spans
COMMENT 'PII-redacted OTel spans'
TBLPROPERTIES (
'quality' = 'gold',
'pipelines.autoOptimize.zOrderCols' = 'trace_id,date'
)
AS
SELECT
trace_id,
span_id,
parent_span_id,
name,
kind,
start_time,
end_time,
status,
date,
record_id,
service_name,
time,
instrumentation_scope,
-- Redact span attributes (VARIANT field)
-- ai_mask replaces PII with masked values in free-text content
CASE
WHEN attributes IS NOT NULL THEN
ai_mask(
CAST(attributes AS STRING),
array(${pii_categories}) -- e.g. array('email','phone','ssn','name','address')
)
ELSE attributes
END AS attributes,
-- Redact resource attributes
CASE
WHEN resource:attributes IS NOT NULL THEN
named_struct(
'attributes',
ai_mask(
CAST(resource:attributes AS STRING),
array(${pii_categories})
),
'dropped_attributes_count',
resource:dropped_attributes_count
)
ELSE resource
END AS resource,
-- Redact events (may contain exception messages with PII)
CASE
WHEN events IS NOT NULL THEN
ai_mask(
CAST(events AS STRING),
array(${pii_categories})
)
ELSE events
END AS events,
-- Pass through links unchanged (typically just trace/span IDs)
links
FROM STREAM(${source_catalog}.${source_schema}.${table_prefix}_otel_spans);
-- =============================================================
-- Streaming Table: Redacted Logs
-- =============================================================
CREATE OR REFRESH STREAMING TABLE redacted_logs
COMMENT 'PII-redacted OTel logs'
AS
SELECT
trace_id,
span_id,
severity_number,
severity_text,
date,
record_id,
service_name,
time,
instrumentation_scope,
-- Redact log body
CASE
WHEN body IS NOT NULL THEN
ai_mask(
CAST(body AS STRING),
array(${pii_categories})
)
ELSE body
END AS body,
-- Redact log attributes
CASE
WHEN attributes IS NOT NULL THEN
ai_mask(
CAST(attributes AS STRING),
array(${pii_categories})
)
ELSE attributes
END AS attributes,
-- Redact resource attributes
CASE
WHEN resource:attributes IS NOT NULL THEN
named_struct(
'attributes',
ai_mask(
CAST(resource:attributes AS STRING),
array(${pii_categories})
),
'dropped_attributes_count',
resource:dropped_attributes_count
)
ELSE resource
END AS resource
FROM STREAM(${source_catalog}.${source_schema}.${table_prefix}_otel_logs);
-- =============================================================
-- Streaming Table: Annotations (passthrough — no PII expected)
-- =============================================================
CREATE OR REFRESH STREAMING TABLE redacted_annotations
COMMENT 'OTel annotations (passthrough, no PII redaction applied)'
AS
SELECT *
FROM STREAM(${source_catalog}.${source_schema}.${table_prefix}_otel_annotations);
Étape 3 : Créez la ressource de pipeline
Utilisez la configuration suivante comme template.
{
"name": "otel-pii-redaction",
"catalog": "${target_catalog}",
"schema": "${target_schema}",
"serverless": true,
"continuous": false,
"channel": "CURRENT",
"configuration": {
"source_catalog": "<value>",
"source_schema": "<value>",
"table_prefix": "<value>",
"pii_categories": "'email','phone','ssn','credit_card','name','address'"
},
"libraries": [{ "file": { "path": "/Workspace/path/to/pii_redaction_pipeline.sql" } }]
}
Exécutez la pipeline en mode Trigger (par exemple, toutes les 15 minutes ou toutes les heures) en fonction de vos exigences en matière de latence. Le mode continu est également une option, mais il augmente les coûts.
Étape 4 : Créer la vue unifiée sur les tables expurgées.
-- Recreate the trace_unified view pointing at redacted tables
CREATE OR REPLACE VIEW ${target_catalog}.${target_schema}.${table_prefix}_trace_unified AS
SELECT
s.trace_id,
s.date,
min(s.start_time) AS request_time,
max(s.end_time) - min(s.start_time) AS execution_duration,
collect_list(
named_struct(
'span_id', s.span_id,
'parent_span_id', s.parent_span_id,
'name', s.name,
'kind', s.kind,
'start_time', s.start_time,
'end_time', s.end_time,
'status', s.status,
'attributes', s.attributes,
'events', s.events
)
) AS spans,
a.tags,
a.assessments
FROM ${target_catalog}.${target_schema}.redacted_spans s
LEFT JOIN ${target_catalog}.${target_schema}.redacted_annotations a
ON s.trace_id = a.target_id
GROUP BY s.trace_id, s.date, a.tags, a.assessments;
Étape 5 : Accorder un accès plus large aux tables censurées
GRANT USE CATALOG ON CATALOG ${target_catalog} TO `data_team`;
GRANT USE SCHEMA ON SCHEMA ${target_catalog}.${target_schema} TO `data_team`;
GRANT SELECT ON SCHEMA ${target_catalog}.${target_schema} TO `data_team`;
Étape 6 : Configurer la rétention sur les tables brutes (facultatif, pour la conformité GDPR)
Si retention_days est configuré (supérieur à 0), utilisez la durée de vie automatique pour supprimer automatiquement les lignes expirées. Les tables de trace OTel sont des tables Delta gérées par Unity Catalog avec time TIMESTAMP colonnes, de sorte que l'auto-TTL est pris en charge. L'optimisation prédictive doit être activée sur le Workspace (ou la table).
ALTER TABLE ${source_catalog}.${source_schema}.${table_prefix}_otel_spans
DELETE ROWS ${retention_days} DAYS AFTER time;
ALTER TABLE ${source_catalog}.${source_schema}.${table_prefix}_otel_logs
DELETE ROWS ${retention_days} DAYS AFTER time;
Databricks exécute DELETE, PURGE et VACUUM opérations en arrière-plan automatiquement — aucun job planifié n'est requis.
Le délai de suppression exact n'est pas garanti. Il peut y avoir un délai de grâce allant jusqu'à 6 jours entre l'expiration de la ligne et la suppression permanente, plus la durée de conservation des données (7 jours default). Si vos exigences de conformité nécessitent des délais de suppression stricts, utilisez un Job planifié avec DELETE manuel et VACUUM comme fallback. Consultez la durée de vie automatique pour plus de détails sur le calcul des valeurs de configuration pour une période d'expiration cible.
Flux 2 : Rédaction basée sur la vue (sans duplication des données)
Ce flux applique ai_mask dans une vue Unity Catalog, de sorte que la rédaction se fait au moment de la lecture et aucune copie rédigée n'est stockée.
Quand utiliser
- Le coût de stockage est une préoccupation majeure.
- Les données expurgées sont rarement interrogées.
- Il est acceptable de payer le coût de compute pour chaque query.
Architecture

Mise en œuvre
CREATE OR REPLACE VIEW ${target_catalog}.${target_schema}.${table_prefix}_otel_spans_redacted
AS
SELECT
trace_id,
span_id,
parent_span_id,
name,
kind,
start_time,
end_time,
status,
date,
service_name,
time,
instrumentation_scope,
links,
ai_mask(
CAST(attributes AS STRING),
array(${pii_categories})
) AS attributes,
ai_mask(
CAST(events AS STRING),
array(${pii_categories})
) AS events,
named_struct(
'attributes',
ai_mask(CAST(resource:attributes AS STRING), array(${pii_categories})),
'dropped_attributes_count',
resource:dropped_attributes_count
) AS resource
FROM ${source_catalog}.${source_schema}.${table_prefix}_otel_spans;
Compromis
Aspect | Avantages | Inconvénients |
|---|---|---|
Stockage | Aucune duplication. | — |
Calculer | — |
|
Latence | Reflète immédiatement les nouvelles données. | Réponse de query plus lente. |
Flexibilité | Les règles de rédaction se mettent à jour instantanément. | — |
Comparaison des flux
Dimension | Flux 1 : pipeline de batch | Flux 2 : basé sur la vue |
|---|---|---|
Fidélité des données préservée | Oui (table brute conservée). | Oui (table brute conservée). |
Coût de stockage | 2x (en fenêtre temporelle, ou ~1x si l'auto-TTL s'applique). | 1x. |
Coût du compute | Une seule fois par enregistrement. | Par query. |
Performances de query. | Rapide (pré-matérialisé). | Lent (recalculs). |
Latence à la disponibilité | Minutes (intervalle de pipeline). | Immédiat. |
Déploiement du changement de règle | refresh du pipeline. | Instantané. |
Conformité GDPR | Auto-TTL ou nettoyage planifié sur les tables brutes. | Auto-TTL ou nettoyage planifié sur les tables brutes. |
Idéal pour | Utilisation principale en production. | Utilisation à faible volume de queries. |
Fonctionnalité Databricks | LakeFlow Pipelines. | Vue Unity Catalog et AI Functions. |
Approche recommandée
Utilisez le Flow 1 (pipeline batch) comme solution principale pour la plupart des déploiements d'entreprise :
- Préserve les données de pleine fidélité pour le debugging autorisé.
- Optimise les performances de query grâce à la matérialisation.
- Prend en charge la conformité GDPR avec la rétention TTL automatique sur les données brutes.
- Gère à la fois la rédaction des IPI et le filtrage des traces dans un seul pipeline.
- Est entièrement managée avec monitoring et alertes intégrées.
Utilisez **Flow 2 (basé sur la vue)** comme option légère pour les scénarios à faible volume de requêtes, ou comme solution intermédiaire rapide pendant que vous configurez Flow 1.
Prérequis
- AI Functions — nécessite un SQL Warehouse ou un Serverless compute avec accès aux AI Functions.
- Unity Catalog — Les traces OTel doivent être stockées dans des tables Unity Catalog avec une liaison de trace MLflow vers Unity Catalog configurée. Consultez Stocker les traces OpenTelemetry dans Unity Catalog.
- Service principal — pour l'exécution de pipeline, avec les autorisations appropriées sur les tables source.
- Endpoint du modèle de fondation —
ai_maskutilise un modèle de fondation. Vérifiez que l'endpoint est disponible et dimensionné pour le throughput.
Check-list de mise en œuvre
- Validez le comportement
ai_masksur les colonnes VARIANT avec des exemples de données d'étendue OTel. - Évaluez le throughput
ai_maskpour dimensionner l'intervalle de planification du pipeline. - Définissez les clés d'attributs de la liste verte qui doivent ignorer la rédaction.
- Configurez les groupes de contrôle d'accès (accès brut versus accès expurgé).
- Configurez l'auto-TTL pour la rétention des tables brutes (ou un job
DELETEetVACUUMplanifié si un calendrier de suppression strict est requis). - Créez un tableau de bord de monitoring pour la santé du pipeline et la couverture de la rédaction.