Skip to content

feat: initial magic_sentry plugin - #1

Merged
anilcancakir merged 2 commits into
mainfrom
feature/initial-plugin
Sep 25, 2026
Merged

anilcancakir merged 2 commits into
mainfrom
feature/initial-plugin

Conversation

@anilcancakir

Copy link
Copy Markdown
Member

feat: initial magic_sentry plugin

Sentry for Magic apps: MagicSentry.run opens one zone for the binding, the
.env load, SentryFlutter.init and the app (web needs the outer zone,
flutter#100277); an ErrorWidget breadcrumb installer; and SentryServiceProvider,
inert without a DSN, which wires sentry_dio (captureFailedRequests off) plus a
network interceptor that reports server failures fingerprinted by the
normalised endpoint, a user context that follows Auth.stateNotifier (id, email
and app-supplied tags), and SentryNavigatorObserver. The install stub publishes
the app's own configureSentry; the barrel does not export one.

Part of the "framework-level support" round (plan 2 of 3): code that uptizm carried because a plugin lacked a seam moves into the owning package. Companion PRs: fluttersdk/magic, fluttersdk/magic_starter, fluttersdk/magic_notifications, fluttersdk/magic_deeplink, fluttersdk/wind, fluttersdk/magic_sentry, and the uptizm adoption.

This PR compiles and tests against its siblings' current default branches; nothing here depends on another PR in the round being merged first. No version bump and no publish.

Sentry for Magic apps: MagicSentry.run opens one zone for the binding, the
.env load, SentryFlutter.init and the app (web needs the outer zone,
flutter#100277); an ErrorWidget breadcrumb installer; and SentryServiceProvider,
inert without a DSN, which wires sentry_dio (captureFailedRequests off) plus a
network interceptor that reports server failures fingerprinted by the
normalised endpoint, a user context that follows Auth.stateNotifier (id, email
and app-supplied tags), and SentryNavigatorObserver. The install stub publishes
the app's own configureSentry; the barrel does not export one.
@codecov

codecov Bot commented Sep 25, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@kodizm

kodizm Bot commented Sep 25, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

The plugin looks sound and follows its own CLAUDE.md. There is one boot-path risk in the published config stub to confirm, and one silent-misconfiguration trap in the provider constructor.

Major

assets/stubs/install/sentry_config.stub:70: correctness, not verified. options.tracesSampleRate = Env.get<double>(...) reads a value that comes out of .env as text (SENTRY_TRACES_SAMPLE_RATE=0.5). I could not read magic's Env source in this checkout. If Env.get<T> casts rather than parses, this throws a TypeError inside configure, and therefore inside SentryFlutter.init, before appRunner runs. The app would then fail to boot in exactly the environments that set the key (production and staging), while local runs and CI, which leave it unset, stay green. Nothing tests configureSentry, so please confirm Env.get<double> parses a numeric string, or use double.tryParse(Env.getString(...)), and add a test that sets the key.

Minor

lib/src/sentry_service_provider.dart:35: If a host passes userId without userEmail, user reporting is switched off with no warning. For example, an app with no email field would write userId: (u) => u.id and never see a scope user. userEmail already returns String? and userFor already drops an empty email, so the check could require only userId, with email defaulting to (_) => null. Alternatively, assert or log when only one of the two is given.

Tests

The interceptor (disposition, normalisation, dedupe, event shape), the user context (login, logout, extras, double install), the provider wiring and MagicSentry.run are all covered. The published configureSentry stub has no test.

CI

  • Lint & Test: success
  • codecov/patch: success (no base report to compare against)

@anilcancakir

Copy link
Copy Markdown
Member Author

@kodizm review. Minor fixed: userId alone now turns user reporting on and userEmail is optional (new test, red first). The Major is a false alarm: magic's Env.get<double> parses with double.tryParse(value) ?? defaultValue (magic 0.0.21 lib/src/foundation/env.dart, the T == double branch), so SENTRY_TRACES_SAMPLE_RATE=0.5 yields 0.5 and a malformed value falls back to the default instead of throwing.

@kodizm

kodizm Bot commented Sep 25, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

The fix commit looks correct and I have no new findings. CI is still running on it, so this isn't green yet.

Changes since my last review: one commit (a05c02f). It makes userId alone enough to turn on user reporting, and userEmail now defaults to (T user) => null. The docs in CLAUDE.md and README.md are updated to match, and a new test covers it. SentryUserContext already maps a null or empty email to null (lib/src/sentry_user_context.dart:138), so a model with no email now reports its id with no email. That settles my earlier Minor.

You were right about the earlier Major: magic's Env.get<double> parses with double.tryParse, so the SENTRY_TRACES_SAMPLE_RATE read in the stub is safe. I've dropped it.

Tests

The new test reports the user from userId alone, for a model with no email checks that the scope user gets the id and a null email. The published configureSentry stub still has no test.

CI

  • Lint & Test: still running (in progress on a05c02f)

@anilcancakir
anilcancakir merged commit 5f929bf into main Sep 25, 2026
3 checks passed
@anilcancakir
anilcancakir deleted the feature/initial-plugin branch September 27, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant