otel-ottl

Par dash0hq · agent-skills

Expert en OpenTelemetry Transformation Language (OTTL). À utiliser lors de la rédaction ou du débogage d'expressions OTTL pour tout composant OpenTelemetry Collector prenant en charge OTTL (processors, connectors, receivers, exporters). Se déclenche pour les tâches impliquant la transformation de télémétrie, le filtrage, la manipulation d'attributs, la rédaction de données, les politiques de sampling, le routage ou la configuration du Collector. Couvre la syntaxe, les contextes, les fonctions, la gestion des erreurs et les performances.

npx skills add https://github.com/dash0hq/agent-skills --skill otel-ottl

Langage de transformation OpenTelemetry (OTTL)

Composants qui utilisent OTTL

OTTL ne se limite pas aux processeurs transform et filter. Les processeurs (transform, filter, attributes, span, tailsampling, cumulativetodelta, logdedup, lookup), les connecteurs (routing, count, sum, signaltometrics) et le receiver hostmetrics acceptent tous des expressions OTTL. Consultez components pour la liste complète avec les cas d'usage.

Syntaxe OTTL

Expressions de chemin

Naviguez dans les données de télémétrie en utilisant la notation pointée :

span.name
span.attributes["http.method"]
resource.attributes["service.name"]

Contextes (premier segment du chemin) : resource, scope, span, spanevent, metric, datapoint, log.

Énumérations

Utilisez des constantes int64 pour les champs d'énumération :

span.status.code == STATUS_CODE_ERROR
span.kind == SPAN_KIND_SERVER

Opérateurs

Attribution : = — Comparaison : ==, !=, >, <, >=, <= — Logique : and, or, not

Fonctions

Convertisseurs (majuscules, retournent des valeurs) :

ToUpperCase(span.attributes["http.request.method"])
Substring(log.body.string, 0, 1024)
Concat(["prefix", span.attributes["request.id"]], "-")
IsMatch(metric.name, "^k8s\\..*$")

Éditeurs (minuscules, modifient les données sur place) :

set(span.attributes["region"], "us-east-1")
delete_key(resource.attributes, "internal.key")
limit(log.attributes, 10, [])

Consultez function-reference pour la liste complète des éditeurs et convertisseurs.

Instructions conditionnelles

Utilisez where pour appliquer les transformations conditionnellement :

span.attributes["db.statement"] = "REDACTED" where resource.attributes["service.name"] == "accounting"

Vérifications nil

Utilisez nil pour les vérifications d'absence (non null) :

resource.attributes["service.name"] != nil

Flux de validation

  1. Valider la syntaxe de configuration — exécutez otelcol validate --config=config.yaml pour détecter les erreurs de compilation avant de démarrer le Collector.
  2. Tester avec l'exporteur debug — routez la télémétrie transformée vers un exporteur debug et inspectez la sortie :
exporters:
  debug:
    verbosity: detailed

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [transform, batch]
      exporters: [debug]   # remplacez par l'exporteur de production une fois validé
  1. Définir error_mode: ignore en production — consultez Error handling.
  2. Promouvoir vers les exporteurs de production — remplacez debug par l'exporteur de production.

Motifs courants

Définir des attributs

set(resource.attributes["k8s.cluster.name"], "prod-aws-us-west-2")

Masquer les données sensibles

Consultez redaction pour les stratégies (replace, mask, hash, delete, drop) avec des exemples.

Supprimer la télémétrie par motif

IsMatch(metric.name, "^k8s\\.replicaset\\..*$")

Supprimer les données obsolètes

time_unix_nano < UnixNano(Now()) - 21600000000000

Remplir les timestamps manquants

processors:
  transform:
    log_statements:
      - context: log
        statements:
          - set(log.observed_time, Now()) where log.observed_time_unix_nano == 0
          - set(log.time, log.observed_time) where log.time_unix_nano == 0

Exemple de processeur filter

processors:
  filter:
    metrics:
      datapoint:
        - 'IsMatch(ConvertCase(String(metric.name), "lower"), "^k8s\\.replicaset\\.")'

service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [filter, batch]
      exporters: [debug]

Exemple de processeur transform

processors:
  transform:
    trace_statements:
      - context: span
        statements:
          - set(span.status.code, STATUS_CODE_ERROR) where span.attributes["http.response.status_code"] >= 500
          - set(span.attributes["env"], "production") where resource.attributes["deployment.environment"] == "prod"

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [transform, batch]
      exporters: [debug]

Vérifications nil défensives

resource.attributes["service.namespace"] != nil
and
IsMatch(ConvertCase(String(resource.attributes["service.namespace"]), "lower"), "^platform.*$")

Consultez cardinality pour normaliser les attributs à haute cardinalité (segments de chemin, masquage d'IP, limites de nombre/longueur d'attributs) et enrichment pour ajouter des attributs de ressource statiques.

Gestion des erreurs

Erreurs de compilation

Surviennent pendant l'initialisation du processeur et empêchent le démarrage du Collector :

  • Syntaxe invalide (guillemets manquants)
  • Fonctions inconnues
  • Expressions de chemin invalides
  • Incompatibilités de type

Erreurs d'exécution

Surviennent pendant le traitement de la télémétrie :

  • Accès à des attributs inexistants
  • Échecs de conversion de type
  • Erreurs d'exécution de fonction

Configuration du mode d'erreur

Définissez toujours error_mode explicitement.

Mode Comportement Quand l'utiliser
propagate (par défaut) Arrête le traitement de l'élément actuel Développement et environnements stricts où vous voulez capturer chaque erreur
ignore Enregistre l'erreur, continue le traitement Production — définissez cela sauf si vous avez une raison spécifique de ne pas le faire
silent Ignore les erreurs sans journalisation Pipelines à haut volume avec transformations sûres connues où les journaux d'erreur sont du bruit
processors:
  transform:
    error_mode: ignore
    trace_statements:
      - context: span
        statements:
          - set(span.attributes["parsed"], ParseJSON(span.attributes["json_body"]))

Performance

Utilisez les clauses where pour ignorer les éléments tôt.

# MAUVAIS — exécute replace_pattern sur chaque span
replace_pattern(span.attributes["url.path"], "/\\d+", "/{id}")

# BON — ignore les spans dépourvus de l'attribut
replace_pattern(span.attributes["url.path"], "/\\d+", "/{id}") where span.attributes["url.path"] != nil

Références

Skills similaires