Skip to content

Output Formats

albertoodev edited this page Aug 15, 2026 · 8 revisions

Output formats

analyze and the instrumented app write JSON Lines: one self-contained JSON object per line. The field names and types below come from the toJson methods in lib/src/features/*/data/models/. Extracted Features explains how each static metric is calculated.

Static analysis JSONL (analyze)

One JSON object is written for each rebuild scope: a State subclass, a ConsumerWidget/HookConsumerWidget, or the builder callback of a state-management widget (BlocBuilder, Consumer, Obx, …). The analyze output contains exactly these 18 fields (AnalysisResultModel.toJson):

{
  "instanceId": "42",
  "filePath": "lib/screens/shopping_cart_screen.dart",
  "scopeName": "_ShoppingCartScreenState",
  "scopeType": "State",
  "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 scope: hash of the root-relative path plus the scope name (and, for non-State scopes, its type and occurrence index). 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.
scopeName string Class name of the scope, or <Widget>_builder for a builder callback (e.g. BlocBuilder_builder). (Named stateClassName before rebuild-scope support.)
scopeType string Kind of rebuild scope: State, ConsumerWidget, or the builder widget name (BlocBuilder, BlocSelector, BlocConsumer, Consumer, Selector, Obx, GetX, GetBuilder, Observer).
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/.useDelegate, or a list that is lazy by contract), 2 eager O(N) (concrete children: on a scroll list, a SliverChildListDelegate, or runtime-length Column/Row/Wrap/Flex children). Scroll lists are ListView, GridView, ReorderableListView, PageView, ListWheelScrollView. (Replaced the buildUsesListViewBuilder boolean on 2026-07-20; widened beyond ListView/GridView/slivers on 2026-08-15.)
rootBuildReturnsConstWidget 0/1 Whether every top-level return of the root State.build is a const widget. (Any one const return set it before 2026-08-15.)
treeConstWidgetCount int Const widget boundaries across reachable build bodies and helper bodies alike. (Named constConstructorRatio in JSONL produced before 2026-07-18; helper-body const widgets went to helperWidgetCount before 2026-08-15.)
helperReferenceCount int Widget-returning helper reference sites in reachable build bodies: invocations, tear-offs, and explicit getters. Helpers returning List<Widget> count; SDK pass-throughs such as toList do not.
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, linear collection operations, and List.generate 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, List.generate, and lazy builders. Includes widgets built by a local function called from inside such a scope.
valueObjectAllocCount int All non-const, non-widget constructor allocations across build and helper bodies.
helperWidgetCount int Non-const widget instantiations in reachable helper bodies; const ones are counted by treeConstWidgetCount. (Included const widgets before 2026-08-15.)
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 — since renamed to scopeName) are unchanged. The legacy boolean buildUsesListViewBuilder maps onto the none/lazy levels of the ordinal only; it cannot express eager (2).

Rebuild-scope rows

analyze emits one row per rebuild scope, so a file can contribute several overlapping rows: a State row counts the widgets built inside a nested BlocBuilder callback and the callback gets its own row. That is deliberate — a parent rebuild re-runs the callback, while the callback row measures the path its package can rebuild on its own.

Use --scope-types to narrow the output (--scope-types=State reproduces the pre-rebuild-scope rows). inject only instruments State subclasses and skips rows of any other scopeType, so a full-scope JSONL can be passed to it unchanged.

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