ur logging initialize logic is to re-use a build modes implementation:</p>
<figure id="4da9">
<div>
<div>
<iframe class="gist-iframe" src="/gist/fredgrott/9e45ed320fc2b764c2df357b8dbbb689.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="d9fa">Now, I can show you the full logging initialize logic:</p>
<figure id="c788">
<div>
<div>
<iframe class="gist-iframe" src="/gist/fredgrott/f903562350871fa3c01fd5e1e1b05472.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="5234">We in debug mode use simple_logger to set our level to INFO. Then we use the logging package to set to listen to those streams that have log events. Then we use the logging appenders package to set up a print appender.</p><p id="8ec9">In release mode, we make sure to turn off logging by setting the log level to OFF. And, the last part of it is using simple_logger to format how the logger outputs the output for each log level.</p><p id="0616">Now, I have to explain my logging strategy as that then helps everyone see why I have implemented the specific logger helpers I have implemented.</p><h1 id="d904">My Logging Strategy</h1><p id="882b">If we go into this blind, then at certain parts and points we do not get full logging coverage of errors and exceptions. And to complicate things we do not have checked exceptions that would be useful in functional programming. So we need an implementation of logger helpers that is flexible but somewhat puts both classes and functions on equal footing as far as being able to log both informs of logger helpers.</p><p id="163c">We are going to use some different features of dart; namely abstract classes, dart types, and mixins to implement this set of logger helpers.</p><h1 id="d9db">Our Logger Helpers Implementation</h1><p id="244e">Let’s start with our types implementation:</p>
<figure id="cc93">
<div>
<div>
<iframe class="gist-iframe" src="/gist/fredgrott/95938c5d8e3f9606d4f507360fc391f0.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="a9f2">The type we are setting up is for the mixins we are going to implement for logging via logger in our classes.</p><p id="d70c">So what is that LoggerSpawner? That bit of magic ensures that we always get a full logger name as the log-tag in any class where we use a logger mixin:</p>
<figure id="a1b8">
<div>
<div>
<iframe class="gist-iframe" src="/gist/fredgrott/7a3704d1d2b019c6ed0fdd30e46a2dfc.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="ad90">The reason why I use different mixins even though I have a class name as the log-tag is for finer filtering when I review logging feedback in log view.</p><p id="8408">The lasted listed function is so that I can log in functions beyond the LogException class implement that I will next show you:</p>
<figure id="5c8d">
<div>
<div>
<iframe class="gist-iframe" src="/gist/fredgrott/3f2d3fe2875612876fc66f1c2d300f57.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="3b82">LogException is used in my Future try-catch blocks.</p><p id="5f09">And the result of this logger helper infrastructure is that I can get full logger logging coverage even in my functions!</p><figure id="e6c5"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*q7Cg1ysYgjkFMg5pKZsKcg.png"><figcaption></figcaption></figure><p id="015f">BTW, can you please log your damn state changes! Like this:</p>
<figure id="2b32">
<div>
<div>
<iframe class="gist-iframe" src="/gist/fredgrott/ab4
Options
b0f704ebfbf469f277a253be3aefc.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="84dc">Then you have an easy time debugging your business logic! And that bit of code is often called Middleware in reactive architecture discussions.</p><h1 id="4f53">Conclusion</h1><p id="3669">Not only does this logger helper implementation make it easy to debug log flutter app code it's future proof ready for when desktop app support is in the fully stable version of the Flutter SDK with its underlying use of streams to output log event records via the logging package.</p><h1 id="1910">Resources</h1><p id="cfe8">base_riverpod GitHub repo <a href="https://github.com/fredgrott/base_rvierpod">https://github.com/fredgrott/base_rvierpod</a></p><p id="c38e">flutterdeepdive GitHub repo <a href="https://github.com/fredgrott/flutterdeepdiv">https://github.com/fredgrott/flutterdeepdiv</a></p><p id="be41">developer.log source at Github repo <a href="https://github.com/dart-lang/sdk/blob/master/sdk/lib/developer/developer.dart">https://github.com/dart-lang/sdk/blob/master/sdk/lib/developer/developer.dart</a></p><p id="8000">logging package at pub.dev <a href="https://pub.dev/packages/logging">https://pub.dev/packages/logging</a></p><p id="30a3">ansicolor at pub.dev <a href="https://pub.dev/packages/ansicolor">https://pub.dev/packages/ansicolor</a></p><p id="8103">logging appenders at pub.dev <a href="https://pub.dev/packages/logging_appenders">https://pub.dev/packages/logging_appenders</a></p><p id="cb5d">simple logger at pub.dev <a href="https://pub.dev/packages/simple_logger">https://pub.dev/packages/simple_logger</a></p><p id="d7d2">General Flutter and Dart resources:</p><p id="e8f7">Flutter Community Resources <a href="https://flutter.dev/community">https://flutter.dev/community</a></p><p id="35ed">Flutter SDK <a href="https://flutter.dev/docs/get-started/install">https://flutter.dev/docs/get-started/install</a></p><p id="9679">Android Studio IDE <a href="https://developer.android.com/studio">https://developer.android.com/studio</a></p><p id="bd52">Visual Studio Code IDE <a href="https://code.visualstudio.com/">https://code.visualstudio.com/</a></p><p id="f4f4">Flutter Docs <a href="https://flutter.dev/docs">https://flutter.dev/docs</a></p><p id="a080">Dart Docs <a href="https://dart.dev/guides">https://dart.dev/guides</a></p><p id="124d">Google Firebase DeviceLab <a href="https://firebase.google.com/docs/test-lab">https://firebase.google.com/docs/test-lab</a></p><p id="a376"><b>Trademark Notice</b></p><p id="b0ce">Google LLC owns the following trademarks; Dart, Flutter, Android, Roboto, Noto. Apple Inc owns the trademarks iOS, MacOSX, Swift, and Objective-C. Apple Inc owns trademarks to their fonts of SF Pro, Sf Compact, SF mono, and New York. JetBeans Inc owns the trademarks to JetBeans, IntelliJ, and Kotlin. Oracle Inc owns the Java trademark. Microsoft Inc owns the trademarks to MS Windows OS and Powershell. Gradle is a trademark of Gradle Inc. The Git Project owns the trademark to Git. Linux Foundation owns the trademark to Linux. Smartphone OEM’s own trademarks to their mobile phone product names. To the best of my ability, I follow the brand and usage guidelines with the above-mentioned trademarks.</p><h1 id="d7d6">About Fred Grott</h1><p id="7fab">I’m the crazy SOB who as a former android mobile developer is starting to write about flutter mobile app development, design, and life(see <a href="https://fredgrott.medium.com/eff-covid-and-the-gop-e912db0548b8">Eff COVID and GOP</a>). Will I reach the pivotal One Million Medium monthly viewers mark? Sit back and watch. Find me on social platforms such as <a href="https://www.xing.com/profile/Fred_Grott/cv">Xing</a>, <a href="https://www.linkedin.com/in/fredgrottstartupfluttermobileappdesigner/">LinkedIN</a>, <a href="https://keybase.io/fredgrott">Keybase</a>, and <a href="https://twitter.com/fredgrott">Twitter</a>.</p>
<figure id="5b76">
<div>
<div>
There is a proliferation of logging plugins and almost the same amount of alleged expert ways to implement logging in Flutter Application projects. This is my expert way to log in Flutter application projects based on the application development process and in-depth knowledge of how dart and flutter work.
NOTE: As always, these sample flutter app demos are collated at my flutterdeepdive GitHub repo:
And at some point by flutter developer book app code will also be collated there as well.
Background
Why do we need to log? It’s not because writing log statements is fun, obviously! Let me give you an image:
The way we get an error-free program that reliably works is that we move all the uncaught errors in both the hard and soft groups to the caught group. And we accomplish that by implementing a logging infrastructure in our flutter app to make it easy to add log statements as we write and test code.
And since one of the artifacts produced in such a process is a better knowledge of how the dart and flutter APIs work and how the activity we are automating works is the full reason why I emphatically insist on learning both Dart and Flutter you have to start with a-tricked-out-skeleton-app like the ones I’m implementing such as this one:
Let me close out the background by stating that most of the logging plugins came out during a time when the logging package did not exist in the Dart and Flutter plugin-and-package ecosystem. They all implemented their own hacky-system that happens to be somewhat not real good in performance.
You should be moving towards fully using all the power of the developer.log and logging-package pairing, and I am showing exactly how to do that very set of steps.
Our Logging Implementation First Steps
First, we need to install these plugins:
-ansicolor
-logging
-logging_appenders
-simple_logger
So, in your pubspec under the dependencies block:
ansicolor: ^1.1.1
logging: ^1.0.1
logging_appenders: ^1.0.0
simple_logger: ^1.8.0+1
At first, we will use the ansicolor to create some helper classes to colorize our logs:
And that is just using the plugin API directions from the pub.dev plugin page:
Now we need to set up our logging initialize logic to set up the logging package, logging appenders, and the simple logger settings.
Our Logging Initialize Logic
The first part of our logging initialize logic is to re-use a build modes implementation:
Now, I can show you the full logging initialize logic:
We in debug mode use simple_logger to set our level to INFO. Then we use the logging package to set to listen to those streams that have log events. Then we use the logging appenders package to set up a print appender.
In release mode, we make sure to turn off logging by setting the log level to OFF. And, the last part of it is using simple_logger to format how the logger outputs the output for each log level.
Now, I have to explain my logging strategy as that then helps everyone see why I have implemented the specific logger helpers I have implemented.
My Logging Strategy
If we go into this blind, then at certain parts and points we do not get full logging coverage of errors and exceptions. And to complicate things we do not have checked exceptions that would be useful in functional programming. So we need an implementation of logger helpers that is flexible but somewhat puts both classes and functions on equal footing as far as being able to log both informs of logger helpers.
We are going to use some different features of dart; namely abstract classes, dart types, and mixins to implement this set of logger helpers.
Our Logger Helpers Implementation
Let’s start with our types implementation:
The type we are setting up is for the mixins we are going to implement for logging via logger in our classes.
So what is that LoggerSpawner? That bit of magic ensures that we always get a full logger name as the log-tag in any class where we use a logger mixin:
The reason why I use different mixins even though I have a class name as the log-tag is for finer filtering when I review logging feedback in log view.
The lasted listed function is so that I can log in functions beyond the LogException class implement that I will next show you:
LogException is used in my Future try-catch blocks.
And the result of this logger helper infrastructure is that I can get full logger logging coverage even in my functions!
BTW, can you please log your damn state changes! Like this:
Then you have an easy time debugging your business logic! And that bit of code is often called Middleware in reactive architecture discussions.
Conclusion
Not only does this logger helper implementation make it easy to debug log flutter app code it's future proof ready for when desktop app support is in the fully stable version of the Flutter SDK with its underlying use of streams to output log event records via the logging package.
Google LLC owns the following trademarks; Dart, Flutter, Android, Roboto, Noto. Apple Inc owns the trademarks iOS, MacOSX, Swift, and Objective-C. Apple Inc owns trademarks to their fonts of SF Pro, Sf Compact, SF mono, and New York. JetBeans Inc owns the trademarks to JetBeans, IntelliJ, and Kotlin. Oracle Inc owns the Java trademark. Microsoft Inc owns the trademarks to MS Windows OS and Powershell. Gradle is a trademark of Gradle Inc. The Git Project owns the trademark to Git. Linux Foundation owns the trademark to Linux. Smartphone OEM’s own trademarks to their mobile phone product names. To the best of my ability, I follow the brand and usage guidelines with the above-mentioned trademarks.
About Fred Grott
I’m the crazy SOB who as a former android mobile developer is starting to write about flutter mobile app development, design, and life(see Eff COVID and GOP). Will I reach the pivotal One Million Medium monthly viewers mark? Sit back and watch. Find me on social platforms such as Xing, LinkedIN, Keybase, and Twitter.