engine_tracking 1.5.0
engine_tracking: ^1.5.0 copied to clipboard
Plugin Flutter para tracking, analytics, crashlytics e logs do Engine Framework
Engine Tracking #
📋 Sobre o Projeto #
Uma biblioteca Flutter completa para tracking de analytics e bug reporting, oferecendo integração com Firebase Analytics, Firebase Crashlytics, Microsoft Clarity, Grafana Faro, Splunk e Google Cloud Logging.
📱 Plataformas Suportadas #
- ✅ iOS
- ✅ Android
🚀 Principais Características #
- 📊 Analytics Múltiplo: Firebase Analytics, Microsoft Clarity, Grafana Faro, Splunk e Google Cloud Logging
- 🐛 Bug Tracking Avançado: Firebase Crashlytics, Grafana Faro e Google Cloud Logging para monitoramento completo
- 🌐 HTTP Tracking: Monitoramento automático de requisições HTTPS com métricas detalhadas
- 👁️ View Tracking: Sistema automático de tracking de telas com
EngineStatelessWidget
eEngineStatefulWidget
- ⚙️ Configuração Flexível: Ative/desative serviços individualmente através de configurações
- 📝 Logging Estruturado: Sistema de logs com diferentes níveis e contextos
- 🆔 Session ID Automático: UUID v4 único por abertura do app para correlação de logs e analytics
- 🔒 Tipo-seguro: Implementação completamente tipada em Dart
- 🧪 Testável: Cobertura de testes superior a 95% para componentes testáveis
- 🏗️ Arquitetura Consistente: Padrão unificado entre Analytics e Bug Tracking
- 🎯 Inicialização Condicional: Serviços são inicializados apenas se habilitados na configuração
- 📦 Export Unificado: Todos os imports através de
package:engine_tracking/engine_tracking.dart
- 🚀 Exemplos Completos: Apps de demonstração com casos de uso reais (HTTP + View Tracking)
🗺️ Arquitetura da Solução #
🆔 Sistema de Session ID (Correlação Automática) #
graph TD
A["App Initialization"] --> B["EngineSession.instance"]
B --> C["Generate UUID v4"]
C --> D["xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"]
D --> E["Session ID em Memória"]
E --> F["Auto-inject Automático"]
G["EngineAnalytics.logEvent()"] --> F
H["EngineBugTracking.log()"] --> F
I["EngineLog.info()"] --> F
J["Firebase Analytics"] --> F
K["Google Cloud Logging"] --> F
L["Crashlytics"] --> F
F --> M["Enrich Data"]
M --> N["session_id: UUID v4"]
N --> O["Firebase Analytics"]
N --> P["Google Cloud Logging"]
N --> Q["Grafana Faro"]
N --> R["Splunk"]
N --> S["Crashlytics"]
U["Correlação de Logs"] --> V["Mesmo session_id"]
V --> W["Jornada Completa do Usuário"]
📱 Widgets Stateless e Stateful com Tracking Automático #
graph TD
A["App"] --> B["EngineStatelessWidget"]
A --> C["EngineStatefulWidget"]
B --> D["buildWithTracking()"]
C --> E["buildWithTracking()"]
B --> F["Métodos Executáveis"]
C --> G["Métodos Executáveis"]
F --> H["logUserAction()"]
F --> I["logCustomEvent()"]
F --> J["logScreenError()"]
G --> K["logUserAction()"]
G --> L["logCustomEvent()"]
G --> M["logScreenError()"]
G --> N["logStateChange()"]
H --> O["EngineLog.debug()"]
I --> O
J --> P["EngineLog.error()"]
K --> O
L --> O
M --> P
N --> O
B --> Q["Lifecycle Tracking"]
C --> R["Lifecycle Tracking"]
Q --> S["screen_initialized"]
Q --> T["screen_viewed"]
Q --> U["screen_closed"]
R --> V["screen_initialized"]
R --> W["screen_viewed"]
R --> X["screen_closed"]
S --> O
T --> O
U --> O
V --> O
W --> O
X --> O
📝 Sistema de Logging (EngineLog) #
graph TD
A["Aplicação"] --> B["EngineLog"]
B --> C["debug()"]
B --> D["info()"]
B --> E["warning()"]
B --> F["error()"]
B --> G["fatal()"]
C --> H["_logWithLevel()"]
D --> H
E --> H
F --> H
G --> H
H --> I["developer.log()"]
H --> J{{"EngineAnalytics.isEnabled && includeInAnalytics?"}}
H --> K{{"EngineBugTracking.isEnabled?"}}
J -->|Sim| L["EngineAnalytics.logEvent()"]
J -->|Não| M["Skip Analytics"]
K -->|Sim| N["EngineBugTracking.log()"]
K -->|Não| O["Skip Bug Tracking"]
L --> P["Firebase Analytics"]
L --> Q["Grafana Faro"]
L --> R["Splunk"]
N --> T["Firebase Crashlytics"]
N --> U["Grafana Faro Bug Tracking"]
K -->|Sim| V{{"level == error || fatal?"}}
V -->|Sim| W["EngineBugTracking.recordError()"]
V -->|Não| X["Apenas log normal"]
W --> Y["Crash Reporting"]
Y --> T
Y --> U
📊 Sistema de Analytics (EngineAnalytics) #
graph TD
A["Aplicação"] --> B["EngineAnalytics"]
B --> C["init()"]
B --> D["logEvent()"]
B --> E["setUserId()"]
B --> F["setUserProperty()"]
B --> G["setPage()"]
B --> H["logAppOpen()"]
C --> I["EngineAnalyticsModel"]
I --> J["Firebase Analytics Config"]
I --> K["Faro Config"]
I --> L["Splunk Config"]
I --> M["Google Logging Config"]
D --> O["Adapters"]
E --> O
F --> O
G --> O
H --> O
O --> P["EngineFirebaseAnalyticsAdapter"]
O --> Q["EngineFaroAnalyticsAdapter"]
O --> R["EngineSplunkAnalyticsAdapter"]
O --> S["EngineGoogleLoggingAnalyticsAdapter"]
P --> T["Firebase Analytics SDK"]
Q --> U["Grafana Faro SDK"]
R --> V["Splunk SDK"]
S --> W["Google Cloud Logging API"]
T --> X["Google Analytics Dashboard"]
U --> Y["Grafana Dashboard"]
V --> Z["Splunk Dashboard"]
W --> AA["Google Cloud Console"]
🐛 Sistema de Bug Tracking (EngineBugTracking) #
graph TD
A["Aplicação"] --> B["EngineBugTracking"]
B --> C["init()"]
B --> D["log()"]
B --> E["recordError()"]
B --> F["recordFlutterError()"]
B --> G["setCustomKey()"]
B --> H["setUserIdentifier()"]
B --> I["testCrash()"]
C --> J["EngineBugTrackingModel"]
J --> K["Crashlytics Config"]
J --> L["Faro Config"]
J --> M["Google Logging Config"]
D --> N["Adapters"]
E --> N
F --> N
G --> N
H --> N
I --> N
N --> O["EngineCrashlyticsAdapter"]
N --> P["EngineFaroBugTrackingAdapter"]
N --> Q["EngineGoogleLoggingBugTrackingAdapter"]
O --> R["Firebase Crashlytics SDK"]
P --> S["Grafana Faro SDK"]
Q --> T["Google Cloud Logging API"]
R --> U["Firebase Console"]
S --> V["Grafana Dashboard"]
T --> W["Google Cloud Console"]
X["Flutter Error Handler"] --> F
Y["Platform Error Handler"] --> E
Z["Custom Errors"] --> E
AA["Logging Events"] --> D
📦 Instalação #
Adicione ao seu pubspec.yaml
:
dependencies:
engine_tracking: ^1.4.0
Execute:
flutter pub get
🚀 Exemplos de Uso #
📱 Exemplos Inclusos #
O pacote inclui exemplos completos demonstrando todas as funcionalidades:
cd example && flutter run
- 📱 Exemplo Principal: Inicialização, tracking de eventos, propriedades de usuário e navegação
- 🌐 Exemplo HTTP Tracking: Requisições com PokéAPI e JSONPlaceholder
- 👁️ Exemplo View Tracking: Sistema automático de tracking de telas
🚀 Inicialização Centralizada (Recomendado) #
Novo! Use o EngineTrackingInitialize
para inicializar Analytics e Bug Tracking de uma só vez:
import 'package:engine_tracking/engine_tracking.dart';
// Ambos os serviços
await EngineTrackingInitialize.initWithModels(
analyticsModel: EngineAnalyticsModel(/* configs */),
bugTrackingModel: EngineBugTrackingModel(/* configs */),
);
// Apenas Analytics
await EngineTrackingInitialize.initWithModels(
analyticsModel: EngineAnalyticsModel(/* configs */),
bugTrackingModel: null,
);
// Apenas Bug Tracking
await EngineTrackingInitialize.initWithModels(
analyticsModel: null,
bugTrackingModel: EngineBugTrackingModel(/* configs */),
);
// Com Adapters (controle granular)
await EngineTrackingInitialize.initWithAdapters(
analyticsAdapters: [EngineFirebaseAnalyticsAdapter(/* config */)],
bugTrackingAdapters: null, // Skip bug tracking
);
// Inicialização rápida (ambos desabilitados)
await EngineTrackingInitialize.initWithDefaults();
// Status
bool bothReady = EngineTrackingInitialize.isInitialized;
bool anyEnabled = EngineTrackingInitialize.isEnabled;
// Cleanup
await EngineTrackingInitialize.dispose();
🎯 Configuração Básica (Método Individual) #
import 'package:engine_tracking/engine_tracking.dart';
Future<void> setupTracking() async {
final analyticsModel = EngineAnalyticsModel(
firebaseAnalyticsConfig: const EngineFirebaseAnalyticsConfig(enabled: true),
clarityConfig: const EngineClarityConfig(
enabled: true,
projectId: 'seu-projeto-clarity',
),
faroConfig: const EngineFaroConfig(
enabled: true,
endpoint: 'https://faro-collector.grafana.net/collect',
appName: 'MeuApp',
appVersion: '1.0.0',
environment: 'production',
apiKey: 'sua-chave-api-faro',
),
googleLoggingConfig: const EngineGoogleLoggingConfig(
enabled: true,
projectId: 'seu-projeto-gcp',
logName: 'engine-tracking',
credentials: {
"type": "service_account",
"project_id": "seu-projeto-gcp",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "sua-service-account@seu-projeto-gcp.iam.gserviceaccount.com",
// ... resto das credenciais
},
resource: {
'type': 'global',
'labels': {'project_id': 'seu-projeto-gcp'},
},
),
splunkConfig: const EngineSplunkConfig(enabled: false),
);
final bugTrackingModel = EngineBugTrackingModel(
crashlyticsConfig: const EngineCrashlyticsConfig(enabled: true),
faroConfig: const EngineFaroConfig(
enabled: true,
endpoint: 'https://faro-collector.grafana.net/collect',
appName: 'MeuApp',
appVersion: '1.0.0',
environment: 'production',
apiKey: 'sua-chave-api-faro',
),
googleLoggingConfig: const EngineGoogleLoggingConfig(enabled: true, /* configs */),
);
await EngineAnalytics.initWithModel(analyticsModel);
await EngineBugTracking.initWithModel(bugTrackingModel);
}
📈 Tracking de Eventos #
// Evento simples (Session ID incluído automaticamente)
await EngineAnalytics.logEvent('button_clicked');
// Evento com parâmetros
await EngineAnalytics.logEvent('purchase_completed', {
'item_id': 'premium_plan',
'value': 29.99,
'currency': 'BRL',
'category': 'subscription',
});
// Evento de abertura do app
await EngineAnalytics.logAppOpen();
👤 Gerenciamento de Usuário #
// Definir ID do usuário
await EngineAnalytics.setUserId('user_12345');
// Com informações completas (para Faro/Clarity)
await EngineAnalytics.setUserId(
'user_12345',
'usuario@exemplo.com',
'João Silva',
);
// Propriedades do usuário
await EngineAnalytics.setUserProperty('user_type', 'premium');
await EngineAnalytics.setUserProperty('plan', 'monthly');
🧭 Navegação de Telas #
// Tela simples
await EngineAnalytics.setPage('HomeScreen');
// Com contexto completo
await EngineAnalytics.setPage(
'ProductScreen', // Tela atual
'HomeScreen', // Tela anterior
'ECommerceApp', // Classe da tela
);
🐛 Bug Tracking #
// Log estruturado
await EngineBugTracking.log('Usuário realizou compra', {
'user_id': '12345',
'product_id': 'abc-123',
'amount': 29.99,
});
// Capturar erros
try {
// código que pode falhar
} catch (error, stackTrace) {
await EngineBugTracking.recordError(
error,
stackTrace,
reason: 'Falha no processamento de pagamento',
);
}
// Definir contexto do usuário
await EngineBugTracking.setUserIdentifier('user_12345');
await EngineBugTracking.setCustomKey('subscription_plan', 'premium');
📝 Sistema de Logging #
// Diferentes níveis de log
EngineLog.debug('Debug information');
EngineLog.info('Informational message');
EngineLog.warning('Warning message');
EngineLog.error('Error occurred');
EngineLog.fatal('Fatal error');
// Com contexto adicional
EngineLog.info('User action', context: {
'action': 'button_click',
'screen': 'home',
'user_id': '12345',
});
// Incluir em analytics (padrão: false para debug/info)
EngineLog.warning('Important warning', includeInAnalytics: true);
👁️ View Tracking com Widgets #
class HomePage extends EngineStatelessWidget {
HomePage({super.key});
@override
String get screenName => 'home';
@override
Map<String, dynamic>? get screenParameters => {
'user_type': 'premium',
'version': '1.0.0',
};
@override
Widget buildWithTracking(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: ElevatedButton(
onPressed: () {
logUserAction('cta_clicked', parameters: {
'button_type': 'primary',
'location': 'header',
});
},
child: const Text('Click Me'),
),
);
}
}
class ShoppingCartPage extends StatefulWidget {
final List<Product> initialProducts;
const ShoppingCartPage({super.key, required this.initialProducts});
@override
State<ShoppingCartPage> createState() => _ShoppingCartPageState();
}
class _ShoppingCartPageState extends EngineStatefulWidgetState<ShoppingCartPage> {
late List<Product> _products;
@override
void initState() {
super.initState();
_products = List.from(widget.initialProducts);
}
@override
String get screenName => 'shopping_cart';
@override
Map<String, dynamic>? get screenParameters => {
'initial_product_count': widget.initialProducts.length,
'cart_value': _calculateTotal(),
};
@override
Widget buildWithTracking(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Carrinho')),
body: ListView.builder(
itemCount: _products.length,
itemBuilder: (context, index) {
final product = _products[index];
return ListTile(
title: Text(product.name),
trailing: IconButton(
icon: const Icon(Icons.remove_circle),
onPressed: () {
setState(() {
_products.removeAt(index);
});
logUserAction('product_removed', parameters: {
'product_id': product.id,
'product_name': product.name,
'remaining_count': _products.length,
});
logStateChange('cart_updated', additionalData: {
'action': 'removal',
'new_total': _calculateTotal(),
});
},
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
logUserAction('checkout_initiated', parameters: {
'product_count': _products.length,
'total_value': _calculateTotal(),
});
},
child: const Icon(Icons.shopping_cart_checkout),
),
);
}
double _calculateTotal() {
return _products.fold(0.0, (sum, product) => sum + product.price);
}
}
✅ Verificação de Status #
// Verificar se analytics está habilitado
if (EngineAnalytics.isEnabled) {
print('✅ Analytics está ativo');
}
// Verificar serviços específicos
if (EngineAnalytics.isFirebaseAnalyticsEnabled) {
print('🔥 Firebase Analytics ativo');
}
if (EngineAnalytics.isFaroEnabled) {
print('📊 Faro Analytics ativo');
}
if (EngineAnalytics.isGoogleLoggingInitialized) {
print('☁️ Google Cloud Logging ativo');
}
🧪 Testes #
Execute os testes:
flutter test
Status dos Testes:
- ✅ 96 testes passando (100% dos testes implementados)
- ✅ Testes otimizados para integrações Firebase/Faro/Google Cloud (evitam dependências externas)
- ✅ 100% de cobertura nos arquivos de configuração e modelos
- ✅ Testes completos para sistema de logging e Google Cloud Logging
- ✅ Testes completos para Session ID com validação UUID v4 RFC 4122
Para cobertura de testes:
flutter test --coverage
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.html
🤝 Como Contribuir #
Contribuições são bem-vindas! Por favor:
- Fork o projeto
- Crie uma branch para sua feature (
git checkout -b feature/AmazingFeature
) - Commit suas mudanças (
git commit -m 'Add some AmazingFeature'
) - Push para a branch (
git push origin feature/AmazingFeature
) - Abra um Pull Request
📋 Diretrizes de Contribuição #
- Mantenha 95%+ de cobertura de testes
- Siga o padrão de código existente
- Documente novas funcionalidades
- Teste em Android e iOS
- Atualize o CHANGELOG.md
📄 Licença #
Este projeto está licenciado sob a Licença MIT - veja o arquivo LICENSE para detalhes.
🏢 Sobre a STMR #
Desenvolvido pela STMR - Especialistas em soluções móveis.
A STMR é uma empresa focada no desenvolvimento de soluções tecnológicas inovadoras para dispositivos móveis, especializando-se em arquiteturas robustas, performance otimizada e experiências de usuário excepcionais.
🎯 Nossa Missão #
Fornecer ferramentas e bibliotecas Flutter de alta qualidade que aceleram o desenvolvimento de aplicações móveis enterprise, mantendo os mais altos padrões de segurança, performance e usabilidade.
💡 Dica v1.4.0: Para máxima eficiência, configure apenas os serviços que você realmente utiliza. A biblioteca é otimizada para funcionar com qualquer combinação de serviços habilitados ou desabilitados. Com Session ID automático, você agora tem correlação completa de logs e centralização avançada! 🆔🔥