Using the Debug service¶
The Debug service sets property breakpoints: it watches one property of one node and acts when the value meets a condition.
It is separate from the Overwatch service because the two do different kinds of thing. Overwatch
reports on a running application. A breakpoint intervenes in one — it can halt the process in an
attached debugger at the assignment that changed a property, or run a console command when it changes. That
is why it has its own configuration key, ServiceDebugEnabled, and why its commands use the
debug.* prefix rather than overwatch.*.
Note
ServiceDebugEnabled is independent of ServiceOverwatchEnabled: the debug commands are
available with the Overwatch service switched off, and can be switched off while Overwatch runs.
The one part that does depend on Overwatch is the screenshot action, which captures through whichever service owns the framebuffer. With Overwatch disabled, that action reports that no capture source is available, and debug.breakpointscreenshot then has nothing to return. The other five commands are unaffected. To capture the frames leading up to a breakpoint instead, attach capture.stop with debug.breakcommand and let the capture service ring hold the run-up.
debug.breakprop <path> <property> <op> <value|$"..."> [once] [hitcount:N] [actions]
Add a property breakpoint.
debug.breakpoints Get property breakpoints
as JSON.
debug.removebreakpoint <id> Remove a breakpoint by ID.
debug.enablebreakpoint <id> <0|1> Activate or deactivate a
breakpoint.
debug.breakcommand <id> <command> Run a console command when
a breakpoint triggers.
debug.clearbreakpoints Remove all breakpoints.
debug.breakpointscreenshot Fetch the capture a
breakpoint took.
A performance watcher runs once per frame. A breakpoint instead rides a Kanzi property notification handler, which fires inside the assignment that changed the value. With the break action and a debugger attached, execution therefore stops on the code that wrote the property. That is what makes a breakpoint useful for finding who set a value rather than only that something set it.
<op> is one of eq, neq, below, above, beloweq, aboveeq, or the
equivalent symbol (==, !=, <, >, <=, >=). float and int properties
accept all of them; bool, string, Vector2, Vector3 and Vector4 accept eq
and neq only. Vector values are comma-separated with exactly one number per component —
1,0,0 for a Vector3. A missing or extra component is rejected rather than read as 0,
and so is a number outside the property type’s range: an int target beyond 32 bits, or a
float target that is not finite.
The property name can be unqualified: Opacity resolves to Node.Opacity. Because a node path
can contain spaces, debug.breakprop parses its arguments from the right — the property,
operator and value are always single tokens, so whatever precedes them is the path, unquoted. A
value that is not a single plain token is written as one $"..." literal (see below):
debug.breakprop /Screen/RootPage/Viewport 2D/Image Opacity below 0.5 break
Quoting the path is unnecessary for that reason, but debug.breakprop accepts it — it strips one layer of matching single or double quotes, the same way overwatch.props does, so a path copied from a command that needed quotes works here too. An unbalanced quote stays in place rather than being guessed at, so the resulting Node not found names exactly what you asked for.
Warning
Quotes do not delimit the value — write a $"..." literal instead.
debug.breakprop /A/B Text eq "Hello" creates a breakpoint whose target is the
seven-character string "Hello", quotes included. It is listed as armed and never fires, with
no error, because any string is a valid target for a string property. Write a one-word target
unquoted. Write any other target – one with a space, a line break, a tab or quotes, or one that
spells an operator such as eq – as a $"..." string literal, which is decoded as JSON, as
overwatch.setprop reads one (Setting any text: the string literal):
debug.breakprop /A/B TextConcept.Text eq $"Hello world" log
debug.breakprop /A/B TextConcept.Text eq $"line 1\nline 2" log
A literal is never read as the operator, once, hitcount:N or an action, so it is always
the target. A path can also be given as one literal; the MCP add_breakpoint tool and the Web
UI’s breakpoint form write the target and the path that way when they need to.
overwatch.setprop is not the precedent here despite appearances: it does not use this
quote stripping at all, it uses a different argument reader that treats a leading quote as
running to the end of the line. So overwatch.setprop "/A/B Opacity 5 reports a missing
property name, where debug.breakprop keeps the quote in the path. The two commands agree on
unquoted spaced paths and disagree on malformed quoting.
You can give actions as one comma-separated token or as separate words, and one breakpoint can
carry several either way — log,screenshot and log screenshot are the same request. The
separate-word form takes at most three trailing arguments in total, counting once and
hitcount:N: ... 0.5 log screenshot once hitcount:3 is four and is rejected with the usage
line, while the comma-packed ... 0.5 log,screenshot once hitcount:3 is three and parses. Pack
the actions into one token when a breakpoint needs both modifiers as well. They
run in a fixed order, with break last, so every diagnostic is in place before execution stops.
Note
The graphics API call logging actions - gfxlog and gfxframe, and the legacy gllog, gldump, glframe and glframedump spellings - are not available, because this Kanzi baseline has no call logging to drive. debug.breakprop recognizes all six names and rejects them with that explanation, rather than reporting them as an unknown action.
Action |
Effect |
|---|---|
|
Traps into an attached debugger. Without one, this is skipped and logged — raising a trap with nothing to catch it would terminate the application. |
|
Logs the triggering value and leaves the application running. A tracepoint. On a property that changes every frame, such as an animated one, this fills the log buffer
and evicts everything else in it. Pair it with |
|
Captures the default framebuffer on the next render, fetched with
|
|
Runs a console command. Attach the command with |
hitcount:N triggers on every Nth matching change rather than every one, and once deactivates
the breakpoint after its first trigger, leaving it listed but inert. N must be a non-negative
whole number, and the target value must be readable as the property’s type and within its range —
both are rejected outright, with a response that names the offending component and the accepted
form, rather than quietly becoming 0 or wrapping, which would leave the listing showing a
condition the breakpoint is not testing. The target is parsed once, when the breakpoint is
created, and that parsed value is what every later property write is compared against.
debug.breakprop is stricter than overwatch.setprop about two values. It rejects inf and
nan: exact equality never matches nan, and a breakpoint waiting on infinity is almost always
a typo; to catch a property actually going infinite, use above 3.4e38. It also rejects a number
too small to store, such as 1e-1000, which would become 0 while the listing still showed
what you typed.
To break the tenth time a layout width is written, and stop there:
debug.breakprop /Screen/RootPage/Grid LayoutWidth above 100 once hitcount:10 break
To log every write of a state without stopping, and capture what the screen looked like:
debug.breakprop /Screen/RootPage Focused eq true log,screenshot
Note
The property needs no value beforehand. Registering the breakpoint creates the node’s property storage entry for it, so you can break on a property nothing has written yet and catch the first write to it — often the write worth catching.
The node itself must exist, because there is nothing to register the handler on otherwise. If no
property type can be resolved for the name at all, the breakpoint is still created but reported
with "notification": false, and never fires. debug.breakpoints shows the same flag,
and the Monitor Web UI labels such a breakpoint Dormant — check the name against
overwatch.props, then remove and add it again.
Note
The node path is resolved against every enumerated view root, matching each root’s own
canonical path, so every path overwatch.nodes reports round-trips — including on a host with
several roots, such as a service-hosted application with one view adapter per client. A path
that names no node returns Node not found rather than silently answering for the first root.
overwatch.props and overwatch.setprop share the same resolver.
When a breakpoint’s command runs¶
The condition is evaluated inside the property write, and the log,
screenshot and break actions run there. The command action does not: it is queued on the
Kanzi UI thread, like a command from a console, and runs after the write has returned, once the
application handles its queued tasks.
That is what makes any command safe to run from a breakpoint. A command run inside the write would
run while the node being written, and any parent going through its children, are still in the
middle of a call. A command that changes the node tree, such as a nodetree.* command or
ui 0, or that runs application logic, such as overwatch.dispatchmessage, could then destroy
the node under its own write.
The command sees the application after the write: reading the property gives the new value.
When a breakpoint triggers several times before the queue is handled, its command runs once for each trigger, in the order of the triggers.
A command that writes the watched property again triggers the breakpoint again, and its command runs in the next frame, not inside the first one. Such a breakpoint repeats once per frame until its condition no longer holds; use
onceorhitcount:Nto stop it.The command’s output goes to the application log rather than to a client, as
Breakpoint #<id>: ran '<command>' (result <n>) -> <output>.
Available commands¶
Command |
Description |
|---|---|
|
Adds a property breakpoint. Usage: |
|
Gets property breakpoints as JSON. |
|
Removes a property breakpoint. Usage: |
|
Activates or deactivates a breakpoint, resetting its hit count when activating. Usage: |
|
Attaches a console command to a breakpoint and enables its command action. Usage: |
|
Removes all property breakpoints. |
|
Fetches the screenshot a breakpoint’s screenshot action captured, and frees the
single capture slot for the next breakpoint. |