Skip to main content

rea_flight_recorder 0.1.1 copy "rea_flight_recorder: ^0.1.1" to clipboard
rea_flight_recorder: ^0.1.1 copied to clipboard

In-app diagnostic blackbox and flight recorder for Flutter. Captures logs, crashes, and network calls in a rotating buffer with a developer viewer modal.

example/lib/main.dart

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:rea_flight_recorder/rea_flight_recorder.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 1. Initialize the Flight Recorder engine with automatic error hooks
  await FlightRecorder.instance.init(
    options: const FlightRecorderOptions(
      maxInMemoryLogs: 500,
      echoToConsole: true,
      sanitizeSecrets: true,
      attachErrorHooks: true,
    ),
  );

  // 2. Set startup diagnostic header
  FlightRecorder.instance.setDiagnosticHeader(
    appName: 'FlightRecorderDemo',
    appVersion: '1.0.0',
    buildNumber: '1',
    deviceModel: 'Flutter Demo Device',
    osVersion: 'Android / iOS / Web',
    userId: 'user_dev_001',
    customFields: {
      'Environment': 'Staging',
      'Feature': 'Diagnostic Blackbox',
    },
  );

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flight Recorder Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  int _counter = 0;
  late final Dio _dio;

  @override
  void initState() {
    super.initState();
    _dio = Dio(BaseOptions(
      baseUrl: 'https://jsonplaceholder.typicode.com',
      connectTimeout: const Duration(seconds: 5),
    ));
    _dio.interceptors.add(const FlightRecorderDioInterceptor());
  }

  void _simulateSuccessAction() {
    setState(() => _counter++);
    FlightRecorder.instance.info(
      'User tapped button. Counter incremented to $_counter',
      tag: 'UI_ACTION',
      metadata: {'counter': _counter},
    );
  }

  void _simulateWarning() {
    FlightRecorder.instance.warn(
      'Device network signal is weak (latency > 800ms)',
      tag: 'NETWORK',
      metadata: {'latency_ms': 850},
    );
  }

  void _simulateError() {
    try {
      throw const FormatException('Simulated unexpected payload parse error');
    } catch (e, stackTrace) {
      FlightRecorder.instance.error(
        'Failed to process checkout payload',
        tag: 'CHECKOUT',
        error: e,
        stackTrace: stackTrace,
      );
    }
  }

  Future<void> _simulateDioCall() async {
    try {
      await _dio.get('/posts/1');
    } catch (e) {
      debugPrint('Dio request failed: $e');
    }
  }

  void _simulateFlutterHookError() {
    FlutterError.reportError(
      FlutterErrorDetails(
        exception: StateError('Simulated unhandled state fault caught by hook'),
        library: 'checkout_module',
        context: ErrorDescription('testing global error interception'),
      ),
    );
  }

  void _simulateHttpCall() {
    FlightRecorder.instance.logHttp(
      method: 'POST',
      url: 'https://api.churtech.com/v1/auth/login',
      statusCode: 200,
      duration: const Duration(milliseconds: 142),
      requestHeaders: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer secret_token_xyz',
      },
      requestBody: {
        'username': 'john.doe@example.com',
        'password': 'superSecretPassword!',
      },
      responseBody: {
        'status': 'success',
        'token': 'jwt_access_token_123',
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flight Recorder Demo'),
        actions: [
          IconButton(
            icon: const Icon(Icons.bug_report_rounded),
            tooltip: 'Open Blackbox Logs',
            onPressed: () => FlightRecorder.instance.showViewer(
              context,
              strings: FlightRecorderStrings.spanish(),
            ),
          ),
        ],
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(24.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Icon(Icons.flight_takeoff_rounded, size: 64, color: Colors.deepPurple),
              const SizedBox(height: 16),
              const Text(
                'In-App Flight Recorder',
                style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 8),
              const Text(
                'Generate test logs below, then long-press the version text or tap the bug icon to view the blackbox modal.',
                textAlign: TextAlign.center,
                style: TextStyle(color: Colors.grey),
              ),
              const SizedBox(height: 24),

              Wrap(
                spacing: 12,
                runSpacing: 12,
                alignment: WrapAlignment.center,
                children: [
                  ElevatedButton.icon(
                    icon: const Icon(Icons.add),
                    label: const Text('Info Log'),
                    onPressed: _simulateSuccessAction,
                  ),
                  ElevatedButton.icon(
                    style: ElevatedButton.styleFrom(backgroundColor: Colors.amber.shade100),
                    icon: const Icon(Icons.warning_amber_rounded, color: Colors.amber),
                    label: const Text('Warn Log', style: TextStyle(color: Colors.black87)),
                    onPressed: _simulateWarning,
                  ),
                  ElevatedButton.icon(
                    style: ElevatedButton.styleFrom(backgroundColor: Colors.red.shade100),
                    icon: const Icon(Icons.error_outline_rounded, color: Colors.red),
                    label: const Text('Error Log', style: TextStyle(color: Colors.red)),
                    onPressed: _simulateError,
                  ),
                  ElevatedButton.icon(
                    style: ElevatedButton.styleFrom(backgroundColor: Colors.blue.shade100),
                    icon: const Icon(Icons.http_rounded, color: Colors.blue),
                    label: const Text('HTTP Call', style: TextStyle(color: Colors.blue)),
                    onPressed: _simulateHttpCall,
                  ),
                  ElevatedButton.icon(
                    style: ElevatedButton.styleFrom(backgroundColor: Colors.teal.shade100),
                    icon: const Icon(Icons.cloud_sync_rounded, color: Colors.teal),
                    label: const Text('Dio Request', style: TextStyle(color: Colors.teal)),
                    onPressed: _simulateDioCall,
                  ),
                  ElevatedButton.icon(
                    style: ElevatedButton.styleFrom(backgroundColor: Colors.purple.shade100),
                    icon: const Icon(Icons.flash_on_rounded, color: Colors.purple),
                    label: const Text('Crash Hook', style: TextStyle(color: Colors.purple)),
                    onPressed: _simulateFlutterHookError,
                  ),
                ],
              ),

              const SizedBox(height: 48),

              // Trigger wrapper matching the konjunto secret trigger pattern
              FlightRecorderTrigger(
                mode: FlightRecorderTriggerMode.longPress,
                strings: FlightRecorderStrings.spanish(),
                child: Container(
                  padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                  decoration: BoxDecoration(
                    color: Colors.grey.shade200,
                    borderRadius: BorderRadius.circular(20),
                  ),
                  child: const Text(
                    'Version 1.0.0 (Hold to open blackbox)',
                    style: TextStyle(fontWeight: FontWeight.w600, color: Colors.black54),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
2
likes
160
points
540
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

In-app diagnostic blackbox and flight recorder for Flutter. Captures logs, crashes, and network calls in a rotating buffer with a developer viewer modal.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

dio, flutter, path_provider, share_plus, web

More

Packages that depend on rea_flight_recorder