flog_dart 0.8.0
flog_dart: ^0.8.0 copied to clipboard
Flutter companion for flog terminal log viewer. Structured logging, Network Inspector (HTTP/SSE/WS), FlogDio drop-in, mock interceptor. Tree-shakes to zero in release builds.
Changelog #
All notable changes to flog_dart. This project follows
Semantic Versioning.
0.8.0 — 2026-04-27 #
Breaking release. The SSE subsystem is redesigned into three
composable StreamTransformers (DART-033). Non-SSE APIs (FlogLogger,
FlogDio non-sse surface, FlogWebSocket, FlogMockInterceptor,
Flog.init) are unchanged and source-compatible.
What's new #
SseByteDecoder : StreamTransformer<List<int>, String>— UTF-8 boundary reassembly with zero-copyUint8Listview slicing, leading BOM strip, and a bounded buffer (default 1 MiB, configurable viamaxBufferBytes) that errors out on runaway producers.SseLineDecoder : StreamTransformer<String, SseEvent>— pure W3C line/field parser as a proper transformer; all state lives on the transformer's per-subscription sink, no closure-captured locals.FlogSseReporter : StreamTransformer<SseEvent, SseEvent>— tee that mirrors every event to flog_net (req/chunk/done/errframes) while passing events through untouched. WhenflogEnabledisfalseat compile time, AOT tree-shakes the whole reporter away.SseResponse.events—Stream<SseEvent>typed access fromFlogDio.sse(). Exposesevent:/id:/retry:fields that the legacy data-only.streamhid.SseResponse.options— exposes the finalRequestOptions.
Migration #
FlogSseParser — no code changes required
FlogSseParser.wrap / FlogSseParser.wrapTyped keep their exact v0.7
signatures and behavior. They now delegate to the new transformer
pipeline internally:
// Before (v0.7.x) and after (v0.8.0) — unchanged:
final dataStream = FlogSseParser.wrap(response.data!.stream, url: url);
final events = FlogSseParser.wrapTyped(response.data!.stream, url: url);
If you were depending on FlogSseParser directly, nothing changes.
SseResponse.stream → .events (recommended)
.stream is still functional; it's annotated @Deprecated and will be
removed in v1.0. Prefer .events for new code:
// Before — data-only:
final sse = await dio.sse('/chat');
await for (final data in sse.stream) {
print(data);
}
// After — typed, with event:, id:, retry:
final sse = await dio.sse('/chat');
await for (final evt in sse.events) {
if (evt.data == '[DONE]') break; // now explicit
print('${evt.event ?? "message"}[${evt.id}]: ${evt.data}');
}
[DONE] filtering is NOT applied to .events — users that relied on
the legacy filter should add .where((e) => e.data != '[DONE]')
explicitly.
.stream and .events share ONE subscription to the underlying byte
stream. Listening to both on the same SseResponse raises
StateError: Stream has already been listened to. — pick one.
Custom pipelines
You can now build your own pipeline, swap the reporter for a custom one, or bypass the reporter entirely:
import 'package:flog_dart/flog_dart.dart';
final events = byteStream
.transform(const SseByteDecoder(maxBufferBytes: 4 * 1024 * 1024))
.transform(const SseLineDecoder())
// .transform(FlogSseReporter(url: url)) // omit for no telemetry
;
Internal #
flog_sse_parser.dart417 lines → 75 lines (compat shim).- New files:
lib/src/sse/byte_decoder.dart,lib/src/sse/line_decoder.dart,lib/src/sse/reporter.dart,lib/src/sse/event.dart. - Test count: 133 → 161 (+28 new across the three transformer layers
and the
SseResponseintegration tests).
Red lines honored #
- All 47 tests in
flog_sse_parser_test.dartpass unchanged against the compat shim. - Non-SSE public API byte-identical to 0.7.3.
- No new dependencies (everything is
dart:async/dart:convert/dart:typed_data).
0.7.3 — 2026-04-24 #
Consolidation release of the Phase 3 / 4 / 5 cleanup campaign. All B-class bugs identified in the Phase 1 audit are fixed; README + CHANGELOG rewritten; public API is unchanged from 0.7.2 (breaking changes deferred to v0.8 per DART-033). Safe to pick up as a drop-in upgrade.
DART-024 / DART-025 audit resolution (Phase 5) #
- README rewritten — covers
Flog.init,FlogDio+FlogHttpConfig, SSE (FlogDio.sse/FlogSseParser.wrap/FlogSseParser.wrapTyped- typed
SseEvent),FlogWebSocket, mock rules sync semantics, replay round-trip,flogEnabledoverride matrix, and the planned v0.8 breaking-change set.
- typed
- CHANGELOG gap-filled back to v0.1.0 from git history.
- Forward reference added for the planned v0.8 release (DART-033) — see "Planned for v0.8" below.
Phase 3 Step 3.4 — flog_dart redesign (B+D-class fixes) #
Bug fixes and refactors landed during the Phase 3 cleanup campaign
(2026-04-22 → 2026-04-24). These ship in the current 0.7.2 line.
Bug fixes (B-class):
- DART-001 —
FlogSseParsernow correctly handles W3C-compliant multi-event-per-chunk payloads and multi-linedata:joins. The previous parser dropped every event after the firstdata:in a single chunk. - DART-002 —
FlogSseParser.wrapTypedand theSseEventtype are now implemented. The pre-existingflog_dart/test/suite (which referenced these APIs before they existed) now compiles and passes. - DART-004 —
FlogMockInterceptor.onRequestis now a no-op whenflogEnabled == false(previously ran mock-matching logic in release builds too, adding per-request overhead). - DART-006 —
FlogWebSocket.streamis now an actual broadcast stream (previously documented as broadcast but implemented as single-subscription). - DART-007 —
FlogHttpInterceptor._truncatecompares against a byte budget using byte length rather than character count (previously could truncate multi-byte UTF-8 mid-rune). - DART-008 —
FlogHttpInterceptorcleans up its internal_idMap/_startMapon every exit path, including when an earlier interceptor rejected or resolved the request. - DART-009 —
emitNetnow clones the caller-supplied map before stamping protocol metadata (type,id, timestamp). Previously mutated caller-owned maps.
Architecture (D-class):
- DART-010 —
FlogDio.sseextracted intoflog_dio_sse.dartto keepflog_dio.dartbelow the 500-line budget. Public API unchanged. - DART-011..DART-014 — Mock extras key (
flog_mocked) extracted to a named constant; match semantics (substring, first-match-wins, case-sensitive) documented onFlogMockInterceptor. - DART-015..DART-017 —
FlogServerport-scan range is now a named_portScanRange = 10constant; the server logs a clear error when all 10 ports are taken;_handleReplaynow surfaces Dio errors viadebugPrintinstead of silently fire-and-forget. - DART-018 / DART-019 —
FlogWebSocket.fromChanneldeduplicated with the primary constructor; the<binary: N bytes>format string extracted to a named constant. - DART-020 —
FlogStorecapacity (50 000) lifted to a named constant. - DART-021 —
nextNetIdandemitNetmarked@internal. Still exported from the library barrel for v0.x back-compat (see "Planned for v0.8" below). - DART-022 — Dead
appName/appVersion/packageNameparameters removed fromFlogServer.start. Callers now useFlogServer.updateAppInfo(...). - DART-023 —
Flog.initnow logsPackageInfofailures viadebugPrintinstead of swallowing them silently. - DART-026 —
FlogDio.ssenow guards against a nullresponse.dataso empty-body streams do not crash. - DART-027 — HTTP interceptor emit path refactored: a new
_emitHttpCompletionhelper deduplicates ~30 lines of request-emit logic shared between the real-response and mocked-response paths.
Planned for v0.8 #
Breaking release. Wire protocol stays unchanged — flog TUI 0.4.x will continue to work against v0.7.x and v0.8.x; migration only affects Dart-side SSE call sites.
- DART-033 — SSE subsystem redesign:
FlogSseParserbecomes a properStreamTransformer<List<int>, SseEvent>; parsing and telemetry (theemitNetchunk logging) separate into two composable transformers.FlogDio.ssereturns the raw byte stream alongside the typedSseEventstream so callers can pick whichever layer they need.- Hard byte-buffer limit added; oversized events error out rather than OOM the isolate.
- UTF-8 decode cost reduced by buffering at the byte layer.
nextNetIdandemitNetremoved from the public library barrel (DART-021). Callers that still depend on them should import frompackage:flog_dart/src/flog_net.dart(and note that file is@internal— it may move again in v1.0).
0.7.2 — 2026-04-22 #
flogEnableddefault now recognises--dart-define=APP_FLAVOR:APP_FLAVOR=release→ disabled (tree-shaken away).APP_FLAVOR=alphaor any other value → enabled.- Unset → falls back to the original
!dart.vm.productderivation.
- Explicit
--dart-define=FLOG_ENABLED=...continues to take precedence over both derivations.
0.7.1 — 2026-04-21 #
- FlogHttpInterceptor —
onErrornow emits HTTP status code, response headers, and response body for server error responses (4xx / 5xx). Previously only a generic error string was sent, causing flog to show "failed" instead of the actual status code.
0.6.4 — 2026-04-20 #
- Rename the library file from
flog_logger.darttoflog_dart.dartsopackage:flog_dart/flog_dart.dartis the canonical import.
0.6.3 — 2026-04-20 #
- Add a
flog_dart.dartbarrel file sopackage:flog_dart/flog_dart.dartresolves cleanly.
0.6.2 — 2026-04-20 #
- Remove the upper bound on
package_info_plusto avoid false resolution conflicts.
0.6.1 — 2026-04-20 #
- Widen
package_info_plusconstraint to support v9+.
0.6.0 — 2026-04-20 #
- New:
Flog.init()— top-level bootstrap. Auto-detects app name / version / package name viapackage_info_plus; registersdebugPrint+FlutterError.onError+PlatformDispatcher.onErrorhooks so framework logs + crashes reach the TUI automatically. FlogDiodecoupled from the logger bootstrap — previously constructing aFlogDioimplicitly started the WS server; nowFlog.init()is the only entry point that starts the server.- System log capture:
debugPrintand Flutter error hooks are now captured as regularLogEntrys.
0.5.0 — 2026-04-19 #
- Data source architecture:
FlogStoreintroduced — a 50 000-entry FIFO ring buffer that stores every log + network frame as it's produced. When a TUI connects (or resubscribes after a session switch), the buffer is replayed and then the app transitions seamlessly to live. - System log capture hooks registered at startup.
0.4.0 — 2026-04-18 #
- Direct Socket architecture: the app now hosts a WebSocket server
(
FlogServer); flog TUI is the client. Logs and network frames no longer flow through VM Serviceprint/developer.log— they travel directly over the WS channel. FlogClient(earlier short-lived rename) removed;FlogServeris the single transport component on the Dart side.- Multi-app connection framework: flog TUI can attach to several running apps simultaneously and switch between them with per-app session isolation.
0.3.0 — 2026-04-17 #
FlogDio— drop-inDioreplacement that auto-insertsFlogMockInterceptor+FlogHttpInterceptorat the front of the chain.- Interceptor-based mock system (replaces the earlier proxy-server approach): rules authored in the flog TUI sync over the control channel; matching requests resolve locally with the canned response.
- Mocked responses emit
flog_netreq+resframes so they appear in the inspector taggedMocked. - Release builds tree-shake
flog_dartto zero viaflogEnabled. - iOS real device support via
developer.logfallback alongsideprintfor the initial channel.
0.2.0 — 2026-04-15 #
- FlogHttpInterceptor — Dio interceptor for HTTP request /
response logging, emitted to flog's Network Inspector via the
shared
emitNethelper. - FlogSseParser — SSE stream wrapper with chunk-level logging.
- FlogWebSocket — WebSocket wrapper with send / recv message logging.
- Shared
emitNet()helper using the[INFO][flog_net]protocol prefix. - All interceptors configurable: headers, body, max size, filter predicate.
0.1.0 — 2026-04-10 #
- Initial release.
FlogLoggerclass with tag-based structured logging.- Full-word methods:
verbose(),debug(),info(),warning(),error(). - Single-letter shorthand:
v(),d(),i(),w(),e(). - Optional
error+stackTracenamed parameters ondebug/warning/error.