juice_observability 0.3.0 copy "juice_observability: ^0.3.0" to clipboard
juice_observability: ^0.3.0 copied to clipboard

Crash reporting and breadcrumbs as a Juice bloc, with global error-handler capture behind a fan-out reporter seam.

example/lib/main.dart

import 'package:juice/juice.dart';
import 'package:juice_observability/juice_observability.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  // Mirror Juice's structured log entries (use-case runs, emissions, bloc
  // lifecycle, leaks, errors) to the VM's extension-event stream as
  // `juice:<type>` events — live in DevTools and any VM-service listener.
  // A decorator: console logging keeps working underneath.
  JuiceLoggerConfig.configureLogger(DevtoolsJuiceLogger());

  // Console reporter so reports are visible with no backend. A real app adds a
  // Sentry/Crashlytics reporter to the list.
  BlocScope.register<ObservabilityBloc>(
    () => ObservabilityBloc.withConfig(
      ObservabilityConfig(
        reporters: [ConsoleCrashReporter()],
        maxBreadcrumbs: 10,
      ),
    ),
    lifecycle: BlocLifecycle.permanent,
  );

  runApp(const DemoApp());
}

class DemoApp extends StatelessWidget {
  const DemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'juice_observability demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.red),
        useMaterial3: true,
      ),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessJuiceWidget<ObservabilityBloc> {
  HomeScreen({super.key}) : super(groups: {ObservabilityGroups.status});

  @override
  Widget onBuild(BuildContext context, StreamStatus status) {
    final s = bloc.state;
    return Scaffold(
      appBar: AppBar(title: const Text('juice_observability demo')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('${s.errorCount} errors · ${s.breadcrumbs.length} breadcrumbs'),
            if (s.lastError != null)
              Padding(
                padding: const EdgeInsets.all(8),
                child: Text('last: ${s.lastError}',
                    style: const TextStyle(color: Colors.red)),
              ),
            const SizedBox(height: 24),
            OutlinedButton(
              onPressed: () =>
                  bloc.breadcrumb('tapped at ${s.breadcrumbs.length}', category: 'ui'),
              child: const Text('Drop a breadcrumb'),
            ),
            const SizedBox(height: 8),
            FilledButton(
              onPressed: () =>
                  bloc.recordError(StateError('demo error'), StackTrace.current),
              child: const Text('Record an error'),
            ),
            const SizedBox(height: 8),
            // An *uncaught* error — the installed FlutterError/PlatformDispatcher
            // handlers capture this automatically.
            TextButton(
              onPressed: () => Future<void>.error(StateError('uncaught async')),
              child: const Text('Throw uncaught (auto-captured)'),
            ),
          ],
        ),
      ),
    );
  }
}
0
likes
0
points
148
downloads

Documentation

Documentation

Publisher

unverified uploader

Weekly Downloads

Crash reporting and breadcrumbs as a Juice bloc, with global error-handler capture behind a fan-out reporter seam.

Homepage
Repository (GitHub)
View/report issues

Topics

#crash-reporting #observability #sentry #bloc #state-management

Funding

Consider supporting this project:

github.com

License

unknown (license)

Dependencies

flutter, juice

More

Packages that depend on juice_observability