Always check the first few bytes of the file to detect the format: if the second character is a newline or
"
, it's NDJSON; if it's a space or newline followed by spaces, it's pretty-printed.
Search order
— check these locations relative to the project root:
.evlog/logs/
(default)
Any
.evlog/logs/
inside app directories (monorepos:
apps/*/.evlog/logs/
)
Use glob to find log files:
.evlog/logs/*.jsonl
/.evlog/logs/.jsonl
apps//.evlog/logs/.jsonl
Files are named by date:
2026-03-14.jsonl
. Start with the most recent file.
If no logs are found
The file system drain may not be enabled. Guide the user to set it up:
import
{
createFsDrain
}
from
'evlog/fs'
// Nuxt / Nitro: server/plugins/evlog-drain.ts
export
default
defineNitroPlugin
(
(
nitroApp
)
=>
{
nitroApp
.
hooks
.
hook
(
'evlog:drain'
,
createFsDrain
(
)
)
}
)
// Hono / Express / Elysia: pass in middleware options
app
.
use
(
evlog
(
{
drain
:
createFsDrain
(
)
}
)
)
// Fastify: pass in plugin options
await
app
.
register
(
evlog
,
{
drain
:
createFsDrain
(
)
}
)
// NestJS: pass in module options
EvlogModule
.
forRoot
(
{
drain
:
createFsDrain
(
)
}
)
// Standalone: pass to initLogger
initLogger
(
{
drain
:
createFsDrain
(
)
}
)
After setup, the user needs to trigger some requests to generate logs, then re-analyze.
Log format
Each line is a self-contained JSON object (wide event). Key fields:
Field
Type
Description
timestamp
string
ISO 8601 timestamp
level
string
info
,
warn
,
error
,
debug
service
string
Service name
environment
string
development
,
production
, etc.
method
string
HTTP method (
GET
,
POST
, etc.)
path
string
Request path (
/api/checkout
)
status
number
HTTP response status code
duration
string
Request duration (
"234ms"
)
requestId
string
Unique request identifier
error
object
Error details:
name
,
message
,
stack
,
statusCode
,
data
error.data.why
string
Human-readable explanation of what went wrong
error.data.fix
string
Suggested fix for the error
source
string
client
for browser logs, absent for server logs
userAgent
object
Parsed browser/OS/device info
All other fields are application-specific context added via
log.set()
(e.g.
user
,
cart
,
payment
).
How to analyze
Step 1: Read the most recent log file
Read the latest
.jsonl
file. Each line is one JSON event. Parse each line independently.
Step 2: Identify the relevant events
Filter based on the user's question:
Errors
look for
"level":"error"
or
status >= 400
Specific endpoint
match on
path
Slow requests
parse
duration
(e.g.
"706ms"
) and filter high values
Specific user/action
match on application-specific fields
Client-side issues
filter by
"source":"client"
Time range
compare
timestamp
values
Step 3: Analyze and explain
For each relevant event:
What happened
summarize the
path
,
method
,
status
,
level
Why it failed
(errors): read
error.message
,
error.data.why
, and the stack trace
How to fix
check
error.data.fix
for suggested remediation
Context
examine application-specific fields for business context (user info, payment details, etc.)
Patterns
look for recurring errors, degrading performance, or correlated failures
Analysis patterns
Find all errors
Filter: level === "error"
Group by: error.message or path
Look for: recurring patterns, common failure modes
Find slow requests
Filter: parse duration string, compare > threshold (e.g. 1000ms)
Sort by: duration descending
Look for: specific endpoints, time-of-day patterns
Trace a specific request
Filter: requestId === "the-request-id"
Result: single wide event with all context for that request
Error rate by endpoint
Group events by: path
Count: total events vs error events per path
Look for: endpoints with high error ratios
Client vs server errors
Split by: source === "client" vs no source field
Compare: error patterns between client and server
Look for: client errors that don't have corresponding server errors (network issues)
Important notes
Each line is a
complete, self-contained event
. Unlike traditional logs, you don't need to correlate multiple lines — one line has all the context for one request.
The
error.data.why
and
error.data.fix
fields are evlog-specific structured error fields. When present, they provide the most actionable information.
Duration values are strings with units (e.g.
"706ms"
). Parse the numeric part for comparisons.
Events with
"source":"client"
originated from browser-side logging and were sent to the server via the transport endpoint.
Log files are
.gitignore
'd automatically — they exist only on the local machine or server where the app runs.