Die Basis-Suche & das Pipe |
Merke: Alles vor der ersten Pipe ist die Basis-Suche. Danach kommt | + Befehl. Wie Unix-Pipes.
Nur Basis-Suche (Rohdaten)
index=firewall action=blocked
Basis-Suche + eine Pipe
index=firewall action=blocked
| stats count by src_ip
Verkettete Pipes
index=firewall action=blocked
| stats count by src_ip
| sort -count
| head 10
Tipp: Filtere so früh wie möglich in der Pipe-Kette → weniger Events zu verarbeiten = schneller.
Implizites AND zwischen Termen
Mehrere Begriffe ohne Operator werden mit AND verknüpft. Splunk fügt das AND implizit ein.
Diese Queries sind äquivalent
index=windows EventCode=4625 User=admin
index=windows EventCode=4625 AND User=admin
Logische Operatoren
| Operator | Beispiel | Bedeutung |
AND | error AND timeout | Beide müssen vorkommen |
OR | error OR warning | Eines muss vorkommen |
NOT | NOT error | Darf nicht vorkommen |
( ) | (A OR B) AND C | Gruppierung / Vorrang |
Beispiel mit Gruppierung
index=auth (failed OR error) AND NOT src_ip=10.0.0.1
Index – Datenquelle bestimmen
Der Index ist der primäre Filter. Ohne index= durchsucht Splunk alle Indizes, auf die du Zugriff hast — teuer!
Syntax-Varianten
index=windows
index=windows OR index=linux
index=prod_*
index=*
Typische CSIRT-Indizes
Firewall / NSM
index=network
Index + Sourcetype kombinieren
index=windows sourcetype=WinEventLog:Security
index=network sourcetype=cisco:asa
Metadata – Indizes & Sourcetypes entdecken
Was ist metadata? Ein spezieller SPL-Befehl, der nicht Events durchsucht, sondern die Metadaten der Indizes abfragt – z.B. welche Sourcetypes, Hosts oder Sources existieren, wann zuletzt Daten kamen, und wie viele Events vorhanden sind. Extrem schnell, da keine Event-Daten gelesen werden.
Alle verfügbaren Indizes anzeigen
| tstats count as totalCount, max(_time) as recentTime where index=* by index
| rename index as title
| table title, totalCount, recentTime
| eventcount summarize=false index=*
| dedup index
| table index
Alle Sourcetypes eines Index anzeigen
| metadata type=sourcetypes index=botsv1
index=botsv1 | stats count by sourcetype
Alle Indizes mit ihren Sourcetypes (Gesamtübersicht)
| tstats count as totalCount, max(_time) as recentTime where index=* by index, sourcetype
| eval last_seen=strftime(recentTime, "%Y-%m-%d %H:%M:%S")
| table index, sourcetype, totalCount, last_seen
| sort index
Metadata-Typen
| type= | Zeigt | Typischer Use Case |
sourcetypes | Alle Sourcetypes | Welche Log-Formate sind vorhanden? |
sources | Alle Source-Pfade | Woher kommen die Daten? |
hosts | Alle Hosts | Welche Systeme liefern Logs? |
Tipp: metadata ist ideal, um sich in einer unbekannten Splunk-Umgebung schnell zurechtzufinden – z.B. bei BOTSv1/v2/v3 Datasets.
Zeitraum & Time Handling
index=windows earliest=-24h latest=now
index=windows earliest=-7d@d latest=@d
index=windows
earliest="06/01/2025:00:00:00"
latest="06/11/2025:23:59:59"
| Kürzel | Bedeutung |
-1h | Letzte Stunde |
-24h | Letzte 24 Stunden |
-7d@d | 7 Tage, auf Tagesbeginn gerundet |
@w0 | Anfang dieser Woche (Sonntag) |
@mon | Anfang dieses Monats |
Zeitkonvertierung in der Pipeline
| eval human = strftime(_time, "%Y-%m-%d %H:%M:%S %Z")
| eval ts = strptime(date, "%d/%b/%Y:%H:%M:%S")
| eval minuten = round((end-start)/60, 2)
| bin _time span=5m
| stats count by _time
Wichtige SPL-Befehle
| Befehl | Beschreibung | Beispiel |
stats | Aggregation: count, sum, avg, dc, values | stats count by host |
table | Felder als Tabelle ausgeben | table _time, host, status |
fields | Felder ein-/ausschließen | fields + host, status |
where | Filtert nach Ausdruck auf Feldern | where len(user) > 3 |
search | Volltext-Filter in der Pipeline | search status=500 |
eval | Neue Felder berechnen / transformieren | eval gb=bytes/1GB |
rex | Regex-Extraktion auf Felder | rex "user=(?<u>\w+)" |
dedup | Duplikate entfernen | dedup src_ip |
sort | Sortieren (- = absteigend) | sort -count, +host |
head/tail | Erste / letzte N Ergebnisse | head limit=20 |
rename | Felder umbenennen | rename data.user as user |
top/rare | Häufigste / seltenste Werte | top limit=10 useragent |
timechart | Zeitbasierte Aggregation für Charts | timechart count by status |
chart | Statistik-Tabelle mit Split | chart avg(cpu) over host |
lookup | Externe Tabelle joinen (IOC) | lookup ioc.csv ip OUTPUT cat |
transaction | Events zu Sessions gruppieren | transaction session maxspan=30m |
eventstats | Statistiken als Felder hinzufügen | eventstats avg(rt) by host |
streamstats | Laufende Summen / Kumulativ | streamstats sum(bytes) as total |
bin | Werte in Buckets gruppieren | bin _time span=5m |
tstats | High-Perf. auf indizierten Feldern | tstats count where index=web |
appendpipe | Summenzeile ans Ergebnis anhängen | appendpipe [stats sum(count)] |
fillnull | Null-Werte ersetzen | fillnull value="N/A" |
mvexpand | Multivalue in Einzel-Events | mvexpand recipients |
inputlookup | CSV als Datenquelle laden | inputlookup employees.csv |
outputlookup | Ergebnisse in CSV schreiben | outputlookup results.csv |
Praxis-Queries (CSIRT)
Brute-Force Logins erkennen
index=windows sourcetype=WinEventLog:Security EventCode=4625
| stats count by src_ip, Account_Name
| where count > 10
| sort -count
PowerShell Execution mit Encoded Command
index=edr process_name="powershell.exe" CommandLine=*-EncodedCommand*
| table _time, host, user, CommandLine
| sort -_time
Lateral Movement via Remote Services (4648)
index=windows EventCode=4648 earliest=-1h
| eval pair=src_user." → ".dest_host
| stats count values(pair) as targets by src_host
| where count > 3
IOC-Lookup gegen Threat Intel Liste
index=network sourcetype=firewall
| lookup malicious_ips.csv dest_ip OUTPUT threat_category
| where isnotnull(threat_category)
| table _time, src_ip, dest_ip, threat_category
Neues Gerät im Netz (first seen)
index=network earliest=-30d
| stats min(_time) as first_seen by src_mac, src_ip
| where first_seen > relative_time(now(), "-24h")
| convert ctime(first_seen)
Wildcards & Feldsuche
process_name=powershell*
CommandLine=*mimikatz*
src_ip=*
NOT error_code=*
Performance: Wildcards am Anfang (*xyz) erzwingen einen Full-Scan. Wenn möglich vermeiden oder mit Index-Filterung kombinieren.
eval – Felder berechnen
| eval asset=host.":".src_ip
| eval severity=if(count>100, "HIGH", "LOW")
| eval risk=case(
score>80, "Critical",
score>50, "Medium",
1==1, "Low"
)
| eval user=coalesce(username, email, "anonymous")
| eval human_time=strftime(_time, "%Y-%m-%d %H:%M:%S")
| eval epoch=strptime(date_field, "%d/%b/%Y:%H:%M:%S")
| eval gb=bytes/1024/1024/1024
| eventstats avg(rt) as avg_rt, stdev(rt) as stdev_rt
| where rt > (avg_rt + 2*stdev_rt)
String-Operationen
Konkatenation
| eval full_name = first_name . " " . last_name
Substring
| eval short = substr(word, 1, 3)
Regex Replacement (rex mode=sed)
| rex mode=sed field=msg "s/\s+/ /g"
| rex mode=sed field=email "s/@/ [at] /"
replace – einfache Ersetzung
| replace "localhost" with "127.0.0.1" in host
Whitespace ignorieren beim Match
| rex field=MessageStatus "(?<status>\w+)"
| eval ok=if(status="delivered", "yes", "no")
Multivalue-Felder
| mvexpand recipients
| eval first = mvindex(items, 0)
| eval userlist = mvjoin(users, ", ")
| eval errors = mvfilter(match(msgs, "ERROR"))
Filterung: where vs search
where – Ausdrücke & Funktionen
| where isnotnull(user) AND len(user) > 3
| where like(url, "%/api/%")
search – Keyword-Matching mit Wildcards
| search user=admin* status!=404
NOT vs != (wichtiger Unterschied!)
status!=500
NOT status=500
Merke: != filtert nur explizite Werte. Mit NOT werden auch Events ohne das Feld ausgeschlossen. Für "alles außer X mit Feld" nimm !=; für "garantiert keine X" nimm NOT.
Analyse: Perzentile & Ausreisser
Perzentile
index=web
| stats avg(rt) as avg_rt,
median(rt) as p50_rt,
perc95(rt) as p95_rt,
perc99(rt) as p99_rt
by endpoint
Ausreisser mit Standardabweichung
index=web
| eventstats avg(rt) as avg_rt, stdev(rt) as stdev_rt
| where rt > (avg_rt + 2*stdev_rt)
Statistische Verteilung
| stats count, dc(src_ip) as unique_visitors,
values(useragent) as ua_list by endpoint
Lookup-Tabellen
CSV-Lookup zur Anreicherung
index=network
| lookup threat_intel.csv ip as src_ip
OUTPUT threat_level, category
Lookup als Datenquelle nutzen
| inputlookup employees.csv
| search department="IT"
Ergebnisse in Lookup schreiben
index=web status=500
| stats count by src_ip
| where count > 100
| outputlookup suspicious_ips.csv
Use Case: IOC-Liste als CSV anlegen und per lookup gegen Firewall-Logs joinen → sofortige Trefferanzeige.
Transaktionen
Session Grouping (teuer)
index=web
| transaction session_id maxspan=30m maxpause=5m
| where duration > 60
| table session_id, duration, eventcount
Alternative mit stats (schneller)
| stats min(_time) as start, max(_time) as end,
count as events by session_id
| eval duration = end - start
| where duration > 60
Performance: transaction ist ressourcenintensiv. Nutze stats + min(_time) / max(_time) wenn möglich.
Mehrere Queries kombinieren
Subsearch
index=web user=[search index=vpn
| dedup user | fields user]
| stats count by user
Join
index=main
| join type=left user [
search index=hr
| stats count by user
]
Append
index=web status=500
| stats count as errors by host
| append [
search index=web status=200
| stats count as success by host
]
Tipp: Subsearch-Ergebnisse werden auf 10.000 Events begrenzt (einstellbar mit format). Subsearch immer in eckige Klammern [ ] setzen!
Performance-Tipps
index=web sourcetype="access_log" status=500
| fields host, status, response_time
| stats avg(response_time) by host
| tstats count where index=web by host, status
| stats min(_time) as start by session
Reguläre Ausdrücke (rex)
Felder extrahieren
| rex field=_raw "user=(?<username>\w+)"
| rex field=url "\/api\/(?<version>v\d+)\/(?<endpoint>\w+)"
Mehrere Treffer pro Event (max_match)
| rex field=_raw max_match=0
"error_code=(?<codes>\d+)"
Häufige Regex-Patterns
(?<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})
(?<email>[\w.+-]+@[\w-]+\.\w+)
(?<uuid>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})
(?<path>\/[\w\/.-]+)
(?<domain>(?:https?:\/\/)?([\w.-]+)\/)
Tips & Tricks
|
|
Macro
`get_errors(index)`
Schnelle Feldübersicht
| fieldsummary
| top limit=20 useragent
| highlight error, warning, critical
Alerting – Error Rate überwachen
index=web
| bin _time span=5m
| stats count(eval(status>=500)) as errors,
count as total by _time
| eval error_rate = round(errors/total*100, 2)
| where error_rate > 5
Nützliche SPL-Idiome
| fillnull value="N/A" username, email
| eval users = mvjoin(mvdedup(user_list), ", ")
| stats count(eval(status="success")) as successes,
count(eval(status="failure")) as failures
| sort -_time | dedup src_ip
| rename signals.ip_address as ip_addr
| eval ip_addr = if(isnull(ip_addr), "unknown", ip_addr)
JSON & strukturierte Daten (spath)
spath extrahiert Felder aus JSON/XML. Splunk parst Top-Level-JSON oft automatisch – für verschachtelte Pfade brauchst du spath explizit.
Verschachteltes Feld extrahieren
index=api sourcetype=json
| spath output=user path=event.actor.username
| spath output=action path=event.action
| table _time, user, action
JSON aus einem Feld (statt _raw) parsen
| spath input=payload
Array-Elemente ansprechen & aufsplitten
| spath path=event.tags{} output=tags
| mvexpand tags
| spath path=event.ips{0} output=first_ip
Tipp: {} steht für „alle Array-Elemente", {0} für ein bestimmtes. Mit | eval x=json_extract(_raw, "a.b") geht Ähnliches direkt in eval.
IP- & Netzwerk-Analyse
CIDR-Match – gehört IP zu Subnetz?
index=network
| where cidrmatch("10.0.0.0/8", src_ip)
| eval zone=if(cidrmatch("10.0.0.0/8", src_ip), "intern", "extern")
GeoIP – Herkunft anreichern
index=network action=blocked
| iplocation src_ip
| stats count by Country, City
| sort -count
Geo-Karte rendern
| iplocation src_ip
| geostats count
Verdächtige Länder / seltene Geo-Logins
index=auth action=success
| iplocation src_ip
| stats dc(Country) as laender values(Country) as liste by user
| where laender > 1
Impossible Travel: Logins desselben Users aus mehreren Ländern in kurzer Zeit sind ein starkes Kompromittierungs-Signal.
Encoding & Decoding (CSIRT)
Angreifer verschleiern gerne per Base64 / URL-Encoding. Beim Decodieren wird der wahre Befehl sichtbar.
URL-Decoding (nativ)
| eval clear = urldecode(request_uri)
PowerShell -EncodedCommand isolieren
index=edr CommandLine=*-enc*
| rex field=CommandLine "-[eE]nc(?:odedCommand)?\s+(?<b64>[A-Za-z0-9+/=]+)"
| table _time, host, user, b64
Base64 decodieren (URL Toolbox App)
| eval decoded = base64decode(b64)
| rex mode=sed field=decoded "s/\x00//g"
Hinweis: base64decode() ist keine Core-Funktion – sie kommt aus der App URL Toolbox. Ohne App per Lookup/Script decodieren.
Windows Security Event Codes (Referenz)
| EventCode | Bedeutung | Relevanz für Detection |
4624 | Erfolgreiche Anmeldung | Logon-Type prüfen (3=Netzwerk, 10=RDP) |
4625 | Fehlgeschlagene Anmeldung | Brute-Force / Password-Spraying |
4634/4647 | Logoff | Session-Dauer, Transaktionen |
4648 | Logon mit expliziten Credentials | Lateral Movement, RunAs |
4672 | Sonderrechte bei Anmeldung | Admin-/Privileged-Logon |
4688 | Prozess erstellt | Process-Tree, verdächtige CommandLine |
4689 | Prozess beendet | Lebensdauer kurzlebiger Prozesse |
4720 | Benutzerkonto erstellt | Persistenz / Rogue-Accounts |
4726 | Benutzerkonto gelöscht | Anti-Forensik |
4728/4732 | Zu (Global/Local) Gruppe hinzugefügt | Privilege Escalation |
4740 | Konto gesperrt (Lockout) | Brute-Force-Nebeneffekt |
4768/4769 | Kerberos TGT / Service-Ticket | Kerberoasting, Golden/Silver Ticket |
1102 | Audit-Log gelöscht | Anti-Forensik – immer alarmieren |
7045 | Neuer Dienst installiert | Persistenz (System-Log) |
4104 | PowerShell Script Block Logging | Obfuskierte Skripte (Op.-Log) |
Tipp: 4688 & 4104 müssen per GPO aktiviert werden – sonst fehlen dir die wertvollsten Detection-Quellen.
Data Models & tstats (CIM)
Beschleunigte Data Models (CIM) erlauben blitzschnelle Suchen über normalisierte Felder – ideal für Dashboards & Correlation Searches.
tstats auf beschleunigtem Data Model
| tstats summariesonly=true count
from datamodel=Authentication
where Authentication.action=failure
by Authentication.user, Authentication.src
Data Model als Datenquelle
| datamodel Network_Traffic All_Traffic search
| stats sum(All_Traffic.bytes) as bytes by All_Traffic.dest
Verfügbare Data Models auflisten
| datamodel
summariesonly=true nutzt nur beschleunigte Daten (sehr schnell), verpasst aber noch nicht beschleunigte Events. Für Vollständigkeit: false.
REST API & Introspection
Der | rest-Befehl fragt die Splunk-Management-API ab – z.B. für Indizes (auch leere!), User oder laufende Suchen.
Alle Indizes inkl. Größe & Zeitspanne
| rest /services/data/indexes
| table title, totalEventCount, currentDBSizeMB, maxTime, minTime
| sort -currentDBSizeMB
Aktuell laufende Suchen (Jobs)
| rest /services/search/jobs
| search isDone=0
| table author, label, runDuration, sid
Aktivierte Correlation Searches / Alerts
| rest /services/saved/searches
| search is_scheduled=1 disabled=0
| table title, cron_schedule, search
Use Case: | rest ist perfekt fürs Onboarding auf einem fremden Search Head – zeigt Lizenz, Indizes und Konfiguration ohne CLI-Zugriff.
Testing & Utility-Befehle
Testdaten ohne Index (makeresults)
| makeresults count=5
| streamstats count as row
| eval status = if(row%2==0, "ok", "fail")
foreach – über mehrere Felder iterieren
| foreach *_bytes
[ eval <<FIELD>>_mb = '<<FIELD>>'/1024/1024 ]
Summenzeile / Spaltensummen
| stats count by host, status
| addtotals row=true col=true labelfield=host
Feld-Diagnose einer unbekannten Quelle
index=neu
| fieldsummary
| table field, count, distinct_count, values
Ergebnisspalten transponieren
| stats count by status
| transpose
Detection Engineering: Baselines & Anomalien
Rolling Baseline mit streamstats (Zeitfenster)
index=proxy
| bin _time span=1h
| stats sum(bytes_out) as bytes by _time, src_ip
| streamstats window=24 avg(bytes) as avg, stdev(bytes) as sd by src_ip
| eval zscore = round((bytes-avg)/sd, 2)
| where zscore > 3
Rare / erstmalig gesehene Kombinationen (first seen)
index=edr earliest=-30d
| stats earliest(_time) as first, latest(_time) as last, count by host, process_name
| where first > relative_time(now(), "-24h")
| convert ctime(first) ctime(last)
Beaconing erkennen (gleichmäßige Intervalle)
index=proxy
| sort 0 src_ip, _time
| streamstats current=f last(_time) as prev by src_ip, dest
| eval delta = _time - prev
| stats count, avg(delta) as avg_delta, stdev(delta) as sd_delta by src_ip, dest
| where count > 20 AND sd_delta < 5
Textcluster – ähnliche Log-Zeilen gruppieren
index=app error
| cluster field=_raw t=0.8 showcount=true
| table cluster_count, _raw
| sort -cluster_count
Merke: eventstats/streamstats berechnen Statistiken ohne die Events zu kollabieren – dadurch kannst du jedes Event gegen seine Baseline vergleichen (Z-Score, Abweichung).
Search Macros – Wiederverwendung
Macros kapseln wiederkehrende SPL-Bausteine. Aufruf mit Backticks `name`. Definiert unter Settings → Advanced Search → Macros.
Macro ohne Argumente aufrufen
index=windows
| `windows_logons`
Macro mit Argumenten
index=windows
| `failed_logins(10.0.0.5)`
Macro-Definition ansehen (Introspection)
| rest /servicesNS/-/-/admin/macros
| table title, definition, args
Tipp: Macro-Namen mit Argumenten brauchen die Anzahl im Namen: failed_logins(1). Ideal für standardisierte Detection-Logik im ganzen Team.
Alerts & Scheduled Searches
Eine gespeicherte Suche + Trigger-Bedingung + Aktion (E-Mail, Webhook, Notable) = Alert. Zeitplan per Cron.
Trigger-Query: mehr als N Treffer
index=windows EventCode=4625
| stats count by src_ip
| where count > 20
Throttling gegen Alert-Flut
| Einstellung | Zweck |
| Trigger: per-result | Pro Treffer feuern |
Throttle by src_ip | Gleiche IP nicht doppelt melden |
| Suppress 1h | Ruhezeit nach Alarm |
Cron-Zeitplan (Beispiele)
Best Practice: Zeitfenster (earliest) etwas größer als das Cron-Intervall wählen (Überlappung), damit keine Events zwischen zwei Läufen durchrutschen.
join & Subsearch vermeiden – bessere Muster
join und Subsearches sind auf 50.000 Zeilen (join) bzw. 10.000 Events / 60 s (subsearch) begrenzt und oft langsam. Meist gibt es ein schnelleres, vollständiges stats-Muster.
❌ join (langsam, limitiert)
index=web
| join user [ search index=hr | fields user, dept ]
✓ stats-Merge (schnell, kein Limit)
index=web OR index=hr
| stats values(dept) as dept, count(eval(index=="web")) as hits by user
| where hits > 0
✓ Lookup statt Subsearch-Filter
index=vpn | stats count by user | outputlookup vpn_users.csv
index=web | lookup vpn_users.csv user | where isnotnull(count)
✓ format – Subsearch bewusst als Filter
index=vpn | top limit=100 user | fields user | format
Faustregel: Sobald du join tippst, frag dich: „Geht das mit stats … by <key> über beide Indizes?" – meistens ja, und ohne Zeilenlimit.
MITRE ATT&CK – Detection-Mapping
Beispiel-Queries je Taktik. Feldnamen an dein Datenmodell anpassen – die Muster gelten generisch (auch für BOTSv1/v2/v3).
| Technik | Detection-Idee | SPL-Kern |
T1110 Brute Force | Viele 4625 pro Quelle | EventCode=4625 | stats count by src_ip | where count>20 |
T1059.001 PowerShell | Encoded/obfuskiert | 4104 OR CommandLine=*-enc* | search *FromBase64String* |
T1071 C2 / Beaconing | Gleichmäßige Intervalle | streamstats … | stats stdev(delta) | where sd<5 |
T1078 Valid Accounts | Login aus neuem Land | iplocation src_ip | stats dc(Country) by user | where >1 |
T1053 Scheduled Task | schtasks / 4698 | EventCode=4698 OR process_name=schtasks.exe |
T1003 Cred Dumping | lsass-Zugriff / mimikatz | CommandLine=*mimikatz* OR TargetImage=*lsass.exe* |
T1070.001 Log Clearing | Audit-Log gelöscht | EventCode=1102 |
T1105 Ingress Transfer | certutil/bitsadmin Download | process_name IN (certutil.exe,bitsadmin.exe) CommandLine=*http* |
Tipp: Wenn die App Splunk Security Essentials installiert ist, findest du für viele Techniken fertige Beispiel-Suchen inkl. ATT&CK-Navigator-Export.
Boss of the SOC (BOTS) – Starter-Queries
Die BOTSv1/v2/v3-Datasets sind Übungsdaten für SOC-Analysten. Diese Queries helfen beim ersten Erkunden – Index heißt je nach Setup botsv1, botsv2 oder botsv3.
1 · Überblick: was steckt drin?
| tstats count where index=botsv1 by sourcetype
| sort -count
2 · Web-Angriffe finden (Stream/Suricata)
index=botsv1 sourcetype=stream:http http_method=POST
| search form_data=*passwd* OR uri=*sql*
| table _time, src_ip, dest_ip, uri, http_user_agent
3 · Verdächtige User-Agents (Scanner-Fingerprint)
index=botsv1 sourcetype=stream:http
| stats count by http_user_agent
| search http_user_agent=*acunetix* OR http_user_agent=*nikto* OR http_user_agent=*sqlmap*
4 · Sysmon: Prozess-Ketten (Parent → Child)
index=botsv1 sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
| table _time, Computer, ParentImage, Image, CommandLine
| sort -_time
Workflow: Erst mit Query 1 die Sourcetypes entdecken, dann gezielt pro Sourcetype tiefer graben. Genau dafür ist | tstats … by sourcetype der schnellste Einstieg.