app_log_tracker 0.3.1 copy "app_log_tracker: ^0.3.1" to clipboard
app_log_tracker: ^0.3.1 copied to clipboard

Event + API log tracker with dedup and offline outbox for Flutter.

example/lib/main.dart

import 'package:app_log_tracker/app_log_tracker.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

/// Demo app_log_tracker:
/// - custom event (errorApi, notif_read)
/// - auto API log via Dio + http
/// - dedup, preview payload, flush manual + otomatis, halaman Track Log
void main() {
  runApp(const TrackerDemoApp());
}

class TrackerDemoApp extends StatefulWidget {
  const TrackerDemoApp({super.key});

  @override
  State<TrackerDemoApp> createState() => _TrackerDemoAppState();
}

class _TrackerDemoAppState extends State<TrackerDemoApp> {
  late final LogTracker tracker;
  late final Dio dio;
  String _log = 'Siap. Track sesuatu dulu.';
  TrackerLanguage _lang = TrackerLanguage.indonesian;

  @override
  void initState() {
    super.initState();
    // Ganti ke SqfliteTrackStorage() untuk persist antar restart.
    tracker = LogTracker(storage: InMemoryTrackStorage());
    dio = Dio()..interceptors.add(TrackerDioInterceptor(tracker));
  }

  @override
  void dispose() {
    tracker.stopAutoExport();
    super.dispose();
  }

  void _info(String s) => setState(() => _log = s);

  /// Contoh NEGATIVE case: API gagal / validasi gagal / error bisnis.
  Future<void> _trackErrorApi() async {
    final added = await tracker.track(
      keyEvent: 'errorApi',
      id: 'user_123',
      status: TrackStatus.failed,
      data: {'code': 'EMAIL_TAKEN', 'message': 'Email sudah dipakai'},
    );
    _info(added ? 'errorApi DITAMBAH' : 'DUPLIKAT -> di-skip');
  }

  /// Contoh POSITIVE case: aksi user berhasil (baca notif, dsb).
  Future<void> _trackNotifRead() async {
    final added = await tracker.track(
      keyEvent: 'notif_read',
      id: 'notif_${DateTime.now().millisecond}',
      status: TrackStatus.success,
      data: {'read': true},
    );
    _info(added ? 'notif_read DITAMBAH' : 'DUPLIKAT -> di-skip');
  }

  Future<void> _hitDio() async {
    try {
      await dio.get('https://jsonplaceholder.typicode.com/posts/1');
      _info('Dio GET sukses -> cek Track Log, ada api_log');
    } catch (e) {
      _info('Dio error: $e');
    }
  }

  Future<void> _hitHttp() async {
    try {
      final client = TrackedHttpClient(tracker, http.Client());
      final res = await client.get(
        Uri.parse('https://jsonplaceholder.typicode.com/posts/2'),
      );
      _info('http GET ${res.statusCode} -> cek Track Log, ada api_log');
    } catch (e) {
      _info('http error: $e');
    }
  }

  /// Preview payload: LIHAT data yang akan dikirim, tanpa menghapus local.
  /// Dipakai buat debug / sync manual (copy -> POST sendiri -> deleteEvents).
  Future<void> _previewPayload() async {
    final payload = await tracker.buildPayload();
    final events = payload['events'] as List;
    _info(
      'batch_id: ${payload['batch_id']}\n'
      'events: ${events.length}\n'
      '${events.take(3).map((e) => (e as Map)['key_event']).join(', ')}',
    );
  }

  /// Flush: KIRIM batch ke server + HAPUS yang sukses dari local.
  /// Device lanjut nge-log data fresh sesudahnya.
  Future<void> _flush() async {
    final result = await tracker.flush((payload) async {
      // Ganti dengan API server lu:
      // await dio.post('https://api.lu/logs', data: payload);
      await Future<void>.delayed(const Duration(milliseconds: 300));
      debugPrint(
        'FLUSH: ${payload['batch_id']} '
        '${(payload['events'] as List).length} events',
      );
    });
    _info(
      result.success
          ? 'FLUSH sukses, ${result.sentCount} terkirim, local dibersihkan'
          : 'FLUSH gagal, retryable=${result.retryable}: ${result.error}',
    );
  }

  /// Export otomatis tiap 10 detik (demo). Produksi: 5 menit / 15 menit.
  /// Sukses = local dibersihkan otomatis. Gagal = dicoba lagi interval berikut.
  Future<void> _toggleAutoExport() async {
    if (tracker.isAutoExportRunning) {
      tracker.stopAutoExport();
      _info('Auto-export MATI');
      return;
    }
    tracker.startAutoExport(
      (payload) async {
        await Future<void>.delayed(const Duration(milliseconds: 300));
        debugPrint('AUTO-EXPORT: ${(payload['events'] as List).length} events');
      },
      interval: const Duration(seconds: 10),
      onResult: (r) => _info(
        r.sentCount == 0
            ? 'Auto-export: antrean kosong'
            : 'Auto-export: ${r.sentCount} terkirim, local dibersihkan',
      ),
    );
    _info('Auto-export NYALA (tiap 10 detik)');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'app_log_tracker demo',
      theme: ThemeData(colorSchemeSeed: Colors.indigo, useMaterial3: true),
      home: Scaffold(
        appBar: AppBar(title: const Text('app_log_tracker demo')),
        floatingActionButton: TrackerBubble(tracker: tracker, language: _lang),
        body: ListView(
          padding: const EdgeInsets.all(16),
          children: [
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                ElevatedButton(
                  onPressed: _trackErrorApi,
                  child: const Text('Track errorApi (gagal)'),
                ),
                ElevatedButton(
                  onPressed: _trackNotifRead,
                  child: const Text('Track notif_read (sukses)'),
                ),
                ElevatedButton(
                  onPressed: _hitDio,
                  child: const Text('Dio GET'),
                ),
                ElevatedButton(
                  onPressed: _hitHttp,
                  child: const Text('http GET'),
                ),
                ElevatedButton(
                  onPressed: _previewPayload,
                  child: const Text('Preview payload'),
                ),
                ElevatedButton(onPressed: _flush, child: const Text('Flush')),
                ElevatedButton(
                  onPressed: _toggleAutoExport,
                  child: const Text('Auto-export on/off'),
                ),
                ElevatedButton(
                  onPressed: () => setState(() {
                    _lang = _lang == TrackerLanguage.indonesian
                        ? TrackerLanguage.english
                        : TrackerLanguage.indonesian;
                    _info(
                      _lang == TrackerLanguage.indonesian
                          ? 'Bahasa overlay: Indonesia'
                          : 'Overlay language: English',
                    );
                  }),
                  child: Text(
                    _lang == TrackerLanguage.indonesian
                        ? 'Bahasa: ID (tap = EN)'
                        : 'Language: EN (tap = ID)',
                  ),
                ),
              ],
            ),
            const SizedBox(height: 16),
            Container(
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(
                color: Colors.black87,
                borderRadius: BorderRadius.circular(8),
              ),
              child: Text(
                _log,
                style: const TextStyle(
                  color: Colors.greenAccent,
                  fontFamily: 'monospace',
                ),
              ),
            ),
            const SizedBox(height: 16),
            const Text(
              'Coba: tekan "Track errorApi" 2x -> yang kedua di-skip (dedup).\n'
              'Buka halaman "Track Log" lewat tombol pojok kanan bawah.',
            ),
          ],
        ),
      ),
    );
  }
}
4
likes
160
points
513
downloads
screenshot

Documentation

Documentation
API reference

Publisher

verified publisherachmadirfanda.is-a.dev

Weekly Downloads

Event + API log tracker with dedup and offline outbox for Flutter.

Repository (GitHub)
View/report issues

Topics

#logging #debugging #dio #http #offline

License

MIT (license)

Dependencies

dio, flutter, http, path, sqflite, uuid

More

Packages that depend on app_log_tracker