FractalUp Radar
fractalup is the Flutter SDK for FractalUp Radar, the FractalUp observability
service that brings frontend, backend, infrastructure, and AI-agent telemetry
into one operational view.
Radar correlates application signals with your team's work in FractalUp. This helps engineering and product teams investigate incidents, coordinate responses, assign ownership and tickets, and follow issues through resolution.
flutter pub add fractalup
1. Install and Initialize
Configure FractalUp once in main.dart before runApp.
import 'package:flutter/material.dart';
import 'package:fractalup/fractalup.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await FractalUp.init((options) {
options.ingestionKey = const String.fromEnvironment(
'FRACTALUP_INGESTION_KEY',
);
options.endpoint = Uri.parse(
const String.fromEnvironment('FRACTALUP_ENDPOINT'),
);
options.environment = const String.fromEnvironment('FRACTALUP_ENV');
options.serviceName = 'my-flutter-app';
options.autoInstrumentation = true;
options.firstPartyHosts = {'api.example.com'};
}, appRunner: () => runApp(const MyApp()));
}
autoInstrumentation enables Flutter and platform error capture, async
appRunner zone error capture, lifecycle events, durable queued delivery, and
runtime, app, and device context. Pass runApp through appRunner to capture
uncaught asynchronous errors from the application zone.
Flutter apps still need one-time wiring for navigation and HTTP clients:
MaterialApp(
navigatorObservers: [FractalUp.navigatorObserver],
home: const AppHome(),
);
final api = FractalUp.httpClient();
firstPartyHosts limits distributed trace-header injection to your APIs.
requestHeadersProvider is optional. When used, connect it to your existing
API client so events can include safe request context. Authorization headers,
cookies, API keys, session tokens, secrets, and passwords are redacted before
delivery.
2. Configure an Environment
Create an app/project in FractalUp Radar, then copy its client ingestion key and ingestion URL from the FractalUp platform. Do not use an administrative or server credential in a Flutter application.
Pass the values to any flutter run or flutter build command:
flutter run \
--dart-define=FRACTALUP_ENDPOINT=your_fractalup_ingestion_url \
--dart-define=FRACTALUP_INGESTION_KEY=your_client_ingestion_key \
--dart-define=FRACTALUP_ENV=preview-us
FRACTALUP_ENV is a free-form environment label, not a fixed enum. Common
values include dev, stage, and prod, but names such as qa,
customer-demo, preview-42, and production-eu are also supported. Create
as many ingestion keys and environment labels in FractalUp as your deployment
model requires.
Use the same environment label consistently across frontend, backend, infrastructure, and AI-agent telemetry when those signals belong to the same deployment. This allows Radar to correlate them correctly.
Required build-time values:
FRACTALUP_ENDPOINT: ingestion URL provided by the FractalUp platformFRACTALUP_INGESTION_KEY: client ingestion key for the app/project
Recommended build-time values:
FRACTALUP_ENV: deployment label; defaults toprodwhen omittedFRACTALUP_SERVICE_NAME: stable service name, such ascheckout-flutterFRACTALUP_SOURCE_ID: optional source override from the FractalUp platformFRACTALUP_RELEASE: application version or release identifierFRACTALUP_APP_NAME: human-readable application name
3. Send Manual Events
await FractalUp.debug('debug.panel.opened', data: {
'screen': 'settings',
});
await FractalUp.info('profile.opened', data: {
'screen': 'profile',
});
await FractalUp.warning('network.retry', data: {
'attempt': 2,
});
await FractalUp.error('payment.failed', data: {
'provider': 'stripe',
'status_code': 402,
});
await FractalUp.fatal('checkout.unrecoverable', data: {
'step': 'payment_confirmation',
});
Use tags for low-cardinality filters:
await FractalUp.error(
'payment.failed',
data: {'status_code': 402},
tags: {'feature': 'checkout'},
);
Use requestHeaders only when overriding the configured provider for one specific failed request:
await FractalUp.error(
'api.request.failed',
data: {'status_code': response.statusCode},
tags: {'feature': 'checkout'},
requestHeaders: response.request?.headers ?? const {},
);
4. Capture Exceptions
try {
await submitPayment();
} catch (error, stackTrace) {
await FractalUp.captureException(
error,
stackTrace: stackTrace,
data: {'screen': 'checkout'},
tags: {'feature': 'payments'},
);
}
With installErrorHooks: true, uncaught Flutter framework and platform dispatcher errors are captured automatically.
5. Fast Migration
For existing exception/event instrumentation, keep the call shape and use FractalUp names after a mass replacement.
await FractalUp.init((options) {
options.ingestionKey = const String.fromEnvironment(
'FRACTALUP_INGESTION_KEY',
);
options.endpoint = Uri.parse(
const String.fromEnvironment('FRACTALUP_ENDPOINT'),
);
options.environment = const String.fromEnvironment('FRACTALUP_ENV');
options.serviceName = 'my-flutter-app';
}, appRunner: () => runApp(const MyApp()));
await FractalUp.configureScope((scope) {
scope.setTag('feature', 'checkout');
scope.setExtra('screen', 'checkout');
scope.setUser(FractalUpUser(id: user.id, email: user.email));
});
await FractalUp.captureException(
error,
stackTrace: stackTrace,
);
await FractalUp.captureMessage(
'Checkout opened',
level: FractalUpLevel.info,
);
The visible API stays FractalUp while preserving the familiar migration concepts: scope, tags, extras, user, breadcrumbs, exception capture, messages, and levels.
Setup-only exception-monitoring migration
Existing application instrumentation can keep its call shapes after replacing
the previous SDK namespace with FractalUp. Only initialization must be
changed to provide the FractalUp ingestion key and service configuration.
The compatibility contract includes:
FractalUp.initand common Flutter optionsFractalUp.captureEvent,captureException,captureMessage, and feedback- scope, users, tags, contexts, breadcrumbs, attributes, and attachments
FractalUpWidgetandFractalUpNavigatorObserver- transactions, child spans, callback spans, and trace identifiers
- structured logger, formatted logger, metrics, and feature flags
- lifecycle methods, screenshot request API, and app-hang control API
await FractalUp.init((options) {
options.ingestionKey = const String.fromEnvironment(
'FRACTALUP_INGESTION_KEY',
);
options.endpoint = Uri.parse(
const String.fromEnvironment('FRACTALUP_ENDPOINT'),
);
options.environment = const String.fromEnvironment('FRACTALUP_ENV');
options.serviceName = 'my-flutter-app';
options.tracesSampleRate = 0.2;
options.enableLogs = true;
options.enableMetrics = true;
}, appRunner: () {
runApp(const FractalUpWidget(child: MyApp()));
});
This is source compatibility for application-facing Dart and Flutter APIs. Native crash engines, native symbol processing, continuous profiling, real screenshot/view-hierarchy attachments, app-hang/ANR engines, frame tracking, and session replay require dedicated platform implementations and are not silently emulated.
6. Logs, Metrics, Sessions, and Mobile-Agent Style Calls
Global attributes are attached to future events, logs, metrics, and compatibility-facade calls:
FractalUp.startSession(id: sessionId);
FractalUp.setAttribute('screen', 'checkout');
FractalUp.incrementAttribute('retry_count');
await FractalUp.logger.warn(
'Payment latency high',
event: 'checkout.payment.latency',
attributes: {'duration_ms': 1250},
tags: {'feature': 'payments'},
);
await FractalUp.metric(
'checkout.duration',
category: 'Checkout',
value: 321,
);
For mobile-agent style migrations, keep the call shape and replace the visible SDK name with FractalUp:
await FractalUpMobile.instance.startAgent(Config(
accessToken: const String.fromEnvironment('FRACTALUP_INGESTION_KEY'),
endpoint: Uri.parse(const String.fromEnvironment('FRACTALUP_ENDPOINT')),
environment: const String.fromEnvironment('FRACTALUP_ENV'),
serviceName: 'my-flutter-app',
));
await FractalUpMobile.instance.setUserId(user.id);
await FractalUpMobile.instance.setAttribute('cart_value', 99.5);
await FractalUpMobile.instance.recordCustomEvent(
'Checkout',
eventName: 'Payment Failed',
eventAttributes: {'provider': 'stripe'},
);
await FractalUpMobile.instance.recordMetric(
'checkout.duration',
'Checkout',
value: 321,
valueUnit: MetricUnit.MILLISECONDS,
);
All of these APIs normalize into the same FractalUp ingestion payload with session, trace, service, environment, user, tags, attributes, and safe request context.
The FractalUp.metrics facade aggregates counters, gauges, and distributions
locally for ten seconds by default. FractalUp.flush() sends pending metric
aggregations and queued events. Use FractalUp.metric(...) when an individual
metric event must be sent immediately.
7. Setup-Only Mobile-Agent Migration
For an existing mobile-agent integration, replace the dependency/imports and agent class once. Existing calls such as recordError, recordCustomEvent, recordMetric, setUserId, attributes, breadcrumbs, interactions, network notices, and logging keep the same method and parameter shapes.
Use these FractalUp imports:
import 'package:fractalup/config.dart';
import 'package:fractalup/fractalup_mobile.dart';
import 'package:fractalup/loglevel.dart';
import 'package:fractalup/metricunit.dart';
import 'package:fractalup/network_failure.dart';
Initialize once:
final config = Config(
accessToken: const String.fromEnvironment(
'FRACTALUP_INGESTION_KEY',
),
endpoint: Uri.parse(const String.fromEnvironment('FRACTALUP_ENDPOINT')),
environment: const String.fromEnvironment('FRACTALUP_ENV'),
serviceName: 'my-flutter-app',
crashReportingEnabled: true,
httpInstrumentationEnabled: true,
offlineStorageEnabled: true,
distributedTracingEnabled: true,
);
await FractalUpMobile.instance.start(
config,
() => runApp(const MyApp()),
);
After that setup, existing instrumentation keeps its call shape:
FractalUpMobile.instance.recordError(error, stackTrace);
await FractalUpMobile.instance.recordCustomEvent(
'Checkout',
eventName: 'Payment Failed',
eventAttributes: {'provider': 'stripe'},
);
await FractalUpMobile.instance.recordMetric(
'checkout.duration',
'Checkout',
value: 321,
valueUnit: MetricUnit.MILLISECONDS,
);
Optional compatibility imports are also available for navigation, raw dart:io HTTP clients, global HTTP overrides, trace constants, and version metadata:
import 'package:fractalup/fractalup_navigation_observer.dart';
import 'package:fractalup/fractalup_http_client.dart';
import 'package:fractalup/fractalup_http_overrides.dart';
import 'package:fractalup/fractalup_dt_trace.dart';
import 'package:fractalup/version.dart';
8. RUM Views, Actions, and HTTP Tracking
Track screens automatically with the navigation observer:
MaterialApp(
navigatorObservers: [
FractalUp.navigatorObserver,
],
home: const AppHome(),
);
Track RUM views and user actions manually when needed:
await FractalUp.rum.startView('/checkout', 'Checkout');
await FractalUp.rum.addAction(
RumActionType.tap,
'Pay button',
{'button.id': 'pay'},
);
await FractalUp.rum.stopView('/checkout');
Wrap package:http clients to capture resources and inject W3C trace headers:
final client = FractalUp.httpClient();
final response = await client.get(
Uri.parse('https://api.example.com/pay'),
);
Each tracked request emits resource start/finish events with method, URL, status code, duration, response size, session id, and trace context. Use FractalUpHttpClient directly only when a specific client needs custom attributes or its own first-party host list.
9. Offline Queue
Enable persisted queued events when mobile delivery should survive process restarts:
FractalUp.configureFromEnvironment(
endpoint: const String.fromEnvironment('FRACTALUP_ENDPOINT'),
serviceName: 'my-flutter-app',
persistQueuedEvents: true,
maxPersistedQueuedEvents: 500,
maxPersistedQueueBytes: 2 * 1024 * 1024,
);
Mobile-agent style setup enables offline storage by default. Set offlineStorageEnabled: false to disable it.
await FractalUpMobile.instance.startAgent(Config(
accessToken: const String.fromEnvironment('FRACTALUP_INGESTION_KEY'),
endpoint: Uri.parse(const String.fromEnvironment('FRACTALUP_ENDPOINT')),
offlineStorageEnabled: true,
));
10. Sampling and Privacy Hooks
Use sampling to control event volume and beforeSend for final payload filtering:
FractalUp.configureFromEnvironment(
endpoint: const String.fromEnvironment('FRACTALUP_ENDPOINT'),
serviceName: 'my-flutter-app',
sampleRate: 1.0,
logSampleRate: 0.25,
rumSampleRate: 0.5,
networkSampleRate: 0.5,
beforeSend: (payload) {
if (payload['event'] == 'debug.noisy_event') {
return null;
}
return payload;
},
);
URL query values are redacted by default in event attributes, contexts, RUM resources, and persisted queue records.
FractalUp.configureFromEnvironment(
endpoint: const String.fromEnvironment('FRACTALUP_ENDPOINT'),
serviceName: 'my-flutter-app',
redactUrlQueryParameters: true,
);
11. Attach Current User
After login:
FractalUp.setUser(userId: user.id);
After logout:
FractalUp.clearUser();
Optional customer-side account grouping:
FractalUp.setUser(
userId: user.id,
tenantId: account.id,
);
tenantId is observability metadata only. The ingestion key already identifies the FractalUp customer/project on the backend.
12. Production Delivery Controls
The defaults are designed to protect the host app and control ingestion cost:
- Error deduplication uses a bounded 30-second window.
- The client permits 600 total events and 120 error events per minute.
- Transient failures use up to three attempts with capped exponential jitter.
- HTTP
429responses honorRetry-After. - Queues, persisted storage, payload depth, collection size, strings, and total payload bytes are bounded.
- Dropped, deduplicated, and rate-limited totals are attached as client reports.
- Fatal unhandled errors mark the active session as crashed for crash-free session reporting.
Every limit is configurable through FractalupRadarOptions,
FractalUp.configureHosted, FractalUp.configureFromEnvironment, or the
matching FractalUpOptions fields.
13. Platform Wiring
Automatic Flutter/framework errors, platform dispatcher errors, async
appRunner zone errors, startup timing, lifecycle, sessions, context, privacy,
sampling, queueing, and delivery controls require only initialization.
Flutter does not expose a reliable global hook for every router or every HTTP client. Add these once:
MaterialApp(
navigatorObservers: [FractalUp.navigatorObserver],
);
final httpClient = FractalUp.httpClient();
Raw dart:io global HTTP overrides are available for compatible VM platforms.
Browser requests, custom networking stacks, native crashes, native symbols,
continuous profiling, screenshots/view hierarchy, ANR engines, frame tracking,
and session replay require platform-specific integration and are not reported
as active unless a real implementation is installed.
14. Package Documentation and License
pub.dev generates the package page and API reference from this repository; no separate documentation website is required.
This package is licensed under the Elastic License 2.0. See LICENSE and
NOTICE. Security reports should follow SECURITY.md.
Libraries
- config
- Mobile-agent style FractalUp configuration types.
- fractalup
- FractalUp observability for Flutter applications.
- fractalup_dt_trace
- Distributed-trace compatibility constants.
- fractalup_http_client
- Platform-compatible instrumented HTTP client exports.
- fractalup_http_overrides
- Platform-compatible global HTTP override exports.
- fractalup_mobile
- Mobile-agent style FractalUp API.
- Flutter navigation instrumentation.
- loglevel
- Mobile-agent compatible log levels.
- metricunit
- Mobile-agent compatible metric units.
- network_failure
- Network failure classification used by manual instrumentation.
- version
- FractalUp package version metadata.