Skip to content

Commit 7102be7

Browse files
committed
update
1 parent 69f0a44 commit 7102be7

4 files changed

Lines changed: 67 additions & 158 deletions

File tree

ARTICLE.md

Lines changed: 65 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# The Ultimate Guide to `df_log`: Go Beyond `print()` in Flutter
1+
## Tired of `print()`? A Pragmatic Guide to Better Logging in Flutter.
22

3-
### A beginner-friendly tutorial and complete reference manual for making your Flutter debugging, analytics, and crash reporting smarter.
3+
### An honest, beginner-friendly look at `df_log` — a package that aims to make your console debugging, analytics, and crash reporting smarter, not just more complicated.
44

5-
![](https://raw.githubusercontent.com/dev-cetera/df_log/main/example/example.png)
5+
![Screenshot of df_log output in a terminal](https://raw.githubusercontent.com/dev-cetera/df_log/main/example/example.png)
66

7-
If you're a Flutter developer, your journey probably started with `print()`. It’s our oldest and most reliable friend for debugging. We sprinkle it everywhere to check a variable's value, confirm a function was called, or see if a widget rebuilt.
7+
If you're a Flutter developer, your journey started with `print()`. It’s our oldest friend for debugging. We sprinkle it everywhere to check a variable, confirm a function was called, or see if a widget rebuilt.
88

9-
But let's be honest. As our apps grow, the console becomes a chaotic wall of white text.
9+
But as our apps grow, the console becomes a chaotic, colorless waterfall of text.
1010

1111
```
1212
Button tapped
@@ -16,40 +16,25 @@ Network error
1616
UI updated
1717
```
1818

19-
You're left asking: _Which_ button was tapped? _Where_ did the network error happen? This ambiguity is where we waste precious time.
19+
You're left asking: *Which* button was tapped? *Where* did that network error happen? This ambiguity is where we waste precious time.
2020

21-
What if your logs could be smart, organized, beautiful, and tell you _exactly_ where they came from? What if they could power your analytics and crash reporting automatically?
21+
Of course, there are powerful, "correct" ways to debug. The **Flutter Debugger** is an incredible tool that lets you pause your app with breakpoints, inspect the entire state, and step through code line by line. For complex bug hunting, it’s unbeatable.
2222

23-
Meet **[df_log](https://pub.dev/packages/df_log)**, a simple but profoundly powerful logging package for Dart and Flutter. This guide will take you from a complete beginner to a master of `df_log`, showing you how it will fundamentally change the way you build and debug your apps.
23+
So, why talk about another logging package?
2424

25-
---
26-
27-
### Part 1: Your First Steps - The 5-Minute Upgrade
28-
29-
Let’s get you started. The initial payoff is immediate.
25+
Because sometimes, you don’t want to pause your app. You just want to watch the story of your code unfold in the console. You want the simplicity of `print()` but with more clarity, context, and control. What if your logs could also power your analytics and crash reporting automatically?
3026

31-
#### Installation
27+
Meet **[df_log](https://pub.dev/packages/df_log)**, a pragmatic, opinionated tool designed to do one thing well: **make your console output beautiful, readable, and powerful.**
3228

33-
1. Open your `pubspec.yaml` file.
34-
2. Add `df_log` to your dependencies:
35-
36-
```yaml
37-
dependencies:
38-
flutter:
39-
sdk: flutter
40-
df_log: ^latest_version # Check pub.dev for the latest version
41-
```
29+
---
4230

43-
3. Run `flutter pub get` in your terminal.
44-
4. Import the package in any Dart file where you want to log:
31+
### Part 1: Your First Steps - The 5-Minute Upgrade
4532

46-
```dart
47-
import 'package:df_log/df_log.dart';
48-
```
33+
The initial payoff is immediate. After adding `df_log` to your `pubspec.yaml` and importing it, you can immediately upgrade your `print()` statements.
4934

5035
#### Your First "Smart" Log
5136

52-
Now, replace a `print()` statement with a `df_log` equivalent.
37+
Replace a `print()` statement with a `df_log` equivalent.
5338

5439
**Before:**
5540

@@ -60,17 +45,19 @@ print('User successfully authenticated.');
6045
**After:**
6146

6247
```dart
48+
import 'package:df_log/df_log.dart';
49+
6350
Log.ok('User successfully authenticated.');
6451
```
6552

6653
Run your app and look at the console. Instead of plain text, you’ll see something like this:
6754

68-
`🟢 [lib/data/auth_repository.dart:42] User successfully authenticated.`
55+
`🟢 [auth_service/authenticateUser #42] User successfully authenticated.`
6956

7057
This is the first "Aha!" moment. You instantly get three upgrades:
7158

7259
1. **A Category Icon (`🟢`):** You can tell at a glance that this was a success.
73-
2. **The Exact Location:** You know this log came from `auth_repository.dart` on line `42`. No more guessing! You can click this in most IDEs to jump straight to the code.
60+
2. **Precise Context `[filename/member #linenumber]`:** You know exactly where this log came from: the `authenticateUser` function inside the `auth_service.dart` file, on line `42`. No more guessing! You can click this in most IDEs to jump straight to the code.
7461
3. **Color:** In supported consoles, the output is beautifully colored, making it easy to scan.
7562

7663
You’ve already saved yourself minutes of future debugging time.
@@ -83,7 +70,7 @@ Now let's explore the foundational features that make `df_log` so effective.
8370

8471
#### 1. Semantic Logging: Speaking with Intent
8572

86-
`df_log` provides methods for different kinds of events. This gives your logs meaning.
73+
`df_log` provides methods for different kinds of events. This gives your logs meaning and turns your console into a readable story of your app's execution.
8774

8875
```dart
8976
void main() {
@@ -96,8 +83,6 @@ void main() {
9683
}
9784
```
9885

99-
This turns your console into a readable story of your app's execution, not just a random list of events.
100-
10186
#### 2. Precision Filtering with Tags
10287

10388
This is arguably the most powerful debugging feature. You can assign tags to your logs and then filter the console to show only what you need.
@@ -110,15 +95,12 @@ Let’s see it in action.
11095
// main.dart
11196
void main() {
11297
// Let's say we only want to debug the UI for the authentication flow.
113-
Log.addTags({#ui, #auth});
98+
Log.activeTags = {#ui, #auth};
11499
115100
// ✅ Printed! Has the #auth tag, which is active.
116101
Log.ok('User logged in.', {#auth});
117102
118-
// ✅ Printed! Has the #ui tag, which is active.
119-
Log.info('Rendering profile screen...', {#ui});
120-
121-
// ❌ NOT Printed! It requires the #network tag, which we haven't activated.
103+
// ❌ NOT Printed! It requires the #network tag, which we haven't activated yet.
122104
Log.trace('Fetching user avatar...', {#ui, #network});
123105
124106
// --- Now, let's debug the network call for the avatar ---
@@ -137,11 +119,11 @@ With tags, you can silence the noise from every other part of your app and focus
137119

138120
This is where `df_log` transcends being just a logger. Using callbacks, you can turn it into a central event bus for your entire application.
139121

140-
The `Log.addCallback()` method lets you execute a function every single time a log is created, giving you access to the complete `LogItem` object (message, tags, timestamp, etc.).
122+
The `Log.addCallback()` method lets you execute a function every single time a log is created, giving you access to the complete `LogItem` object.
141123

142124
#### Use Case 1: Smarter Crash Reporting with Breadcrumbs
143125

144-
When a crash happens, the error message is only half the story. The other half is _what the user did right before it_. `df_log` can automatically provide this context.
126+
When a crash happens, the error message is only half the story. The other half is *what the user did right before it*. `df_log` can automatically provide this context.
145127

146128
```dart
147129
// In your main.dart
@@ -157,7 +139,7 @@ void main() {
157139
// Get the history of recent events.
158140
final breadcrumbs = Log.items.map((item) => item.toMap()).toList();
159141
160-
// Send the error and the breadcrumbs to your reporting service.
142+
// Send the error and the breadcrumbs to your reporting service (e.g., Sentry).
161143
MyCrashReporter.captureException(
162144
exception: logItem.message,
163145
extraData: {'log_breadcrumbs': breadcrumbs},
@@ -172,7 +154,6 @@ void main() {
172154
void updateUserProfile() {
173155
Log.info('Navigated to profile screen.', {#ui, #profile});
174156
try {
175-
// ... code that might fail ...
176157
throw Exception('Connection timed out');
177158
} catch (e) {
178159
// This single line now does two things:
@@ -194,7 +175,11 @@ void setupAnalytics() {
194175
if (logItem.tags.contains(#analytics_event)) {
195176
// The log message can be the event name!
196177
final eventName = logItem.message.toString();
197-
MyAnalyticsService.logEvent(name: eventName);
178+
// The LogItem can be converted to a map for parameters.
179+
final parameters = logItem.toMap();
180+
181+
// Send to your service, e.g., Google Analytics / Firebase
182+
FirebaseAnalytics.instance.logEvent(name: eventName, parameters: parameters);
198183
}
199184
});
200185
}
@@ -208,62 +193,61 @@ void onPurchaseButtonPressed() {
208193
}
209194
```
210195

211-
If you ever change your analytics provider, you only have to update one callback function, not hundreds of files. Your code becomes cleaner and completely decoupled from the analytics implementation.
196+
If you ever change your analytics provider, you only have to update **one callback function**, not hundreds of files. Your code becomes cleaner and completely decoupled from the analytics implementation.
212197

213198
---
214199

215-
### Part 4: The Official `df_log` Manual (API Reference)
200+
### Part 4: The `df_log` Manual (Full Feature Set)
216201

217-
Here is a quick reference to all the main features available in `df_log`.
202+
Here is a quick reference to all the main features available.
218203

219204
#### Main Logging Methods
220205

221-
- `Log.info(message, [tags])`: For general informational messages. (`🟣`)
222-
- `Log.ok(message, [tags])`: For success operations. (`🟢`)
223-
- `Log.err(message, [tags])`: For errors or exceptions. (`🔴`)
224-
- `Log.alert(message, [tags])`: For warnings that need attention. (`🟠`)
225-
- `Log.start(message, [tags])`: To mark the beginning of a process. (`🔵`)
226-
- `Log.stop(message, [tags])`: To mark the end of a process. (`⚫`)
227-
- `Log.trace(message, [tags])`: For fine-grained debugging information. (`⚪️`)
228-
- `Log.printGreen(message)`: Prints a message in a specific color without any other formatting. Many other colors are available (`printRed`, `printYellow`, etc.).
206+
- `Log.info(msg, [tags])`: For general informational messages. (`🟣`)
207+
- `Log.ok(msg, [tags])`: For success operations. (`🟢`)
208+
- `Log.err(msg, [tags])`: For errors or exceptions. (`🔴`)
209+
- `Log.alert(msg, [tags])`: For warnings that need attention. (`🟠`)
210+
- `Log.start(msg, [tags])`: To mark the beginning of a process. (`🔵`)
211+
- `Log.stop(msg, [tags])`: To mark the end of a process. (``)
212+
- `Log.trace(msg, [tags])`: For fine-grained debugging information. (`⚪️`)
213+
- `Log.printGreen(message)`: Prints a message in a specific color without any other formatting. Many other colors are available (`printRed`, `printYellow`, `printBlue`, etc.).
229214

230215
#### Configuration (Static Properties on `Log`)
231216

232-
- `Log.enableStyling = true`: Enables/disables ANSI colors and icons. Set to `false` if your console doesn't support them.
233-
- `Log.showTimestamps = true`: Shows a `HH:mm:ss.SSS` timestamp on each log.
234-
- `Log.showTags = true`: Shows tags like `#auth #ui` on each log.
235-
- `Log.showIds = false`: Shows a unique ID on each log.
236-
- `Log.enableReleaseAsserts = false`: By default, logs only work in debug mode. Set this to `true` to enable logging and asserts in release builds (use with caution).
217+
- `Log.enableStyling = true`: Enables/disables ANSI colors and icons.
218+
- `Log.showTimestamps = true`: Shows a `HH:mm:ss.SSS` timestamp on each log.
219+
- `Log.showTags = true`: Shows tags like `#auth #ui` on each log.
220+
- `Log.showIds = false`: Shows a unique ID on each log.
221+
- `Log.enableReleaseAsserts = false`: By default, logs only work in debug mode. Set to `true` to enable logging in release builds (use with caution).
237222

238-
#### In-Memory Storage
223+
#### In-Memory Storage & Callbacks
239224

240-
- `Log.storeLogs = true`: If `true`, keeps a history of logs in memory.
241-
- `Log.maxStoredLogs = 1000`: Sets the maximum number of `LogItem` objects to store in the queue.
242-
- `Log.items`: A `Queue<LogItem>` containing the stored logs. You can access it directly to inspect history.
225+
- `Log.storeLogs = true`: If `true`, keeps a history of logs in memory.
226+
- `Log.maxStoredLogs = 1000`: Sets the max number of `LogItem` objects to store.
227+
- `Log.items`: A `Queue<LogItem>` containing the stored logs.
228+
- `Log.addCallback(callback)`: Registers a function `void Function(LogItem item)` that runs for every log.
229+
- `Log.removeCallback(callback)`: Removes a previously registered callback.
243230

244-
#### Tag Management
231+
#### Advanced Output
245232

246-
- `Log.activeTags`: A `Set<Symbol>` of all currently active tags.
247-
- `Log.addTags(Set<Symbol> tags)`: Adds one or more tags to the active set.
248-
- `Log.removeTags(Set<Symbol> tags)`: Removes tags from the active set.
233+
- `Log.useDeveloperLog()`: Switches output to `dart:developer`'s `log` function for a richer experience in some IDEs.
234+
- `Log.useStandardPrint()`: Reverts the output to the standard `print` function.
249235

250-
#### Advanced Features
236+
---
251237

252-
- `Log.addCallback(callback)`: Registers a function `void Function(LogItem item)` that is called every time a log is created. Returns the callback so you can remove it later.
253-
- `Log.removeCallback(callback)`: Removes a previously registered callback.
254-
- `Log.useDeveloperLog()`: Switches the output to `dart:developer`'s `log` function, which can provide a richer experience in IDEs like VS Code's Debug Console.
255-
- `Log.useStandardPrint()`: Reverts the output to the standard `print` function.
238+
### Final Thoughts: Is This For You?
256239

257-
---
240+
Let’s be clear to pre-emptively address the critics. `df_log` is not trying to be the most powerful logging framework in the world.
241+
242+
- If you need advanced features like log rotation, writing to files, or complex custom formatters, a package like `logger` or `floggy` might be a better choice.
243+
- If you are deep in a bug and need to inspect object properties and the call stack, **use the Flutter Debugger**. It is the right tool for that job.
258244

259-
### Conclusion
245+
So, who is `df_log` for?
260246

261-
`df_log` is more than just a pretty logger. It's a complete instrumentation framework that encourages you to treat events in your app as structured data. By adopting it, you get:
247+
It’s for the developer who finds themselves littering their code with `print('--- HERE 1 ---')` and wishes it was just a little bit… better. It’s for adding semantic, colorful, filterable breadcrumbs to trace the flow of an application. It's for centralizing your app's event-based logic, like analytics and crash reporting, through a single, clean API.
262248

263-
- **Clarity:** Know exactly where every log comes from.
264-
- **Organization:** Use categories and tags to make your console readable and filterable.
265-
- **Power:** Use callbacks to drive crash reporting, analytics, and performance monitoring from a single, clean source of truth.
249+
The goal is to be **pragmatic**: to provide a massive step up from `print()` without the cognitive overhead of a full-fledged logging framework. It's a simple tool for a common, multifaceted problem.
266250

267-
It's a small change to your workflow that pays massive dividends in productivity and code quality.
251+
If that sounds like something that could clean up your debug console and your codebase, give it a try.
268252

269-
This is an open-source project actively maintained by **[Robert Mollentze](https://github.com/robert-mollentze)** and contributors. If you find it valuable, give the [GitHub repo](https://github.com/dev-cetera/df_log) a star, and consider [buying the author a coffee](https://www.buymeacoffee.com/dev_cetera) to support future development. Happy logging!
253+
This is an open-source project. If you find it valuable, give the [**GitHub repo**](https://github.com/dev-cetera/df_log) a star, and consider [**buying the author a coffee**](https://www.buymeacoffee.com/dev_cetera) to support future development. Happy logging

DEVELOPER_NOTES.md

Lines changed: 0 additions & 76 deletions
This file was deleted.

lib/src/log.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ final class Log {
558558

559559
// Only print if combinedTags is empty or all of combinedTags are in activeTags.
560560
if (combinedTags.isNotEmpty && !activeTags.containsAll(combinedTags)) {
561+
// TODO: Or just use contains?
561562
return;
562563
}
563564

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ funding:
1818
- https://www.patreon.com/c/RobertMollentze
1919
- https://github.com/sponsors/robmllze
2020
description: A package that provides logging utilities for better debugging.
21-
version: 0.3.20
21+
version: 0.3.21
2222
topics:
2323
- console
2424
- debugging

0 commit comments

Comments
 (0)