Conversation
Groundwork for delivering the Rust core through Dart's Native Assets, which is only stable from Flutter 3.38 / Dart 3.10 onwards. The newer language version turns on lints the tree does not yet satisfy: - `*.g.dart` joins the analyzer exclusions. AGENTS.md already described json_serializable output as excluded, but only the protobuf patterns actually were; 47 of the 48 new `use_null_aware_elements` hits are in generated files nobody edits by hand. - The remaining `use_null_aware_elements` hit, in `Room`, and four `unnecessary_underscores` hits in the RPC tests, are fixed directly. Crossing Dart 3.7 also switches `dart format` to the tall style, which reformats the whole tree. That is mechanical and lands separately, in the commit that follows, so it does not bury this one. `dart format --set-exit-if-changed` is therefore red at this commit and green again at the next. No functional change.
Pure output of `dart format .`. No functional or semantic change. The formatter picks its style from the package language version, so the SDK bump in the previous commit crosses Dart 3.7 and switches the whole tree from the short style to the tall one. `dart format --set-exit-if-changed` is CI-enforced, so this has to land -- it is split out only so the bump and its lint fixes stay readable. Reproduce with `dart format .` on the parent commit.
Establishes the development loop for calling into `livekit-uniffi` from this SDK, and exercises it with `buildVersion()` -- a synchronous, argument-free call returning a string, so a green test means the whole chain is intact: the build hook resolved a cdylib for the target, Native Assets bundled it, `@Native` bound the symbol, and a value crossed back. `lib/src/uniffi/` splits native/web with the same conditional-import pattern as the rest of the SDK. There is no dynamic library to load on the web, so `uniffi_io.dart` is the only file permitted to import the generated bindings -- reaching them from anywhere web-reachable pulls `dart:ffi` into a web compile and breaks `flutter build web`/`--wasm`. Callers branch on `LiveKitUniffi.isAvailable`. The facade is internal for now; nothing is added to the public API surface. `livekit_uniffi` is not on pub.dev, so both pubspecs override it to a sibling rust-sdks checkout -- overrides do not propagate from a dependency, hence both. Until it is published this branch cannot merge: CI has no rust-sdks checkout, so `flutter pub get` will fail there. Verified: 392 tests pass, web and wasm builds succeed, analyze and format are clean.
# Conflicts: # example/pubspec.yaml # lib/src/core/engine.dart # lib/src/core/room.dart # lib/src/e2ee/key_provider.dart # lib/src/extensions.dart # lib/src/json/agent_attributes.g.dart # lib/src/token_source/caching.g.dart # lib/src/token_source/jwt.g.dart # lib/src/token_source/room_configuration.g.dart # lib/src/token_source/token_source.g.dart # pubspec.lock # pubspec.yaml
livekit_uniffi 0.1.10 is published, and its release carries the prebuilt libraries the build hook downloads, so the path overrides to a sibling rust-sdks checkout are no longer needed in either pubspec.
The path override becomes the opt-in for developing against unreleased crate changes rather than the default, and the note about releases lacking assets is replaced with how download mode behaves.
flutter_webrtc moved to 1.6.2+hotfix.1 on main.
0.1.12 is the first version published by the release pipeline. Its build hook keeps each target architecture's downloaded library in its own directory, which the universal macOS release build needs; 0.1.10 wrote both to one path and the macOS CI job failed in lipo. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
# Conflicts: # pubspec.lock
The example logs the Rust core build version at startup and shows it on the connect page, one synchronous FFI call that proves the native library was bundled and loads on the platform.
…ngine and tracks Mirrors the Swift integration. The core (livekit-telemetry over UniFFI) owns every policy; Dart adds only what a core cannot: a bytes-moving transport, instruments that feed OS signals in, and the wiring of Room / Engine / tracks / stats / logs into the core's typed API. Shape: - lib/src/telemetry/telemetry.dart: public TelemetryOptions (mirrors TelemetryConfig), TelemetryInstrument, Telemetry (configure / setAttribute / diagnostics / log), plus the internal ConnectStep vocabulary and the zone-carried ambient span. Conditionally exports the hooks from telemetry_io.dart (native) or telemetry_web.dart (all no-ops), so the SDK keeps compiling for web with telemetry off. UniFFI types never appear in the public API; uniffi_io.dart stays the single import site of the bindings and re-exports them for telemetry_io.dart. - Transport: telemetryConfigurePulled + a Dart loop serving the TelemetryExportQueue with package:http (uniffi-dart callbacks are isolate-bound, so the core never calls into Dart from its threads). - Instruments: device (app lifecycle and memory pressure via WidgetsBindingObserver, network via connectivity_plus, audio outputs via Hardware.onDeviceChange), logs (the SDK logger at warn+ into telemetryLog, the core's own log lines pulled through log_forward into Logger 'livekit.ffi.<target>'), rtc (raw getStats reports forwarded per track with recordStatsReport; remote track lifecycle for the core-owned lk.subscribe span). Capture failures from LocalTrack.createStream. - Room takes its scope at construction; telemetrySetServer on connect; lk.connect span with ws_open / signal / join_recv / pc_created / offer_sent / answer_sent / engine / pc_connected / room_connected; lk.reconnect per cycle with attempt N quick|full steps; setRoom after the join response; disconnected(reason) once per real session; room.telemetryTraceId and room.emitTelemetryEvent; lk.publish spans in LocalParticipant.publishAudioTrack / publishVideoTrack (parented to an open connect span). LiveKitClient.setTelemetry(options) next to initialize. - Reasons map through telemetryDisconnectReason / telemetryReconnectReason from the protocol numbers; the SDK's client-side values map directly. Tests: test/telemetry/telemetry_e2e_test.dart runs a mock session against a local collector (connect, publish, quick reconnect, stats windows, disconnect) and asserts on the OTLP/JSON it wrote; the mock peer connection grew a sender whose getStats reports an outbound-rtp stream. telemetry_instruments_test.dart checks instruments start/stop on the Dart thread. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nder the Room Follows the core fixes (63-bit span ids, a finishable pull queue, scope-level log records): - Span ids always round-trip now: TraceSpan.spanId has no fallback and the e2e test asserts the log-to-span correlation unconditionally. - The pipeline's export queue is kept; configure(null) calls finish() after the shutdown and a replacing configure() finishes the previous queue, so next() resolves null and the serving loop exits, closing its http.Client. Covered in telemetry_instruments_test.dart. - The Room subscribes its engine, signal, RPC and data-stream listeners in a zone carrying its RoomTelemetry; a warn/error record logged from one of its handlers with no span open goes through TelemetryScope.log and lands in the Room's session instead of the process scope. Records inside a span keep going through telemetryLog with the span id; records with no Room stay process-scoped. The e2e test drives a Room-handler warning and asserts it carries the Room's trace and scope attributes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Telemetry
Draft: integrates the shared Rust telemetry core (
livekit-telemetry, livekit/rust-sdks#1396) into the Flutter SDK, per the "Client Telemetry" design doc. Same shape as the Swift integration (livekit/client-sdk-swift#1108); the core owns policy and vocabulary, the SDK contributes a transport, instruments and the wiring.Design
Telemetryis the one entry point:LiveKitClient.setTelemetry(options)/Telemetry.configure(options)configure the process-wide pipeline (it lives in the Rust core) at any time; everyRoomtakes a scope with its own trace id at construction (room.telemetryTraceId), so pre-connect failures are captured and nothing leaks a session handle.TelemetryOptionsmirrors the core's config (endpoint, headers, storage directory, flush interval, stats window, instruments, log level); nothing from UniFFI is public.TelemetryOptions.instruments(room,rtc,logs,device; all by default): device (app lifecycle, memory pressure, connectivity type, audio device changes, capture failures), warn/error records from the SDK logger and the Rust core, and per Room thelk.connect/lk.reconnect/lk.publishspans with their checkpoints fromRoom,EngineandLocalParticipant; remote-track lifecycle goes to the core, which runs thelk.subscribespan itself; each track's existing stats monitor hands the rawgetStats()report to the core, which maps and windows it.package:http(uniffi-dart callbacks are isolate-bound); the destination is derived from the connect URL unlessTelemetryOptions.endpointis set.Testing
test/telemetry/telemetry_e2e_test.dartruns a mock session (mock websocket and peer connection) with telemetry pointed at anotelcol-contribwriting OTLP/JSON to disk and asserts the spans, steps, records and stats windows that reached it;test/telemetry/telemetry_instruments_test.dartcovers the instrument lifecycle.pubspec.yamlcarries adependency_overridesto a locally builtlivekit_uniffifor now.