Skip to main content

ai_logger 2026.6.3 copy "ai_logger: ^2026.6.3" to clipboard
ai_logger: ^2026.6.3 copied to clipboard

AI-friendly Flutter logger that captures app errors, prints, routes, and stacks as Markdown, JSON, or diagnostics.

example/lib/main.dart

import 'package:ai_logger/ai_logger.dart' as ailog;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

final memorySink = ailog.MemorySink();
final routeObserver = ailog.AiLoggerRouteObserver();

void main() {
  ailog.runApp(
    const AiLoggerExampleApp(),
    options: const ailog.Options(captureLevel: ailog.Level.trace),
    sinks: [memorySink],
  );
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ai_logger example',
      navigatorObservers: [routeObserver],
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
        useMaterial3: true,
      ),
      home: const LogConsolePage(),
    );
  }
}

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

  @override
  State<LogConsolePage> createState() => _LogConsolePageState();
}

class _LogConsolePageState extends State<LogConsolePage> {
  String? _aiReport;
  ailog.ReportFormat _reportFormat = ailog.ReportFormat.markdown;

  void _refresh() {
    setState(() {});
  }

  void _logInfo() {
    ailog.context.setRoute('/example');
    ailog.breadcrumb('tap_manual_log');
    ailog.i('manual info log from example');
    _refresh();
  }

  void _logWarning() {
    ailog.breadcrumb('tap_manual_warning');
    ailog.logger.log(
      ailog.Level.warning,
      'manual warning log from example',
      kind: 'manual_warning',
      probableCause: 'The example intentionally emitted a warning event.',
      suggestedFix: 'Inspect the recent signals and decide if action is needed.',
    );
    _refresh();
  }

  void _logPrint() {
    print('print() log from example button');
    _refresh();
  }

  void _logDebugPrint() {
    debugPrint('debugPrint() log from example button');
    _refresh();
  }

  void _reportFlutterError() {
    FlutterError.reportError(
      FlutterErrorDetails(
        exception: FlutterError('RenderFlex overflowed by 42 pixels.'),
        stack: StackTrace.fromString(
          '#0      LogConsolePage.build '
          '(package:ai_logger_example/main.dart:88:12)',
        ),
      ),
    );
    _refresh();
  }

  void _throwAsyncError() {
    Future<void>.delayed(Duration.zero, () {
      throw StateError('async failure captured by ai_logger');
    });
    Future<void>.delayed(const Duration(milliseconds: 50), _refresh);
  }

  void _clear() {
    memorySink.clear();
    _aiReport = null;
    _refresh();
  }

  Future<void> _copyAiReport() async {
    final report = ailog.formatLastReport(_reportFormat);
    final text =
        report ?? 'No warning, error, or fatal event has been captured yet.';
    setState(() {
      _aiReport = text;
    });
    try {
      await Clipboard.setData(ClipboardData(text: text));
    } on PlatformException {
      ailog.w('Clipboard.setData failed in ai_logger example');
    }
    if (mounted) {
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(const SnackBar(content: Text('AI report copied')));
    }
  }

  @override
  Widget build(BuildContext context) {
    final events = memorySink.events.reversed.toList(growable: false);

    return Scaffold(
      appBar: AppBar(
        title: const Text('ai_logger runtime capture'),
        actions: [
          IconButton(
            tooltip: 'Clear captured events',
            onPressed: _clear,
            icon: const Icon(Icons.delete_outline),
          ),
        ],
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                FilledButton(onPressed: _logInfo, child: const Text('ailog.i')),
                FilledButton.tonal(
                  onPressed: _logWarning,
                  child: const Text('warning'),
                ),
                FilledButton.tonal(
                  onPressed: _logPrint,
                  child: const Text('print'),
                ),
                FilledButton.tonal(
                  onPressed: _logDebugPrint,
                  child: const Text('debugPrint'),
                ),
                FilledButton.tonal(
                  onPressed: _reportFlutterError,
                  child: const Text('FlutterError'),
                ),
                OutlinedButton(
                  onPressed: _throwAsyncError,
                  child: const Text('async error'),
                ),
                SegmentedButton<ailog.ReportFormat>(
                  segments: const [
                    ButtonSegment(
                      value: ailog.ReportFormat.markdown,
                      icon: Icon(Icons.article_outlined),
                      label: Text('Markdown'),
                    ),
                    ButtonSegment(
                      value: ailog.ReportFormat.diagnostic,
                      icon: Icon(Icons.terminal_outlined),
                      label: Text('Diagnostic'),
                    ),
                    ButtonSegment(
                      value: ailog.ReportFormat.compactJson,
                      icon: Icon(Icons.data_object_outlined),
                      label: Text('JSON'),
                    ),
                  ],
                  selected: {_reportFormat},
                  onSelectionChanged: (selection) {
                    setState(() {
                      _reportFormat = selection.single;
                    });
                  },
                ),
                OutlinedButton.icon(
                  onPressed: _copyAiReport,
                  icon: const Icon(Icons.content_copy),
                  label: const Text('copy AI report'),
                ),
              ],
            ),
          ),
          if (_aiReport != null) ...[
            const Divider(height: 1),
            Padding(
              padding: const EdgeInsets.all(16),
              child: DecoratedBox(
                decoration: BoxDecoration(
                  border: Border.all(color: Theme.of(context).dividerColor),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: ConstrainedBox(
                  constraints: const BoxConstraints(maxHeight: 180),
                  child: SingleChildScrollView(
                    padding: const EdgeInsets.all(12),
                    child: SelectableText(
                      _aiReport!,
                      style: Theme.of(
                        context,
                      ).textTheme.bodySmall?.copyWith(fontFamily: 'monospace'),
                    ),
                  ),
                ),
              ),
            ),
          ],
          const Divider(height: 1),
          Expanded(
            child: events.isEmpty
                ? const Center(child: Text('No captured events yet.'))
                : ListView.separated(
                    itemCount: events.length,
                    separatorBuilder: (_, _) => const Divider(height: 1),
                    itemBuilder: (context, index) {
                      final event = events[index];
                      return ListTile(
                        dense: true,
                        title: Text('[${event.level.code}] ${event.message}'),
                        subtitle: Text(
                          [
                            event.source,
                            if (event.kind != null) event.kind,
                            if (event.location != null) event.location,
                          ].join(' • '),
                        ),
                      );
                    },
                  ),
          ),
        ],
      ),
    );
  }
}
0
likes
140
points
46
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

AI-friendly Flutter logger that captures app errors, prints, routes, and stacks as Markdown, JSON, or diagnostics.

Repository (GitHub)
View/report issues

Topics

#ai #logging #diagnostics #debugging #flutter

License

MIT (license)

Dependencies

ai_logger_core, flutter

More

Packages that depend on ai_logger