Skip to content

Output Formats

albertoodev edited this page Jul 21, 2026 · 8 revisions

Output Formats

Every SPM command emits JSON Lines (JSONL): one self-contained JSON object per line. This page documents the schemas produced by analyze (static) and the instrumented app under run (runtime). Field names and types here are taken directly from the toJson methods in lib/features/*/data/models/. For the meaning of each analysis metric, see Extracted Features.


Static analysis JSONL (analyze)

One JSON object per line, one line per State class. The analyze output contains exactly these 17 fields (AnalysisResultModel.toJson):

{
  "instanceId": "42",
  "filePath": "lib/screens/shopping_cart_screen.dart",
  "stateClassName": "_ShoppingCartScreenState",
  "treeNonConstWidgetCount": 24,
  "treeMaxWidgetNestingDepth": 7,
  "treeListRenderingStrategy": 2,
  "rootBuildReturnsConstWidget": 0,
  "treeConstWidgetCount": 2,
  "helperReferenceCount": 2,
  "usesLayoutDependentBuilder": 1,
  "treeCyclomaticComplexity": 5,
  "treeIterationCount": 1,
  "treeMaxIterationNestingDepth": 1,
  "iterationWidgetCount": 3,
  "valueObjectAllocCount": 4,
  "helperWidgetCount": 3,
  "helperMaxWidgetNestingDepth": 2
}

Field reference

Field Type Description
instanceId string ID for this State class: hash of the root-relative path + class name. Used to join with runtime profiler data. It is not unique across transplanted targets that share one file/class, so the benchmark pipeline keys by sample_id instead.
filePath string Source path relative to the analyzed project root.
stateClassName string Name of the State subclass.
treeNonConstWidgetCount int Non-const widget instantiations across reachable build bodies; excludes const boundaries and helper-body widgets.
treeMaxWidgetNestingDepth int Maximum widget depth composed across reachable custom-widget build bodies.
treeListRenderingStrategy 0/1/2 Worst list-rendering form across builds and helpers: 0 none, 1 lazy (.builder/.separated/.custom, slivers), 2 eager O(N) (concrete children: on a scroll list, or runtime-length Column/Row/Wrap/Flex children). (Replaced the buildUsesListViewBuilder boolean on 2026-07-20.)
rootBuildReturnsConstWidget 0/1 Whether the root State.build directly returns a const widget.
treeConstWidgetCount int Const widget boundaries across reachable build bodies; helper-body const widgets belong to helperWidgetCount. (Named constConstructorRatio in JSONL produced before 2026-07-18.)
helperReferenceCount int Widget-returning helper reference sites in reachable build bodies: invocations, tear-offs, and explicit getters.
usesLayoutDependentBuilder 0/1 Whether builds or helpers use LayoutBuilder, CustomMultiChildLayout, or Flow.
treeCyclomaticComplexity int Complexity summed across reachable build bodies, plus helper-body decision points without extra helper base points.
treeIterationCount int Loops, collection-for elements, and linear collection operations across build and helper bodies.
treeMaxIterationNestingDepth int Maximum lexical iteration nesting within any analyzed build or helper body.
iterationWidgetCount int Non-const widgets built in per-element scopes across builds and helpers: loops, collection-op callbacks, and lazy builders.
valueObjectAllocCount int All non-const, non-widget constructor allocations across build and helper bodies.
helperWidgetCount int Widget instantiations in reachable helper bodies, including const widgets.
helperMaxWidgetNestingDepth int Maximum widget nesting within any individual reachable helper body.

0/1 fields are Dart bools serialized as 1/0 by toJson. See Extracted Features for the precise definition of each metric.

Key migration (2026-07-20 rename)

Feature keys were renamed so every name states its scope: tree* = aggregated over the whole static call tree, root* = root build() only, helper* = helper bodies only. Older JSONL files can be normalized with this map:

Old key (pre-2026-07-20) Current key
buildWidgetInstanceCount treeNonConstWidgetCount
buildMaxWidgetNestingDepth treeMaxWidgetNestingDepth
buildUsesListViewBuilder (bool, pre-07-20) / buildListRenderingStrategy treeListRenderingStrategy
buildReturnsConstWidget rootBuildReturnsConstWidget
constConstructorRatio (pre-07-18) / constWidgetCount treeConstWidgetCount
buildHelperMethodCount helperReferenceCount
buildCyclomaticComplexity treeCyclomaticComplexity
buildIterationCount treeIterationCount
buildMaxIterationNestingDepth treeMaxIterationNestingDepth
helperMethodWidgetCount helperWidgetCount
helperMethodMaxNestingDepth helperMaxWidgetNestingDepth

usesLayoutDependentBuilder, iterationWidgetCount, valueObjectAllocCount, and the identity keys (instanceId, filePath, stateClassName) are unchanged. The legacy boolean buildUsesListViewBuilder maps onto the none/lazy levels of the ordinal only; it cannot express eager (2).


Runtime profiler JSONL (run / instrumented app)

Two event types are emitted, distinguished by the event field. Which one you get depends on the Flutter build mode (see inject): --profileperformance_metric, --debugdataflow-metric. Every event carries a timestamp (ISO-8601) and the instanceId that joins back to the static-analysis record.

Performance event, emitted under --profile (PerformanceMetricsModel.toJson):

{
  "timestamp": "2026-02-20T10:15:30.123Z",
  "event": "performance_metric",
  "instanceId": "42",
  "buildSpan": 4123
}
Field Type Description
timestamp string ISO-8601 timestamp of the event.
event string Always "performance_metric".
instanceId string The instrumented State instance.
buildSpan int Build duration of the matched rebuild frame, in microseconds (0 on the 5-second timeout fallback).

Dataflow event, emitted under --debug (DataflowMetricsModel.toJson):

{
  "timestamp": "2026-02-20T10:15:30.456Z",
  "event": "dataflow-metric",
  "instanceId": "42",
  "taintedRebuildCount": 5,
  "totalWidgetCount": 42,
  "maxNestingDepth": 7,
  "taintedRatio": 0.119,
  "opacityRebuildCount": 0,
  "shaderMaskRebuildCount": 0,
  "clipRRectRebuildCount": 1,
  "clipOvalRebuildCount": 0,
  "clipPathRebuildCount": 0,
  "backdropFilterRebuildCount": 0
}
Field Type Description
timestamp string ISO-8601 timestamp of the event.
event string Always "dataflow-metric".
instanceId string The instrumented State instance.
taintedRebuildCount int Widgets that actually rebuilt as a result of the setState.
totalWidgetCount int Total widgets in the analyzed subtree.
maxNestingDepth int Maximum nesting depth of the analyzed subtree.
taintedRatio double taintedRebuildCount / totalWidgetCount.
opacityRebuildCount int Rebuilt Opacity widgets.
shaderMaskRebuildCount int Rebuilt ShaderMask widgets.
clipRRectRebuildCount int Rebuilt ClipRRect widgets.
clipOvalRebuildCount int Rebuilt ClipOval widgets.
clipPathRebuildCount int Rebuilt ClipPath widgets.
backdropFilterRebuildCount int Rebuilt BackdropFilter widgets.

Clone this wiki locally