bugwatch 0.1.6
bugwatch: ^0.1.6 copied to clipboard
BugWatch — crash, error, and log observability for Flutter. Capture exceptions, messages, breadcrumbs, and scope from your app via native iOS/Android bridges.
example/lib/main.dart
import 'dart:async';
import 'package:bugwatch/bugwatch.dart';
import 'package:flutter/material.dart';
/// Project id + signing secret. For a local stack, pass them (and a local
/// endpoint) at build time, e.g.:
/// flutter run --dart-define=BW_PROJECT_ID=bwp_xxx \
/// --dart-define=BW_APP_SECRET=xxx \
/// --dart-define=BW_ENDPOINT=http://localhost:5050 --dart-define=BW_ENV=production
/// The secret only signs a short-lived ingest token locally (HMAC) inside the
/// native SDK — it is never transmitted. Production omits BW_ENDPOINT to use the
/// SDK default (https://api.newinstance.cloud).
const String exampleProjectId =
String.fromEnvironment('BW_PROJECT_ID', defaultValue: 'bwp_replace_me');
const String exampleAppSecret =
String.fromEnvironment('BW_APP_SECRET', defaultValue: 'replace_me_app_secret');
const String exampleEndpoint =
String.fromEnvironment('BW_ENDPOINT', defaultValue: 'https://api.newinstance.cloud');
const String exampleEnv =
String.fromEnvironment('BW_ENV', defaultValue: 'development');
/// Headless E2E hook: with --dart-define=BW_AUTO_ERROR=true the app throws an
/// UNHANDLED async error shortly after launch so auto-capture can be verified
/// without a tap.
const bool exampleAutoError =
bool.fromEnvironment('BW_AUTO_ERROR', defaultValue: false);
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// autoCaptureErrors defaults to true → BugWatch installs FlutterError.onError
// + PlatformDispatcher.onError, so UNHANDLED Flutter/Dart errors are captured
// and forwarded to the native SDK automatically (no try/catch needed).
await BugWatch.instance.init(const BugWatchOptions(
projectId: exampleProjectId,
appSecret: exampleAppSecret,
endpoint: exampleEndpoint,
environment: exampleEnv,
release: 'bugwatch_example@0.1.0',
debug: true,
));
runApp(const ExampleApp());
if (exampleAutoError) {
Future<void>.delayed(const Duration(seconds: 2), () {
throw StateError('BugWatch Flutter E2E: unhandled async error');
});
}
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'BugWatch example',
home: BugWatchDemoPage(),
);
}
}
/// Minimal demo: BugWatch is initialized in `main()`. The buttons capture a
/// message, a handled exception, and throw an UNHANDLED error (caught
/// automatically by BugWatch's auto-capture handlers) — all delivered via the
/// native SDK.
class BugWatchDemoPage extends StatefulWidget {
const BugWatchDemoPage({super.key});
@override
State<BugWatchDemoPage> createState() => _BugWatchDemoPageState();
}
class _BugWatchDemoPageState extends State<BugWatchDemoPage> {
String _status = 'Tap to capture an event.';
Future<void> _captureMessage() async {
final String? id = await BugWatch.instance.captureMessage(
'Hello from the BugWatch Flutter example',
level: Severity.info,
);
setState(() => _status = 'captureMessage -> ${id ?? '(no id)'}');
}
Future<void> _captureException() async {
try {
throw StateError('Sample demo exception from the Flutter example');
} catch (error, stack) {
final String? id = await BugWatch.instance.captureException(error, stack);
setState(() => _status = 'captureException -> ${id ?? '(no id)'}');
}
}
void _throwUnhandled() {
setState(() => _status = 'Throwing an UNHANDLED error (auto-captured)…');
// Escapes to PlatformDispatcher.onError → BugWatch auto-capture.
Future<void>.delayed(const Duration(milliseconds: 100), () {
throw StateError('Unhandled error from the Flutter example');
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('BugWatch')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(_status, textAlign: TextAlign.center),
const SizedBox(height: 24),
FilledButton(
onPressed: _captureMessage,
child: const Text('Capture message'),
),
const SizedBox(height: 12),
OutlinedButton(
onPressed: _captureException,
child: const Text('Capture exception (handled)'),
),
const SizedBox(height: 12),
OutlinedButton(
onPressed: _throwUnhandled,
child: const Text('Throw unhandled error'),
),
],
),
),
),
);
}
}