Exception handling and logging in dart/Flutter - Talker
Stanislav Ilin
Posted on June 4, 2022
Exceptions, Exceptions, Exceptions...
We see them constantly during development and support of Applications.
Some of them we expect, and some we haven't even thought about. The worst thing you can do as a programmer is not to think about catching and tracking errors. Let's figure out how to do it...
Exceptions handling in dart
For example, we have this code. This is a call of logic from some service.
final result = service.makeLogic();
print(result);
What will happen if we get an error in the service?
The answer is simple: program crashes and ends with an error
Such moments should be avoided. To do this, dart has a try-catch construct.
String? result;
try {
result = service.makeLogic();
} on Exception catch (e) {
print(e);
}
result ??= 'Can`t get result';
print(result);
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68pdxigf9o6iosf5575s.png)
In this case, the program will be able to continue execution and will terminate correctly
## Exceptions Tracking
We've figured out how to catch bugs, but what to do with tracking and error analysis?
There is a [Crashlytics](https://firebase.google.com/products/crashlytics) service from firebase for Flutter applications.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/07031x14um8cux7cvdoz.png)
It can track errors in your Flutter application.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bb4k88s0rqc3q7fnsn3f.png)
Crashlytics, Sentry, AppsFlyer and many others. There are even projects that make their own analytical system.
In startups, these tools can change frequently. Are you want to **manually write something like this every time?**
```dart
try {
// your code...
} on Exception catch (exception, stackTrace) {
Crashlytics.instance
.recordError(exception, stackTrace, reason: exception.message);
Sentry.captureException(exception, stackTrace: stackTrace);
YourOwnAnalytics.sendError(exception, stackTrace: stackTrace);
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(exception.toString())));
Logger.error('Something Service exception', exception, stackTrace);
}
```
It looks terrible🤢
But **how we can fix this case?**
## Talker
![Image description](https://github.com/Frezyx/talker/raw/master/docs/assets/gifs/talker_big.gif?raw=true)
I present to you the stable release of my library [Talker](https://github.com/Frezyx/talker)
Talker is advanced exception handling and logging tool for dart/flutter applications.
It is a system for storing and distributing debugging information of your application.
### Get started
You can get started at [Talker documentation site](https://frezyx.github.io/talker/guide/get-started.html)
But I'll tell you here too
For [Dart](https://dart.dev/) applications you need add **talker** dependency to your **pubspec.yaml**
```yaml
dependencies:
talker: ^1.0.0
```
For [Flutter](https://flutter.dev/) applications you can add **talker_flutter** or **talker** dependency to your **pubspec.yaml**
```yaml
dependencies:
talker_flutter: ^1.0.0
```
**What's difference ?**<br>
**talker_flutter** has advanced features that's convenient to use in the Flutter application
like [TalkerScreen](../guide/talker-flutter.html#TalkerScreen) or [TalkerRouteObserver](../guide/talker-flutter.html#TalkerRouteObserver)<br>
**talker** package working both for dart and flutter applications
## Easy to use
All you need for the first start is to import the dependency and create an instance of the Talker class
```dart
import 'package:talker/talker.dart';
void main(){
final talker = Talker();
talker.info('I`m alive 😄');
}
You can use Talker instance everywhere in your code
Simple and concise syntax will help you with this
final talker = Talker();
// Handle exceptions and errors
try {
// your code...
} on Exception catch (e, st) {
talker.handle(e, st, 'Exception in ...');
}
// Make logs
talker.log('App is started'),
talker.error('App is started'),
talker.waring('App is started'),
More examples you can get there or in GitHub
Flutter initialization
Setup Talker to listen your app uncaught exceptions in runZonedGuarded onError() callback
void main() {
final talker = Talker();
runZonedGuarded(
() => runApp(BaseEample(talker: talker)),
(Object error, StackTrace stack) {
talker.handle(error, stack, 'Uncaught app exception');
},
);
}
After such initialization, all uncaught errors and exceptions will be sent to Talker for processing
Observers
And now I will tell you how to fix the problematic situation from the beginning of the article
Using the Talker library, you can simplify error handling in several services
And now this terrible spaghetti code is replaced
try {
// your code...
} on Exception catch (exception, stackTrace) {
Crashlytics.instance
.recordError(exception, stackTrace, reason: exception.message);
Sentry.captureException(exception, stackTrace: stackTrace);
YourOwnAnalytics.sendError(exception, stackTrace: stackTrace);
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(exception.toString())));
Logger.error('Something Service exception', exception, stackTrace);
}
To this ->
try {
// your code...
} on Exception catch (e, st) {
talker.handle(e, st, 'Something Service exception');
}
To send analytics to other services, just add an observer
class ExceptionsAnalyticsTalkerObserver extends TalkerObserver {
ExceptionsAnalyticsTalkerObserver();
@override
Function(TalkerException e) get onException => (e) {
Crashlytics.instance
.recordError(e.exception, stack: e.stackTrace, reason: e.message);
Sentry.captureException(e.exception, stackTrace: e.stackTrace);
YourOwnAnalytics.sendError(e.exception, stackTrace: e.stackTrace);
};
}
And implement this observer in talker's settings
final talker = Talker(
observers: [
ExceptionsAnalyticsTalkerObserver(),
],
);
Now all your app exception events will come to ExceptionsAnalyticsTalkerObserver observer and will be redirected to the necessary services
Isn 't it beautiful? 😌
You can read more in Customization topic at Talker documentation site
In addition to the above, Talker can do a lot of other things. Customize logs, share a log report, etc.
I put a lot of effort and time into this package. Develop and test it for 4 months. Now I am implementing it into my existing production projects. It works great and the developers are very happy with it.
❤️I will be very pleased if you promote this project and put a star on GitHub and pub.dev
I will also be very glad if you try it in your project and report any shortcomings. For documentation, visit our personal website
Thank you very much for your attention!!!
Posted on June 4, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.