spl-to-apl

Traduit les requêtes Splunk SPL en Axiom APL. Fournit des correspondances de commandes, des équivalents de fonctions et des transformations de syntaxe. À utiliser lors d'une migration depuis Splunk, pour convertir des requêtes SPL ou pour apprendre les équivalents APL des patterns SPL.

npx skills add https://github.com/axiomhq/skills --skill spl-to-apl

Traducteur SPL vers APL

Sécurité des types : Les champs comme status sont souvent stockés en tant que chaînes. Toujours transtyper avant une comparaison numérique : toint(status) >= 500, pas status >= 500.


Différences critiques

  1. Le temps est explicite en APL : Les sélecteurs de temps SPL ne se traduisent pas — ajouter where _time between (ago(1h) .. now())
  2. Structure : SPL index=... | command → APL ['dataset'] | operator
  3. Join est une preview : limitée à 50k lignes, inner/innerunique/leftouter uniquement
  4. Paramètres cidrmatch inversés : SPL cidrmatch(cidr, ip) → APL ipv4_is_in_range(ip, cidr)

Mappages de commandes principales

SPL APL Notes
search index=... ['dataset'] Dataset remplace index
search field=value where field == "value" where explicite
where where Identique
stats summarize Syntaxe d'agrégation différente
eval extend Créer/modifier des champs
table / fields project Sélectionner des colonnes
fields - project-away Supprimer des colonnes
rename x as y project-rename y = x Renommer
sort / sort - order by ... asc/desc Trier
head N take N Limiter les lignes
top N field summarize count() by field \| top N by count_ Deux étapes
dedup field summarize arg_max(_time, *) by field Garder le plus récent
rex parse ou extract() Extraction regex
join join Fonctionnalité preview
append union Combiner des datasets
mvexpand mv-expand Développer les tableaux
timechart span=X summarize ... by bin(_time, X) Binning manuel
rare N field summarize count() by field \| order by count_ asc \| take N Bottom N
spath parse_json() ou json['path'] Accès JSON
transaction Pas d'équivalent direct Utiliser summarize + make_list

Mappages complets : reference/command-mapping.md


Stats → Summarize

# SPL
| stats count by status

# APL  
| summarize count() by status

Mappages de fonctions clés

SPL APL
count count()
count(field) countif(isnotnull(field))
dc(field) dcount(field)
avg/sum/min/max Identique
median(field) percentile(field, 50)
perc95(field) percentile(field, 95)
first/last arg_min/arg_max(_time, field)
list(field) make_list(field)
values(field) make_set(field)

Motif de comptage conditionnel

# SPL
| stats count(eval(status>=500)) as errors by host

# APL
| summarize errors = countif(status >= 500) by host

Liste complète des fonctions : reference/function-mapping.md


Eval → Extend

# SPL
| eval new_field = old_field * 2

# APL
| extend new_field = old_field * 2

Mappages de fonctions clés

SPL APL Notes
if(c, t, f) iff(c, t, f) Double 'f'
case(c1,v1,...) case(c1,v1,...,default) Nécessite un default
len(str) strlen(str)
lower/upper tolower/toupper
substr substring 0-indexé en APL
replace replace_string
tonumber toint/tolong/toreal Types explicites
match(s,r) s matches regex "r" Opérateur
split(s, d) split(s, d) Identique
mvjoin(mv, d) strcat_array(arr, d) Joindre un tableau
mvcount(mv) array_length(arr) Longueur du tableau

Motif case statement

# SPL
| eval level = case(
    status >= 500, "error",
    status >= 400, "warning",
    1==1, "ok"
  )

# APL  
| extend level = case(
    status >= 500, "error",
    status >= 400, "warning",
    "ok"
  )

Note : Le catch-all 1==1 de SPL devient un default implicite en APL.


Rex → Parse/Extract

# SPL
| rex field=message "user=(?<username>\w+)"

# APL - parse avec regex
| parse kind=regex message with @"user=(?P<username>\w+)"

# APL - fonction extract  
| extend username = extract("user=(\\w+)", 1, message)

Motif simple (non-regex)

# SPL
| rex field=uri "^/api/(?<version>v\d+)/(?<endpoint>\w+)"

# APL
| parse uri with "/api/" version "/" endpoint

Gestion du temps

Les sélecteurs de temps SPL ne se traduisent pas. Toujours ajouter une plage de temps explicite :

# SPL (sélecteur de temps : Last 24 hours)
index=logs

# APL
['logs'] | where _time between (ago(24h) .. now())

Traduction timechart

# SPL
| timechart span=5m count by status

# APL
| summarize count() by bin(_time, 5m), status

Motifs courants

Calcul du taux d'erreur

# SPL
| stats count(eval(status>=500)) as errors, count as total by host
| eval error_rate = errors/total*100

# APL
| summarize errors = countif(status >= 500), total = count() by host
| extend error_rate = toreal(errors) / total * 100

Sous-requête (subsearch)

# SPL
index=logs [search index=errors | fields user_id | format]

# APL
let error_users = ['errors'] | where _time between (ago(1h) .. now()) | distinct user_id;
['logs']
| where _time between (ago(1h) .. now())
| where user_id in (error_users)

Joindre des datasets

# SPL
| join user_id [search index=users | fields user_id, name]

# APL
| join kind=inner (['users'] | project user_id, name) on user_id

Groupement de type transaction

# SPL
| transaction session_id maxspan=30m

# APL (pas d'équivalent direct — reconstruire avec summarize)
| summarize 
    start_time = min(_time),
    end_time = max(_time),
    events = make_list(pack("time", _time, "action", action)),
    duration = max(_time) - min(_time)
  by session_id
| where duration <= 30m

Performance de correspondance de chaînes

SPL APL Vitesse
field="value" field == "value" La plus rapide
field="*value*" field contains "value" Modérée
field="value*" field startswith "value" Rapide
match(field, regex) field matches regex "..." La plus lente

Préférer has à contains (la correspondance de limite de mot est plus rapide). Utiliser les variantes _cs pour la sensibilité à la casse (plus rapide).


Référence

  • reference/command-mapping.md — liste complète des commandes
  • reference/function-mapping.md — liste complète des fonctions
  • reference/examples.md — exemples complets de traduction de requêtes
  • Docs APL : https://axiom.co/docs/apl/introduction

Skills similaires