axiom-building-dashboards

Par axiomhq · skills

Conçoit et crée des tableaux de bord Axiom via l'API. Couvre les types de graphiques, les modèles de requêtes APL et métriques/MPL, les SmartFilters, la mise en page et les options de configuration. À utiliser lors de la création de tableaux de bord, de la migration depuis Splunk ou de la configuration des options de graphiques.

npx skills add https://github.com/axiomhq/skills --skill axiom-building-dashboards

Construire des tableaux de bord

Philosophie

  1. Les décisions d'abord. Chaque panneau répond à une question qui mène à une action.
  2. Vue d'ensemble → détails → preuves. Commencez large, réduisez au clic/filtre, terminez par les logs bruts.
  3. Taux et percentiles plutôt que moyennes. Les moyennes cachent les problèmes ; p95/p99 les exposent.
  4. La simplicité dépasse la densité. Une question par panneau. Pas de décor graphique.
  5. Validez avec les données. Ne devinez jamais les champs — découvrez d'abord le schéma.
  6. Calculez ce qu'on demande, ou reportez. Si un panneau ne peut pas être calculé, remplacez-le par une Note documentant le blocage. Ne substituez jamais une quantité différente, même avec avertissement. Voir Calculer ou reporter.

Points d'entrée

Commencer par Flux de travail
Description vague Intake → vérifier le type de dataset → concevoir le blueprint (APL ou MPL) → requêtes par panneau → déployer
Template Choisir template → personnaliser dataset/service/env → déployer
Dashboard Splunk Extraire SPL → traduire via axiom-spl-to-apl → mapper aux types de graphique → déployer
Dashboard Grafana Projeter spec de panneau canonique (expr, legendFormat, unit, title, description) → traduire PromQL → mapper types de graphique → déployer. Voir reference/grafana-migration.md.
Exploration Utiliser axiom-sre pour découvrir schéma/signaux → transformer en panneaux

Intake : Questions à poser d'abord

  1. Audience & décision

    • Triage oncall ? (rafraîchissement rapide, erreurs en focus)
    • Santé de l'équipe ? (tendances quotidiennes, suivi SLO)
    • Rapports exécutifs ? (résumés hebdomadaires, haut niveau)
  2. Périmètre

    • Service, environnement, région, cluster, endpoint ?
    • Vue d'un seul service ou multi-service ?
  3. Type de dataset. Utiliser MCP listDatasets et vérifier kind. Pour un déploiement configuré séparément, utiliser scripts/metrics/datasets <deploy>.

    • otel:metrics:v1 / otel-metrics-v1 → dataset de métriques, suivre le chemin Métriques.
    • n'importe quoi d'autre → dataset d'événements/logs, suivre le chemin APL.

    Ne jamais exécuter getschema sur un dataset de métriques. Il retourne 0 lignes sans erreur.

    Chemin APL : découvrir les champs avec ['dataset'] | where _time between (ago(1h) .. now()) | getschema. Continuer aux étapes 4–5.

    Chemin Métriques : Utiliser Axiom MCP pour la découverte de métriques et les requêtes, puis suivre le Blueprint Métriques/MPL.

  4. Signaux clés (chemin APL)

    • Trafic : requêtes/sec, événements/min
    • Erreurs : taux d'erreur, compte 5xx
    • Latence : p50, p95, p99 durée
    • Saturation : CPU, mémoire, profondeur file, connexions
  5. Dimensions de détail (chemin APL)

    • Sur quoi les utilisateurs filtrent/regroupent-ils ? (service, route, status, pod, customer_id)

Blueprint de tableau de bord

Choisir le blueprint correspondant au type de dataset.

Blueprint APL (datasets événements/logs)

1. Vue d'ensemble (panneaux Statistic)

Nombres uniques qui répondent à « est-ce cassé maintenant ? »

  • Taux d'erreur (5 dernières min)
  • Latence p95 (5 dernières min)
  • Taux de requête (5 dernières min)
  • Alertes actives (si applicable)

2. Tendances (panneaux TimeSeries)

Motifs basés sur le temps qui répondent à « qu'est-ce qui a changé ? »

  • Trafic au fil du temps
  • Taux d'erreur au fil du temps
  • Percentiles de latence au fil du temps
  • Empilé par status/service pour comparaison

3. Ventilations (panneaux Table/Pie)

Analyse Top-N qui répond à « où dois-je regarder ? »

  • Top 10 routes en erreur
  • Top 10 messages d'erreur
  • Pods les plus mauvais par taux d'erreur
  • Distribution des requêtes par status

4. Preuves (LogStream + SmartFilter)

Événements bruts qui répondent à « que s'est-il exactement passé ? »

  • LogStream filtré sur erreurs
  • SmartFilter pour service/env/route
  • Champs clés projetés pour lisibilité

Blueprint Métriques/MPL (datasets de métriques)

Utiliser align to $__interval using … pour bucketing — $__interval est fourni par le runtime du tableau de bord. Les fenêtres en dur sur- ou sous-résolvent. Suivre le contrat de graphique Métriques/MPL pour la découverte et la validation. chart-add --mpl rejette les plages de temps inline ([1h..]).

Exception : pour les métriques creuses où $__interval arrondit à des buckets vides, une fenêtre fixe plus large (ex. 1h) est acceptable ; documenter pourquoi sur le graphique.

1. Vue d'ensemble (panneaux Statistic)

Valeurs actuelles — « quel est l'état maintenant ? »

  • Choisir la fonction group par ce que le panneau doit montrer entre les séries.
  • Passer l'unité du résultat à chart-add --unit : l'unit de la métrique depuis ses métadonnées, ou la nouvelle unité après une map ou un rate qui la change (prom::rate sur By donne By/s). Les métriques de ratio (0–1) besoin de | map * 100 en MPL avant --unit "%".

2. Tendances (panneaux TimeSeries)

Tendances au fil du temps — « qu'est-ce qui a changé ? »

  • Choisir la fonction align par ce que chaque intervalle doit montrer.
  • Regrouper uniquement par tags de faible cardinalité (≤10 séries par graphique).
  • Intégrer l'unité dans --name ("P95 Latency (ms)", "Memory (MiB)"); mettre à l'échelle les magnitudes en MPL (| map / 1048576 pour bytes → MiB).

3. Ventilations (panneaux TimeSeries ou Table)

Détail par entité — « où dois-je regarder ? »

  • Métriques ventilées par entité (host, pod, service).
  • Filtrer pour garder le compte de séries gérable.
  • Une dimension par panneau ; ne pas surcharger un seul graphique.

4. État de l'entité (panneaux TimeSeries ou Table)

Métriques booléennes/état — répondre « qu'est-ce qui est on/off/actif ? »

  • Choisir la fonction align par la question d'état que chaque intervalle répond.
  • Les métriques d'état creuses peuvent avoir besoin d'un intervalle fixe plus large (1h+).

Structure de graphique requise

Chaque graphique a besoin d'un id unique kebab-case (error-rate, p95-latency) ; chaque i de layout doit en correspondre un. Passer le même id à chart-add --id et layout-pack <id>:…. dashboard-assemble fait une vérification croisée avant émission.


Configuration d'unité de graphique

Passer une string d'unité à chart-add --unit ("%", "ms", "req/s"). chart-add n'écrit jamais l'enum unit, que la Console ignore. Sur une Statistic MPL, chart-add écrit set custom_unit="<unit>"; dans la requête et ajoute un suffixe customUnits uniquement pour les unités que la Console ne formate pas. Passer le code UCUM du résultat (USD, s, By, %), jamais un symbole comme $. Pour un ratio 0–1, multiplier par 100 et passer --unit "%". Sur une Statistic APL, chart-add ajoute le suffixe uniquement pour les unités que la Console ne formate pas, car la Console formate un champ depuis ses métadonnées d'unité. % garde son suffixe là. Voir configuration de graphique pour d'autres options.


Calculer ou reporter

Chaque panneau soit calcule la quantité demandée, soit il est remplacé par une Note documentant le blocage. Substituer une quantité différente n'est jamais acceptable — les avertissements ne parviennent pas à qui agit sur le nombre.

Template de report (utiliser chart-add --type Note) :

**Reporté — bloqué par :** <raison d'une ligne>.

**Spec original :** <ce que le panneau doit calculer, dimensions, unité>.

**Pour débloquer :** <pointeur vers le correctif>.

Blocages courants : limites du parser MPL, tag manquant sans équivalent reverse-tag, métrique manquante sans correspondance de renommage OTel. Justification complète : reference/design-playbook.md § Substituting a Different Quantity for the Asked One.


Types de graphique

Type Quand Contrainte clé
Statistic KPI unique, valeur actuelle La requête doit retourner une ligne.
TimeSeries Tendances au fil du temps, overlays de percentiles bin_auto(_time) ; percentiles_array() pour multi-percentile.
Table Listes Top-N, ventilations Borner avec top N ; contrôler colonnes via project.
Pie Part du total pour ≤6 catégories Agréger à ≤6 tranches ; jamais haute cardinalité.
LogStream Inspection d'événement brut Pas de limite de lignes (take, limit, top), agrégation ou join. La Console ajoute son propre tri et limite. Sélectionner les champs avec project-keep, conserver _time, et filtrer dur.
Heatmap Distribution / densité de latence summarize histogram(field, buckets) by bin_auto(_time).
Scatter Plot Corréler deux métriques par groupe summarize avg(x), avg(y) by group.
SmartFilter Barre de filtre interactive Chaque requête de panneau a besoin de declare query_parameters. Voir reference/smartfilter.md.
Monitor List Affichage d'état du moniteur Pas d'APL — sélectionner moniteurs dans l'UI.
Note Contexte Markdown, headers, liens runbook chart-add --type Note --text "<md>".

Recettes par type APL : reference/chart-cookbook.md.


Configuration de graphique

chart-add couvre le chemin courant (type, id, name, query, dataset, unit, sparkline). Pour les options qu'il n'expose pas — variantes aggChartOpts sur TimeSeries, tableSettings.columns sur Table/LogStream, hideHeader, etc. — commencer depuis une sortie chart-add et fusionner les champs supplémentaires avec jq. Voir reference/chart-config.md pour l'ensemble complet des options, et la liste des champs rejetés avant de fusionner quoi que ce soit de bespoke.


Motifs APL

Filtrage temporal

Les requêtes du graphique de tableau de bord héritent le temps du sélecteur — omettre les filtres _time. Les requêtes ad-hoc (onglet Axiom Query, axiom-sre) ont besoin d'un filtre where _time between (ago(1h) .. now()) explicite.

Sélection de taille bin

Utiliser bin_auto(_time) — elle s'ajuste à la fenêtre de temps du tableau de bord. Le bin(_time, …) manuel est justifié uniquement pour les cas non-standard (ex. correspondre à un intervalle batch upstream) ; documenter pourquoi.

Garde-fous de cardinalité

Borner summarize … by … avec top N ou un filtre. Le regroupement non borné sur les champs haute cardinalité (user_id, trace_id) explose.

| summarize count() by route | top 10 by count_   // borné
| summarize count() by user_id                    // non borné — éviter

Échappement de champs

Les champs avec des points ont besoin de notation entre crochets :

| where ['kubernetes.pod.name'] == "frontend"

Les champs avec des points DANS le nom (pas hiérarchie) ont besoin d'échappement :

| where ['kubernetes.labels.app\\.kubernetes\\.io/name'] == "frontend"

Recettes

Trafic, taux-d'erreur, latence-percentile, et autres recettes APL de signal clé : reference/chart-cookbook.md.


Composition de layout

layout-pack empile les graphiques ligne-majeure dans la grille 12-colonnes en utilisant les défauts par type (Statistic 3×3, TimeSeries 6×4, Table 6×5, LogStream 12×6, Note 12×2). Remplacer avec id:WxH si besoin. Recettes de grille : reference/layout-recipes.md. Conventions de nommage et d'ordre de panneaux : reference/design-playbook.md.

Sections

Les groupes repliables sont un tableau top-level sections. Les passer à dashboard-assemble. Ne pas inventer sectionId sur le fichier de graphique, et ne pas découvrir la forme en envoyant une mise à jour invalide.

dashboard-assemble \
  --name "API" \
  --datasets logs \
  --layout /tmp/d/layout.json \
  --section "Requests:err-rate,traffic-ts" \
  --section-collapsed "Errors:top-errors" \
  /tmp/d/c-err-rate.json /tmp/d/c-traffic-ts.json /tmp/d/c-top-errors.json
  • Le titre est le texte avant le premier :. Les ids de graphique suivent, séparés par des virgules, et doivent correspondre aux ids de graphique.
  • L'ordre du flag est l'ordre d'affichage. --section-collapsed définit defaultCollapsed: true.
  • L'id de section est un UUID dérivé du titre, donc le même titre garde le même id à la prochaine exécution.
  • Un graphique omis de chaque --section reste non groupé. Laisser chaque graphique SmartFilter non groupé.
  • Une Note utilisée comme header de grille est layout, pas une section. Utiliser --section quand le tableau de bord doit replier un groupe et arrêter ses requêtes.

Paramètres du tableau de bord

Taux de rafraîchissement

dashboard-assemble --refresh oncall|team|exec (60/300/900s) ou passer un entier explicite (≥60). Rafraîchissement court + plage de temps long = requêtes chères ; choisir le plus long pour les tableaux exec/hebdomadaires.

Partage

Les tokens API créent uniquement des tableaux partagés (owner: "X-AXIOM-EVERYONE"); les tableaux privés ne sont pas supportés. La visibilité des données par utilisateur est toujours appliquée par les permissions du dataset.

Paramètres URL de plage de temps

?t_qr=24h (plage rapide), ?t_ts=...&t_te=... (personnalisée), ?t_against=-1d (comparaison)


Configuration

Outils, prérequis, et configuration ~/.axiom.toml : voir README.md. Vérifier avec scripts/setup.


Déploiement

Scripts

Script Utilisation
scripts/chart-add --type <T> --id <id> --name <n> [--apl <q> \| --mpl <q> --dataset <d>] [--unit <u>] Émettre une seule JSON de graphique vers stdout. Divise APL vs MPL ; les requêtes MPL sont vérifiées pour les plages de temps inline ; champs d'unité appliqués par type de graphique.
scripts/layout-pack <id>:<Type\|WxH> ... Émettre un tableau JSON de layout vers stdout. Ligne-majeure dans une grille 12-colonnes ; les noms de type correspondent à des tailles par défaut.
scripts/dashboard-assemble --name … --datasets … --layout F.json [--section TITLE:id,id ...] [opts] CHART_FILES… Composer une JSON de tableau de bord complet depuis les fichiers de graphique + layout. Possède l'enveloppe (owner, schemaVersion, préfixe qr-, validation refreshTime, vérifications d'id croisées, sections).
scripts/dashboard-list <deploy> Lister tous les tableaux de bord
scripts/dashboard-get <deploy> <id> Récupérer JSON de tableau de bord
scripts/dashboard-validate <file> Valider structure JSON
scripts/dashboard-create <deploy> <file> Créer tableau de bord
scripts/dashboard-update <deploy> <id> <file> Mettre à jour (a besoin de version)
scripts/dashboard-chart-patch <deploy> <id> <chart-id> <patch-file> (--version <version> \| --overwrite) Patcher un graphique
scripts/dashboard-copy <deploy> <id> Cloner tableau de bord
scripts/dashboard-link <deploy> <id> Obtenir URL partageable
scripts/dashboard-delete <deploy> <id> Supprimer (avec confirmation)
scripts/axiom-api <deploy> <method> <path> Dashboard/app API uniquement (réécrit en app.*). Pour les endpoints data/metrics utiliser scripts/metrics/axiom-api
scripts/metrics/axiom-api <deploy> <method> <path> Data/metrics API (supporte AXIOM_URL_OVERRIDE pour edge routing)
scripts/metrics/datasets <deploy> Lister datasets avec kind et déploiement edge
scripts/metrics/metrics-spec Récupérer spécification de requête MPL
scripts/metrics/metrics-info <deploy> <dataset> ... Découvrir métriques, tags, et valeurs
scripts/metrics/metrics-query <deploy> <mpl> <start> <end> Exécuter une requête de métrique (brut — pas injection $__interval)
scripts/metrics/mpl-validate-chart <deploy> '<MPL>' [start] [end] Valider un pipeline MPL de graphique. Rejette les plages de temps inline. Le serveur remplit $__interval. Utiliser ceci à la place de raw metrics-query lors de l'authoring de requêtes de graphique.

Les deux scripts axiom-api ne sont pas interchangeables. scripts/axiom-api est pour l'API app de tableau de bord ; scripts/metrics/axiom-api est pour les endpoints data/metrics et edge routing. Mauvais — 404.

Mises à jour ciblées de graphique

Utiliser scripts/dashboard-chart-patch quand changer un graphique existant et le layout du tableau de bord, métadonnées, et autres graphiques doivent rester inchangés. Il appelle PATCH /v2/dashboards/uid/{uid}/charts/{chartId} avec un JSON Merge Patch sous le champ requête chart.

Les fichiers patch contiennent uniquement les champs de graphique à changer :

{
  "name": "Error Rate (5m)",
  "query": { "apl": "['logs'] | summarize errors=countif(status >= 500)" },
  "config": { "stale": null }
}

null supprime un champ existant. Les objets imbriqués fusionnent récursivement. Si id est présent dans le patch, il doit correspondre à l'argument de chemin <chart-id>. Le serveur valide le tableau de bord complet résultant avant sauvegarde.

Utiliser --version <version> pour concurrence optimiste après récupération du tableau de bord avec dashboard-get. Utiliser --overwrite uniquement quand le comportement last-write-wins est intentionnel. Continuer à utiliser dashboard-update pour les changements de layout, édits multi-graphique, métadonnées de tableau de bord, owner, intervalle de rafraîchissement, ou mises à jour de fenêtre de temps.

Flux de travail

chart-add, layout-pack, et dashboard-assemble possèdent la forme JSON. Chaque graphique vit dans son propre fichier temp ; rien de graphique-shaped ne rentre dans le contexte de l'agent.

  1. Découvrir schéma (axiom-sre / getschema pour événements ; Axiom MCP pour métriques).
  2. Écrire chaque requête de panneau. Valider APL via axiom-sre avec un filtre de temps explicite ; suivre le contrat de graphique Métriques/MPL pour MPL.
  3. chart-add --type … --apl '<APL>' ou chart-add --type … --mpl '<MPL>' --dataset <name> par graphique, redirigé vers son propre fichier.
  4. layout-pack <id>:<Type|WxH> … pour le layout (ids en ordre d'affichage).
  5. dashboard-assemble --name … --datasets … --layout LAYOUT [--section TITLE:id,id ...] CHART_FILES… pour composer. Répéter --section pour chaque groupe repliable. Utiliser --section-collapsed quand le groupe doit démarrer replié.
  6. dashboard-validate puis dashboard-create (ou dashboard-update).
  7. dashboard-link pour l'URL — ne jamais construire à la main.

Intégration de compétence partenaire

  • axiom-spl-to-apl — Splunk SPL → APL (timechart → TimeSeries, stats → Statistic/Table). Voir reference/splunk-migration.md.
  • axiom-sre — découverte de schéma via getschema, exploration de baseline.

Templates

Composer avec chart-add + layout-pack + dashboard-assemble. Les templates pré-construits restent sous reference/templates/ (blank.json, service-overview.json, service-overview-with-filters.json, api-health.json) pour usage legacy ; dashboard-from-template les instancie mais suppose des noms de champs spécifiques (service, status, route, duration_ms) et a besoin de sed-fixing. Préférer la composition pour le nouveau travail.


Pièges courants

Problème Cause Solution
getschema retourne 0 lignes Dataset est otel:metrics:v1 ou otel-metrics-v1 Utiliser MCP listMetrics pour découverte de métriques.
404 depuis appels API metrics Utilisé scripts/axiom-api (dashboard) au lieu de scripts/metrics/axiom-api Utiliser scripts/metrics/axiom-api pour /v1/query/*, /v1/datasets.
Statistic montre 1 au lieu de 100% pour ratio 0–1 La Console ne met pas à l'échelle l'unité OTel 1 \| map * 100 en MPL, puis chart-add --unit "%".
Statistic montre l'unité deux fois ($1.031K$) Suffixe customUnits sur une unité que la Console formate ("$" sur USD) Passer le code UCUM (--unit USD). chart-add rejette $.
Statistic MPL montre un nombre brut après map ou un rate Le résultat ne porte plus l'unité de la métrique Passer l'unité du résultat à chart-add --unit (map / 3600 sur s donne --unit h).
Tuile rate MPL montre KB au lieu de KB/s --unit nomme l'unité de la métrique, pas du rate Passer l'unité par-seconde (prom::rate sur By donne --unit By/s).
Graphique histogram OTel montre du charabia Histogram aligné comme scalaire Utiliser bucket … using interpolate_cumulative_histogram (ou _delta par temporality). Voir promql-to-mpl.md § Histogram translation.
Migration Grafana filtre/groupe sur le mauvais sous-ensemble Lire expr sans description, ou vice versa Projeter les cinq champs de panneau avant authoring ; voir reference/grafana-migration.md.
Nom de métrique PromQL non trouvé Omis les règles de renommage OTel Supprimer _total, décomposer histograms, normaliser unités ; valider avec listMetrics. Les labels ont besoin découverte reverse-tag. Voir grafana-migration.md § Name Mapping.
Graphique MPL agrège à travers une dimension que PromQL a filtré/groupé Supprimé un sélecteur ou by(...) lors de la traduction Chaque {label=…} → where ; chaque by(…) → group by. Voir reference/promql-to-mpl.md.
Panneau a livré une quantité différente de celle demandée Substitué au lieu de reporter Remplacer par une Note documentant le blocage. Voir Calculer ou reporter.
403 « création de tableaux privés » Les tokens API créent uniquement les tableaux partagés Laisser owner comme défaut de dashboard-assemble (X-AXIOM-EVERYONE).
400 invalid_dashboard lors d'ajout de sections JSON de graphique a inventé sections ou sectionId Passer --section / --section-collapsed à dashboard-assemble. Ne pas sonder l'API.

Référence

  • reference/chart-config.md — Toutes les options de configuration de graphique (JSON)
  • reference/metrics-mpl.md — Contrat de graphique Métriques/MPL et scripts de découverte
  • reference/smartfilter.md — Configuration complète SmartFilter/FilterBar
  • reference/chart-cookbook.md — Motifs APL par type de graphique
  • reference/layout-recipes.md — Layouts de grille et blueprints de section
  • reference/splunk-migration.md — Panneau Splunk → Axiom mapping
  • reference/grafana-migration.md — Panneau Grafana → Axiom mapping (projection canonical-spec, pointeurs PromQL→MPL, règles de renommage OTel)
  • reference/promql-to-mpl.md — Règles de traduction PromQL → MPL (sélecteurs, groupages, rate, histograms, ratios, découverte reverse-tag)
  • reference/design-playbook.md — Principes de conception décision-first
  • reference/templates/ — Fichiers JSON de tableau de bord prêts à l'emploi

Pour syntaxe APL : https://axiom.co/docs/apl/introduction

Skills similaires