Day 4: Fields and Filtering
What You Will Learn Today
- Types of fields and how they are extracted
- Creating fields with the eval command
- Filtering with the where command
- Extracting fields with the rex command
- Field aliases and calculated fields
Types of Fields
Splunk fields fall into two broad categories: default fields and extracted fields.
flowchart TB
subgraph Fields["Field Types"]
Default["Default Fields<br>_time, host, source,<br>sourcetype, _raw"]
Extracted["Extracted Fields<br>Automatic: status, user<br>Manual: rex, erex"]
Calculated["Calculated Fields<br>Created with eval"]
end
style Default fill:#3b82f6,color:#fff
style Extracted fill:#22c55e,color:#fff
style Calculated fill:#f59e0b,color:#fff
Default Fields
| Field | Description |
|---|---|
_time |
Event timestamp |
_raw |
Raw event data |
host |
The host that generated the data |
source |
The data source (file path, etc.) |
sourcetype |
The data type |
index |
The destination index |
_indextime |
The time the event was indexed |
linecount |
Number of lines in the event |
Automatic Field Extraction
Splunk automatically extracts fields from key=value patterns.
2026-01-30 10:00:01 status=200 user=alice duration=0.023
From the log above, status, user, and duration are automatically extracted as fields.
The eval Command
Use eval to create new fields or transform existing ones.
Basic Usage
index=main
| eval response_time_ms = duration * 1000
| eval status_category = if(status >= 400, "Error", "OK")
| table _time, status, status_category, duration, response_time_ms
eval Functions
String Functions
| eval lower_user = lower(user)
| eval upper_host = upper(host)
| eval greeting = "Hello, " . user # String concatenation
| eval domain = replace(email, ".*@", "")
| eval length = len(message)
| eval first3 = substr(uri, 1, 3)
| Function | Description | Example |
|---|---|---|
lower(x) |
Convert to lowercase | lower("ABC") -> "abc" |
upper(x) |
Convert to uppercase | upper("abc") -> "ABC" |
len(x) |
String length | len("hello") -> 5 |
substr(x,s,e) |
Substring | substr("hello",1,3) -> "hel" |
replace(x,r,n) |
Regex replacement | replace(ip, "\.\d+$", ".0") |
trim(x) |
Strip whitespace | trim(" abc ") -> "abc" |
Numeric Functions
| eval rounded = round(duration, 2)
| eval absolute = abs(difference)
| eval power = pow(2, 10)
| eval log_value = log(count, 10)
Conditional Functions
# if
| eval severity = if(status >= 500, "Critical", "Normal")
# case
| eval severity = case(
status >= 500, "Critical",
status >= 400, "Warning",
status >= 300, "Redirect",
1=1, "OK"
)
# coalesce (returns the first non-null value)
| eval display_name = coalesce(full_name, username, "Unknown")
# null check
| eval has_error = if(isnull(error_message), "No", "Yes")
Date/Time Functions
| eval event_date = strftime(_time, "%Y-%m-%d")
| eval event_hour = strftime(_time, "%H")
| eval day_of_week = strftime(_time, "%A")
| eval epoch = strptime("2026-01-30", "%Y-%m-%d")
| eval elapsed = now() - _time
| Function | Description |
|---|---|
strftime(_time, fmt) |
Format a timestamp as a string |
strptime(str, fmt) |
Parse a string into a timestamp |
now() |
Current epoch time |
relative_time(t, offset) |
Calculate a relative time |
The where Command
Use where for advanced filtering with eval expressions.
# Basic comparison
index=main
| where status >= 400
# String comparison (where is case-sensitive)
index=main
| where user = "alice"
# Filtering with functions
index=main
| where like(uri, "/api/%")
| where len(user) > 3
| where isnotnull(error_message)
# Regex matching
index=main
| where match(uri, "^/api/v[0-9]+/")
search vs where
| Comparison | search |
where |
|---|---|---|
| Position | Before or after the pipe | After the pipe only |
| Case sensitivity | Case-insensitive | Case-sensitive |
| Wildcards | Uses * |
Uses like() |
| eval functions | Not available | Available |
| Speed | Faster | Slightly slower |
# search (keyword search, case-insensitive)
index=main
| search user=alice status>400
# where (eval expression, case-sensitive)
index=main
| where user="alice" AND status > 400
The rex Command
Use rex to extract fields with regular expressions.
# Extract an IP address
index=main
| rex field=_raw "(?P<ip_address>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"
| table _time, ip_address
# Extract an email address
index=main
| rex field=_raw "(?P<email>[\w.+-]+@[\w-]+\.[\w.]+)"
| table _time, email
# Extract path parameters from a URI
index=main
| rex field=uri "/api/(?P<api_version>v\d+)/(?P<resource>\w+)"
| table _time, api_version, resource
# Extract multiple named groups at once
index=main
| rex field=_raw "user=(?P<user>\w+).*status=(?P<status>\d+)"
Regex Syntax Reference
| Pattern | Description | Matches |
|---|---|---|
\d |
Digit | 0-9 |
\w |
Word character | a-z, 0-9, _ |
\s |
Whitespace | Space, tab |
. |
Any single character | Anything |
+ |
One or more | \d+ -> 123 |
* |
Zero or more | \d* -> "" or 123 |
? |
Zero or one | \d? -> "" or 1 |
(?P<name>...) |
Named capture group | Extracted as a field |
rex mode=sed
Use sed syntax to replace strings in place.
# Mask IP addresses
index=main
| rex mode=sed field=_raw "s/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/xxx.xxx.xxx.xxx/g"
Field Aliases and Calculated Fields
Configuring in props.conf
# props.conf
[my_sourcetype]
# Field aliases
FIELDALIAS-src = src_ip AS source_ip
FIELDALIAS-dst = dst_ip AS dest_ip
# Calculated fields
EVAL-response_time_ms = response_time * 1000
EVAL-severity = case(status >= 500, "critical", status >= 400, "warning", 1=1, "info")
Key point: Field aliases and calculated fields are applied automatically at search time, so you do not need to write
evalstatements in every query.
Hands-On: Log Analysis Queries
# 1. Classify response times
index=main sourcetype=access_combined
| eval response_class = case(
response_time < 0.1, "Fast",
response_time < 1.0, "Normal",
response_time < 5.0, "Slow",
1=1, "Critical"
)
| stats count by response_class
| sort response_class
# 2. Error rate by hour of day
index=main sourcetype=access_combined
| eval hour = strftime(_time, "%H")
| eval is_error = if(status >= 400, 1, 0)
| stats avg(is_error) AS error_rate by hour
| eval error_rate_pct = round(error_rate * 100, 2)
| table hour, error_rate_pct
| sort hour
# 3. Extract browser from user agent
index=main sourcetype=access_combined
| rex field=useragent "(?P<browser>Chrome|Firefox|Safari|Edge|Opera)"
| stats count by browser
| sort -count
# 4. Subnet analysis from IP addresses
index=main sourcetype=access_combined
| rex field=clientip "(?P<subnet>\d+\.\d+\.\d+)\.\d+"
| eval subnet = subnet . ".0/24"
| stats count by subnet
| sort -count
| head 10
Summary
| Concept | Description |
|---|---|
| Default fields | _time, host, source, sourcetype |
eval |
Create and transform fields |
where |
Filter using eval expressions |
rex |
Extract fields with regular expressions |
| Field aliases | Alternative names for existing fields |
| Calculated fields | Automatically applied eval expressions |
Key Takeaways
evalis the fundamental command for creating new fieldswhereuses eval functions for powerful filteringrexextracts fields from unstructured data using regex- Understand the difference between
searchandwhere(case sensitivity matters)
Exercises
Exercise 1: Basic
Use eval with case to classify HTTP status codes into "Success" (2xx), "Redirect" (3xx), "Client Error" (4xx), and "Server Error" (5xx).
Exercise 2: Applied
Use rex to extract the process name and PID from syslog messages, then display the event count per process.
Challenge
Combine eval and where to find error events that occurred outside business hours (before 9:00 or after 18:00), and aggregate them by hour of day.
References
Next up: In Day 5, you will learn about statistics and aggregation -- mastering stats, chart, and timechart to summarize your data.