Ghost Logger

Stealing errors before they steal your users' experience.

Can be Unseen but always there. Stealing errors before they steal your users' experience. A lightweight, flexible logging utility with emoji indicators and optional crash reporting integration.

Features

  • ๐Ÿ‘ป Silent Operation - Works invisibly in the background
  • ๐Ÿšจ Automatic Reporting - Steals errors to prevent user impact
  • ๐ŸŽฏ Multiple Log Levels - Debug, info, warning, and error categorization
  • ๐Ÿ˜Š Emoji Indicators - Quick visual scanning of logs
  • ๐Ÿ”Œ Pluggable Crash Reporting - Implement CrashReporter interface for any service
  • ๐Ÿ› ๏ธ Multiple Output Mechanisms - Print or developer.log output
  • ๐Ÿงช Fully Testable - Zero hard dependencies on crash services
  • ๐Ÿ“ฆ Zero Dependencies - Only depends on Dart SDK
  • ๐ŸŒ Multi-Platform - Works on iOS, Android, Web, macOS, Windows, Linux

Installation

Add ghost_logger to your pubspec.yaml:

dependencies:
  ghost_logger: ^0.1.0

Then run:

dart pub get

Quick Start

Basic Setup

Import and configure Ghost Logger at your app startup:

import 'package:ghost_logger/ghost_logger.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await GhostLogger.configure(
    isDebugMode: true,
    loggerType: LoggerType.console,
  );

  runApp(const MyApp());
}

Logging Messages

Log messages with different severity levels:

GhostLogger.log(
  message: 'Processing user data',
  level: LogLevel.debug,
  tag: 'DataManager',
);

GhostLogger.log(
  message: 'User logged in successfully',
  level: LogLevel.info,
  tag: 'Auth',
);

GhostLogger.log(
  message: 'Deprecated API usage detected',
  level: LogLevel.warning,
  tag: 'API',
);

GhostLogger.log(
  message: 'Network request failed',
  level: LogLevel.error,
  tag: 'Network',
  stackTrace: StackTrace.current,
);

Log Levels

Ghost Logger supports four severity levels, each with a unique emoji for quick identification:

Level Emoji Use Case
Debug โš’๏ธ Development information, variable values
Info ๐Ÿ‘‰ General app events, user actions
Warning โš ๏ธ Potential issues, deprecations
Error โŒ Failures that need attention

Output Mechanisms

Choose how Ghost Logger outputs messages using LoggerType:

Uses Dart's print() function. Simple but may truncate very long messages.

await GhostLogger.configure(
  isDebugMode: true,
  loggerType: LoggerType.print,
);

Console

Uses dart:developer log with enhanced features including log levels.

await GhostLogger.configure(
  isDebugMode: true,
  loggerType: LoggerType.console,
);

Crash Reporting Integration

Ghost Logger becomes truly powerful when integrated with crash reporting services. It works with any service that implements the CrashReporter interface.

With Firebase Crashlytics

Use the companion package ghost_logger_firebase:

dependencies:
  ghost_logger: ^0.1.0
  ghost_logger_firebase: ^0.1.0
  firebase_core: ^6.0.0
  firebase_crashlytics: ^3.5.0

Configure in your main:

import 'package:firebase_core/firebase_core.dart';
import 'package:ghost_logger/ghost_logger.dart';
import 'package:ghost_logger_firebase/ghost_logger_firebase.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  await GhostLogger.configure(
    isDebugMode: false,
    loggerType: LoggerType.console,
    crashReporter: GhostFirebase(),
    enableCrashReporting: true,
  );

  runApp(const MyApp());
}

Now all errors are silently reported to Firebase Crashlytics while still appearing in your console during development.

Custom Crash Reporter

Implement the CrashReporter interface for custom services:

import 'package:ghost_logger/ghost_logger.dart';

class CustomCrashReporter implements CrashReporter {
  @override
  Future<void> log(String message) async {
    await sendToCrashService(message);
  }

  @override
  Future<void> recordError(
    dynamic exception,
    StackTrace? stackTrace, {
    String? reason,
  }) async {
    await sendErrorToCrashService(exception, stackTrace, reason);
  }

  @override
  Future<void> setCollectionEnabled(bool enabled) async {
    await configureCollection(enabled);
  }
}

await GhostLogger.configure(
  isDebugMode: false,
  crashReporter: CustomCrashReporter(),
  enableCrashReporting: true,
);

API Reference

GhostLogger.configure()

Initializes Ghost Logger with configuration options.

Parameters:

  • isDebugMode (required): Enable/disable console output
  • loggerType: Output mechanism (default: LoggerType.print)
  • crashReporter: Crash reporting implementation (optional)
  • enableCrashReporting: Enable crash service reporting (default: false)
await GhostLogger.configure(
  isDebugMode: !kReleaseMode,
  loggerType: LoggerType.console,
  crashReporter: GhostFirebase(),
  enableCrashReporting: !kDebugMode,
);

GhostLogger.log()

Logs a message with optional metadata.

Parameters:

  • message (required): The log content
  • level: Log severity (default: LogLevel.debug)
  • tag: Optional identifier for the log source
  • stackTrace: Optional stack trace for context
  • reportToCrashService: Override crash reporting for this log (optional)
await GhostLogger.log(
  message: 'Something happened',
  level: LogLevel.info,
  tag: 'MyClass',
  stackTrace: StackTrace.current,
);

Best Practices

  1. Configure Once: Set up Ghost Logger in your main() function, before running the app

  2. Use Tags: Add meaningful tags to identify log sources

GhostLogger.log(message: 'Data loaded', tag: 'DataService');
  1. Appropriate Levels: Use the correct log level for better filtering
LogLevel.debug     // Development only
LogLevel.info      // User actions, flow
LogLevel.warning   // Potential issues
LogLevel.error     // Failures and exceptions
  1. Include Stack Traces: Always include stack traces for errors
GhostLogger.log(
  message: 'Operation failed',
  level: LogLevel.error,
  stackTrace: StackTrace.current,
);
  1. Production Configuration: Disable debug output in production
await GhostLogger.configure(
  isDebugMode: kDebugMode,
  loggerType: LoggerType.console,
  crashReporter: GhostFirebase(),
  enableCrashReporting: kReleaseMode,
);

Examples

See the example directory for a complete Flutter app demonstrating Ghost Logger usage.

Run the example:

cd example
flutter run

Platform Support

Ghost Logger works on all platforms:

  • โœ… Android
  • โœ… iOS
  • โœ… Web
  • โœ… macOS
  • โœ… Windows
  • โœ… Linux

Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues on GitHub.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For issues, questions, or suggestions, please open an issue on GitHub.


Ghost Logger - Stealing errors before they steal your users' experience. ๐Ÿ‘ป

Libraries

ghost_logger
Ghost Logger - Stealing errors before they steal your users' experience.