You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guides/logs.md
+37-7Lines changed: 37 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Log Management
2
2
3
-
View, filter, and manage daemon logs.
3
+
View, filter, and manage daemon logs. Pitchfork stores all daemon logs in an SQLite database (`~/.local/state/pitchfork/logs/logs.db`) with full timestamp indexing, making filtering by time fast and reliable.
4
4
5
5
## View Logs
6
6
@@ -125,6 +125,38 @@ Delete all logs for a daemon:
125
125
pitchfork logs api --clear
126
126
```
127
127
128
+
## Log Rotation
129
+
130
+
Pitchfork supports automatic log rotation via `time_retention` and `line_retention` settings. Old entries are pruned periodically by the supervisor so the database does not grow unbounded.
131
+
132
+
### Automatic Rotation
133
+
134
+
Configure in any `pitchfork.toml` under `[settings.logs]`:
135
+
136
+
```toml
137
+
[settings.logs]
138
+
# Keep only the last 7 days of logs
139
+
time_retention = "7d"
140
+
141
+
# Or keep only the most recent 10,000 entries
142
+
line_retention = 10000
143
+
144
+
# You can also combine both (entries older than 7d OR exceeding 10,000 lines are pruned)
145
+
# time_retention = "7d"
146
+
# line_retention = 10000
147
+
```
148
+
149
+
Supported formats:
150
+
-**Time-based (`time_retention`):**`"7d"`, `"30d"`, `"1h"` — delete entries older than this duration
151
+
-**Count-based (`line_retention`):**`10000`, `5000` — keep only the most recent N entries per daemon
152
+
-**Unset (default):** no automatic pruning
153
+
154
+
The supervisor evaluates this policy during its regular interval watcher cycle.
155
+
156
+
## Migrate Legacy Logs
157
+
158
+
If you were using pitchfork before the SQLite log store was introduced, legacy text log files may still exist under the logs directory. They are automatically imported into the SQLite database on the first access to the log store, so no manual action is required.
159
+
128
160
## Supervisor Logs
129
161
130
162
View pitchfork's own logs:
@@ -133,12 +165,10 @@ View pitchfork's own logs:
133
165
pitchfork logs pitchfork
134
166
```
135
167
136
-
## Log Location
137
-
138
-
Logs are stored in `~/.local/state/pitchfork/logs/<namespace>--<name>/`. See [File Locations](/reference/file-locations#logs) for details on the path format.
139
-
140
-
Each daemon has its own log file that persists across restarts.
141
-
142
168
## TUI and Web UI
143
169
144
170
You can also view logs in real-time through the [TUI](/guides/tui) (`pitchfork tui`) or [Web UI](/guides/web-ui) (if enabled).
171
+
172
+
## Log Storage Location
173
+
174
+
Logs are stored in a single SQLite database at `~/.local/state/pitchfork/logs/logs.db`. Each daemon has its own table partition identified by its qualified ID (`namespace/name`). See [File Locations](/reference/file-locations#logs) for details on the state directory resolution.
Copy file name to clipboardExpand all lines: docs/public/schema.json
+40Lines changed: 40 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -28,6 +28,7 @@
28
28
"api": {},
29
29
"general": {},
30
30
"ipc": {},
31
+
"logs": {},
31
32
"proxy": {},
32
33
"supervisor": {},
33
34
"tui": {},
@@ -225,6 +226,14 @@
225
226
}
226
227
]
227
228
},
229
+
"line_retention": {
230
+
"description": "Maximum number of log entries to keep per daemon.\nOverrides the global `settings.logs.line_retention` when set.",
231
+
"type": [
232
+
"integer",
233
+
"null"
234
+
],
235
+
"format": "int64"
236
+
},
228
237
"memory_limit": {
229
238
"description": "Memory limit for the daemon process (e.g. \"50MB\", \"1GiB\").\nThe supervisor periodically monitors RSS and kills the process if it exceeds the limit.",
230
239
"anyOf": [
@@ -328,6 +337,13 @@
328
337
}
329
338
]
330
339
},
340
+
"time_retention": {
341
+
"description": "Maximum age of log entries to keep (e.g. \"7d\", \"30d\").\nOverrides the global `settings.logs.time_retention` when set.",
342
+
"type": [
343
+
"string",
344
+
"null"
345
+
]
346
+
},
331
347
"user": {
332
348
"description": "Unix user to run this daemon as. Overrides `settings.supervisor.user` when set.",
Copy file name to clipboardExpand all lines: docs/reference/file-locations.md
+9-10Lines changed: 9 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -73,22 +73,21 @@ Within a given project directory, files take precedence in this order:
73
73
74
74
### Logs
75
75
76
-
Each daemon has its own log directory and file. The log path is determined by the daemon's qualified ID (namespace + name):
76
+
Logs are stored in a single SQLite database (`logs.db`) for efficient querying, filtering, and rotation. The database uses WAL mode for concurrent readers so the CLI, TUI, and Web UI can all read logs at the same time without blocking the supervisor's writes.
The namespace is derived from top-level `namespace` in the config when present, otherwise from the project directory name (or `global` for global config files). For example:
83
-
- Daemon `api` in project `myapp` → `logs/myapp--api/myapp--api.log`
84
-
- Daemon `api` in project `yourapp` → `logs/yourapp--api/yourapp--api.log`
85
-
- Daemon `postgres` in global config → `logs/global--postgres/global--postgres.log`
82
+
Inside the database, each daemon is identified by its qualified ID (`namespace/name`). Log entries include a timestamp (millisecond precision) and the raw message text, so time-based filtering is fast and reliable.
86
83
87
-
The `--` separator is used to convert the `/` in qualified daemon IDs (e.g., `myapp/api`) to a filesystem-safe format.
84
+
For backwards compatibility, the legacy log directory structure still exists but is no longer written to by the supervisor:
88
85
89
-
Because `--` is reserved for this encoding, project directory names containing `--` (or other invalid namespace characters) require a top-level `namespace` override in `pitchfork.toml`.
See [Namespaces](/concepts/namespaces) for more details on how daemon IDs work across projects.
90
+
Legacy text log files from older pitchfork versions are automatically imported into the SQLite store on first access, so no manual migration is needed.
0 commit comments