TraceFlagControl
<caos-trace-flag-control>
the trace flags in force, with their expiry and levels editable in the row
May be placed on a page inside an app.
Inputs
Section titled “Inputs”| Name | Attribute | Description | Type | Default | Required |
|---|---|---|---|---|---|
flags |
property only | The flags in force: { id, subject, subjectType?, level, expiresAt? }[]. expiresAt absent means NO EXPIRY WAS STATED, which is not the same as “never” and is counted on its own. |
json | empty list | Optional |
now |
now, markup only |
The instant expiry is judged against — an epoch number or a parseable timestamp. An INPUT rather than a call to the clock, so what this component says about expiry is a function of what it was given. Absent falls back to the real clock, which is what an ordinary placement wants. | datetime | the real clock | Optional |
readonly |
readonly, markup only |
Draw the levels and expiries as text rather than controls, for somebody who may look but not change. The remove control goes with them. | boolean | false | Optional |
search |
search, markup only |
Narrows by subject, subject type or level. | text | none declared | Optional |
sortKey |
sort-key, markup only |
Which column orders the rows. | text — one of subject, level, expiresAt | subject | Optional |
sortDirection |
sort-direction, markup only |
Which way. A flag with no stated expiry sorts last in both directions — it is not the soonest to go and not the furthest away, it is unknown. | text — one of asc, desc | asc | Optional |
emptyText |
empty-text, markup only |
What to say with no flags at all. The default states the consequence, not the absence. | text | No trace flags — nothing is being recorded. | Optional |
Events
Section titled “Events”| Name | When it fires | What it carries |
|---|---|---|
caos-trace-change |
A level or an expiry is changed in the grid. Raised per change, never batched. | { id, level? , expiresAt? } — only what moved. |
caos-trace-remove |
A row’s Remove control is pressed. | { id }. |
Not documented yet — this piece has not said.
Styling hooks
Section titled “Styling hooks”Not documented yet — this piece has not said.
Methods
Section titled “Methods”Not documented yet — this piece has not said.
Readable state
Section titled “Readable state”| Name | Type | What it tells you |
|---|---|---|
active |
CaosTraceFlag[] | The flags still recording. |
expired |
CaosTraceFlag[] | The flags that have stopped. Never counted with the active ones. |
now |
number | The instant expiry is being judged against. |
visibleFlags |
CaosTraceFlag[] | The flags surviving the search, in order. |
Styling parts
Section titled “Styling parts”| Part | Which piece of it | When it is there |
|---|---|---|
::part(control) |
The outer column. | Always |
::part(summary) |
The “N recording · M expired” line. | Always |
::part(search) |
The search box. | Always |
::part(table) |
The composed data table. | Always |
::part(level) |
A row’s level control. | Always |
::part(expires) |
A row’s expiry control. | Always |
::part(state) |
A row’s recording/expired text. | Always |
::part(remove) |
A row’s remove control. | readonly is not set. |
When to use it
Section titled “When to use it”Before reproducing a problem, and whenever the answer to “why is there no log” might be that nothing was recording.
What to use instead
Section titled “What to use instead”- LogList — the flags are set and the question is which log to read.
- DataTable — the rows are not trace flags. This one computes expiry against a clock and says what that means in words.
Accessibility
Section titled “Accessibility”Every in-grid control carries an accessible name naming the flag it belongs to — “Logging level for jrivera (User)” — because a grid of unlabelled dropdowns is what a screen reader otherwise finds. Expiry is stated as WORDS on the row (“expired — not recording”), never as a date the reader must compare to today. The summary is a role="status" live region and, with no flags at all, says “Nothing is being recorded” rather than reporting an empty list neutrally.
Examples
Section titled “Examples”One recording, one expired
Section titled “One recording, one expired”The distinction the component exists for. The expired flag says so in words on its own row and is counted apart in the summary, rather than sitting there looking live.
{ "id": "example", "section": "One recording, one expired", "columns": 1, "items": [ { "id": "trace_flag_control_1", "type": "component", "key": "trace_flag_control", "inputs": { "now": "2026-09-18T16:00:00Z", "flags": [ { "id": "tf1", "subject": "jrivera", "subjectType": "User", "level": "FINEST", "expiresAt": "2026-09-18T18:00:00Z" }, { "id": "tf2", "subject": "integration.user", "subjectType": "User", "level": "DEBUG", "expiresAt": "2026-09-18T09:00:00Z" }, { "id": "tf3", "subject": "BillingService", "subjectType": "Class", "level": "INFO" } ] } } ]}<caos-trace-flag-control id="traceFlagControl1" now="2026-09-18T16:00:00Z"></caos-trace-flag-control>// What an attribute cannot hold, set as a property — the same values the preview is drawn with.const traceFlagControl1 = document.getElementById('traceFlagControl1');traceFlagControl1.flags = [ { "id": "tf1", "subject": "jrivera", "subjectType": "User", "level": "FINEST", "expiresAt": "2026-09-18T18:00:00Z" }, { "id": "tf2", "subject": "integration.user", "subjectType": "User", "level": "DEBUG", "expiresAt": "2026-09-18T09:00:00Z" }, { "id": "tf3", "subject": "BillingService", "subjectType": "Class", "level": "INFO" }];Nothing is being recorded
Section titled “Nothing is being recorded”The dangerous empty state, said as a consequence rather than as an absence — it is the answer to “why is there no log” that people otherwise spend an afternoon on.
{ "id": "example", "section": "Nothing is being recorded", "columns": 1, "items": [ { "id": "trace_flag_control_1", "type": "component", "key": "trace_flag_control", "inputs": { "flags": [] } } ]}<caos-trace-flag-control id="traceFlagControl1"></caos-trace-flag-control>// What an attribute cannot hold, set as a property — the same values the preview is drawn with.const traceFlagControl1 = document.getElementById('traceFlagControl1');traceFlagControl1.flags = [];Look but not change
Section titled “Look but not change”The levels and expiries as text, and no remove control — for somebody without the permission.
{ "id": "example", "section": "Look but not change", "columns": 1, "items": [ { "id": "trace_flag_control_1", "type": "component", "key": "trace_flag_control", "inputs": { "readonly": true, "now": "2026-09-18T16:00:00Z", "flags": [ { "id": "tf1", "subject": "jrivera", "subjectType": "User", "level": "FINEST", "expiresAt": "2026-09-18T18:00:00Z" } ] } } ]}<caos-trace-flag-control id="traceFlagControl1" readonly now="2026-09-18T16:00:00Z"></caos-trace-flag-control>// What an attribute cannot hold, set as a property — the same values the preview is drawn with.const traceFlagControl1 = document.getElementById('traceFlagControl1');traceFlagControl1.flags = [ { "id": "tf1", "subject": "jrivera", "subjectType": "User", "level": "FINEST", "expiresAt": "2026-09-18T18:00:00Z" }];