closeyourit 0.8.1
closeyourit: ^0.8.1 copied to clipboard
Client Dart/Flutter per CloseYourIt — errori, metriche e logs verso il backend di osservabilità interno.
example/lib/main.dart
import 'package:closeyourit/closeyourit.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
/// Esempio minimo di integrazione del client CloseYourIt.
///
/// I valori `CLOSEYOURIT_*` arrivano via `--dart-define`, ad es.:
/// ```
/// flutter run \
/// --dart-define=CLOSEYOURIT_ENDPOINT_URL=https://www.closeyour.it \
/// --dart-define=CLOSEYOURIT_PUBLIC_KEY=<dsn public key> \
/// --dart-define=CLOSEYOURIT_PROJECT_ID=...
/// ```
///
/// Un'app distribuita usa la `publicKey` (DSN, non segreta): niente Bearer
/// server-side nel pacchetto. Vedi il README per token vs publicKey.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await CloseYourIt.init(
CloseYourItOptions(
endpointUrl: const String.fromEnvironment('CLOSEYOURIT_ENDPOINT_URL'),
publicKey: const String.fromEnvironment('CLOSEYOURIT_PUBLIC_KEY'),
projectId: const String.fromEnvironment('CLOSEYOURIT_PROJECT_ID'),
environment: const String.fromEnvironment(
'CLOSEYOURIT_ENVIRONMENT',
defaultValue: 'development',
),
release: const String.fromEnvironment('CLOSEYOURIT_RELEASE'),
// Breadcrumb automatici opt-in (sintetici, senza PII): rete, ciclo di vita
// e interazioni recenti contestualizzano un errore avvenuto poco dopo.
captureLifecycleBreadcrumbs: true,
captureConnectivityBreadcrumbs: true,
captureTapBreadcrumbs: true,
),
appRunner: () => runApp(const ExampleApp()),
);
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'CloseYourIt Example',
navigatorObservers: [CloseYourItNavigatorObserver()],
// Abilita i breadcrumb di tap (captureTapBreadcrumbs): registra tipo e
// rotta dell'interazione, mai il testo o i dati del widget toccato.
builder: (context, child) =>
CloseYourItUserInteraction(child: child ?? const SizedBox()),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
Dio get _dio => Dio()..interceptors.add(CloseYourItDioInterceptor());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('CloseYourIt')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 12,
children: [
Text('Abilitato: ${CloseYourIt.isEnabled}'),
ElevatedButton(
onPressed: () {
CloseYourIt.setUser(id: 'demo-7');
CloseYourIt.addBreadcrumb(
message: 'tap: cattura errore', category: 'ui');
CloseYourIt.captureException(
StateError('errore di esempio'),
stackTrace: StackTrace.current,
handled: true,
);
},
child: const Text('Cattura un errore'),
),
ElevatedButton(
onPressed: () => CloseYourIt.logger.info(
'pulsante premuto',
attributes: {'screen': 'home'},
),
child: const Text('Invia un log'),
),
ElevatedButton(
onPressed: () => CloseYourIt.measure(
'demo.lavoro',
() async =>
Future<void>.delayed(const Duration(milliseconds: 300)),
),
child: const Text('Misura una metrica'),
),
ElevatedButton(
onPressed: () async {
try {
await _dio.get<dynamic>('https://httpbin.org/status/500');
} on DioException {
// L'interceptor ha già catturato l'errore 5xx.
}
},
child: const Text('Chiamata HTTP che fallisce'),
),
],
),
),
);
}
}