Vestara Flutter SDK
Crash reporting and remote logging SDK for Flutter iOS and Android.
Supported Platforms
V1: iOS and Android only. Flutter web and desktop are not supported in V1 due to dart:io dependencies and platform limitations.
Installation
dependencies:
vestara: ^0.1.0
Quick Start
import 'package:vestara/vestara.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Vestara.init(InitOptions(
token: 'YOUR_SDK_TOKEN',
environment: 'production',
appVersion: '1.0.0',
targetCategory: 'flutter_app',
serviceName: 'Flutter App',
appIdentifier: 'flutter-app',
));
runApp(const MyApp());
}
Runtime target metadata
You can provide metadata to identify this application in the dashboard:
targetCategory: The kind of target (e.g.,flutter_app).serviceName: Human-readable name (e.g.,Flutter App).appIdentifier: Technical identifier (e.g.,flutter-app).
API
Vestara.init(options)
Initializes the SDK. Must be called before any other API. token is required.
await Vestara.init(InitOptions(
token: 'YOUR_SDK_TOKEN',
environment: 'production', // production | staging | development
appVersion: '1.0.0',
targetCategory: 'flutter_app',
serviceName: 'Flutter App',
appIdentifier: 'flutter-app',
beforeSend: null, // optional callback
));
Before send hook: The beforeSend callback lets you modify or drop events before they are queued:
SDKEvent? beforeRedact(SDKEvent event) {
// Redact sensitive data
if (event.payload['data']?['secret'] != null) {
final modified = SDKEvent(
id: event.id,
eventType: event.eventType,
sessionId: event.sessionId,
deviceId: event.deviceId,
timestamp: event.timestamp,
sdkVersion: event.sdkVersion,
appVersion: event.appVersion,
osName: event.osName,
osVersion: event.osVersion,
deviceModel: event.deviceModel,
environment: event.environment,
payload: Map<String, dynamic>.from(event.payload)
..['data'] = Map<String, dynamic>.from(event.payload['data'] ?? {})
..['secret'] = '[REDACTED]',
);
return modified;
}
// Drop noisy events
if (event.payload['message'] == 'debug-tick') {
return null; // drops the event
}
return event;
}
await Vestara.init(InitOptions(
token: 'YOUR_SDK_TOKEN',
beforeSend: beforeRedact,
));
Behavior:
- Return a modified
SDKEventto send the modified version - Return
nullto drop the event - If the callback throws, the original event is sent (fail-open)
Note: The Vestara backend also applies server-side redaction as a safety layer.
Note: WidgetsFlutterBinding.ensureInitialized() must be called before Vestara.init() because the SDK requires Flutter's binding to be initialized.
Vestara.log(level, message, data?)
Sends a log event.
Vestara.log(LogLevel.info, 'User signed in', {'userId': '123'});
Vestara.log(LogLevel.warn, 'Slow network response', {'latency': 2000});
Vestara.log(LogLevel.error, 'API call failed', {'code': 500});
Supported levels: debug, info, warn, error, fatal.
Vestara.captureError(error, stackTrace?, context?)
Captures a Dart exception.
try {
await fetchData();
} catch (e, stack) {
Vestara.captureError(e, stack, {'endpoint': '/api/data'});
}
Vestara.setUser(user)
Associates a user with future events.
Vestara.setUser(UserContext(id: 'user-123', email: 'user@example.com'));
Vestara.trackRumMetric(metricType, value, {unit, name, screen, route, operation, tags})
Tracks a Real User Monitoring metric.
Vestara.trackRumMetric(RumMetricType.screenLoad, 450.0, unit: RumMetricUnit.ms, screen: 'HomeScreen');
Vestara.trackRumMetric(RumMetricType.networkRequest, 340.0, unit: RumMetricUnit.ms, name: 'GET /api/users', route: '/api/users?token=secret', operation: 'GET');
Vestara.trackRumMetric(RumMetricType.custom, 42.0, name: 'items_loaded', tags: {'source': 'cache', 'count': 15, 'fresh': true});
Vestara.reportAppStart()
Reports app startup duration measured from Vestara.init() to this call.
// Call after first screen is rendered
Vestara.reportAppStart();
See the backend contract for accepted metric_type, unit, and value constraints. Tags are bounded client-side (max 20 entries, keys ≤64 chars, string values ≤1024 chars). Non-finite values are dropped. Route query strings and fragments are stripped automatically.
Custom API URL
For local development, staging, or self-hosted deployments, pass apiUrl:
await Vestara.init(InitOptions(
token: 'YOUR_SDK_TOKEN',
apiUrl: 'http://10.0.2.2:3000', // Android emulator
environment: 'development',
));
Do not set apiUrl for normal Vestara SaaS usage. The default endpoint is https://api.vestara.dev.
What is Automatically Captured
- Flutter errors:
FlutterError.onErrorcaptures unhandled Flutter exceptions. The error is still shown in the devtools debugger — the SDK only reads and reports it. The previousFlutterError.onErrorhandler (if any) is preserved and called after capture. - Platform errors:
PlatformDispatcher.instance.onErrorcaptures async errors from the Flutter platform layer. The previous handler is preserved and called after capture. - App lifecycle: Breadcrumbs are automatically added when the app is foregrounded or backgrounded.
What is NOT Captured in V1
- Native crashes (iOS/Android native layer). Only Dart-level errors are captured.
- Flutter web: Not supported.
- Flutter desktop: Not supported.
- Dart
Isolateerrors: Not captured automatically. - HTTP request auto-instrumentation: Not available.
Offline Queue
Events are queued locally when offline. The queue persists across app restarts.
- Max 500 events
- Logs dropped (not crashes) when queue is full
- Crash events evict the oldest log when queue is full
- Events are sent in batches of up to 50 every 10 seconds
- Crash events are sent immediately after enqueue
- Internal event IDs are used for exact queue removal; they are NOT sent to the backend
Device Settings
The SDK polls /v1/sdk/device-settings every 60 seconds. If logging_enabled is false, log events are suppressed. Crash events are always sent regardless of this setting.
SDK Token
Find your SDK token in the Vestara dashboard under Settings → SDK & Token.
The SDK token is write-only — it can only ingest events. It cannot read your data.
License
This SDK is licensed under the Apache License 2.0.
Copyright 2026 Ahsan Iqbal.
Vestara, the Vestara name, logos, domain, and related branding are not granted under this license.