Repository navigation
feat(amplify_event_enrichment): add example app - #7076
Open
ekjotmultani wants to merge 33 commits into
Open
ekjotmultani wants to merge 33 commits into
ekjotmultani wants to merge 33 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## feat/event-enrichment-client #7076 +/- ##
================================================================
+ Coverage 56.57% 56.78% +0.21%
================================================================
Files 122 125 +3
Lines 8301 8365 +64
Branches 3612 3644 +32
================================================================
+ Hits 4696 4750 +54
- Misses 3605 3615 +10 🚀 New features to boost your workflow:
|
cadivus
reviewed
Jul 2, 2026
| dependencies: | ||
| amplify_event_enrichment: | ||
| path: ../ | ||
| amplify_foundation_dart: ">=2.11.0 <2.12.0" |
Member
There was a problem hiding this comment.
In example apps for our libs in this repo, I'd use any as a version so that we don't need to care about version bumps.
Member
Author
There was a problem hiding this comment.
Done, switched the example deps to any.
ekjotmultani
force-pushed
the
feat/event-enrichment-client-example
branch
from
July 6, 2026 20:24
14c3d90 to
2a2ccfe
Compare
ekjotmultani
marked this pull request as ready for review
July 6, 2026 22:42
ekjotmultani
force-pushed
the
feat/event-enrichment-client
branch
from
July 29, 2026 21:23
90d1c28 to
f357a12
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client-example
branch
from
July 29, 2026 21:23
2a2ccfe to
9b0c398
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client-example
branch
4 times, most recently
from
August 21, 2026 17:38
c5c9e18 to
c25df04
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client
branch
2 times, most recently
from
August 24, 2026 19:35
09f6a20 to
155ac32
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client-example
branch
from
August 24, 2026 19:35
c25df04 to
47bfbf6
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client
branch
from
August 24, 2026 19:37
155ac32 to
b271735
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client-example
branch
2 times, most recently
from
August 25, 2026 20:31
cbbe5e6 to
d22bc72
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client-example
branch
from
September 1, 2026 18:57
d22bc72 to
fd389de
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client-example
branch
from
September 10, 2026 15:11
fd389de to
82ede0b
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client-example
branch
2 times, most recently
from
September 21, 2026 18:27
4a59dfc to
57f9692
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client-example
branch
from
October 23, 2026 07:48
57f9692 to
4a9ec80
Compare
ekjotmultani
force-pushed
the
feat/event-enrichment-client
branch
from
October 23, 2026 07:57
dd6a04c to
541d0d9
Compare
Records an event, stops the session, then records again and asserts the second event gets a new session id with no stop_timestamp, proving a stopped session is not reused.
Apply prefer_const, prefer_int_literals, and cascade_invocations fixes plus formatting so the per-package CI passes analyze (--fatal-infos --fatal-warnings) and the format check on both enrichment packages.
…etadata provider - assert a sink failure surfaces through Result.error rather than throwing - assert EventEnrichmentClientFlutter.create degrades gracefully when a device metadata provider throws - add coverage for the default PlatformDeviceMetadataProvider
…'s new surface Adapts the suites to the async EventSink and Future-returning record(). New coverage: - a sink that suspends before throwing, proving record() catches an asynchronous failure and returns it as Result.error instead of letting it escape to the zone. Verified by removing the await, which makes this test fail with an unhandled "async sink failure". - a sink that throws synchronously, kept as a separate case. - the injected clientIdProvider, its failure fallback, and the shared preferences default. - the wrapper's session controls, including recording with autoSessionTracking disabled to pin the lazy session start.
… semantics Renames the fakes and call sites for `EventSink` -> `Sender` and `sink:` -> `sender:`. New coverage for the session-stop fix, all of which fails without it: - SessionManager: resume after an explicit `stopSession` leaves tracking stopped; resume after a timeout stop still starts a fresh session; `startSession` clears the explicit stop so lifecycle handling resumes; `clearSession` counts as explicit; a stop with no preceding background is not resurrected either - FlutterLifecycleObserver: neither `onResume` nor a `resumed` `AppLifecycleState` restarts a session stopped explicitly - Client: `handleAppResumed` does not restart after an explicit stop, `record()` still lazily starts one, and `close()` drops the session and blocks later restarts The envelope tests are untouched: the json_serializable conversion had to satisfy them as written. 49 -> 57 dart, 14 -> 17 flutter.
Adds a matrix over every path that can end a session, asserting event type, that the event's session section carries the ended session with its stop timestamp and duration, and exact emission counts. Emits once: explicit stopSession(), stopping a paused session, the session timeout expiring under fakeAsync, close() on a running session, and startSession() displacing a running session (asserting the displaced session is the one reported). Emits nothing: no session ever started (stop and close), stopSession() twice, close() after a stop, close() after a timeout, the first startSession(), a pause/resume inside the timeout, a resume after an explicit stop, and record()'s lazy start after a stop. Also covers a sender that suspends before failing on the session-stop event, which is only caught because the emission awaits send() inside its own guard, and asserts the client stays usable afterwards. Existing client tests await stopSession()/close() now that they return Future<void>. The envelope tests are untouched.
Extends the session boundary matrix to _session.start and renames the file, which now covers both events. Emits a start: at construction with autoSessionTracking on, on an explicit startSession() after the displaced stop, on record()'s lazy start ahead of the recorded event, and when a resume follows a session timeout. The start event's session section carries the new session's id and start timestamp with no stop fields, and gets the same enrichment and globals a recorded event gets. Does not emit a start: at construction with autoSessionTracking off, on a pause/resume inside the timeout window (same session), on a resume after an explicit stop, and on any end path. A full timeout cycle asserts two starts and two stops, interleaved, one pair per session and matched by session id. Two ordering tests use a sender that logs when each send begins and completes, which a synchronously-appending sender cannot distinguish: a displaced stop completes before the new start begins, and a lazy start completes before record()'s own send. The sender-failure group now covers startSession() as well, and counts spell out that both the start and stop attempts failed. Existing client tests updated for the eager start now preceding the first recorded event. The envelope tests are untouched.
…fields Session timeout: the resume path is exercised with a timer that never fires, which is what iOS does to a backgrounded Dart isolate, so only the elapsed-time comparison can detect the expiry. Covers the restart, the stop-then-start report order, that an explicit stop still wins, and that both the resume path and the timer path attribute the stop to the pause rather than to detection. Initial fields: the launch _session.start carries initialUserId and the initial globals, and carries none of them when they are not passed, through both the Dart constructor and the wrapper's create().
aft only emits ddc_test and dart2js_test alongside native_test, which needs a test/ directory, so the jobs the build_test dev dependency gates land with the suite.
… starts record() during a pause whose timeout has already passed must close the dead session out and stamp the event with its replacement, not with the session that ended when the app was backgrounded. Inside the timeout it must stay silent on the same session. Also covers that a session started while the app is backgrounded starts paused and can time out there, and that one started after a resume is active.
…pired, and resumed sessions
…calls and close Covers two unawaited startSession() calls (the second displaces the first, end reported before the replacing start), two unawaited sessionForRecording() calls (one shared session, one start), and a second close() awaiting the same teardown. Also asserts the post-close record() error type.
… ordering Three behaviours had no test holding them: _onTimeoutExpired's paused check. A pause timer already dispatched when the resume cancelled it still runs its callback, and without the check it ends a session that is active again. Covered with a timer stand-in that ignores cancel and hands its callback to the test, plus the stop-while-paused case for symmetry. The session threaded out of a restart. A clearSession() landing while the start is still reporting used to make the recording call fail on a null check, so both the recording and the explicit start path now pin that the session they resolve with is the one that was created. close() setting its closed flag before the teardown. A record() made in the same turn as close(), while the final stop emission is still in flight, has to be refused and its event never sent.
…arts, and a closed client
Covers records and boundaries sharing one queue: a record ahead of a stop called in the same turn, a gated send holding everything behind it, one send finishing before the next begins, and a failed send not stalling the rest. Also pins that nothing started through the sessionManager getter during close() reaches the sender, that the launch start is built at construction, and moves the background launch tests onto fake time.
`ConsoleEventSink` -> `ConsoleSender`, implementing `Sender` instead of `EventSink`, and `sink:` -> `sender:` at the create() call.
stopSession() and close() now return Future<void>, completing once the session stop event has been handed to the Sender. dispose() cannot await, so it fires close() best-effort with a comment saying so. The Close button awaits instead, so the log line follows the emitted event rather than racing it, and a Stop Session button was added to make the _session.stop envelope visible without closing the client.
Adds a Start Session button so the displacement pair is visible (the running session's _session.stop, then the new session's _session.start), and documents the full walkthrough for both event types in the example README.
…xample app The buttons demonstrate setUserId and addGlobalAttribute, which cannot reach the launch _session.start. create() now takes the initial values that can.
The example README said the app records events "with attributes and metrics", but nothing it recorded carried a metric. The purchase event now sends one, and its button says so. Also rewords the three em dashes out of the README; no other example README in the repo uses them.
ekjotmultani
force-pushed
the
feat/event-enrichment-client-example
branch
from
October 23, 2026 17:42
4a9ec80 to
905a53a
Compare
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.
Description
Adds the example Flutter app for the
amplify_event_enrichmentpackage, demonstrating event enrichment client usage with session tracking, global fields, and lifecycle observation.This PR is stacked on #7029 (core package implementation). Review #7029 first.
Structure (3-way split)
feat/event-enrichment-clientfeat/event-enrichment-client-examplefeat/event-enrichment-client-testsWhat's included
EventEnrichmentClientinitialization and usage