pulse_monitoring 0.1.5
pulse_monitoring: ^0.1.5 copied to clipboard
Flutter plugin for Pulse Monitoring, sessions, errors, HTTP metrics and in-app information.
Pulse Monitoring for Flutter #
Plugin Flutter untuk monitoring sesi, crash, error, HTTP, screen, event, dan informasi in-app dari dashboard Pulse. Versi plugin 0.1.5 menggunakan SDK native Android dan iOS 0.1.1.
Pemilik: Idris — idris3097@gmail.com.
Platform yang didukung #
| Platform | Dukungan | Persyaratan dan batasan |
|---|---|---|
| Android | Ya | Android 8.0 / API 26+, compileSdk 37+, Java 17. Perangkat dan emulator. |
| iOS | Ya | iOS 15+, CocoaPods dan Swift Package Manager. Perangkat arm64; simulator arm64 dan x86_64. |
| Web | Belum | Tidak ada implementasi monitoring web. |
| macOS, Windows, Linux | Belum | Tidak ada implementasi monitoring desktop. |
Persyaratan Flutter: Flutter 3.41+ dan Dart >=3.11.0 <4.0.0.
Pada platform yang belum didukung, start() tidak mengaktifkan monitoring.
Untuk compileSdk 37, gunakan Android Gradle Plugin 9.1.1+ dan Gradle yang kompatibel dengan versi AGP aplikasi. Lihat tabel kompatibilitas Android. Untuk iOS, gunakan Xcode yang kompatibel dengan Flutter dan binary Swift yang disertakan. Build simulator telah diverifikasi dengan Xcode 27.1. Plugin mendukung Swift Package Manager mulai versi 0.1.3, sekaligus mempertahankan dukungan CocoaPods untuk aplikasi yang belum bermigrasi.
Fitur dan cara pengumpulan #
| Fitur | Cara penggunaan |
|---|---|
| Sesi dan metadata perangkat/aplikasi | Otomatis setelah start(). |
| Crash Android | Uncaught JVM exceptions; crash NDK/sinyal belum ditangkap. |
| Crash iOS | Diagnostics MetricKit; pengiriman mengikuti jadwal sistem Apple. |
| Error Flutter/Dart | Teruskan melalui recordError() atau handler error aplikasi. |
| Metrik HTTP Dart | Panggil recordHttp() dari HTTP client aplikasi. Tidak ada interceptor Dart otomatis. |
| Screen | Pasang PulseNavigatorObserver pada Navigator, atau panggil trackScreen() secara manual. |
| Event bisnis | Panggil trackEvent(). |
| Maintenance | Dengarkan maintenance dan tampilkan chip; detail dibuka dengan showMaintenance(). |
| Informasi new feature/banner | Feed dan presentasi informasi ditangani SDK native. |
| Push informasi | Opsional; teruskan data FCM melalui handlePush(). Firebase dikonfigurasi aplikasi. |
UI kustom dan force update: mulai 0.1.4, aktifkan customInformation: true.
SDK menyediakan feed lengkap dan requiredUpdate, menjalankan pemeriksaan versi,
serta menyimpan statusnya. Aplikasi menggambar komponen UI; tidak perlu membuat
HTTP client, cache, timer, atau subscription topik Pulse sendiri. Mode default
mempertahankan popup native yang sudah ada.
1. Instalasi #
Tambahkan dependency dari pub.dev:
dependencies:
pulse_monitoring: ^0.1.5
flutter pub get
Pada aplikasi iOS yang menggunakan CocoaPods:
cd ios
pod install
cd ..
Flutter mendaftarkan plugin secara otomatis. Tidak perlu menambahkan SDK manual
ke Gradle aplikasi, Podfile, MainActivity, atau AppDelegate. Untuk CocoaPods,
folder ios/.symlinks/plugins/pulse_monitoring dikelola Flutter; jangan diedit
atau dimasukkan ke Git.
Pada aplikasi yang mengaktifkan SwiftPM, Flutter memilih manifest plugin secara otomatis. Tidak perlu menambahkan package plugin secara manual melalui Xcode. Flutter dapat tetap menggunakan CocoaPods untuk plugin lain yang belum mendukung SwiftPM. Ikuti panduan SwiftPM Flutter untuk pengaturan aplikasi Anda.
Android mengambil dependency native dari Maven Central. Package Flutter membawa XCFramework iOS, sehingga pemasangan tidak memerlukan akses repository GitHub.
2. Inisialisasi #
Ambil workspace key dari dashboard Pulse → Pengaturan → Workspace. Pastikan aplikasi terdaftar dengan package/bundle ID dan platform yang sesuai.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:pulse_monitoring/pulse_monitoring.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// Jika menggunakan Firebase, inisialisasikan Firebase terlebih dahulu.
await PulseMonitoring.start(
workspaceKey: const String.fromEnvironment('PULSE_WORKSPACE_KEY'),
debug: kDebugMode,
autoMaintenancePopups: false,
);
runApp(MaterialApp(
navigatorObservers: [PulseNavigatorObserver()],
home: const Scaffold(body: Center(child: Text('Home'))),
));
}
flutter run --dart-define=PULSE_WORKSPACE_KEY=pk_workspace_anda
Panggil start() sekali di main isolate, setelah Flutter binding siap dan sebelum
mengirim event atau identitas user. Key kosong menonaktifkan inisialisasi; pastikan
konfigurasi build production menyediakan key. Pelaporan sebelum SDK aktif diabaikan.
await start() menunggu inisialisasi bridge, bukan konfirmasi data diterima server.
Opsi start() |
Default | Kegunaan |
|---|---|---|
workspaceKey |
Wajib | Public workspace key dari dashboard. |
baseUrl |
https://pulse-api-mobile.vercel.app/api/v1 |
Endpoint API lengkap, termasuk /api/v1, untuk server sendiri. |
debug |
false |
Log diagnostik SDK; aktifkan saat pengembangan atau troubleshooting. |
customInformation |
false |
Aktifkan controller Flutter dan pemeriksaan force update; matikan popup native otomatis. |
autoMaintenancePopups |
false |
Aktifkan hanya jika ingin dialog maintenance otomatis. |
Untuk dev dan production, gunakan workspace key serta endpoint yang sesuai dengan
lingkungan masing-masing. --dart-define bukan penyimpanan secret; jangan masukkan
credential admin, private key, atau token server ke aplikasi.
UI informasi kustom #
Cukup public workspace key; alamat hosted Pulse sudah menjadi default:
await PulseMonitoring.start(
workspaceKey: const String.fromEnvironment('PULSE_WORKSPACE_KEY'),
customInformation: true,
);
final information = PulseMonitoring.information;
Controller tersedia setelah await start() pada Android/iOS. Jika inisialisasi
atau platform tidak tersedia, nilainya dapat null. Dengarkan controller dengan
ListenableBuilder atau addListener() dan render:
| State/API | Perilaku UI aplikasi |
|---|---|
maintenance |
Chip persisten; ketuk untuk detail, tanpa modal otomatis. |
banners |
Banner inline; dismissBanner(item) menyembunyikan selama proses berjalan. |
nextFeature |
Dialog/carousel; panggil markSeen(item) setelah ditampilkan, sekali per revisi. |
requiredUpdate |
Bottom sheet wajib; isDismissible: false, enableDrag: false, dan PopScope(canPop: false). |
refresh() |
Refresh feed native dan versi, misalnya pull-to-refresh. |
PulseInformationItem membawa halaman, gambar, CTA, prioritas, jadwal, dan revisi.
PulseRequiredUpdate membawa versi, build, catatan rilis, dan URL toko. Aplikasi
membuka storeUrl dan tetap mempertahankan sheet saat kembali dari toko sampai
requiredUpdate null. Dahulukan force update dari pengumuman fitur; jangan
menganggap berhasil membuka toko berarti aplikasi telah diperbarui.
SDK native tetap mengelola feed, cache informasi, targeting, expiry dan topik push.
Controller Flutter memeriksa versi saat start, foreground, push dan setiap menit
selama foreground, menyimpan kewajiban update per workspace/package/platform/build,
dan menyimpan revisi fitur yang sudah dilihat. Kegagalan jaringan tidak menghapus
update wajib yang sudah diketahui. Instalasi baru tanpa hasil cek sebelumnya
belum dapat mengetahui kewajiban update saat offline; pembatasan operasi penting
juga perlu ditegakkan server. Tidak ada dependency Firebase Dart baru; teruskan
push melalui PulseMonitoring.handlePush(message.data) dari aplikasi.
Penarikan notifikasi (0.1.5+) #
Backend Pulse dapat mengirim kontrol data-only type=information, action=retract,
information_id, dan retired_revision. Kontrol ini tidak memiliki alert atau suara.
SDK baru berlangganan topik kapabilitas pulse.<package>.<platform>.retract_v1
agar aplikasi lama tidak menerima kontrol yang belum dikenali.
Sebelum menampilkan notifikasi lokal, teruskan data di callback FCM background:
@pragma('vm:entry-point')
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
if (await PulseMonitoring.handleBackgroundPush(message.data)) return;
// Penanganan notifikasi aplikasi lainnya.
}
RemoteMessage dan Firebase berasal dari dependency Firebase aplikasi.
Handler ini dapat berjalan sebelum PulseMonitoring.start() dan tidak meminta
workspace key lagi. Gunakan juga sebelum penanganan foreground; handlePush()
mengenali kontrol yang sama untuk alur foreground biasa. Jangan menampilkan
notifikasi lokal untuk kontrol yang sudah ditangani.
Pada customInformation: true, bridge native menyaring revisi cache yang sudah
ditarik dan controller melakukan rekonsiliasi notifikasi saat start, foreground,
dan refresh. SDK hanya membersihkan notifikasi yang dipastikan tidak aktif dari
respons feed valid, serta tidak menyamakan kegagalan API dengan feed kosong.
Aplikasi perlu menutup sheet sendiri ketika item tidak lagi ada dalam controller.
UI native lama/default dan paket standalone Android/iOS tetap memakai binary
monitoring sebelumnya; jangan mengasumsikan popup native lama memiliki seluruh
aturan penarikan UI kustom Flutter ini.
Android memakai tag pulse.info.<information_id>.<revision> dari backend dan
NotificationManager.cancel(). Notifikasi Android lama tanpa tag tersebut tidak
bisa dipetakan dengan aman. iOS mencocokkan payload information_id dan
information_revision, lalu menghapus delivered/pending requests terkait.
Notifikasi iOS legacy dengan ID yang cocok tetapi tanpa revisi diperlakukan
sebagai revisi 0. Notifikasi lain dan revisi yang lebih baru tidak dihapus.
Penarikan merupakan best effort: perangkat offline, force-stop Android, atau pembatasan background/silent push iOS dapat menunda penarikan. Pada iOS, aktifkan Background Modes → Remote notifications, konfigurasi APNs/Firebase, dan teruskan handler background aplikasi. Backend menyimpan antrean penarikan terpisah agar penghapusan item tidak menghilangkan perintahnya. Data yang sudah dibaca pengguna tidak dapat dibatalkan. Tidak ada jaminan perangkat telah menghapus notifikasi hanya karena FCM menerima pesan.
3. Identitas user dan event #
Sesudah login berhasil, gunakan ID internal yang stabil. Bersihkan identitas ketika logout agar event selanjutnya tidak terkait akun sebelumnya.
PulseMonitoring.setUser('user_123');
PulseMonitoring.trackEvent('document_sent', {
'document_count': 2,
'delivery_method': 'email',
'success': true,
});
// Saat logout:
PulseMonitoring.setUser(null);
Gunakan nama event yang konsisten dan properties sederhana: string, angka, atau boolean. Hindari email, nama lengkap, isi dokumen, token, dan data sensitif lain.
Untuk screen, PulseNavigatorObserver membaca RouteSettings.name pada
PageRoute. Pasang observer pada Navigator yang digunakan router aplikasi dan
beri nama route. Jika router tidak memberikan nama, laporkan screen secara manual:
PulseMonitoring.trackScreen('document_detail');
Gunakan satu mekanisme pelaporan untuk screen yang sama agar tidak duplikat.
4. Error Flutter dan error yang ditangani aplikasi #
Plugin tidak memasang handler error Flutter secara otomatis. Untuk error yang sudah ditangani, laporkan setelah aplikasi menentukan cara pemulihannya:
try {
// Operasi aplikasi.
} catch (error, stack) {
PulseMonitoring.recordError(error, stack);
// Tampilkan pesan atau lakukan pemulihan sesuai alur aplikasi.
}
Untuk menghubungkan error global, pasang handler sekali setelah start().
Pertahankan handler yang sudah dipasang aplikasi atau Crashlytics:
import 'dart:ui' show PlatformDispatcher;
import 'package:flutter/foundation.dart' show FlutterError;
import 'package:pulse_monitoring/pulse_monitoring.dart';
void installPulseErrorHandlers() {
final previousFlutterError = FlutterError.onError;
FlutterError.onError = (details) {
PulseMonitoring.recordError(details.exception, details.stack);
if (previousFlutterError != null) {
previousFlutterError(details);
} else {
FlutterError.presentError(details);
}
};
final previousPlatformError = PlatformDispatcher.instance.onError;
PlatformDispatcher.instance.onError = (error, stack) {
PulseMonitoring.recordError(error, stack, fatal: true);
return previousPlatformError?.call(error, stack) ?? false;
};
}
Sesuaikan fatal dengan kebijakan error aplikasi. Jangan melaporkan exception
yang sama berulang melalui catch, zone, dan handler global. Error dari isolate
lain perlu diteruskan melalui mekanisme error isolate milik aplikasi.
Lihat penanganan error Flutter.
5. Metrik HTTP #
Tambahkan recordHttp() pada HTTP client/interceptor yang sudah dipakai aplikasi.
Contoh berikut memakai package:http; tambahkan dependency http jika diperlukan.
import 'package:http/http.dart' as http;
import 'package:pulse_monitoring/pulse_monitoring.dart';
Future<http.Response> monitoredGet(http.Client client, Uri uri) async {
final watch = Stopwatch()..start();
try {
final response = await client.get(uri).timeout(const Duration(seconds: 15));
PulseMonitoring.recordHttp(
method: 'GET',
url: uri,
status: response.statusCode,
duration: watch.elapsed,
responseBytes: response.bodyBytes.length,
);
return response;
} catch (error) {
PulseMonitoring.recordHttp(
method: 'GET',
url: uri,
status: 0,
duration: watch.elapsed,
error: error.runtimeType.toString(),
);
rethrow;
} finally {
watch.stop();
}
}
SDK membuang credentials URL, query string, dan fragment sebelum mengirim metrik
melalui bridge. Path URL serta string error tetap perlu diperiksa oleh aplikasi;
jangan memasukkan ID sensitif atau isi respons ke dalamnya. API recordHttp()
tidak menerima request/response body atau header. Jangan membuat request monitoring
kedua jika client aplikasi sudah melaporkan request yang sama.
Gunakan kembali HTTP client milik aplikasi dan tutup client ketika service atau
pemiliknya di-dispose, sehingga koneksi dapat dipakai kembali antar-request.
6. Maintenance chip #
PulseMonitoring.maintenance menyediakan ValueNotifier<PulseMaintenance?>.
Nilainya null ketika tidak ada maintenance aktif. Biarkan SDK mengelola notifier
ini pada aplikasi production.
ValueListenableBuilder<PulseMaintenance?>(
valueListenable: PulseMonitoring.maintenance,
builder: (context, maintenance, child) {
if (maintenance == null) return const SizedBox.shrink();
return ActionChip(
avatar: Icon(Icons.info_outline, color: maintenance.color),
label: Text(maintenance.title),
onPressed: PulseMonitoring.showMaintenance,
);
},
)
Import package:flutter/material.dart untuk widget di atas. Pertahankan
autoMaintenancePopups: false jika memakai chip, sehingga maintenance tidak
membuka dialog otomatis. Menekan chip membuka detail maintenance melalui SDK native.
Untuk dialog otomatis, set autoMaintenancePopups: true saat inisialisasi.
7. Push informasi dengan Firebase (opsional) #
Monitoring dasar tidak memerlukan Firebase. Untuk push, aplikasi perlu memasang
serta mengonfigurasi firebase_core dan firebase_messaging, permission notifikasi,
dan konfigurasi APNs/FCM sesuai platform. Setelah Firebase dan Pulse siap,
teruskan pesan saat foreground dan saat notifikasi dibuka:
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:pulse_monitoring/pulse_monitoring.dart';
void routeMessage(RemoteMessage message) {
if (PulseMonitoring.handlePush(message.data)) return;
// Lanjutkan handler pesan aplikasi yang lain di sini.
}
Future<void> configurePulsePush() async {
FirebaseMessaging.onMessage.listen(routeMessage);
FirebaseMessaging.onMessageOpenedApp.listen(routeMessage);
final initial = await FirebaseMessaging.instance.getInitialMessage();
if (initial != null) routeMessage(initial);
}
handlePush() mengenali data type: information dan meminta SDK memperbarui feed
informasi. Nilai true berarti pesan telah diteruskan, bukan konfirmasi popup sudah
terlihat. Aturan maintenance tetap mengikuti autoMaintenancePopups.
Daftarkan listener sekali dan batalkan subscription ketika pemiliknya di-dispose.
Plugin ini digunakan dari main isolate; jangan memanggilnya langsung dari
background isolate FCM. Untuk konfigurasi lengkap, ikuti
panduan penerimaan pesan Firebase.
Praktik integrasi yang disarankan #
- Mulai SDK sebelum mengirim event, lalu set user setelah session login tersedia.
- Gunakan ID internal dan properties yang tidak memuat data sensitif.
- Pertahankan handler error dan alur push aplikasi yang sudah ada; hindari laporan duplikat.
- Gunakan observer route atau pelaporan screen manual sesuai router aplikasi.
- Biarkan antrean dan retry SDK berjalan; jangan memanggil
flush()pada setiap event. - Gunakan
PulseMonitoring.flush()untuk meminta upload segera saat diperlukan. Pemanggilan ini tidak menunggu upload selesai atau menjamin server menerima data. - Validasi pengiriman melalui dashboard pada perangkat uji. Antrean offline memiliki batas kapasitas; SDK tidak menjamin pengiriman setiap event.
- Uji Android release dengan minification aktif serta iOS pada perangkat fisik. Simulator saja tidak membuktikan penerimaan diagnostics MetricKit.
SDK menyertakan PrivacyInfo.xcprivacy pada framework iOS. Deklarasi privasi aplikasi
perlu mencerminkan identitas user, event custom, dan data lain yang benar-benar dikirim.
Diagnostics crash iOS mengikuti jadwal Apple dan tidak dijamin muncul saat launch
berikutnya. Android belum menangkap crash NDK/sinyal. Gunakan crash reporter lain
sesuai kebutuhan aplikasi.
Upgrade dan troubleshooting #
Untuk memperbarui package yang sudah terpasang:
flutter pub upgrade pulse_monitoring
cd ios
pod update pulse_monitoring --no-repo-update
cd ..
| Masalah | Pemeriksaan |
|---|---|
checkReleaseAarMetadata menyebut android-36 |
Gunakan plugin 0.1.2+ dan compileSdk aplikasi 37+. Periksa versi yang terpilih pada pubspec.lock. |
| SDK tidak mengirim data | Pastikan workspace key terisi, endpoint dapat diakses, serta package/bundle ID terdaftar pada workspace yang benar. |
| Maintenance chip tidak muncul | Pastikan konten published, jadwal aktif, target platform/package cocok, dan feed sudah diterima. Periksa juga ID flavor dev/prod. |
| Screen tidak tercatat | Beri nama route atau panggil trackScreen() manual. |
| Error/HTTP Dart tidak tercatat | Hubungkan handler error dan HTTP client seperti contoh di atas. |
Error MissingPluginException setelah menambah dependency |
Hentikan aplikasi, jalankan pub get/Pods, lalu build ulang penuh; hot reload tidak mendaftarkan plugin native baru. |
| Push tidak muncul | Periksa Firebase/APNs, permission, data type: information, serta forwarding pesan pada main isolate. |
| Crash iOS belum masuk dashboard | Periksa diagnostics pada perangkat; pengiriman MetricKit dapat tertunda. |
Versi native, contoh, dan lisensi #
- Plugin Flutter: 0.1.5.
- Android native:
io.github.mhmadidris:pulse-monitoring:0.1.1dari Maven Central. - iOS native: XCFramework 0.1.1, termasuk privacy manifest dan Swift interfaces.
- Contoh pemakaian: example/lib/main.dart.
Versi plugin dapat naik sendiri untuk perbaikan integrasi tanpa mengganti SDK native. Source implementasi Swift SDK, dSYM, dan archive Xcode tidak disertakan dalam package Flutter. Bridge Flutter dan binary iOS ikut tersedia pada pub.dev; repository GitHub dapat tetap private.
Penggunaan plugin dan binary iOS tunduk pada LICENSE. SDK Android native yang didistribusikan terpisah menggunakan Apache License 2.0. Hubungi idris3097@gmail.com untuk izin penggunaan atau pertanyaan integrasi.