telling_logger 1.0.10
telling_logger: ^1.0.10 copied to clipboard
Comprehensive crash reporting, error tracking, and analytics SDK for Flutter applications. Track errors, monitor performance, and gain insights into your app's behavior.
Telling Logger 📊 #
A production-ready crash reporting, error tracking, and analytics SDK for Flutter applications. Monitor your app's health, track user behavior, and gain actionable insights with minimal setup.
✨ Features #
Core Capabilities #
- 🐛 Automatic Crash Reporting – Captures unhandled Flutter framework and platform errors
- 📊 Event Analytics – Track custom events, user actions, and business metrics
- 📱 Rich Device Context – Auto-collects platform, OS version, device model, and app info
- 🔄 Session Management – Automatic session tracking with app lifecycle hooks
- 📍 Screen Tracking – Built-in NavigatorObserver for automatic screen view analytics
- 👤 User Context – Associate logs with user IDs, names, and emails
- 🎯 Widget-Level Tracking –
.nowTelling()extension for effortless view tracking - ⚡ Smart Batching – Efficient log deduplication and batching to minimize network overhead
- � Offline Support – Persists logs when offline, auto-sends when connection is restored
- 🛡️ Rate Limiting – Built-in deduplication, throttling, and flood protection
- 🌍 Cross-Platform – Works on iOS, Android, Web, macOS, Windows, and Linux
Developer Experience #
- 🚀 5-Minute Setup – Initialize with a single line of code
- 📝 Production-Safe Logging – Debug logs automatically stripped from release builds
- 🎨 Flexible API – Multiple log levels, types, and metadata support
📦 Installation #
Add telling_logger to your pubspec.yaml:
dependencies:
telling_logger: ^1.0.10
Then install:
flutter pub get
🔑 Get Your API Key #
To use Telling Logger, you need an API key.
- Go to the Telling Dashboard.
- Log in or create an account.
- Create a new project to obtain your API key.
🚀 Quick Start #
1. Initialize the SDK #
In your main.dart, initialize Telling before running your app:
import 'package:flutter/material.dart';
import 'package:telling_logger/telling_logger.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Telling SDK
await Telling.instance.init(
'YOUR_API_KEY',
enableDebugLogs: true, // Optional: Control debug logs (defaults to true in debug mode)
);
// Enable automatic crash reporting
Telling.instance.enableCrashReporting();
runApp(MyApp());
}
2. Log Events #
// Simple info log
Telling.instance.log('User completed onboarding');
// Log with metadata
Telling.instance.log(
'Payment processed',
level: LogLevel.info,
metadata: {
'amount': 29.99,
'currency': 'USD',
'payment_method': 'stripe',
},
);
// Error logging
try {
await processPayment();
} catch (e, stack) {
Telling.instance.log(
'Payment failed',
level: LogLevel.error,
error: e,
stackTrace: stack,
);
}
3. Track Analytics #
// Track custom events
Telling.instance.event(
'button_clicked',
properties: {
'button_name': 'Sign Up',
'screen': 'Landing Page',
'user_segment': 'free_trial',
},
);
📚 Core Concepts #
Log Levels #
Control the severity and visibility of your logs:
| Level | Use Case | Severity |
|---|---|---|
LogLevel.trace |
Extremely detailed debugging | 0 |
LogLevel.debug |
Detailed diagnostic information | 1 |
LogLevel.info |
General informational messages | 2 |
LogLevel.warning |
Potentially harmful situations | 3 |
LogLevel.error |
Runtime errors that allow continuation | 4 |
LogLevel.fatal |
Critical errors causing termination | 5 |
Log Types #
Categorize logs for better filtering and analytics:
| Type | Purpose |
|---|---|
LogType.general |
Standard application logs |
LogType.analytics |
User behavior and event tracking |
LogType.event |
Custom business events |
LogType.performance |
Performance metrics and benchmarks |
LogType.network |
API calls and network activity |
LogType.security |
Security-related events |
LogType.exception |
Handled exceptions |
LogType.crash |
Application crashes and fatal errors |
LogType.custom |
Custom log categories |
🎯 Advanced Features #
User Context Tracking #
Associate logs with specific users for better debugging and analytics:
// Set user context after login
Telling.instance.setUser(
userId: 'user_12345',
userName: 'Jane Doe',
userEmail: '[email protected]',
);
// Clear user context after logout
Telling.instance.clearUser();
All subsequent logs will automatically include user information until cleared.
Automatic Screen Tracking #
With MaterialApp
MaterialApp(
navigatorObservers: [
Telling.instance.screenTracker,
],
home: HomeScreen(),
)
With go_router
final router = GoRouter(
observers: [
Telling.instance.goRouterScreenTracker,
],
routes: [...],
);
MaterialApp.router(
routerConfig: router,
)
Screen views are automatically logged with:
- Screen name
- Previous screen
- Time spent on previous screen
- Session context
Widget-Level Tracking #
Use the .nowTelling() extension to track any widget's visibility:
import 'package:telling_logger/telling_logger.dart';
// Basic usage - tracks when widget appears
Column(
children: [
Text('Welcome!'),
],
).nowTelling()
// With custom name
ProductCard(product: item).nowTelling(
name: 'Product Card Impression',
)
// With metadata for context
PremiumFeature().nowTelling(
name: 'Premium Feature Shown',
metadata: {
'feature_id': 'dark_mode',
'user_tier': 'free',
},
)
// Track every appearance (not just once)
AdBanner().nowTelling(
name: 'Banner Ad Impression',
trackOnce: false,
metadata: {'ad_id': 'banner_123'},
)
// Custom log type and level
CriticalAlert().nowTelling(
name: 'Security Alert Displayed',
type: LogType.security,
level: LogLevel.warning,
)
Parameters:
name– Custom name (defaults to widget's runtimeType)type– Log type (defaults toLogType.analytics)level– Log level (defaults toLogLevel.info)metadata– Additional context datatrackOnce– Track only first appearance (defaults totrue)
Session Management #
Sessions are automatically managed based on app lifecycle:
- Session Start: When app launches or returns from background
- Session End: When app goes to background or terminates
- Session Data: Duration, user context, device info
// Session data is automatically included in all logs
{
"sessionId": "user_123_1700745600000",
"userId": "user_123",
"userName": "Jane Doe",
"userEmail": "[email protected]"
}
Crash Reporting #
Enable automatic crash capture for both Flutter and platform errors:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Telling.instance.init('YOUR_API_KEY');
// Captures:
// - Flutter framework errors (FlutterError.onError)
// - Platform dispatcher errors (PlatformDispatcher.onError)
// - Render issues (marked as warnings)
Telling.instance.enableCrashReporting();
runApp(MyApp());
}
Crash Intelligence:
- Render/layout issues are logged as
warnings - Actual crashes are logged as
fatalerrors - Full stack traces included
- Automatic retry with exponential backoff
🔧 Configuration Options #
Initialization Parameters #
await Telling.instance.init(
String apiKey, // Required: Your API key
{
String? userId, // Initial user ID
String? userName, // Initial user name
String? userEmail, // Initial user email
bool? enableDebugLogs, // Control debug logs (defaults to kDebugMode)
}
);
Environment-Specific Setup #
void main() async {
WidgetsFlutterBinding.ensureInitialized();
const isProduction = bool.fromEnvironment('dart.vm.product');
await Telling.instance.init(
isProduction ? 'PROD_API_KEY' : 'DEV_API_KEY',
);
runApp(MyApp());
}
Debug Logs Control #
// Disable debug logs even in debug mode
await Telling.instance.init(
'YOUR_API_KEY',
enableDebugLogs: false,
);
// Enable debug logs explicitly
await Telling.instance.init(
'YOUR_API_KEY',
enableDebugLogs: true,
);
// Default behavior (true in debug mode, false in release)
await Telling.instance.init(
'YOUR_API_KEY',
);
## 🎓 Best Practices
### 1. Initialize Early
```dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize BEFORE runApp
await Telling.instance.init('API_KEY');
Telling.instance.enableCrashReporting();
runApp(MyApp());
}
2. Use Appropriate Log Levels #
// ✅ Good
Telling.instance.log('User login successful', level: LogLevel.info);
Telling.instance.log('Database query slow', level: LogLevel.warning);
Telling.instance.log('Payment failed', level: LogLevel.error);
// ❌ Avoid
Telling.instance.log('Button clicked', level: LogLevel.fatal); // Wrong severity
3. Add Context with Metadata #
// ✅ Good - rich context
Telling.instance.event('purchase_completed', properties: {
'product_id': 'premium_monthly',
'price': 9.99,
'currency': 'USD',
'payment_method': 'stripe',
'user_segment': 'trial_converted',
});
// ❌ Poor - no context
Telling.instance.event('purchase');
4. Track User Context #
// Set user context after authentication
await signIn(email, password);
Telling.instance.setUser(
userId: user.id,
userName: user.name,
userEmail: user.email,
);
// Clear on logout
await signOut();
Telling.instance.clearUser();
5. Use Widget Tracking Wisely #
// ✅ Good - track important screens/components
HomeScreen().nowTelling(name: 'Home Screen');
PremiumPaywall().nowTelling(name: 'Paywall Viewed');
// ❌ Avoid - don't track every tiny widget
Text('Hello').nowTelling(); // Too granular
Container().nowTelling(); // Not meaningful
6. Handle Sensitive Data #
// ❌ Don't log PII or sensitive data
Telling.instance.event('login', properties: {
'password': '123456', // NEVER
'credit_card': '4111...', // NEVER
});
// ✅ Hash or omit sensitive fields
Telling.instance.event('login', properties: {
'email_hash': hashEmail(user.email),
'login_method': 'email',
});
Common Errors #
"Telling SDK not initialized"
- Call
await Telling.instance.init()before using the SDK
"Invalid API Key" (403)
- Verify your API key is correct
- Check backend is running and accessible
"Logs being dropped"
- Reduce log volume or increase limits
📄 License #
MIT License - see the LICENSE file for details.
🙋 Support #
- � Documentation
- 🐛 Report Issues
- � Discussions
- 📧 Email: [email protected]
🌟 Show Your Support #
If Telling Logger helped you build better apps, please:
- ⭐ Star this repo
- 🐦 Share on Twitter
- 📝 Write a blog post
- 💬 Tell your friends
Made with 💙 by Kiishi