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
- Le temps est explicite en APL : Les sélecteurs de temps SPL ne se traduisent pas — ajouter
where _time between (ago(1h) .. now()) - Structure : SPL
index=... | command→ APL['dataset'] | operator - Join est une preview : limitée à 50k lignes, inner/innerunique/leftouter uniquement
- Paramètres cidrmatch inversés : SPL
cidrmatch(cidr, ip)→ APLipv4_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 commandesreference/function-mapping.md— liste complète des fonctionsreference/examples.md— exemples complets de traduction de requêtes- Docs APL : https://axiom.co/docs/apl/introduction