uptimemesh_flutter

pub version license

Flutter SDK for UptimeMesh — automatic crash reporting, session tracking, screen analytics, network monitoring and custom event tracking.

Features

  • Automatic crash reportingFlutterError.onError + PlatformDispatcher.onError
  • Session tracking — device model, OS, app version, network type, duration
  • User identification — associate sessions with users via identify()
  • Screen tracking — automatic via NavigatorObserver
  • Network monitoring — HTTP request tracking with status code & duration
  • Click trackingtrackClick() shortcut for button/element taps
  • Custom events — track any user action with properties
  • Offline bufferSharedPreferences persistence, auto-retry on reconnect
  • AdBlocker bypass — custom proxy endpoint support via ingestUrl
  • Null-safe — Dart 3 / Flutter 3+

Installation

Add to pubspec.yaml:

dependencies:
  uptimemesh_flutter: ^1.2.8

Then:

flutter pub get

Quick Start

// main.dart
import 'package:flutter/material.dart';
import 'package:uptimemesh_flutter/uptimemesh_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await UptimeMesh.init('YOUR_API_KEY');
  runApp(const MyApp());
}

Get your API key from UptimeMesh dashboard → Mobil Uygulamalar → App → Entegrasyon.


API Reference

await UptimeMesh.init(apiKey, [options])

Initialize the SDK. Must be called after WidgetsFlutterBinding.ensureInitialized(). Calling more than once is a no-op.

await UptimeMesh.init(
  'YOUR_API_KEY',
  const UptimeMeshOptions(
    debug: true,
    flushInterval: Duration(seconds: 30),
    maxQueueSize: 50,
    // AdBlocker bypass: use your own proxy
    // ingestUrl: 'https://yourdomain.com/um-proxy',
  ),
);
Option Type Default Description
ingestUrl String? https://ingest.uptimemesh.com Custom ingest endpoint (AdBlocker bypass)
flushInterval Duration 30 seconds Auto-flush interval
maxQueueSize int 50 Flush immediately when queue reaches this size
debug bool false Print [UptimeMesh] logs to console
apiUrl String? Deprecated — use ingestUrl

UptimeMesh.identify(userId)

Associate the current session with a user. Appears as Kullanıcı in the Sessions table.

// After login
UptimeMesh.identify(user.id);   // ID, email or username

// After logout
UptimeMesh.identify(null);

Automatic Screen Tracking

Add UptimeMesh.navigatorObserver to MaterialApp:

MaterialApp(
  navigatorObservers: [UptimeMesh.navigatorObserver],
  routes: {
    '/': (_) => const HomeScreen(),
    '/profile': (_) => const ProfileScreen(),
  },
)

For GoRouter:

GoRouter(
  observers: [UptimeMesh.navigatorObserver],
  routes: [ /* ... */ ],
)

UptimeMesh.trackScreen(name)

Manual screen tracking.

UptimeMesh.trackScreen('HomeScreen');

UptimeMesh.trackClick(elementName, {screen?})

Log a button or element tap. Shortcut for trackEvent('click', {element, screen}).

UptimeMesh.trackClick('checkout_button', screen: 'CartScreen');
UptimeMesh.trackClick('menu_item_profile');

Shows up in the dashboard as a click event with the element name visible in breadcrumbs.


UptimeMesh.trackEvent(name, properties?)

Track custom events with optional properties.

UptimeMesh.trackEvent('purchase_completed', {
  'amount': 99.90,
  'currency': 'TRY',
  'product_id': 'plan_pro',
});

UptimeMesh.captureError(error, stackTrace?)

Manually report a caught (non-fatal) error.

try {
  await loadData();
} catch (e, stack) {
  UptimeMesh.captureError(e, stack);
}

Network Monitoring

Use UptimeMesh.httpClient as a drop-in replacement for http.Client:

final client = UptimeMesh.httpClient;
final response = await client.get(Uri.parse('https://api.example.com/data'));

For Dio, call UptimeMesh.trackNetwork() from an interceptor:

UptimeMesh.trackNetwork(
  url: UptimeMesh.sanitizeNetworkUrl(response.requestOptions.uri.toString()),
  method: response.requestOptions.method,
  statusCode: response.statusCode,
  durationMs: elapsed,
);

await UptimeMesh.flush()

Immediately send all queued events.

await UptimeMesh.flush();

Wrap your app with runZonedGuarded to catch async errors outside the Flutter framework:

void main() {
  runZonedGuarded(() async {
    WidgetsFlutterBinding.ensureInitialized();
    await UptimeMesh.init('YOUR_API_KEY');
    runApp(const MyApp());
  }, (error, stack) {
    UptimeMesh.captureError(error, stack);
  });
}

AdBlocker Bypass (Proxy)

If your users have ad-blockers that block ingest.uptimemesh.com, set up a proxy on your own domain:

nginx:

location /um-proxy/ {
    proxy_pass https://ingest.uptimemesh.com/;
}

Then initialize with ingestUrl:

await UptimeMesh.init(
  'YOUR_API_KEY',
  const UptimeMeshOptions(ingestUrl: 'https://yourdomain.com/um-proxy'),
);

What's Collected Automatically

Data Source
Flutter framework errors FlutterError.onError
Dart async / platform errors PlatformDispatcher.onError
Device model device_info_plus
OS version device_info_plus
App version + build number package_info_plus
Network type (wifi/cellular) connectivity_plus
Session duration Lifecycle observer

Event Types

Type Description Triggered By
crash Unhandled fatal error Framework hooks
error Caught / non-fatal error captureError()
screen Screen view navigatorObserver / trackScreen()
event Custom user action trackEvent() / trackClick()
network HTTP request httpClient / trackNetwork()

Offline Mode

Events are persisted to SharedPreferences when offline. On the next app launch they are loaded and sent automatically.


Troubleshooting

Events not showing up?

  1. Enable debug: true — look for [UptimeMesh] prints
  2. Check your API key in the dashboard
  3. Call await UptimeMesh.flush() to force send immediately

init() throws?

  • Make sure WidgetsFlutterBinding.ensureInitialized() is called before init()

Screen tracking not working?

  • Ensure UptimeMesh.navigatorObserver is in navigatorObservers
  • Named routes must be set — unnamed routes have no route.settings.name

Data goes to ingest.uptimemesh.com but gets blocked?

  • Use ingestUrl to point to your own proxy endpoint

Changelog

1.2.8

  • README and changelog kept up to date with latest version

1.2.7

  • Fix: inactive state now handled — iOS notification banners, Control Center and permission dialogs caused inactive→resumed cycles that created spurious new sessions
  • Fix: Replaced bg==null session-creation logic with an explicit _needsNewSession flag — a new session is only opened after a real grace-period expiry or app detach

1.2.6

  • Fix: flush() called immediately on paused — iOS suspends the Dart isolate before the 30s timer fires; events are now persisted even if the process is killed

1.2.5

  • Fix: Future.delayed replaced with cancellable Timer — multiple background/foreground cycles within 30s no longer left stale timers that fired at the wrong time and split sessions

1.2.4

  • Feat: Session grace period (30s) — quickly backgrounding and returning no longer creates a new session; real app close (30s+ or detached) ends the session correctly

1.2.3

  • Fix: resolvedIngestUrl getter collapsed to single line so // ignore: deprecated_member_use_from_same_package covers the apiUrl reference (CI flutter analyze fix)

1.2.2

  • Feat: UptimeMesh.trackClick(elementName, {screen?}) — shortcut for button/element click events
  • Feat: UptimeMeshOptions.ingestUrl — custom ingest endpoint for AdBlocker bypass
  • Change: Default endpoint changed from api.uptimemesh.comingest.uptimemesh.com
  • apiUrl deprecated

1.2.1

  • Fix: _uuid() critical bug — timestamp-based calculation only produced 16 unique UUIDs; replaced with Random.secure()
  • Fix: _endCurrentSession() now uses await _sender.flush() — session data no longer lost on background
  • Fix: _sdkVersion synced with pubspec

1.2.0

  • New: UptimeMesh.identify(userId) — associate sessions with a user; pass null to clear
  • New: SessionData.userId field

1.1.1

  • UptimeMesh.trackNetwork() — manual network event for Dio / custom HTTP clients
  • sanitizeNetworkUrl() made public

1.0.0

  • Initial release

License

MIT © UptimeMesh

Libraries

uptimemesh_flutter