fractalup 1.0.0
fractalup: ^1.0.0 copied to clipboard
Flutter SDK for FractalUp Radar, FractalUp's observability service for frontend, backend, infrastructure, AI agents, and team workflows.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:fractalup/fractalup.dart';
const _ingestionKey = String.fromEnvironment('FRACTALUP_INGESTION_KEY');
const _endpoint = String.fromEnvironment('FRACTALUP_ENDPOINT');
const _serviceName = String.fromEnvironment(
'FRACTALUP_SERVICE_NAME',
defaultValue: 'fractalup-demo',
);
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
if (_ingestionKey.isEmpty || _endpoint.isEmpty) {
runApp(const FractalUpDemoApp(fractalUpConfigured: false));
return;
}
await FractalUp.init((options) {
options.ingestionKey = _ingestionKey;
options.endpoint = Uri.parse(_endpoint);
options.environment = const String.fromEnvironment('FRACTALUP_ENV');
options.serviceName = _serviceName;
options.appName = 'FractalUp Flutter Demo';
options.release = 'demo-1.0.0';
options.autoInstrumentation = true;
options.defaultAttributes = const <String, Object?>{
'demo': true,
'transport': 'flutter_app',
};
}, appRunner: () {
runApp(const FractalUpDemoApp(fractalUpConfigured: true));
});
}
class FractalUpDemoApp extends StatefulWidget {
const FractalUpDemoApp({
required this.fractalUpConfigured,
super.key,
});
final bool fractalUpConfigured;
@override
State<FractalUpDemoApp> createState() => _FractalUpDemoAppState();
}
class _FractalUpDemoAppState extends State<FractalUpDemoApp> {
static const _fractalUpEnvironment = String.fromEnvironment('FRACTALUP_ENV');
static const _appEnvironment = String.fromEnvironment(
'APP_ENV',
defaultValue: 'prod',
);
static const _eventId = String.fromEnvironment('FRACTALUP_EVENT_ID');
String _status = _ingestionKey.isEmpty || _endpoint.isEmpty
? 'Missing FractalUp platform settings'
: 'Ready';
Future<void> _sendEvent() async {
if (!widget.fractalUpConfigured) {
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.fractalUpConfigured) {
return;
}
setState(() => _status = 'Sending handled error...');
try {
throw StateError('FractalUp 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.fractalUpConfigured) FractalUp.navigatorObserver,
],
home: Scaffold(
appBar: AppBar(title: const Text('FractalUp 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.fractalUpConfigured ? _sendEvent : null,
child: const Text('Emit event'),
),
const SizedBox(height: 12),
OutlinedButton(
onPressed:
widget.fractalUpConfigured ? _sendHandledError : null,
child: const Text('Emit handled error'),
),
],
),
),
),
),
);
}
static String _environmentForDisplay() {
if (_fractalUpEnvironment.isNotEmpty) {
return _fractalUpEnvironment;
}
return _appEnvironment;
}
}