app_health_pings 0.0.1
app_health_pings: ^0.0.1 copied to clipboard
Low-overhead heartbeats and basic device info to your backend. Helps catch broken builds and environment drift early.
App Health Pings #
Low-overhead heartbeats and basic device info to your backend. Helps catch broken builds and environment drift early.
Features #
- 🔄 Automatic Health Pings: Periodic heartbeats to monitor app health
- 📱 Device Information: Collect platform, OS version, device model, and connectivity status
- 🎯 Smart Backoff: Exponential backoff on failures with configurable limits
- 🔄 Lifecycle Aware: Automatic pings on app start and resume
- 🛠 Configurable: Flexible configuration for intervals, endpoints, and data collection
- 🔒 Privacy Focused: Optional device info collection with granular control
- 📦 Lightweight: Minimal dependencies and overhead
- 🌐 Network Aware: Only sends pings when connectivity is available
- 🏷 Tagging Support: Custom tags for environment, version, and deployment tracking
Getting Started #
Add this to your package's pubspec.yaml file:
dependencies:
app_health_pings: ^1.0.0
Usage #
Basic Setup #
import 'package:app_health_pings/app_health_pings.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize health pings
await AppHealthPings.initialize(
AppHealthConfig(
endpoint: Uri.parse('https://your-api.com/health-pings'),
authToken: 'your-bearer-token', // Optional
interval: const Duration(minutes: 15),
enabled: true,
),
);
runApp(MyApp());
}
Advanced Configuration #
await AppHealthPings.initialize(
AppHealthConfig(
endpoint: Uri.parse('https://your-api.com/health-pings'),
authToken: 'bearer-token-here',
tags: {
'env': 'production',
'version': '1.0.0',
'deployment': 'us-east-1',
},
interval: const Duration(minutes: 10),
maxInterval: const Duration(minutes: 30),
enabled: true,
sendOnStart: true,
sendOnResume: true,
collectDeviceInfo: true,
connectTimeout: const Duration(seconds: 10),
),
);
Manual Pings #
// Send a manual ping
await AppHealthPings.pingNow(reason: 'user_action');
// Send ping with extra data
await AppHealthPings.pingNow(
reason: 'feature_usage',
extra: {
'feature': 'payment_completed',
'amount': 99.99,
'user_id': 'user_123',
},
);
Heartbeat Control #
// Start automatic heartbeats
AppHealthPings.startHeartbeat();
// Stop automatic heartbeats
AppHealthPings.stopHeartbeat();
Payload Structure #
Your backend will receive POST requests with the following JSON structure:
{
"timestamp": "2024-01-15T10:30:00.000Z",
"reason": "interval",
"installId": "550e8400-e29b-41d4-a716-446655440000",
"sessionId": "550e8400-e29b-41d4-a716-446655440001",
"package": {
"name": "com.example.myapp",
"version": "1.0.0",
"buildNumber": "1"
},
"connectivity": ["wifi"],
"device": {
"platform": "android",
"androidSdk": 33,
"manufacturer": "Google",
"model": "Pixel 7",
"isPhysicalDevice": true
},
"tags": {
"env": "production",
"version": "1.0.0"
},
"extra": {}
}
Device Information by Platform #
Android:
platform: "android"androidSdk: API levelmanufacturer: Device manufacturermodel: Device modelisPhysicalDevice: true/false
iOS:
platform: "ios"systemName: "iOS"systemVersion: iOS versionmodel: Device identifierisPhysicalDevice: true/false
Other Platforms:
platform: Platform name (web, windows, linux, macos)
Configuration Options #
| Option | Type | Default | Description |
|---|---|---|---|
endpoint |
Uri |
Required | Your backend endpoint URL |
authToken |
String? |
null |
Optional Bearer token for authentication |
tags |
Map<String, String>? |
null |
Custom tags sent with every ping |
interval |
Duration |
15 minutes |
Base interval between automatic pings |
maxInterval |
Duration |
1 hour |
Maximum interval during exponential backoff |
enabled |
bool |
true |
Master switch to enable/disable all pings |
sendOnStart |
bool |
true |
Send ping when app starts |
sendOnResume |
bool |
true |
Send ping when app resumes from background |
collectDeviceInfo |
bool |
true |
Include device information in pings |
connectTimeout |
Duration |
5 seconds |
HTTP request timeout |
Backend Setup #
Your backend should:
- Accept POST requests to the configured endpoint
- Expect
Content-Type: application/json - Handle optional
Authorization: Bearer <token>header - Return HTTP 200-299 status for success
- Handle the
x-apphealth-schema: 1header
Example Express.js Handler #
app.post('/health-pings', (req, res) => {
const ping = req.body;
console.log('Health ping received:', {
timestamp: ping.timestamp,
reason: ping.reason,
platform: ping.device.platform,
appVersion: ping.package.version,
tags: ping.tags
});
// Store in database, send to monitoring service, etc.
res.status(200).json({ success: true });
});
Use Cases #
- Build Monitoring: Detect when new builds stop sending pings
- Environment Drift: Monitor device/OS distribution changes over time
- App Health: Track app crashes or unexpected terminations
- Deployment Verification: Ensure new releases are reaching users
- User Engagement: Basic app usage analytics
- Technical Monitoring: Network connectivity and performance insights
Privacy Considerations #
- Install and session IDs are generated fresh each app install/launch
- Device information collection can be disabled via
collectDeviceInfo: false - No personally identifiable information is collected by default
- All data collection is transparent and configurable
Example App #
See the example directory for a complete Flutter app demonstrating all features.
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
Author #
Muzamil Ghafoor
- GitHub: @Muzamil Ghafoor
License #
This project is licensed under the MIT License - see the LICENSE file for details.
Copyright (c) 2024 Muzamil Ghafoor