fractalup_radar_flutter 0.2.0
fractalup_radar_flutter: ^0.2.0 copied to clipboard
Production observability SDK for Flutter with errors, logs, metrics, RUM, distributed tracing, privacy controls, and offline delivery.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:fractalup_radar_flutter/fractalup_radar_flutter.dart';
const _ingestionKey = String.fromEnvironment('FRACTALUP_RADAR_INGESTION_KEY');
const _serviceName = String.fromEnvironment(
'FRACTALUP_RADAR_SERVICE_NAME',
defaultValue: 'fractalup-radar-flutter-demo',
);
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
if (_ingestionKey.isEmpty) {
runApp(const RadarDemoApp(radarConfigured: false));
return;
}
await FractalUpFlutter.init((options) {
options.ingestionKey = _ingestionKey;
options.environment = const String.fromEnvironment('FRACTALUP_RADAR_ENV');
options.serviceName = _serviceName;
options.appName = 'Radar Flutter Demo';
options.release = 'demo-0.2.0';
options.autoInstrumentation = true;
options.defaultAttributes = const <String, Object?>{
'demo': true,
'transport': 'flutter_app',
};
}, appRunner: () {
runApp(const RadarDemoApp(radarConfigured: true));
});
}
class RadarDemoApp extends StatefulWidget {
const RadarDemoApp({
required this.radarConfigured,
super.key,
});
final bool radarConfigured;
@override
State<RadarDemoApp> createState() => _RadarDemoAppState();
}
class _RadarDemoAppState extends State<RadarDemoApp> {
static const _radarEnvironment =
String.fromEnvironment('FRACTALUP_RADAR_ENV');
static const _appEnvironment = String.fromEnvironment(
'APP_ENV',
defaultValue: 'prod',
);
static const _eventId = String.fromEnvironment('FRACTALUP_RADAR_EVENT_ID');
String _status = _ingestionKey.isEmpty ? 'Missing ingestion key' : 'Ready';
Future<void> _sendEvent() async {
if (!widget.radarConfigured) {
return;
}
setState(() => _status = 'Sending...');
try {
final response = await FractalUp.info(
'codex.flutter.demo',
eventId: _eventId.isEmpty ? null : _eventId,
data: <String, Object?>{
'screen': 'demo',
'trigger': 'button',
'flavor': 'manual',
'nested': <String, Object?>{
'route': '/',
'state': <String, Object?>{
'button_enabled': true,
'environment': _environmentForDisplay(),
},
},
},
);
setState(() => _status = 'Accepted: ${response.json?['offset']}');
} on Object catch (error) {
setState(() => _status = 'Failed: $error');
}
}
Future<void> _sendHandledError() async {
if (!widget.radarConfigured) {
return;
}
setState(() => _status = 'Sending handled error...');
try {
throw StateError('Radar demo handled Flutter error');
} on Object catch (error, stackTrace) {
try {
final response = await FractalUp.error(
'fractalup.radar.demo_handled_error',
exception: error,
stackTrace: stackTrace,
data: <String, Object?>{
'screen': 'demo',
'trigger': 'handled-error-button',
},
);
setState(() => _status = 'Error accepted: ${response.json?['offset']}');
} on Object catch (captureError) {
setState(() => _status = 'Failed: $captureError');
}
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorObservers: <NavigatorObserver>[
if (widget.radarConfigured) FractalUp.navigatorObserver,
],
home: Scaffold(
appBar: AppBar(title: const Text('FractalUp Radar Demo')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(_status, textAlign: TextAlign.center),
const SizedBox(height: 16),
FilledButton(
onPressed: widget.radarConfigured ? _sendEvent : null,
child: const Text('Emit event'),
),
const SizedBox(height: 12),
OutlinedButton(
onPressed: widget.radarConfigured ? _sendHandledError : null,
child: const Text('Emit handled error'),
),
],
),
),
),
),
);
}
static String _environmentForDisplay() {
if (_radarEnvironment.isNotEmpty) {
return _radarEnvironment;
}
return _appEnvironment;
}
}