Skip to content

Commit 43afe37

Browse files
committed
docs: runtime log settings and a retention table
GET and PATCH /logs/settings: the level the engine emits at and the replay ring size, changeable at runtime under control when resources.logs.settings is true. A change applies without a reload and is not written to the configuration; restart or the next activation returns to the configured values, which `source` reports. Level is bounded by the advertised levels, the ring by [64, max_buffered_records]; out of range is 400 with nothing changed. logs.md gains a table of every retained record, its bound and whether it is adjustable at runtime; honk mapping row; one test.
1 parent a3b4182 commit 43afe37

8 files changed

Lines changed: 390 additions & 1 deletion

File tree

‎api/discovery.yaml‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ paths:
176176
available: true
177177
levels: [ trace, debug, info, warn, error ]
178178
max_buffered_records: 4096
179+
settings: true
179180
dns_query:
180181
available: true
181182
record_types: [ A, AAAA, HTTPS ]
@@ -598,10 +599,13 @@ schemas:
598599
available:
599600
const: true
600601
then:
601-
required: [ levels, max_buffered_records ]
602+
required: [ levels, max_buffered_records, settings ]
602603
properties:
603604
available:
604605
type: boolean
606+
settings:
607+
type: boolean
608+
description: Whether PATCH /logs/settings can change the level and ring size at runtime; false makes it return 404 capability_not_supported.
605609
levels:
606610
type: array
607611
minItems: 1

‎api/logs.yaml‎

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,158 @@ paths:
8686
$ref: ./openapi.yaml#/components/responses/RateLimited
8787
"503":
8888
$ref: ./openapi.yaml#/components/responses/Unavailable
89+
/api/v1/logs/settings:
90+
get:
91+
operationId: getLogSettings
92+
summary: Read the engine's log level and replay buffer size
93+
description: |
94+
Requires resources.logs.available. Reports the level the engine currently
95+
emits at and how many records the replay ring keeps. Values are the running
96+
state, which may differ from the configuration file after a PATCH.
97+
x-permission: observe
98+
security:
99+
- bearerAuth: []
100+
- {}
101+
responses:
102+
"200":
103+
description: Current log settings
104+
headers:
105+
Cache-Control:
106+
$ref: ./openapi.yaml#/components/headers/NoStore
107+
X-Content-Type-Options:
108+
$ref: ./openapi.yaml#/components/headers/NoSniff
109+
content:
110+
application/json:
111+
schema:
112+
$ref: ./openapi.yaml#/components/schemas/LogSettings
113+
examples:
114+
current:
115+
value:
116+
observed_at: 2026-08-15T10:00:00Z
117+
level: info
118+
buffered_records: 4096
119+
source: config
120+
x-headers:
121+
Content-Type: application/json
122+
Cache-Control: no-store
123+
X-Content-Type-Options: nosniff
124+
"401":
125+
$ref: ./openapi.yaml#/components/responses/Unauthorized
126+
"403":
127+
$ref: ./openapi.yaml#/components/responses/Forbidden
128+
"404":
129+
$ref: ./openapi.yaml#/components/responses/NotFound
130+
patch:
131+
operationId: patchLogSettings
132+
summary: Change the log level or replay buffer size at runtime
133+
description: |
134+
Requires control, resources.logs.available and resources.logs.settings.
135+
The change applies to the running engine immediately, without a reload, and
136+
lasts until the process restarts or the next configuration activation resets
137+
it; it is not written back to the configuration file. Both fields are
138+
optional; an absent field keeps its value. level must be an advertised level.
139+
buffered_records must lie in [64, resources.logs.max_buffered_records];
140+
shrinking the ring drops the oldest records and cursors older than the new
141+
floor expire. Out-of-range or unadvertised values return 400 invalid_request
142+
and change nothing. Follows the shared idempotency rules.
143+
x-permission: control
144+
security:
145+
- bearerAuth: []
146+
- {}
147+
parameters:
148+
- $ref: ./openapi.yaml#/components/parameters/IdempotencyKey
149+
requestBody:
150+
required: true
151+
content:
152+
application/json:
153+
schema:
154+
$ref: ./openapi.yaml#/components/schemas/LogSettingsPatch
155+
examples:
156+
debug:
157+
value:
158+
level: debug
159+
responses:
160+
"200":
161+
description: Settings after the change
162+
headers:
163+
Cache-Control:
164+
$ref: ./openapi.yaml#/components/headers/NoStore
165+
X-Content-Type-Options:
166+
$ref: ./openapi.yaml#/components/headers/NoSniff
167+
content:
168+
application/json:
169+
schema:
170+
$ref: ./openapi.yaml#/components/schemas/LogSettings
171+
examples:
172+
changed:
173+
value:
174+
observed_at: 2026-08-15T10:00:05Z
175+
level: debug
176+
buffered_records: 4096
177+
source: runtime
178+
x-headers:
179+
Content-Type: application/json
180+
Cache-Control: no-store
181+
X-Content-Type-Options: nosniff
182+
"400":
183+
description: Unadvertised level or buffered_records outside the advertised range
184+
headers:
185+
Cache-Control:
186+
$ref: ./openapi.yaml#/components/headers/NoStore
187+
X-Content-Type-Options:
188+
$ref: ./openapi.yaml#/components/headers/NoSniff
189+
content:
190+
application/json:
191+
schema:
192+
$ref: ./openapi.yaml#/components/schemas/ErrorResponse
193+
examples:
194+
too_many_records:
195+
value:
196+
error:
197+
code: invalid_request
198+
message: buffered_records exceeds the advertised limit.
199+
request_id: request-3
200+
x-headers:
201+
Content-Type: application/json
202+
Cache-Control: no-store
203+
X-Content-Type-Options: nosniff
204+
"401":
205+
$ref: ./openapi.yaml#/components/responses/Unauthorized
206+
"403":
207+
$ref: ./openapi.yaml#/components/responses/Forbidden
208+
"404":
209+
$ref: ./openapi.yaml#/components/responses/NotFound
89210
schemas:
90211
LogLevel:
91212
type: string
92213
enum: [ trace, debug, info, warn, error ]
214+
LogSettings:
215+
type: object
216+
required: [ observed_at, level, buffered_records, source ]
217+
properties:
218+
observed_at:
219+
$ref: ./openapi.yaml#/components/schemas/Timestamp
220+
level:
221+
$ref: ./openapi.yaml#/components/schemas/LogLevel
222+
description: The minimum severity the engine emits; the stream's level filter cannot go below it.
223+
buffered_records:
224+
$ref: ./openapi.yaml#/components/schemas/SafeUInt
225+
minimum: 64
226+
description: Replay ring capacity in records, at most resources.logs.max_buffered_records.
227+
source:
228+
type: string
229+
enum: [ config, runtime ]
230+
description: config while the values come from the activated configuration; runtime after a PATCH overrode them.
231+
LogSettingsPatch:
232+
type: object
233+
additionalProperties: false
234+
minProperties: 1
235+
properties:
236+
level:
237+
$ref: ./openapi.yaml#/components/schemas/LogLevel
238+
buffered_records:
239+
$ref: ./openapi.yaml#/components/schemas/SafeUInt
240+
minimum: 64
93241
LogRecord:
94242
type: object
95243
required: [ ts, level, target, message, fields ]

‎api/openapi.yaml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ paths:
5858
$ref: ./events.yaml#/paths/~1api~1v1~1events
5959
/api/v1/logs:
6060
$ref: ./logs.yaml#/paths/~1api~1v1~1logs
61+
/api/v1/logs/settings:
62+
$ref: ./logs.yaml#/paths/~1api~1v1~1logs~1settings
6163
/api/v1/dns/query:
6264
$ref: ./dns.yaml#/paths/~1api~1v1~1dns~1query
6365
/api/v1/dns/cache:
@@ -472,6 +474,10 @@ components:
472474
$ref: ./logs.yaml#/schemas/LogLevel
473475
LogRecord:
474476
$ref: ./logs.yaml#/schemas/LogRecord
477+
LogSettings:
478+
$ref: ./logs.yaml#/schemas/LogSettings
479+
LogSettingsPatch:
480+
$ref: ./logs.yaml#/schemas/LogSettingsPatch
475481
StreamReadyEvent:
476482
$ref: ./events.yaml#/schemas/StreamReadyEvent
477483
RuntimeUpdatedEvent:

‎source/openapi.yaml‎

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ paths:
224224
- warn
225225
- error
226226
max_buffered_records: 4096
227+
settings: true
227228
dns_query:
228229
available: true
229230
record_types:
@@ -2346,6 +2347,127 @@ paths:
23462347
$ref: '#/components/responses/RateLimited'
23472348
'503':
23482349
$ref: '#/components/responses/Unavailable'
2350+
/api/v1/logs/settings:
2351+
get:
2352+
operationId: getLogSettings
2353+
summary: Read the engine's log level and replay buffer size
2354+
description: |
2355+
Requires resources.logs.available. Reports the level the engine currently
2356+
emits at and how many records the replay ring keeps. Values are the running
2357+
state, which may differ from the configuration file after a PATCH.
2358+
x-permission: observe
2359+
security:
2360+
- bearerAuth: []
2361+
- {}
2362+
responses:
2363+
'200':
2364+
description: Current log settings
2365+
headers:
2366+
Cache-Control:
2367+
$ref: '#/components/headers/NoStore'
2368+
X-Content-Type-Options:
2369+
$ref: '#/components/headers/NoSniff'
2370+
content:
2371+
application/json:
2372+
schema:
2373+
$ref: '#/components/schemas/LogSettings'
2374+
examples:
2375+
current:
2376+
value:
2377+
observed_at: '2026-08-15T10:00:00Z'
2378+
level: info
2379+
buffered_records: 4096
2380+
source: config
2381+
x-headers:
2382+
Content-Type: application/json
2383+
Cache-Control: no-store
2384+
X-Content-Type-Options: nosniff
2385+
'401':
2386+
$ref: '#/components/responses/Unauthorized'
2387+
'403':
2388+
$ref: '#/components/responses/Forbidden'
2389+
'404':
2390+
$ref: '#/components/responses/NotFound'
2391+
patch:
2392+
operationId: patchLogSettings
2393+
summary: Change the log level or replay buffer size at runtime
2394+
description: |
2395+
Requires control, resources.logs.available and resources.logs.settings.
2396+
The change applies to the running engine immediately, without a reload, and
2397+
lasts until the process restarts or the next configuration activation resets
2398+
it; it is not written back to the configuration file. Both fields are
2399+
optional; an absent field keeps its value. level must be an advertised level.
2400+
buffered_records must lie in [64, resources.logs.max_buffered_records];
2401+
shrinking the ring drops the oldest records and cursors older than the new
2402+
floor expire. Out-of-range or unadvertised values return 400 invalid_request
2403+
and change nothing. Follows the shared idempotency rules.
2404+
x-permission: control
2405+
security:
2406+
- bearerAuth: []
2407+
- {}
2408+
parameters:
2409+
- $ref: '#/components/parameters/IdempotencyKey'
2410+
requestBody:
2411+
required: true
2412+
content:
2413+
application/json:
2414+
schema:
2415+
$ref: '#/components/schemas/LogSettingsPatch'
2416+
examples:
2417+
debug:
2418+
value:
2419+
level: debug
2420+
responses:
2421+
'200':
2422+
description: Settings after the change
2423+
headers:
2424+
Cache-Control:
2425+
$ref: '#/components/headers/NoStore'
2426+
X-Content-Type-Options:
2427+
$ref: '#/components/headers/NoSniff'
2428+
content:
2429+
application/json:
2430+
schema:
2431+
$ref: '#/components/schemas/LogSettings'
2432+
examples:
2433+
changed:
2434+
value:
2435+
observed_at: '2026-08-15T10:00:05Z'
2436+
level: debug
2437+
buffered_records: 4096
2438+
source: runtime
2439+
x-headers:
2440+
Content-Type: application/json
2441+
Cache-Control: no-store
2442+
X-Content-Type-Options: nosniff
2443+
'400':
2444+
description: Unadvertised level or buffered_records outside the advertised range
2445+
headers:
2446+
Cache-Control:
2447+
$ref: '#/components/headers/NoStore'
2448+
X-Content-Type-Options:
2449+
$ref: '#/components/headers/NoSniff'
2450+
content:
2451+
application/json:
2452+
schema:
2453+
$ref: '#/components/schemas/ErrorResponse'
2454+
examples:
2455+
too_many_records:
2456+
value:
2457+
error:
2458+
code: invalid_request
2459+
message: buffered_records exceeds the advertised limit.
2460+
request_id: request-3
2461+
x-headers:
2462+
Content-Type: application/json
2463+
Cache-Control: no-store
2464+
X-Content-Type-Options: nosniff
2465+
'401':
2466+
$ref: '#/components/responses/Unauthorized'
2467+
'403':
2468+
$ref: '#/components/responses/Forbidden'
2469+
'404':
2470+
$ref: '#/components/responses/NotFound'
23492471
/api/v1/dns/query:
23502472
get:
23512473
operationId: queryDns
@@ -4011,9 +4133,13 @@ components:
40114133
required:
40124134
- levels
40134135
- max_buffered_records
4136+
- settings
40144137
properties:
40154138
available:
40164139
type: boolean
4140+
settings:
4141+
type: boolean
4142+
description: Whether PATCH /logs/settings can change the level and ring size at runtime; false makes it return 404 capability_not_supported.
40174143
levels:
40184144
type: array
40194145
minItems: 1
@@ -7910,6 +8036,39 @@ components:
79108036
- 'null'
79118037
additionalProperties: true
79128038
description: Sanitized structured fields, or null when unavailable; the message safety rules apply recursively.
8039+
LogSettings:
8040+
type: object
8041+
required:
8042+
- observed_at
8043+
- level
8044+
- buffered_records
8045+
- source
8046+
properties:
8047+
observed_at:
8048+
$ref: '#/components/schemas/Timestamp'
8049+
level:
8050+
$ref: '#/components/schemas/LogLevel'
8051+
description: The minimum severity the engine emits; the stream's level filter cannot go below it.
8052+
buffered_records:
8053+
$ref: '#/components/schemas/SafeUInt'
8054+
minimum: 64
8055+
description: Replay ring capacity in records, at most resources.logs.max_buffered_records.
8056+
source:
8057+
type: string
8058+
enum:
8059+
- config
8060+
- runtime
8061+
description: config while the values come from the activated configuration; runtime after a PATCH overrode them.
8062+
LogSettingsPatch:
8063+
type: object
8064+
additionalProperties: false
8065+
minProperties: 1
8066+
properties:
8067+
level:
8068+
$ref: '#/components/schemas/LogLevel'
8069+
buffered_records:
8070+
$ref: '#/components/schemas/SafeUInt'
8071+
minimum: 64
79138072
StreamReadyEvent:
79148073
type: object
79158074
required:

0 commit comments

Comments
 (0)