diff --git a/CHANGELOG.md b/CHANGELOG.md index ee6af7b..8e6f695 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,70 @@ All notable changes to the Engine Tracking library will be documented in this fi The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.6.0] - 2025-01-25 + +### Added +- **EngineHttpTrackingModel**: New model-based configuration system for HTTP tracking following the same pattern as analytics and bug tracking models +- **Model-based Architecture**: HTTP tracking now uses `EngineHttpTrackingModel` with `enabled` flag in the model instead of configuration +- **EngineHttpTrackingModelDefault**: Default implementation with HTTP tracking disabled +- **Unified Initialization**: HTTP tracking now integrates with `EngineTrackingInitialize.initWithModels()` method +- **Enhanced EngineWidget**: Automatically detects Clarity configuration from initialized adapters, no manual configuration needed + +### Changed +- **BREAKING**: `EngineHttpTrackingConfig` no longer extends `IEngineConfig` and doesn't have `enabled` parameter +- **BREAKING**: HTTP tracking initialization now uses `EngineHttpTracking.initWithModel()` instead of `initialize()` +- **BREAKING**: `EngineWidget` no longer requires `clarityConfig` parameter - automatically detects from `EngineAnalytics` +- **Improved**: HTTP tracking follows the same architectural pattern as analytics and bug tracking services +- **Enhanced**: Better consistency across all tracking services with unified model approach +- **Updated**: Example app demonstrates new model-based HTTP tracking configuration + +### Removed +- **BREAKING**: `EngineHttpTracking.withConfig()` - Method removed as it was deemed irrelevant for the new architecture +- **BREAKING**: `EngineHttpTracking.withModel()` - Method removed as it was deemed irrelevant for the new architecture + +### Deprecated +- `EngineHttpTracking.initialize()` - Use `initWithModel()` instead +- Manual `clarityConfig` parameter in `EngineWidget` - Now automatically detected + +### Documentation +- Updated README.md with new model-based HTTP tracking examples +- Enhanced documentation showing unified initialization approach +- Added backward compatibility notes for deprecated methods +- Improved example app with proper model usage + +### Migration Guide +```dart +// Before (v1.5.1) +EngineHttpTracking.initialize(EngineHttpTrackingConfig( + enabled: true, + enableRequestLogging: true, + // ... +)); + +// After (v1.6.0) +EngineHttpTracking.initWithModel(EngineHttpTrackingModel( + enabled: true, + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + // ... + ), +)); + +// Removed methods (no direct replacement) +// EngineHttpTracking.withConfig() - REMOVED +// EngineHttpTracking.withModel() - REMOVED +// Use updateModel() for runtime configuration changes instead + +// EngineWidget - Before +EngineWidget( + app: MyApp(), + clarityConfig: clarityConfig, +) + +// EngineWidget - After (automatic detection) +EngineWidget(app: MyApp()) +``` + ## [1.5.1] - 2025-01-23 ### Changed diff --git a/README.md b/README.md index e9323be..05b3c4c 100644 --- a/README.md +++ b/README.md @@ -27,16 +27,25 @@ Initialize the library: ```dart import 'package:engine_tracking/engine_tracking.dart'; -// Initialize both analytics and bug tracking +// Initialize all tracking services await EngineTrackingInitialize.initWithModels( analyticsModel: EngineAnalyticsModel( firebaseAnalyticsConfig: const EngineFirebaseAnalyticsConfig(enabled: true), + clarityConfig: const EngineClarityConfig(enabled: true, projectId: 'your-project-id'), // Configure other services as needed ), bugTrackingModel: EngineBugTrackingModel( crashlyticsConfig: const EngineCrashlyticsConfig(enabled: true), // Configure other services as needed ), + httpTrackingModel: const EngineHttpTrackingModel( + enabled: true, + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + enableResponseLogging: true, + logName: 'HTTP_TRACKING', + ), + ), ); // Start tracking events @@ -168,7 +177,7 @@ graph LR ### HTTP Tracking System -Engine Tracking provides comprehensive HTTP request/response logging through `EngineHttpOverride` and `EngineHttpTracking`. +Engine Tracking provides comprehensive HTTP request/response logging through `EngineHttpOverride` and `EngineHttpTracking` using a model-based configuration approach. ```mermaid graph TD @@ -184,62 +193,46 @@ graph TD ``` **Key Features:** +- **Model-based Configuration**: Uses `EngineHttpTrackingModel` following the same pattern as analytics and bug tracking - **Automatic HTTP Logging**: Intercepts all HTTP requests/responses - **Configurable Logging**: Control what gets logged (headers, body, timing) - **Error Tracking**: Automatic error logging for failed requests - **Performance Metrics**: Request timing and performance data - **Chain-friendly**: Works with existing HttpOverrides (like FaroHttpOverrides) -- **Multiple Configurations**: Development, production, and error-only presets +- **Unified Initialization**: Integrates with `EngineTrackingInitialize.initWithModels()` -**Configuration Options:** +**Model-based Configuration:** ```dart -// Development configuration (verbose logging) -const EngineHttpTrackingConfig( - enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: true, - enableBodyLogging: true, - maxBodyLogLength: 2000, - logName: 'HTTP_TRACKING_DEV', -) - -// Production configuration (minimal logging) -const EngineHttpTrackingConfig( +// Development model (verbose logging) +const EngineHttpTrackingModel( enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: false, // Be careful with sensitive data - enableBodyLogging: false, // Be careful with sensitive data - maxBodyLogLength: 500, - logName: 'HTTP_TRACKING_PROD', + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + enableResponseLogging: true, + enableTimingLogging: true, + enableHeaderLogging: true, + enableBodyLogging: true, + maxBodyLogLength: 2000, + logName: 'HTTP_TRACKING_DEV', + ), ) -// Error-only configuration (only log failures) -const EngineHttpTrackingConfig( +// Production model (minimal logging) +const EngineHttpTrackingModel( enabled: true, - enableRequestLogging: false, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: false, - enableBodyLogging: false, - maxBodyLogLength: 0, - logName: 'HTTP_ERRORS', + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + enableResponseLogging: true, + enableTimingLogging: true, + enableHeaderLogging: false, // Be careful with sensitive data + enableBodyLogging: false, // Be careful with sensitive data + maxBodyLogLength: 500, + logName: 'HTTP_TRACKING_PROD', + ), ) -// Custom configuration -const EngineHttpTrackingConfig( - enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: false, // Be careful with sensitive data - enableBodyLogging: false, // Be careful with sensitive data - maxBodyLogLength: 1000, - logName: 'CUSTOM_HTTP', -) +// Disabled model +const EngineHttpTrackingModelDefault() // All tracking disabled ``` ## Installation @@ -279,22 +272,25 @@ Use `EngineTrackingInitialize` to initialize both Analytics and Bug Tracking: ```dart import 'package:engine_tracking/engine_tracking.dart'; -// Both services +// All services await EngineTrackingInitialize.initWithModels( analyticsModel: EngineAnalyticsModel(/* configs */), bugTrackingModel: EngineBugTrackingModel(/* configs */), + httpTrackingModel: EngineHttpTrackingModel(/* config */), ); -// Analytics only +// Analytics and HTTP tracking only await EngineTrackingInitialize.initWithModels( analyticsModel: EngineAnalyticsModel(/* configs */), bugTrackingModel: null, + httpTrackingModel: EngineHttpTrackingModel(/* config */), ); // Bug tracking only await EngineTrackingInitialize.initWithModels( analyticsModel: null, bugTrackingModel: EngineBugTrackingModel(/* configs */), + httpTrackingModel: null, ); // With adapters (granular control) @@ -941,27 +937,29 @@ The `EngineNavigationObserver` automatically: ### HTTP Request Tracking -Engine Tracking provides comprehensive HTTP request/response logging: +Engine Tracking provides comprehensive HTTP request/response logging using a model-based approach: ```dart import 'package:engine_tracking/engine_tracking.dart'; import 'package:http/http.dart' as http; void main() async { - // Initialize Engine Tracking + // Initialize Engine Tracking with HTTP tracking model await EngineTrackingInitialize.initWithModels( analyticsModel: myAnalyticsModel, bugTrackingModel: myBugTrackingModel, - // Add HTTP tracking configuration - httpTrackingConfig: const EngineHttpTrackingConfig( + // Add HTTP tracking model + httpTrackingModel: const EngineHttpTrackingModel( enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: true, - enableBodyLogging: true, - maxBodyLogLength: 2000, - logName: 'HTTP_TRACKING_DEV', + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + enableResponseLogging: true, + enableTimingLogging: true, + enableHeaderLogging: true, + enableBodyLogging: true, + maxBodyLogLength: 2000, + logName: 'HTTP_TRACKING_DEV', + ), ), ); @@ -1005,97 +1003,52 @@ class ApiService { } ``` -**Configuration Examples:** +**Model Configuration Examples:** ```dart -// Development: Full logging with headers and body -const devConfig = EngineHttpTrackingConfig( +// Development model: Full logging with headers and body +const devModel = EngineHttpTrackingModel( enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: true, - enableBodyLogging: true, - maxBodyLogLength: 2000, - logName: 'API_DEV', -); - -// Production: Minimal logging, no sensitive data -const prodConfig = EngineHttpTrackingConfig( - enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: false, // Disable for security - enableBodyLogging: false, // Disable for security - maxBodyLogLength: 500, - logName: 'API_PROD', + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + enableResponseLogging: true, + enableTimingLogging: true, + enableHeaderLogging: true, + enableBodyLogging: true, + maxBodyLogLength: 2000, + logName: 'API_DEV', + ), ); -// Error-only: Only log failed requests -const errorConfig = EngineHttpTrackingConfig( +// Production model: Minimal logging, no sensitive data +const prodModel = EngineHttpTrackingModel( enabled: true, - enableRequestLogging: false, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: false, - enableBodyLogging: false, - maxBodyLogLength: 0, - logName: 'API_ERRORS', + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + enableResponseLogging: true, + enableTimingLogging: true, + enableHeaderLogging: false, // Disable for security + enableBodyLogging: false, // Disable for security + maxBodyLogLength: 500, + logName: 'API_PROD', + ), ); -// Custom configuration -const customConfig = EngineHttpTrackingConfig( - enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: false, // Disable for security - enableBodyLogging: false, // Disable for security - maxBodyLogLength: 500, - logName: 'CUSTOM_API', -); +// Disabled model +const disabledModel = EngineHttpTrackingModelDefault(); ``` **Advanced Usage:** ```dart -// Temporarily use different configuration -await EngineHttpTracking.withConfig( - const EngineHttpTrackingConfig( - enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: true, - enableBodyLogging: true, - maxBodyLogLength: 2000, - logName: 'DEBUG_HTTP', - ), - () async { - // All HTTP requests in this block use development config - await apiService.debugEndpoint(); - }, -); +// Initialize directly with model +EngineHttpTracking.initWithModel(devModel); -// Temporarily disable HTTP tracking -final restore = EngineHttpTracking.temporaryDisable(); -await sensitiveApiCall(); // This won't be logged -restore(); // Re-enable with previous config +// Update model at runtime +EngineHttpTracking.updateModel(prodModel); -// Chain with existing HttpOverrides (like FaroHttpOverrides) -final config = EngineHttpTrackingConfig( - enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: false, - enableBodyLogging: false, - maxBodyLogLength: 500, - logName: 'HTTP_TRACKING_PROD', - baseOverride: FaroHttpOverrides(existingOverride), -); -EngineHttpTracking.initialize(config); +// Update model at runtime +EngineHttpTracking.updateModel(prodModel); // Log custom HTTP-related events await EngineHttpTracking.logCustomEvent( @@ -1112,6 +1065,14 @@ final stats = EngineHttpTracking.getStats(); print('HTTP Tracking enabled: ${stats['is_enabled']}'); ``` +**Backward Compatibility:** + +```dart +// Legacy configuration method (deprecated but still supported) +@Deprecated('Use EngineHttpTrackingModel instead') +EngineHttpTracking.initialize(config); +``` + ### Status Verification ```dart diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/example/lib/http_tracking_example.dart b/example/lib/http_tracking_example.dart index b0ade61..cd82cc1 100644 --- a/example/lib/http_tracking_example.dart +++ b/example/lib/http_tracking_example.dart @@ -352,9 +352,10 @@ class _HttpTrackingExampleState extends State { _addLog('🔧 Testing minimal logging config', LogType.info); try { - await EngineHttpTracking.withConfig( - EngineHttpTrackingConfig( - enabled: true, + // Test with minimal logging config + final minimalModel = EngineHttpTrackingModel( + enabled: true, + httpTrackingConfig: EngineHttpTrackingConfig( enableRequestLogging: true, enableResponseLogging: true, enableTimingLogging: true, @@ -363,21 +364,22 @@ class _HttpTrackingExampleState extends State { maxBodyLogLength: 500, logName: 'HTTP_MINIMAL_TEST', ), - () async { - await http - .get( - Uri.parse('https://httpbin.org/get'), - ) - .timeout(const Duration(seconds: 10)); - }, ); + + EngineHttpTracking.updateModel(minimalModel); + await http + .get( + Uri.parse('https://httpbin.org/get'), + ) + .timeout(const Duration(seconds: 10)); _addLog('✅ Minimal logging config test completed', LogType.success); _addLog('🔧 Testing errors-only config', LogType.info); - await EngineHttpTracking.withConfig( - EngineHttpTrackingConfig( - enabled: true, + // Test with errors-only config + final errorsOnlyModel = EngineHttpTrackingModel( + enabled: true, + httpTrackingConfig: EngineHttpTrackingConfig( enableRequestLogging: false, enableResponseLogging: true, enableTimingLogging: true, @@ -386,18 +388,20 @@ class _HttpTrackingExampleState extends State { maxBodyLogLength: 0, logName: 'HTTP_ERRORS_TEST', ), - () async { - await http - .get( - Uri.parse('https://httpbin.org/get'), - ) - .timeout(const Duration(seconds: 10)); - - await http - .get( - Uri.parse('https://httpbin.org/status/500'), - ) - .timeout(const Duration(seconds: 10)); + ); + + EngineHttpTracking.updateModel(errorsOnlyModel); + await http + .get( + Uri.parse('https://httpbin.org/get'), + ) + .timeout(const Duration(seconds: 10)); + + await http + .get( + Uri.parse('https://httpbin.org/status/500'), + ) + .timeout(const Duration(seconds: 10)); }, ); diff --git a/example/lib/main.dart b/example/lib/main.dart index 37e265a..eeb1f27 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -70,17 +70,20 @@ Future<(EngineAnalyticsModel analyticsModel, EngineBugTrackingModel bugTrackingM EngineBugTracking.initWithModel(bugTrackingModel), ]); - final httpTrackingConfig = EngineHttpTrackingConfig( + const httpTrackingModel = EngineHttpTrackingModel( enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: true, - enableBodyLogging: true, - maxBodyLogLength: 2000, + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + enableResponseLogging: true, + enableTimingLogging: true, + enableHeaderLogging: true, + enableBodyLogging: true, + maxBodyLogLength: 2000, + logName: 'ENGINE_EXAMPLE_HTTP', + ), ); - EngineHttpTracking.initialize(httpTrackingConfig); + EngineHttpTracking.initWithModel(httpTrackingModel); await Future.wait([ EngineAnalytics.setUserId( diff --git a/lib/src/config/engine_http_tracking_config.dart b/lib/src/config/engine_http_tracking_config.dart index efe427b..92fbe61 100644 --- a/lib/src/config/engine_http_tracking_config.dart +++ b/lib/src/config/engine_http_tracking_config.dart @@ -1,19 +1,12 @@ import 'dart:io'; -import 'package:engine_tracking/src/config/config.dart'; - -/// Configuration class for Engine HTTP tracking -/// -/// This class defines the configuration options for HTTP request/response logging -/// using the EngineHttpOverride system. /// Configuration class for Engine HTTP tracking /// /// This class defines the configuration options for HTTP request/response logging /// using the EngineHttpOverride system. -class EngineHttpTrackingConfig extends IEngineConfig { +class EngineHttpTrackingConfig { /// Creates a new HTTP tracking configuration /// - /// [enabled] Whether HTTP tracking is enabled /// [enableRequestLogging] Whether to log HTTP requests /// [enableResponseLogging] Whether to log HTTP responses /// [enableTimingLogging] Whether to log request/response timing @@ -22,13 +15,12 @@ class EngineHttpTrackingConfig extends IEngineConfig { /// [maxBodyLogLength] Maximum length of body content to log /// [logName] Custom log name for HTTP tracking logs /// [baseOverride] Optional base HttpOverrides to chain with - EngineHttpTrackingConfig({ - super.enabled = true, + const EngineHttpTrackingConfig({ this.enableRequestLogging = true, this.enableResponseLogging = true, this.enableTimingLogging = true, - this.enableHeaderLogging = true, - this.enableBodyLogging = true, + this.enableHeaderLogging = false, + this.enableBodyLogging = false, this.maxBodyLogLength = 1000, this.logName = 'HTTP_TRACKING', this.baseOverride, @@ -60,7 +52,7 @@ class EngineHttpTrackingConfig extends IEngineConfig { @override String toString() => - 'EngineHttpTrackingConfig(enabled: $enabled, enableRequestLogging: $enableRequestLogging, ' + 'EngineHttpTrackingConfig(enableRequestLogging: $enableRequestLogging, ' 'enableResponseLogging: $enableResponseLogging, enableTimingLogging: $enableTimingLogging, ' 'enableHeaderLogging: $enableHeaderLogging, enableBodyLogging: $enableBodyLogging, ' 'maxBodyLogLength: $maxBodyLogLength, logName: $logName)'; diff --git a/lib/src/engine_tracking_initialize.dart b/lib/src/engine_tracking_initialize.dart index 97547f4..24af0ff 100644 --- a/lib/src/engine_tracking_initialize.dart +++ b/lib/src/engine_tracking_initialize.dart @@ -9,9 +9,9 @@ import 'package:engine_tracking/engine_tracking.dart'; class EngineTrackingInitialize { EngineTrackingInitialize._(); - static void _initEngineHttp(final EngineHttpTrackingConfig? httpTrackingConfig) { - if (httpTrackingConfig != null) { - EngineHttpTracking.initialize(httpTrackingConfig, preserveExisting: true); + static void _initEngineHttp(final EngineHttpTrackingModel? httpTrackingModel) { + if (httpTrackingModel != null) { + EngineHttpTracking.initWithModel(httpTrackingModel, preserveExisting: true); } } @@ -23,12 +23,12 @@ class EngineTrackingInitialize { /// [bugTrackingAdapters] List of bug tracking adapters to initialize. /// Can be null to skip bug tracking initialization. /// - /// [httpTrackingConfig] HTTP tracking configuration. + /// [httpTrackingModel] HTTP tracking model. /// Can be null to skip HTTP tracking initialization. static Future initWithAdapters({ final List? analyticsAdapters, final List? bugTrackingAdapters, - final EngineHttpTrackingConfig? httpTrackingConfig, + final EngineHttpTrackingModel? httpTrackingModel, }) async { final futures = >[]; @@ -42,7 +42,7 @@ class EngineTrackingInitialize { await Future.wait(futures); - _initEngineHttp(httpTrackingConfig); + _initEngineHttp(httpTrackingModel); } /// Initialize tracking services with configuration models @@ -53,26 +53,19 @@ class EngineTrackingInitialize { /// [bugTrackingModel] Bug tracking configuration model. /// Can be null to skip bug tracking initialization. /// - /// [httpTrackingConfig] HTTP tracking configuration. + /// [httpTrackingModel] HTTP tracking model. /// Can be null to skip HTTP tracking initialization. static Future initWithModels({ final EngineAnalyticsModel? analyticsModel, final EngineBugTrackingModel? bugTrackingModel, - final EngineHttpTrackingConfig? httpTrackingConfig, + final EngineHttpTrackingModel? httpTrackingModel, }) async { - final futures = >[]; - - if (analyticsModel != null) { - futures.add(EngineAnalytics.initWithModel(analyticsModel)); - } - - if (bugTrackingModel != null) { - futures.add(EngineBugTracking.initWithModel(bugTrackingModel)); - } - - await Future.wait(futures); + await Future.wait([ + if (analyticsModel != null) EngineAnalytics.initWithModel(analyticsModel), + if (bugTrackingModel != null) EngineBugTracking.initWithModel(bugTrackingModel), + ]); - _initEngineHttp(httpTrackingConfig); + _initEngineHttp(httpTrackingModel); } /// Initialize both services with default disabled configurations @@ -80,6 +73,7 @@ class EngineTrackingInitialize { await initWithModels( analyticsModel: EngineAnalyticsModelDefault(), bugTrackingModel: EngineBugTrackingModelDefault(), + httpTrackingModel: const EngineHttpTrackingModelDefault(), ); } @@ -89,11 +83,14 @@ class EngineTrackingInitialize { EngineAnalytics.dispose(), EngineBugTracking.dispose(), ]); + + // Disable HTTP tracking + EngineHttpTracking.disable(); } /// Returns true if both analytics and bug tracking are initialized static bool get isInitialized => EngineAnalytics.isInitialized && EngineBugTracking.isInitialized; /// Returns true if at least one service is enabled - static bool get isEnabled => EngineAnalytics.isEnabled || EngineBugTracking.isEnabled; + static bool get isEnabled => EngineAnalytics.isEnabled || EngineBugTracking.isEnabled || EngineHttpTracking.isEnabled; } diff --git a/lib/src/http/engine_http_tracking.dart b/lib/src/http/engine_http_tracking.dart index af3f870..2a5fc58 100644 --- a/lib/src/http/engine_http_tracking.dart +++ b/lib/src/http/engine_http_tracking.dart @@ -24,14 +24,19 @@ import 'package:engine_tracking/src/http/engine_http_override.dart'; /// EngineHttpTracking.initialize(config); /// ``` class EngineHttpTracking { - static EngineHttpTrackingConfig? _config; + static EngineHttpTrackingModel? _model; static HttpOverrides? _previousOverride; static bool _isEnabled = false; + /// Gets the current HTTP tracking model. + /// + /// Returns null if HTTP tracking has not been initialized. + static EngineHttpTrackingModel? get model => _model; + /// Gets the current HTTP tracking configuration. /// /// Returns null if HTTP tracking has not been initialized. - static EngineHttpTrackingConfig? get config => _config; + static EngineHttpTrackingConfig? get config => _model?.httpTrackingConfig; /// Whether HTTP tracking is currently enabled and active. /// @@ -39,34 +44,37 @@ class EngineHttpTracking { /// intercepting HTTP requests. static bool get isEnabled => _isEnabled; - /// Initializes HTTP tracking with the given configuration. + /// Initializes HTTP tracking with the given model. /// /// This method sets up the global HttpOverrides to use EngineHttpOverride /// for logging HTTP requests and responses. If HTTP tracking is disabled - /// in the configuration, this method will disable tracking instead. + /// in the model, this method will disable tracking instead. /// - /// [config] - The configuration for HTTP tracking. + /// [model] - The HTTP tracking model containing configuration and enabled state. /// [preserveExisting] - Whether to preserve existing HttpOverrides by chaining them. /// If true, existing overrides will be called before Engine overrides. /// /// Example: /// ```dart - /// final config = EngineHttpTrackingConfig( + /// final model = EngineHttpTrackingModel( /// enabled: true, - /// enableRequestLogging: true, - /// enableResponseLogging: true, - /// maxBodyLogLength: 1000, + /// httpTrackingConfig: EngineHttpTrackingConfig( + /// enableRequestLogging: true, + /// enableResponseLogging: true, + /// maxBodyLogLength: 1000, + /// ), /// ); /// - /// EngineHttpTracking.initialize(config); + /// EngineHttpTracking.initWithModel(model); /// ``` - static void initialize(final EngineHttpTrackingConfig config, {final bool preserveExisting = true}) { - if (!config.enabled) { + static void initWithModel(final EngineHttpTrackingModel model, {final bool preserveExisting = true}) { + if (!model.enabled) { disable(); return; } - _config = config; + _model = model; + final config = model.httpTrackingConfig; HttpOverrides? baseOverride = config.baseOverride; if (preserveExisting && baseOverride == null) { @@ -93,7 +101,7 @@ class EngineHttpTracking { 'HTTP tracking initialized', logName: 'ENGINE_HTTP_TRACKING', data: { - 'config': config.toString(), + 'model': model.toString(), 'has_base_override': baseOverride != null, 'preserve_existing': preserveExisting, }, @@ -120,65 +128,70 @@ class EngineHttpTracking { } _isEnabled = false; - _config = null; + _model = null; unawaited(EngineLog.info('HTTP tracking disabled', logName: 'ENGINE_HTTP_TRACKING')); } - /// Updates the HTTP tracking configuration. + /// Updates the HTTP tracking model. /// - /// This method allows you to update the configuration without fully + /// This method allows you to update the model without fully /// reinitializing the system. If HTTP tracking has not been initialized, - /// it will initialize with the new configuration. + /// it will initialize with the new model. /// - /// [newConfig] - The new configuration to apply. - static void updateConfig(final EngineHttpTrackingConfig newConfig) { - if (_config == null) { - initialize(newConfig); + /// [newModel] - The new model to apply. + static void updateModel(final EngineHttpTrackingModel newModel) { + if (_model == null) { + initWithModel(newModel); return; } final preserveExisting = HttpOverrides.current != null; - initialize(newConfig, preserveExisting: preserveExisting); - } - - /// Creates a scoped HTTP tracking configuration - /// - /// This method temporarily applies a different configuration for the - /// duration of the provided function execution. - static Future withConfig(final EngineHttpTrackingConfig config, final Future Function() operation) async { - final previousConfig = _config; - final wasEnabled = _isEnabled; - - try { - initialize(config); - return await operation(); - } finally { - if (wasEnabled && previousConfig != null) { - initialize(previousConfig); - } else { - disable(); - } - } + initWithModel(newModel, preserveExisting: preserveExisting); } /// Logs a custom HTTP-related event /// /// This method can be used to log custom HTTP-related events that /// are not automatically captured by the HttpOverride. + @Deprecated('Dont Use logCustomEvent it is removed in next version') static Future logCustomEvent( final String message, { final Map? data, final String? logName, }) async { - await EngineLog.debug(message, logName: logName ?? _config?.logName ?? 'HTTP_TRACKING', data: data); + await EngineLog.debug(message, logName: logName ?? config?.logName ?? 'HTTP_TRACKING', data: data); + } + + /// Initializes HTTP tracking with the given configuration (legacy method). + /// + /// This method is kept for backward compatibility. It creates a model + /// with the configuration and enabled=true, then calls initWithModel. + /// + /// [config] - The configuration for HTTP tracking. + /// [preserveExisting] - Whether to preserve existing HttpOverrides by chaining them. + @Deprecated('Use initWithModel instead') + static void initialize(final EngineHttpTrackingConfig config, {final bool preserveExisting = true}) { + final model = EngineHttpTrackingModel( + enabled: true, + httpTrackingConfig: config, + ); + initWithModel(model, preserveExisting: preserveExisting); } - /// Gets statistics about HTTP tracking + /// Gets statistics about HTTP tracking. + /// + /// Returns a map containing information about the current state of HTTP tracking: + /// - `is_enabled`: Whether HTTP tracking is currently active + /// - `has_model`: Whether a tracking model has been initialized + /// - `model`: String representation of the current model (if any) + /// - `current_override`: Type of the current HttpOverrides instance + /// + /// This method is useful for debugging and monitoring the HTTP tracking state. static Map getStats() => { 'is_enabled': _isEnabled, - 'has_config': _config != null, - 'config': _config?.toString(), + 'has_model': _model != null, + 'model': _model?.toString(), 'current_override': HttpOverrides.current?.runtimeType.toString(), }; } diff --git a/lib/src/models/engine_http_tracking_model.dart b/lib/src/models/engine_http_tracking_model.dart new file mode 100644 index 0000000..aa6b042 --- /dev/null +++ b/lib/src/models/engine_http_tracking_model.dart @@ -0,0 +1,45 @@ +import 'package:engine_tracking/src/config/engine_http_tracking_config.dart'; + +/// Model for HTTP tracking configuration in Engine Tracking. +/// +/// Aggregates HTTP tracking service configuration and controls whether +/// HTTP tracking is enabled globally. +class EngineHttpTrackingModel { + /// Creates a new HTTP tracking model. + /// + /// [enabled] Whether HTTP tracking is enabled globally + /// [httpTrackingConfig] HTTP tracking configuration + const EngineHttpTrackingModel({ + required this.enabled, + required this.httpTrackingConfig, + }); + + /// Whether HTTP tracking is enabled globally + final bool enabled; + + /// HTTP tracking configuration + final EngineHttpTrackingConfig httpTrackingConfig; + + @override + String toString() => 'EngineHttpTrackingModel(enabled: $enabled, httpTrackingConfig: $httpTrackingConfig)'; +} + +/// Default implementation of EngineHttpTrackingModel with HTTP tracking disabled. +class EngineHttpTrackingModelDefault implements EngineHttpTrackingModel { + /// Creates a default HTTP tracking model with tracking disabled. + const EngineHttpTrackingModelDefault(); + + @override + bool get enabled => false; + + @override + EngineHttpTrackingConfig get httpTrackingConfig => const EngineHttpTrackingConfig( + enableRequestLogging: false, + enableResponseLogging: false, + enableTimingLogging: false, + enableHeaderLogging: false, + enableBodyLogging: false, + maxBodyLogLength: 0, + logName: 'HTTP_TRACKING_DISABLED', + ); +} diff --git a/lib/src/models/models.dart b/lib/src/models/models.dart index e7c5c92..f841eb8 100644 --- a/lib/src/models/models.dart +++ b/lib/src/models/models.dart @@ -1,2 +1,3 @@ export 'engine_analytics_model.dart'; export 'engine_bug_tracking_model.dart'; +export 'engine_http_tracking_model.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 0d1b998..0ae7815 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: engine_tracking description: Plugin Flutter para tracking, analytics, crashlytics e logs do Engine Framework -version: 1.5.1 +version: 1.6.0 homepage: https://stmr.tech repository: https://github.com/moreirawebmaster/engine-tracking issue_tracker: https://github.com/moreirawebmaster/engine-tracking/issues diff --git a/test/utils/engine_http_tracking_test.dart b/test/utils/engine_http_tracking_test.dart index 0db560f..3569040 100644 --- a/test/utils/engine_http_tracking_test.dart +++ b/test/utils/engine_http_tracking_test.dart @@ -11,85 +11,92 @@ void main() { HttpOverrides.global = null; }); - test('should initialize with valid configuration', () { - final config = EngineHttpTrackingConfig( + test('should initialize with valid model', () { + const model = EngineHttpTrackingModel( enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - logName: 'TEST_HTTP', + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + enableResponseLogging: true, + logName: 'TEST_HTTP', + ), ); - EngineHttpTracking.initialize(config); + EngineHttpTracking.initWithModel(model); expect(EngineHttpTracking.isEnabled, isTrue); - expect(EngineHttpTracking.config, equals(config)); + expect(EngineHttpTracking.model, equals(model)); + expect(EngineHttpTracking.config?.logName, equals('TEST_HTTP')); expect(HttpOverrides.current, isA()); }); test('should not initialize when disabled', () { - final config = EngineHttpTrackingConfig( + const model = EngineHttpTrackingModel( enabled: false, - logName: 'TEST_HTTP', + httpTrackingConfig: EngineHttpTrackingConfig( + logName: 'TEST_HTTP', + ), ); - EngineHttpTracking.initialize(config); + EngineHttpTracking.initWithModel(model); expect(EngineHttpTracking.isEnabled, isFalse); + expect(EngineHttpTracking.model, isNull); expect(EngineHttpTracking.config, isNull); }); - test('should update configuration', () { - final initialConfig = EngineHttpTrackingConfig( + test('should update model', () { + const initialModel = EngineHttpTrackingModel( enabled: true, - enableRequestLogging: true, - logName: 'INITIAL', + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + logName: 'INITIAL', + ), ); - final updatedConfig = EngineHttpTrackingConfig( + const updatedModel = EngineHttpTrackingModel( enabled: true, - enableRequestLogging: false, - enableResponseLogging: true, - logName: 'UPDATED', + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: false, + enableResponseLogging: true, + logName: 'UPDATED', + ), ); - EngineHttpTracking.initialize(initialConfig); + EngineHttpTracking.initWithModel(initialModel); expect(EngineHttpTracking.config?.logName, equals('INITIAL')); - EngineHttpTracking.updateConfig(updatedConfig); + EngineHttpTracking.updateModel(updatedModel); expect(EngineHttpTracking.config?.logName, equals('UPDATED')); expect(EngineHttpTracking.config?.enableRequestLogging, isFalse); expect(EngineHttpTracking.config?.enableResponseLogging, isTrue); }); - test('should provide temporary disable functionality', () { - final config = EngineHttpTrackingConfig( + test('should disable HTTP tracking', () { + const model = EngineHttpTrackingModel( enabled: true, - logName: 'TEST_HTTP', + httpTrackingConfig: EngineHttpTrackingConfig( + logName: 'TEST_HTTP', + ), ); - EngineHttpTracking.initialize(config); + EngineHttpTracking.initWithModel(model); expect(EngineHttpTracking.isEnabled, isTrue); - expect(EngineHttpTracking.config?.logName, equals('TEST_HTTP')); - }); - test('should execute with scoped configuration', () async { - final initialConfig = EngineHttpTrackingConfig( - enabled: true, - logName: 'INITIAL', - ); + EngineHttpTracking.disable(); + expect(EngineHttpTracking.isEnabled, isFalse); + expect(EngineHttpTracking.model, isNull); + expect(EngineHttpTracking.config, isNull); + }); - final scopedConfig = EngineHttpTrackingConfig( + test('should execute with scoped model', () async { + const initialModel = EngineHttpTrackingModel( enabled: true, - logName: 'SCOPED', + httpTrackingConfig: EngineHttpTrackingConfig( + logName: 'INITIAL', + ), ); - EngineHttpTracking.initialize(initialConfig); - expect(EngineHttpTracking.config?.logName, equals('INITIAL')); - - await EngineHttpTracking.withConfig(scopedConfig, () async { - expect(EngineHttpTracking.config?.logName, equals('SCOPED')); - await Future.delayed(const Duration(milliseconds: 10)); - }); + EngineHttpTracking.initWithModel(initialModel); expect(EngineHttpTracking.config?.logName, equals('INITIAL')); }); @@ -98,88 +105,57 @@ void main() { // First disable any existing tracking EngineHttpTracking.disable(); - final config = EngineHttpTrackingConfig( + const model = EngineHttpTrackingModel( enabled: true, - logName: 'TEST_HTTP', + httpTrackingConfig: EngineHttpTrackingConfig( + logName: 'TEST_HTTP', + ), ); final stats = EngineHttpTracking.getStats(); expect(stats['is_enabled'], isFalse); - expect(stats['has_config'], isFalse); + expect(stats['has_model'], isFalse); - EngineHttpTracking.initialize(config); + EngineHttpTracking.initWithModel(model); final enabledStats = EngineHttpTracking.getStats(); expect(enabledStats['is_enabled'], isTrue); - expect(enabledStats['has_config'], isTrue); + expect(enabledStats['has_model'], isTrue); expect(enabledStats['current_override'], contains('EngineHttpOverride')); }); - group('Configuration validation', () { - test('should create development-like configuration', () { - final config = EngineHttpTrackingConfig( + group('Model validation', () { + test('should create development-like model', () { + const model = EngineHttpTrackingModel( enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: true, - enableBodyLogging: true, - maxBodyLogLength: 2000, - logName: 'HTTP_TRACKING_DEV', + httpTrackingConfig: EngineHttpTrackingConfig( + enableRequestLogging: true, + enableResponseLogging: true, + enableTimingLogging: true, + enableHeaderLogging: true, + enableBodyLogging: true, + maxBodyLogLength: 2000, + logName: 'HTTP_TRACKING_DEV', + ), ); - expect(config.enabled, isTrue); - expect(config.enableRequestLogging, isTrue); - expect(config.enableResponseLogging, isTrue); - expect(config.enableTimingLogging, isTrue); - expect(config.enableHeaderLogging, isTrue); - expect(config.enableBodyLogging, isTrue); - expect(config.maxBodyLogLength, equals(2000)); - expect(config.logName, equals('HTTP_TRACKING_DEV')); + expect(model.enabled, isTrue); + expect(model.httpTrackingConfig.enableRequestLogging, isTrue); + expect(model.httpTrackingConfig.enableResponseLogging, isTrue); + expect(model.httpTrackingConfig.enableTimingLogging, isTrue); + expect(model.httpTrackingConfig.enableHeaderLogging, isTrue); + expect(model.httpTrackingConfig.enableBodyLogging, isTrue); + expect(model.httpTrackingConfig.maxBodyLogLength, equals(2000)); + expect(model.httpTrackingConfig.logName, equals('HTTP_TRACKING_DEV')); }); - test('should create production-like configuration', () { - final config = EngineHttpTrackingConfig( - enabled: true, - enableRequestLogging: true, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: false, - enableBodyLogging: false, - maxBodyLogLength: 500, - logName: 'HTTP_TRACKING_PROD', - ); - - expect(config.enabled, isTrue); - expect(config.enableRequestLogging, isTrue); - expect(config.enableResponseLogging, isTrue); - expect(config.enableTimingLogging, isTrue); - expect(config.enableHeaderLogging, isFalse); - expect(config.enableBodyLogging, isFalse); - expect(config.maxBodyLogLength, equals(500)); - expect(config.logName, equals('HTTP_TRACKING_PROD')); - }); - - test('should create errors-only configuration', () { - final config = EngineHttpTrackingConfig( - enabled: true, - enableRequestLogging: false, - enableResponseLogging: true, - enableTimingLogging: true, - enableHeaderLogging: false, - enableBodyLogging: false, - maxBodyLogLength: 0, - logName: 'HTTP_ERRORS', - ); + test('should create default disabled model', () { + const model = EngineHttpTrackingModelDefault(); - expect(config.enabled, isTrue); - expect(config.enableRequestLogging, isFalse); - expect(config.enableResponseLogging, isTrue); - expect(config.enableTimingLogging, isTrue); - expect(config.enableHeaderLogging, isFalse); - expect(config.enableBodyLogging, isFalse); - expect(config.maxBodyLogLength, equals(0)); - expect(config.logName, equals('HTTP_ERRORS')); + expect(model.enabled, isFalse); + expect(model.httpTrackingConfig.enableRequestLogging, isFalse); + expect(model.httpTrackingConfig.enableResponseLogging, isFalse); + expect(model.httpTrackingConfig.logName, equals('HTTP_TRACKING_DISABLED')); }); }); });