amwal_pay_sdk 1.1.43

SDKflutter
Platformandroid

A Flutter SDK for integrating Amwal Pay payment solutions into your mobile apps, providing secure, seamless, and customizable payment experiences.

Logar - Centralized Logging System for Amwal Pay SDK

Logar is a comprehensive, singleton-based logging utility designed specifically for the Amwal Pay SDK. It provides structured, configurable logging with support for multiple output formats, external collectors, and clean architecture principles.

Features

  • Multiple Log Levels: debug, info, warning, error, fatal
  • Flexible Output Formats: Pretty-print for development, JSON for production
  • External Collectors: Integration with Firebase Crashlytics and custom services
  • Tagging System: Organize logs with custom tags
  • Global Configuration: Enable/disable logging, set minimum levels
  • Platform Agnostic: Works across mobile, web, and backend
  • Clean Architecture: Follows dependency injection and SOLID principles
  • Migration Support: Easy migration from existing print() and debugPrint() calls

Quick Start

1. Initialize Logar

import 'package:amwal_pay_sdk/core/logger/logger.dart';

// For development
LogarInjector.instance.initializeForDevelopment();

// For production
LogarInjector.instance.initializeForProduction(
  minimumLevel: LogLevel.info,
  globalPrefix: 'AMWAL_SDK',
);

2. Basic Logging

// Simple logging
Logar.debug('Debug message');
Logar.info('Info message');
Logar.warning('Warning message');
Logar.error('Error message');
Logar.fatal('Fatal error');

// With tags
Logar.debug('Network request started', tag: 'NETWORK');
Logar.info('User logged in', tag: 'AUTH');

// With additional data
Logar.info('User action', data: {
  'userId': '123',
  'action': 'button_click',
  'timestamp': DateTime.now().toIso8601String(),
});

// With errors and stack traces
try {
  // some code that might throw
} catch (error, stackTrace) {
  Logar.error(
    'Operation failed',
    error: error,
    stackTrace: stackTrace,
    tag: 'BUSINESS_LOGIC',
  );
}

3. Configuration

// Custom configuration
Logar.configure(LogarConfig(
  minimumLevel: LogLevel.warning,
  format: LogFormat.json,
  enabled: true,
  includeStackTrace: true,
  includeTimestamp: true,
  maxMessageLength: 1000,
  globalPrefix: 'MY_APP',
));

// Runtime configuration changes
Logar.setEnabled(false); // Disable logging
Logar.setMinimumLevel(LogLevel.error); // Only log errors and fatal
Logar.setFormat(LogFormat.pretty); // Switch to pretty format

Migration from print() and debugPrint()

Option 1: Drop-in Replacement (Quick Migration)

import 'package:amwal_pay_sdk/core/logger/logger.dart';

// Replace this:
print('Hello World');
debugPrint('Debug info');

// With this:
LogarMigrationHelper.print('Hello World');
LogarMigrationHelper.debugPrint('Debug info');
// Instead of:
print('User clicked button');

// Use:
Logar.info('User clicked button', tag: 'USER_INTERACTION');

// Instead of:
debugPrint('Network response: $response');

// Use:
Logar.debug('Network response received', 
  tag: 'NETWORK', 
  data: {'response': response}
);

Advanced Usage

External Log Collectors

// Add Firebase Crashlytics
await Logar.addCollector(FirebaseCrashlyticsCollector());

// Add custom collector
await Logar.addCollector(CustomLogCollector(
  collectFunction: (entry) async {
    // Send to your custom logging service
    await myLoggingService.send(entry.toJson());
  },
));

Network Logging

// Log network requests
LogarMigrationHelper.logNetworkRequest(
  method: 'POST',
  url: 'https://api.example.com/users',
  headers: {'Authorization': 'Bearer token'},
  body: {'name': 'John'},
);

// Log network responses
LogarMigrationHelper.logNetworkResponse(
  method: 'POST',
  url: 'https://api.example.com/users',
  statusCode: 201,
  responseData: {'id': '123', 'name': 'John'},
);

// Log network errors
LogarMigrationHelper.logNetworkError(
  method: 'POST',
  url: 'https://api.example.com/users',
  error: exception,
  stackTrace: stackTrace,
);

UI Lifecycle Logging

// Log widget lifecycle events
LogarMigrationHelper.logLifecycle(
  widget: 'PaymentScreen',
  event: 'initState',
  data: {'userId': '123'},
);

// Log user interactions
LogarMigrationHelper.logUserInteraction(
  action: 'button_tap',
  widget: 'PayButton',
  data: {'amount': 100.0},
);

Business Logic Logging

// Log business events
LogarMigrationHelper.logBusinessEvent(
  event: 'payment_initiated',
  data: {
    'amount': 100.0,
    'currency': 'USD',
    'paymentMethod': 'card',
  },
);

Log Levels

LevelPriorityUsage
debug0Detailed information for debugging
info1General information about app flow
warning2Warning messages for potential issues
error3Error messages for handled exceptions
fatal4Critical errors that might crash the app

Output Formats

Pretty Format (Development)

[AMWAL_SDK_DEV] [14:30:25.123] [INFO] [NETWORK] Network request started | Data: {"method":"POST","url":"https://api.example.com"}

JSON Format (Production)

{
  "level": "INFO",
  "message": "Network request started",
  "timestamp": "2023-12-07T14:30:25.123Z",
  "tag": "NETWORK",
  "data": {
    "method": "POST",
    "url": "https://api.example.com"
  },
  "prefix": "AMWAL_SDK"
}

Best Practices

1. Use Appropriate Log Levels

// ✅ Good
Logar.debug('Entering function calculateTotal()');
Logar.info('Payment process started');
Logar.warning('Deprecated API endpoint used');
Logar.error('Failed to process payment', error: exception);
Logar.fatal('Critical system failure', error: exception);

// ❌ Bad
Logar.error('User clicked button'); // Should be info
Logar.debug('Payment failed'); // Should be error

2. Use Tags Consistently

// ✅ Good - Consistent tagging
Logar.debug('Request started', tag: 'NETWORK');
Logar.info('Response received', tag: 'NETWORK');
Logar.error('Request failed', tag: 'NETWORK');

// ❌ Bad - Inconsistent tagging
Logar.debug('Request started', tag: 'NETWORK');
Logar.info('Response received', tag: 'HTTP');
Logar.error('Request failed', tag: 'API');

3. Include Relevant Context

// ✅ Good - Rich context
Logar.error(
  'Payment processing failed',
  tag: 'PAYMENT',
  error: exception,
  stackTrace: stackTrace,
  data: {
    'userId': userId,
    'amount': amount,
    'paymentMethod': paymentMethod,
    'transactionId': transactionId,
  },
);

// ❌ Bad - No context
Logar.error('Payment failed');

4. Avoid Logging Sensitive Data

// ✅ Good
Logar.info('User authenticated', data: {
  'userId': userId,
  'loginMethod': 'email',
});

// ❌ Bad - Contains sensitive data
Logar.info('User authenticated', data: {
  'email': 'user@example.com',
  'password': 'secret123', // Never log passwords!
  'creditCard': '1234-5678-9012-3456', // Never log card numbers!
});

Configuration Examples

Development Configuration

LogarInjector.instance.initializeForDevelopment(
  minimumLevel: LogLevel.debug,
  globalPrefix: 'AMWAL_DEV',
);

Production Configuration

LogarInjector.instance.initializeForProduction(
  minimumLevel: LogLevel.warning,
  globalPrefix: 'AMWAL_PROD',
  collectors: [
    FirebaseCrashlyticsCollector(),
    CustomLogCollector(
      collectFunction: (entry) => sendToAnalytics(entry),
    ),
  ],
);

Testing Configuration

Logar.configure(LogarConfig(
  minimumLevel: LogLevel.error,
  format: LogFormat.json,
  enabled: true,
  includeStackTrace: false,
  includeTimestamp: false,
));

Integration with Existing Code

1. Update Dependency Injection

// In your main injector
class AppInjector {
  void initialize() {
    // Initialize Logar first
    LogarInjector.instance.initializeForDevelopment();
    
    // Then initialize other services
    _initializeNetworking();
    _initializeRepositories();
  }
}

2. Update Network Layer

// In your Dio interceptors
class MyLogInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    LogarMigrationHelper.logNetworkRequest(
      method: options.method,
      url: options.uri.toString(),
      headers: options.headers,
      body: options.data,
    );
    super.onRequest(options, handler);
  }
}

3. Update Error Handling

// In your repositories
class PaymentRepository {
  Future<PaymentResult> processPayment(PaymentData data) async {
    try {
      Logar.info('Processing payment', tag: 'PAYMENT', data: {
        'amount': data.amount,
        'currency': data.currency,
      });
      
      final result = await _networkService.processPayment(data);
      
      Logar.info('Payment processed successfully', tag: 'PAYMENT');
      return result;
    } catch (error, stackTrace) {
      Logar.error(
        'Payment processing failed',
        tag: 'PAYMENT',
        error: error,
        stackTrace: stackTrace,
        data: {'amount': data.amount},
      );
      rethrow;
    }
  }
}

Performance Considerations

  1. Conditional Logging: Logar automatically checks log levels before processing
  2. Async Collectors: External collectors run asynchronously to avoid blocking
  3. Memory Management: Log history is limited to 1000 entries
  4. Production Optimization: Use JSON format and higher log levels in production

Troubleshooting

Common Issues

  1. Logs not appearing: Check if logging is enabled and log level is appropriate
  2. Performance issues: Reduce log level or disable verbose logging in production
  3. Memory usage: Clear log history periodically in long-running applications

Debug Configuration

// Enable all logs for debugging
Logar.configure(LogarConfig(
  minimumLevel: LogLevel.debug,
  format: LogFormat.pretty,
  enabled: true,
  includeStackTrace: true,
  includeTimestamp: true,
));

API Reference

See the individual class documentation for detailed API information:

  • Logar - Main logging class
  • LogarConfig - Configuration options
  • LogarInjector - Dependency injection setup
  • LogarMigrationHelper - Migration utilities
  • LogCollector - External collector interface