Capturing & Extraction

This chapter covers the specialized capture syntax used for numeric and textual analysis. For the canonical explanation of how captured values drive query output, see Querying .

Numeric Capture

Capture integers or floating-point numbers for numeric analysis:

(?int) Capture an integer value
(?num(N)) Capture a floating-point value with fixed precision

Integer Capture Examples

Capture response times

.*took (?(?int))ms.*

Extracts milliseconds from "took 245ms" → y=245

Capture memory usage

.*memory: (?(?int)) MB.*

Plots memory usage over time

Capture HTTP status codes

.*HTTP/\d\.\d\" (?(?int)).*

Visualizes status code distribution

Floating-Point Capture

Capture precise latency (3 decimal places)

.*latency=(?(?num(3)))s.*

Captures "latency=0.123s" with 3-digit precision

Capture CPU percentage

.*cpu_usage=(?(?num(1)))%.*

Captures "cpu_usage=45.2%" → y=45.2

Textual Capture

Extract text for grouping and aggregation:

(?txt(subexpr)) Capture up to 31 bytes for textual analysis
(?subexpr) Capture as grouping key

Textual Analysis Examples

Group by error type

.*ERROR: (?(?txt([A-Za-z_]+))).*

Groups errors by type: "ConnectionTimeout", "AuthFailed", etc.

Group by service name

.*\[(?(?txt(\w+)))\].*

Aggregates logs by service tag like "[api]", "[worker]", "[db]"

Coordinate Capture (X/Y)

You can also capture named values such as X and Y coordinates:

(?subexpr) Capture numeric for X-coordinate
(?subexpr) Capture numeric for Y-coordinate

Scatter Plot Examples

Response time vs. payload size

.*size=(?(?int))B.*time=(?(?int))ms.*

Plots response time against request size

Error rate by hour (requires timestamp parsing)

.*T(?\d{2}):\d{2}:\d{2}.*status=(?(?int)).*

X=hour, Y=status code to see error patterns by time

Critical: Eager Matching Behavior

Important: Numeric capture in logging24 is eager and does not backtrack. The capture starts as soon as the pattern reaches the capture clause:

❌ Incorrect: Greedy prefix consumes too much

.*(?(?int)).*X.*

On "5 is X, 7 is Y", .* matches "5 is X, " and (?int) captures 7, not 5!

✅ Correct: Specific prefix

.*value for X is (?(?int)).*

Use unique prefixes to ensure correct capture

Combined Examples

Memory usage by service (textual key + numeric value)

.*\[(?(\w+))\].*mem=(?(?int))MB.*

Groups memory usage by service name in brackets

Response time distribution by endpoint

.*endpoint=(?(?txt(/\w+))).*time=(?(?int))ms.*

Shows latency per API endpoint

CPU vs Memory correlation

.*cpu=(?(?num(1)))%.*mem=(?(?int))MB.*

Scatter plot of CPU vs memory usage

Capture Size Limits

Textual captures are limited to 31 bytes, so keep grouping keys short and deliberate:

# Capture first 31 bytes of error message