"The best bugs are the ones you never ship."
Debugging after an app hits production isn't just frustrating — it's expensive. It drains time, money, and your team's morale. But what if you could catch most issues before they ever reach your users?
That's the power of smart, debug-only logging in Flutter — a small practice that delivers huge returns.
Why Debug-Only Logging?
In Flutter, logs can be useful, but without structure, they become noise. My approach? A
custom DebugUtils utility that adds:
- Log Levels —
success,info,warning,error,debug - Timestamps for tracking event order
- Tagging to identify which feature or module the log came from
- Optional breakpoints during development
And best of all — it only runs when assert statements are active. That means:
- No performance hit in production
- Zero clutter in release builds
The Code
debug_utils.dartimport 'dart:developer' as dev; enum LogLevel { success, info, warning, error, debug } class DebugUtils { static void debugLog( String message, { LogLevel level = LogLevel.debug, bool breakPoint = false, String? tag, }) { assert(() { if (breakPoint) dev.debugger(); _logMessage(message, level: level, tag: tag); return true; }()); } static void _logMessage( String message, { required LogLevel level, String? tag, }) { final timestamp = DateTime.now().toIso8601String(); final levelStr = level.toString().split('.').last.toUpperCase(); final effectiveTag = tag ?? 'DebugUtils'; final formattedMessage = '[$timestamp][$levelStr] $message'; dev.log( formattedMessage, name: '$effectiveTag @rohan-165', level: _mapLogLevelToInt(level), ); } static int _mapLogLevelToInt(LogLevel level) { switch (level) { case LogLevel.success: return 850; case LogLevel.info: return 800; case LogLevel.warning: return 900; case LogLevel.error: return 1000; case LogLevel.debug: return 700; } } }
Real Benefits in Real Projects
This small utility has made a big difference in projects like Nagarik App and Ambition Guru:
- Catches issues early in development
- Prevents crashes before release
- Saves hours of troubleshooting
- Speeds up delivery of stable apps
How to Use It
main.dartvoid main() { DebugUtils.debugLog( "App Init successfully", level: LogLevel.info, ); DebugUtils.debugLog("No Data Found"); DebugUtils.debugLog( "Failed to load user data", level: LogLevel.error, tag: 'UserModel', ); }
Pro Tip: Tag Your Logs
Using tags like 'UserModel' or 'LoginBloc' lets you filter and
track logs by feature in the DevTools console. This makes it much easier to diagnose
bugs fast — even in large, complex apps.
💡 By Rohan Kumar Chaudhary | Flutter Developer | Clean Code Advocate 🧼💙
Happy Coding! 💙