Tutorials
Diagnose one execution with DevTools
Connect the extension, reproduce a policy conflict, trace one Execution, and disclose only safe application data.
Diagnose one execution with DevTools
This tutorial turns an unclear report — “the second save did not run” — into a traceable lifecycle explanation. The extension remains read-only throughout the session.
Install the development tool
Add DevTools directly to the application being inspected, not only to another workspace package.
dev_dependencies:
usecase_forge_devtools: ^0.1.0-dev.3
Resolve dependencies and restart both the application and DevTools. No application initialize() call is required.
Create a policy conflict worth observing
Assume SaveDocument uses the document identifier as its executionKey and rejects a new Command while related work is active.
registerCommand<SaveDocument>(
_save,
instructions: const UseCaseInstructionOverrides(
processing: UseCaseProcessingInstructionOverrides(
existingExecutionPolicy: UseCaseExistingExecutionPolicy.rejectNew,
),
),
);
Run a development build, submit two saves for the same document before the first finishes, and keep the UseCase alive while opening DevTools.
Find the earliest visible boundary
Open the UseCase Forge tab and select the relevant UseCase. Read the lifecycle in order:
- confirm the exact Command type and
executionKey; - check whether the second entry reached Admission or Pending;
- inspect rejection events before blaming handler duration;
- look for
activeConflictand therejectNewpolicy; - verify that the first Execution continues independently.
The rejected Command does not enter terminal history because processing never started. That absence is part of the contract, not missing telemetry.
Trace the accepted Execution
Use its Execution ID to connect positions, Snapshot changes, cancellation events, error routing, and the terminal Entry. Command type and group key explain related work; only the Execution ID identifies one attempt.
Expose a safe diagnostic representation
Technical lifecycle metadata is automatic. Application values stay hidden until the UseCase explicitly provides bounded JSON-safe data.
import 'package:usecase_forge/diagnostics.dart';
final class DocumentUseCase extends UseCase<DocumentState>
with UseCaseDiagnosticsDataProvider {
@override
String get useCaseDiagnosticLabel => 'Document editor';
@override
Object? encodeUseCaseDiagnosticValue(
UseCaseDiagnosticValueKind kind,
Object? value,
) {
if (kind == UseCaseDiagnosticValueKind.state && value is DocumentState) {
return {'dirty': value.isDirty, 'revision': value.revision};
}
return null;
}
}
Do not expose document contents, credentials, personal data, unrestricted stack traces, or full network payloads. Returning null keeps a value hidden.
Write down the diagnosis
A useful result names evidence and ownership:
The second
SaveDocumentwas rejected withactiveConflict. Both Commands had the same exact type and document key. The registeredrejectNewpolicy preserved the first active Execution. The save handler did not receive the second Command.
From here, decide whether product behavior requires rejectNew, restart, or coexist. DevTools proves what happened; it does not choose the product policy.
Continue with queue and policy diagnosis, safe diagnostic data, and error-route tracing.