smart_grow_logs_plugin 2.0.1
smart_grow_logs_plugin: ^2.0.1 copied to clipboard
Flutter plugin for Smart Grow Logs SDK. Secure logging with end-to-end encryption. Supports Android and iOS.
Smart Grow Logs Plugin for Flutter #
Smart Grow Logs for Flutter sends encrypted logs from your app to Smart Grow Logs, with optional automatic capture of uncaught errors.
What This Plugin Is For #
Use this plugin if you want to:
- send debug, info, warn, error and fatal logs from Flutter
- attach metadata such as user, session or business context
- capture uncaught Flutter errors automatically
- capture async errors launched in a guarded zone
- capture failures from secondary isolates when you wire them explicitly
Before You Start #
You need:
- A Smart Grow Logs project.
- An API key.
- Your ingestion URL, for example
https://logs-api.smart-grow.app/.
Installation #
Add the dependency:
dependencies:
smart_grow_logs_plugin: ^2.0.1
Then run:
flutter pub get
Quick Start #
This is the recommended startup pattern for most Flutter apps:
import 'package:flutter/widgets.dart';
import 'package:smart_grow_logs_plugin/smart_grow_logs_plugin.dart';
Future<void> main() async {
SmartGrowLogs.runWithAutoCapture<void>(() async {
WidgetsFlutterBinding.ensureInitialized();
await SmartGrowLogs.initialize(
apiKey: 'sgl_your_api_key',
baseUrl: 'https://logs-api.smart-grow.app/',
autoCaptureEnabled: true,
androidAnrWatchdogEnabled: true,
androidAnrTimeoutMs: 5000,
);
runApp(const MyApp());
});
}
Why this exact order:
WidgetsFlutterBinding.ensureInitialized()andrunApp()must run in the same zone in debug mode.runWithAutoCapture()ensures uncaught async errors in that zone are reported.initialize()must be called once before sending logs.
Common Use Cases #
1. Send a Simple Log #
await SmartGrowLogs.instance.info('User opened settings');
2. Send a Log With Metadata #
await SmartGrowLogs.instance.warn(
'Payment retry scheduled',
metadata: '{"orderId":"ORD-123","retry":2}',
userIdentifier: 'user@example.com',
sessionId: 'session-abc-123',
);
3. Capture a Caught Exception #
try {
await repository.sync();
} catch (error, stackTrace) {
await SmartGrowLogs.instance.errorWithException(
'Sync failed',
error,
stackTrace: stackTrace,
metadata: '{"feature":"sync"}',
);
}
4. Send a Full Custom Log #
final response = await SmartGrowLogs.instance.sendLog(
LogOptions(
level: LogLevel.error,
message: 'Checkout failed',
stackTrace: StackTrace.current.toString(),
metadata: '{"cartId":"CART-42","step":"payment"}',
userIdentifier: 'user@example.com',
sessionId: 'session-abc-123',
),
);
if (!response.success) {
debugPrint('Log failed: ${response.error}');
}
Auto-Capture #
When autoCaptureEnabled is true, the plugin installs these mechanisms automatically:
FlutterError.onErrorfor framework and rendering errorsPlatformDispatcher.instance.onErrorfor uncaught main-isolate runtime errorsrunWithAutoCapture()for async errors inside the guarded zone
What Is Captured Today #
All auto-captured errors are sent at fatal level.
- unhandled Flutter framework errors
- unhandled runtime errors on the main isolate
- unhandled async errors inside
runWithAutoCapture() - secondary-isolate errors when you wire them explicitly
- Android main-thread ANR watchdog when enabled
- iOS uncaught
NSExceptionreported on the next app launch
What Is Not Captured Automatically Yet #
- native crash signals
- every possible failure from child isolates unless you attach them explicitly
Disable Auto-Capture #
Disable it if your app already owns global error handling and you want to forward failures manually:
await SmartGrowLogs.initialize(
apiKey: 'sgl_your_api_key',
baseUrl: 'https://logs-api.smart-grow.app/',
autoCaptureEnabled: false,
);
Secondary Isolates #
If your app uses Isolate.spawn, create one listener on the main isolate and pass its sendPort to child isolates.
final isolateErrorPort = SmartGrowLogs.createIsolateErrorListener(
mechanism: 'MyBackgroundIsolate',
);
await Isolate.spawn<SendPort>(
backgroundEntryPoint,
isolateErrorPort.sendPort,
onError: isolateErrorPort.sendPort,
errorsAreFatal: true,
);
void backgroundEntryPoint(SendPort errorPort) {
SmartGrowLogs.attachCurrentIsolateToAutoCapture(errorPort);
throw StateError('Background isolate failure');
}
When that listener is no longer needed:
isolateErrorPort.close();
API Essentials #
Main entry points:
SmartGrowLogs.initialize(...)SmartGrowLogs.instanceSmartGrowLogs.runWithAutoCapture(...)SmartGrowLogs.createIsolateErrorListener(...)SmartGrowLogs.attachCurrentIsolateToAutoCapture(...)
Main send methods:
logDebug(...)info(...)warn(...)error(...)errorWithException(...)fatal(...)sendLog(LogOptions(...))
Response object:
success: whether the log was accepted locally for deliverylogId: server log id when successfulerror: failure message when not successful
Performance Recommendation #
Logging does network work. If you do not need to wait for the result, prefer non-blocking usage:
unawaited(SmartGrowLogs.instance.info('Screen opened'));
Use await only when you need to inspect success, logId or error.
Troubleshooting #
I get a zone error when starting the app #
Make sure WidgetsFlutterBinding.ensureInitialized() and runApp() are both inside SmartGrowLogs.runWithAutoCapture(...).
My child isolate errors are not showing up #
Make sure you:
- create the listener on the main isolate
- pass its
sendPorttoIsolate.spawn - call
attachCurrentIsolateToAutoCapture(sendPort)inside the child isolate
iOS crashes appear on the next launch #
That is expected for uncaught NSException. The plugin persists a crash marker and retries delivery on the next successful startup.
Requirements #
- Flutter 3.3.0+
- Dart 3.0.0+
- iOS 15.0+
- Android API 26+
License #
Proprietary - Smart Dev Agency