kelora 1.0.0

A command-line log analysis tool with embedded Rhai scripting
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
# Common Errors Reference

Quick reference for common issues and their solutions.

## Common Issues

### "Field not found" or Empty Output

**Problem:** No output or errors like "field 'status' not found".

**Possible causes:**

1. **Wrong format specified** - Default is `-f auto` (content-based). Force `-f json`, `-f logfmt`, or `-f line` if detection disagrees.
2. **Field doesn't exist** - Field name is misspelled or doesn't exist in all events
3. **All events filtered out** - Your filters are too restrictive

**Solutions:**

```bash
# Check if format is correct
kelora -j app.log -F inspect --take 3        # For JSON
kelora -f logfmt app.log -F inspect --take 3 # For logfmt
kelora -f line app.log -F inspect --take 3   # For raw lines

# See what fields are actually present
kelora -j app.log -F inspect --head 20

# Check if field exists before using it
kelora -j app.log --filter 'e.has("status") && e.status >= 500'

# See statistics to understand what's happening
kelora -j app.log --filter 'e.status >= 500' --stats
```

**Common mistakes:**

- Using `-j` when logs are not JSON format
- Accessing nested fields incorrectly: use `e.user.id`, not `e["user.id"]`
- Filtering before creating computed fields (see Stage Order below)

---

### Filters Not Working

**Problem:** Filter expressions don't match expected events.

**Possible causes:**

1. **Stage ordering** - Filtering on fields created by `--exec` that comes later
2. **Type mismatch** - Comparing string "500" with number 500
3. **Missing fields** - Field doesn't exist in some events
4. **Logic errors** - Boolean logic isn't what you think

**Solutions:**

```bash
# Check field types with inspect
kelora -j app.log -F inspect --take 5

# Safe field access with existence check
kelora -j app.log --filter 'e.has("status") && e.status >= 500'

# Handle missing fields with defaults
kelora -j app.log --filter 'e.get("status", 0) >= 500'

# Debug with verbose output
kelora -j app.log --filter 'e.status >= 500' --verbose

# See how many events match
kelora -j app.log --filter 'e.status >= 500' --stats
```

**Stage order matters:**

```bash
# ❌ WRONG: Filter runs before exec creates the field
kelora -j app.log --filter 'e.duration_s > 1' \
    -e 'e.duration_s = e.duration_ms / 1000'

# ✅ RIGHT: Exec creates field first, then filter uses it
kelora -j app.log \
    -e 'e.duration_s = e.duration_ms / 1000' \
    --filter 'e.duration_s > 1'
```

---

### Type Comparison Errors

**Problem:** Errors like "cannot compare string with number" or unexpected filter behavior.

**Cause:** Fields have different types than expected. Common with string numbers like `"500"` vs integer `500`.

**Solutions:**

```bash
# Check actual types
kelora -j app.log -F inspect --take 5

# Convert strings to numbers safely
kelora -j app.log --filter 'e.status.to_int_or(0) >= 500'

# Convert to string for comparison
kelora -j app.log --filter 'e.status.to_string() == "500"'

# Handle nulls and missing values
kelora -j app.log \
    --filter 'e.has("status") && e.status.to_int_or(0) >= 500'
```

**Common type conversions:**

| Function | Purpose | Safe Default |
|----------|---------|--------------|
| `.to_int_or(0)` | String → Integer | Returns 0 on error |
| `.to_float_or(0.0)` | String → Float | Returns 0.0 on error |
| `.to_string()` | Any → String | Always succeeds |
| `.get("field", default)` | Field access with fallback | Returns default if missing |

---

### Empty Output Despite Having Data

**Problem:** Kelora processes logs but outputs nothing.

**Possible causes:**

1. **All events filtered out** - Level filtering, time ranges, or filters too restrictive
2. **Quiet mode enabled** - Using `-q` or `--quiet` suppresses event output (use `--silent` to suppress diagnostics too)
3. **Timestamp filtering** - Events outside `--since`/`--until` range

**Solutions:**

```bash
# Check statistics to see what happened
kelora -j app.log --stats

# Remove all filtering temporarily
kelora -j app.log --take 10

# Check if level filtering is too restrictive
kelora -j app.log --levels error --stats  # See how many events have ERROR level

# Verify output format
kelora -j app.log --take 10

# Check timestamp range
kelora -j app.log --since '1 hour ago' --stats
```

---

### Parse Errors

**Problem:** Errors like "failed to parse JSON" or "invalid format".

**Possible causes:**

1. **Wrong format specified** - File isn't actually JSON/logfmt/etc
2. **Malformed data** - Invalid syntax in log lines
3. **Mixed formats** - File contains multiple formats
4. **Multiline events** - JSON/messages span multiple lines

**Solutions:**

```bash
# Try auto-detection
kelora -f auto app.log --take 10

# Check raw file content
head -20 app.log

# See parse errors with verbose
kelora -j app.log --verbose --stats

# Use strict mode to fail on first error
kelora -j --strict app.log --head 20

# For multiline JSON, use multiline mode
kelora -j -M start app.log  # Multiline starting with {

# For mixed formats, use line filtering
kelora -j app.log --keep-lines '^\{'  # Only lines starting with {
```

**Check format detection:**

```bash
# Test different formats
kelora -f json app.log --take 5 -F inspect
kelora -f logfmt app.log --take 5 -F inspect
kelora -f line app.log --take 5 -F inspect
```

---

### Performance Issues

**Problem:** Kelora is slow or uses too much memory.

**Solutions:**

```bash
# Use parallel mode for large files
kelora -j --parallel large.log

# Adjust batch size for parallel processing
kelora -j --parallel --batch-size 10000 large.log

# Filter early in pipeline to reduce work
kelora -j app.log \
    --levels error \           # Filter early
    -e 'e.heavy_transform()'   # Then do expensive work

# Use line-level filtering before parsing
kelora -j app.log --keep-lines 'ERROR|CRITICAL'

# Process compressed files directly
kelora -j app.log.gz  # Automatic decompression

# Limit output for testing
kelora -j large.log --take 100 --stats
```

**Performance tips:**

- Put cheap filters before expensive transforms
- Use `--parallel` for files > 100MB
- Filter at line level with `--keep-lines` when possible
- Use `--take` to limit output during development

See [Performance Model](../concepts/performance-model.md) for details.

---

### Script Errors in --exec

**Problem:** Runtime errors in Rhai scripts with `--exec` or `-e`.

**Common causes:**

1. **Accessing missing fields** - Use `.has()` or `.get()` to check first
2. **Type errors** - Operating on wrong types
3. **Null values** - Field exists but is null
4. **Syntax errors** - Invalid Rhai syntax

**Solutions:**

```bash
# Check field existence before access
kelora -j app.log -e '
    if e.has("duration_ms") {
        e.duration_s = e.duration_ms / 1000
    }
'

# Use safe accessors with defaults
kelora -j app.log -e 'e.duration_s = e.get("duration_ms", 0) / 1000'

# Handle nulls explicitly
kelora -j app.log -e '
    if e.value != () {
        e.processed = e.value * 2
    }
'

# Test with strict mode to catch errors early
kelora -j --strict app.log -e 'e.result = e.value.to_int()'

# Use verbose to see which line failed
kelora -j app.log --verbose -e 'e.result = e.value.to_int()'
```

---

### Stage Order Confusion

**Problem:** Computed fields aren't available where expected.

**Key principle:** Stages run **in the order you specify them** on the command line.

**Examples:**

```bash
# ❌ WRONG: Filtering before field exists
kelora -j app.log \
    --filter 'e.duration_s > 1' \
    -e 'e.duration_s = e.duration_ms / 1000'
# Error: e.duration_s doesn't exist yet!

# ✅ RIGHT: Create field, then filter
kelora -j app.log \
    -e 'e.duration_s = e.duration_ms / 1000' \
    --filter 'e.duration_s > 1'

# ❌ WRONG: Level filtering before level is set
kelora -j app.log \
    --levels error \
    -e 'e.level = "ERROR"'
# Event filtered out before level is set!

# ✅ RIGHT: Set level, then filter
kelora -j app.log \
    -e 'if !e.has("level") { e.level = "ERROR" }' \
    --levels error
```

**Rule of thumb:** Put creation before filtering, filtering before transformation.

---

### Configuration Issues

**Problem:** Unexpected behavior due to configuration files.

**Solutions:**

```bash
# Ignore config files for testing
kelora --ignore-config -j app.log

# Check which config files are being used
kelora -j app.log --verbose 2>&1 | grep -i config

# Check config file syntax
cat ~/.config/kelora/kelora.ini

# Test with explicit config
kelora --config-file ./test.ini -j app.log
```

**Config file locations (in precedence order):**

1. `./.kelora.ini` (project directory)
2. `~/.config/kelora/kelora.ini` (user config)
3. System defaults

See [Configuration System](../concepts/configuration-system.md).

---

## Exit Codes for Automation

Kelora uses standard exit codes:

| Code | Meaning | Common Cause |
|------|---------|--------------|
| `0` | Success | No errors occurred |
| `1` | Processing errors | Parse errors, filter errors, exec errors, file I/O failures |
| `2` | Usage errors | Invalid flags, incompatible options, bad config |
| `130` | Interrupted | Ctrl+C (SIGINT) |
| `141` | Broken pipe | Normal in pipelines with `head` |

**Check exit code in scripts:**

```bash
if ! kelora -j app.log --strict > /dev/null 2>&1; then
    echo "❌ Validation failed (exit code: $?)"
    exit 1
fi
```

See [Exit Codes Reference](exit-codes.md) for complete documentation.

---

## Common Error Messages

### "Failed to parse JSON on line N"

**Cause:** Invalid JSON syntax on that line.

**Solutions:**

- Check the line: `sed -n 'Np' app.log` (where N is the line number)
- Use `--verbose` to see the problematic line
- Use `-f auto` to try auto-detection
- Use multiline mode if JSON spans multiple lines: `-M start`

---

### "Cannot access field 'X' of non-object value"

**Cause:** Trying to access field on a value that isn't an object (e.g., null, array, primitive).

**Solutions:**

- Check field existence: `e.has("field")`
- Use inspect to see structure: `-F inspect`
- Handle nulls: `if e.field != () { ... }`

---

### "Type mismatch: cannot compare String with Integer"

**Cause:** Comparing values of different types (e.g., `"500" >= 500`).

**Solutions:**

- Convert types: `e.status.to_int_or(0) >= 500`
- Check types with inspect: `-F inspect`
- Use string comparison: `e.status == "500"`

---

### "Field 'X' not found"

**Cause:** Accessing a field that doesn't exist in the event.

**Solutions:**

- Check field name spelling
- Verify field exists: `e.has("field")`
- Use safe accessor: `e.get("field", default)`
- Check actual field names: `-F inspect`

---

### "No events matched filter"

**Cause:** All events filtered out by your filters.

**Solutions:**

- Check filter logic
- Use `--stats` to see filtering breakdown
- Remove filters temporarily to see all events
- Check if level filtering is too restrictive

---

### "Failed to open file"

**Cause:** File doesn't exist, no permission, or path is wrong.

**Solutions:**

- Check file exists: `ls -l file.log`
- Check permissions: `stat file.log`
- Use absolute path
- Check if file is actually stdin: use `-` for stdin