flutter_logging_service 0.2.0
flutter_logging_service: ^0.2.0 copied to clipboard
A comprehensive logging service for Flutter apps with file persistence, log aggregation, crash tracking, sessions, masking, and isolate-backed writes.
import 'package:flutter/material.dart';
import 'package:flutter_logging_service/flutter_logging_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await LoggingService.init(
LoggingConfig(
appName: 'LoggingExample',
logFileName: 'example.log',
crashLogFileName: 'example_crashes.log',
maxLogFileSize: 2 * 1024 * 1024,
maxLogFiles: 3,
enableAggregation: true,
enableDefaultMasking: true,
sessionStartExtra: 'example-1.0.0',
useIsolateWriter: true,
),
);
LoggingService.addMaskingRule(
MaskingRule('super-secret', replacement: '[HIDDEN]'),
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Logging Service Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
home: const LoggingExamplePage(),
);
}
}
class LoggingExamplePage extends StatefulWidget {
const LoggingExamplePage({super.key});
@override
State<LoggingExamplePage> createState() => _LoggingExamplePageState();
}
class _LoggingExamplePageState extends State<LoggingExamplePage>
with Loggable {
String _status = '';
void _testLogging() {
Log.debug('This is a debug message');
Log.info('This is an info message');
Log.warning('This is a warning message');
Log.error('This is an error message');
Log.info('email user@example.com password=hunter2');
Log.info('token super-secret should be masked');
logDebug('Debug from Loggable mixin');
logInfo('Info from Loggable mixin');
for (var i = 0; i < 5; i++) {
Log.info('fetch(id=$i)');
}
try {
throw Exception('Test exception');
} catch (e, st) {
Log.error('Caught an exception', error: e, stackTrace: st);
}
setState(() => _status = 'Test logs written (session=${LoggingService.sessionId})');
}
Future<void> _exportZip() async {
final path = await LoggingService.exportLogsZip();
setState(() => _status = path == null ? 'Zip export failed' : 'Zip: $path');
}
Future<void> _newSession() async {
final id = LoggingService.startSession(extra: 'manual');
setState(() => _status = 'New session $id');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Logging Service Example'),
actions: [
IconButton(
tooltip: 'Open LogViewer',
icon: const Icon(Icons.terminal),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => const LogViewer(),
),
);
},
),
],
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Session: ${LoggingService.sessionId ?? "(none)"}',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
if (_status.isNotEmpty) Text(_status),
const SizedBox(height: 16),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
ElevatedButton.icon(
onPressed: _testLogging,
icon: const Icon(Icons.bug_report),
label: const Text('Test Logging'),
),
ElevatedButton.icon(
onPressed: _newSession,
icon: const Icon(Icons.refresh),
label: const Text('New Session'),
),
ElevatedButton.icon(
onPressed: _exportZip,
icon: const Icon(Icons.archive),
label: const Text('Export Zip'),
),
ElevatedButton.icon(
onPressed: () async {
await LoggingService.clearLogs();
setState(() => _status = 'Logs cleared');
},
icon: const Icon(Icons.delete),
label: const Text('Clear'),
),
],
),
const SizedBox(height: 16),
const Expanded(
child: LogViewer(showAppBar: false),
),
],
),
),
);
}
}