api_network_logger 2.0.0
api_network_logger: ^2.0.0 copied to clipboard
A production-ready, publishable Flutter package that transparently logs and stores API calls, offline events, and navigation routes.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:system_info2/system_info2.dart';
import 'package:battery_plus/battery_plus.dart';
import 'package:api_network_logger/api_network_logger.dart';
import 'shared/adapters_registry.dart';
import 'state_management/bloc_demo/counter_bloc.dart';
import 'app.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize API Logger with zero-config defaults + customizable options
await ApiLogger.instance.init(
config: const ApiLoggerConfig(
exportEndpoint: 'https://httpbin.org/post',
redactedFields: ['password', 'token', 'cvv', 'secret'],
redactedHeaders: ['Authorization', 'Cookie'],
showOverlay: true, // Explicitly enable overlay for active sandbox debugging
),
);
// Wire every diagnostic observer and lifecycle listener at startup
Bloc.observer = ApiLoggerBlocObserver();
AppLifecycleLogger.instance.start();
ConnectivityLogger.instance.start();
AppLinksLogger.instance.start();
// Capture session init telemetry once per session
final initTrace = await SystemTelemetryLogger.instance.getFullTelemetry();
await ApiLogger.instance.logSystemTrace('init', initTrace);
// Capture fresh battery/RAM snapshot on uncaught errors/crashes
FlutterError.onError = (details) async {
FlutterError.presentError(details);
final errorTrace = await SystemTelemetryLogger.instance.getFullTelemetry();
errorTrace['error_details'] = {
'exception': details.exceptionAsString(),
'stack': details.stack?.toString(),
};
await ApiLogger.instance.logSystemTrace('error_crash', errorTrace);
};
runApp(const ExampleApp());
}
// ==========================================
// 📱 SYSTEM TELEMETRY LOGGER (CORE LOGIC)
// ==========================================
class SystemTelemetryLogger {
SystemTelemetryLogger._();
static final SystemTelemetryLogger instance = SystemTelemetryLogger._();
Map<String, dynamic>? _cachedStaticContext;
/// Captures static system telemetry (runs once on init)
Future<Map<String, dynamic>> getStaticContext() async {
if (_cachedStaticContext != null) return _cachedStaticContext!;
final context = <String, dynamic>{};
try {
// 1. Package Info
final packageInfo = await PackageInfo.fromPlatform();
context['app'] = {
'name': packageInfo.appName,
'package': packageInfo.packageName,
'version': packageInfo.version,
'build': packageInfo.buildNumber,
};
// 2. Device Info
final deviceInfo = DeviceInfoPlugin();
if (Platform.isAndroid) {
final androidInfo = await deviceInfo.androidInfo;
context['device'] = {
'platform': 'Android',
'model': androidInfo.model,
'brand': androidInfo.brand,
'manufacturer': androidInfo.manufacturer,
'version': androidInfo.version.release,
'sdk': androidInfo.version.sdkInt,
};
} else if (Platform.isIOS) {
final iosInfo = await deviceInfo.iosInfo;
context['device'] = {
'platform': 'iOS',
'name': iosInfo.name,
'model': iosInfo.model,
'systemName': iosInfo.systemName,
'version': iosInfo.systemVersion,
};
} else {
context['device'] = {
'platform': Platform.operatingSystem,
'version': Platform.operatingSystemVersion,
};
}
// 3. System Info (Physical CPU Cores & Static RAM Specs)
context['system'] = {
'cpu_cores': SysInfo.cores.length,
'total_physical_memory': _formatMemory(SysInfo.getTotalPhysicalMemory()),
};
} catch (e) {
debugPrint('[SystemTelemetryLogger] Error fetching static context: $e');
}
_cachedStaticContext = context;
return context;
}
/// Captures dynamic snapshots (like RAM and Battery) during initialization or on errors
Future<Map<String, dynamic>> getDynamicSnapshot() async {
final snapshot = <String, dynamic>{};
try {
// 4. Battery Plus info
final battery = Battery();
final level = await battery.batteryLevel;
final state = await battery.batteryState;
snapshot['battery'] = {
'level': level,
'status': state.toString().split('.').last,
};
// Dynamic RAM Specs
snapshot['ram'] = {
'free_physical_memory': _formatMemory(SysInfo.getFreePhysicalMemory()),
'total_virtual_memory': _formatMemory(SysInfo.getTotalVirtualMemory()),
'free_virtual_memory': _formatMemory(SysInfo.getFreeVirtualMemory()),
};
} catch (e) {
debugPrint('[SystemTelemetryLogger] Error fetching dynamic snapshot: $e');
}
return snapshot;
}
/// Combined session info payload
Future<Map<String, dynamic>> getFullTelemetry() async {
final staticCtx = await getStaticContext();
final dynamicSnap = await getDynamicSnapshot();
return {
...staticCtx,
...dynamicSnap,
};
}
String _formatMemory(int bytes) {
if (bytes <= 0) return '0 B';
final gb = bytes / (1024 * 1024 * 1024);
if (gb >= 1) return '${gb.toStringAsFixed(2)} GB';
final mb = bytes / (1024 * 1024);
return '${mb.toStringAsFixed(2)} MB';
}
}