266 lines
7.4 KiB
Dart
266 lines
7.4 KiB
Dart
// ignore_for_file: deprecated_member_use
|
|
|
|
import 'dart:developer' as developer;
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:onufitness/environment/app_environment.dart';
|
|
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
|
|
class LoggerService {
|
|
static final LoggerService _instance = LoggerService._internal();
|
|
|
|
factory LoggerService() {
|
|
return _instance;
|
|
}
|
|
|
|
LoggerService._internal();
|
|
//................................................................................................
|
|
void log(
|
|
String message, {
|
|
String? name,
|
|
Object? error,
|
|
StackTrace? stackTrace,
|
|
Map<String, dynamic>? extras,
|
|
}) {
|
|
if (AppEnvironment.isDevelopment) {
|
|
// Use dart:developer log for production (inverted for testing)
|
|
developer.log(
|
|
message,
|
|
name: name ?? 'App',
|
|
error: error,
|
|
stackTrace: stackTrace,
|
|
);
|
|
|
|
// Also print extras if provided
|
|
if (extras != null && extras.isNotEmpty) {
|
|
developer.log('Extras: $extras', name: name ?? 'App');
|
|
}
|
|
} else {
|
|
// Use Sentry in DEVELOPMENT for testing
|
|
final attributes = <String, SentryLogAttribute>{};
|
|
|
|
// Add extras as attributes
|
|
if (extras != null) {
|
|
extras.forEach((k, v) {
|
|
attributes[k] = SentryLogAttribute.string(v.toString());
|
|
});
|
|
}
|
|
|
|
// Add error and stackTrace as attributes if provided
|
|
if (error != null) {
|
|
attributes['error'] = SentryLogAttribute.string(error.toString());
|
|
}
|
|
if (stackTrace != null) {
|
|
attributes['stackTrace'] = SentryLogAttribute.string(
|
|
stackTrace.toString(),
|
|
);
|
|
}
|
|
|
|
Sentry.logger.info(
|
|
message,
|
|
attributes: attributes.isNotEmpty ? attributes : null,
|
|
);
|
|
|
|
// If debug mode is enabled in UAT, also print to console
|
|
if (kDebugMode) {
|
|
developer.log(message, name: name ?? 'App');
|
|
}
|
|
}
|
|
}
|
|
|
|
//................................................................................................
|
|
/// Logs warning messages
|
|
/// In Development: Prints to console with warning indicator
|
|
/// In UAT/Production: Sends to Sentry as warning breadcrumb
|
|
void warning(
|
|
String message, {
|
|
String? name,
|
|
Object? error,
|
|
StackTrace? stackTrace,
|
|
Map<String, dynamic>? extras,
|
|
}) {
|
|
if (AppEnvironment.isDevelopment) {
|
|
developer.log(
|
|
'⚠️ WARNING: $message',
|
|
name: name ?? 'App',
|
|
error: error,
|
|
stackTrace: stackTrace,
|
|
);
|
|
|
|
if (extras != null && extras.isNotEmpty) {
|
|
developer.log('Extras: $extras', name: name ?? 'App');
|
|
}
|
|
} else {
|
|
// Use Sentry for UAT and Production
|
|
final attributes = <String, SentryLogAttribute>{};
|
|
|
|
// Add extras as attributes
|
|
if (extras != null) {
|
|
extras.forEach((k, v) {
|
|
attributes[k] = SentryLogAttribute.string(v.toString());
|
|
});
|
|
}
|
|
|
|
// Add error and stackTrace as attributes if provided
|
|
if (error != null) {
|
|
attributes['error'] = SentryLogAttribute.string(error.toString());
|
|
}
|
|
if (stackTrace != null) {
|
|
attributes['stackTrace'] = SentryLogAttribute.string(
|
|
stackTrace.toString(),
|
|
);
|
|
}
|
|
|
|
Sentry.logger.warn(
|
|
message,
|
|
attributes: attributes.isNotEmpty ? attributes : null,
|
|
);
|
|
|
|
// If debug mode is enabled in UAT, also print to console
|
|
if (kDebugMode) {
|
|
developer.log('⚠️ WARNING: $message', name: name ?? 'App');
|
|
}
|
|
}
|
|
}
|
|
|
|
//................................................................................................
|
|
/// Logs error messages
|
|
/// In Development: Prints to console with error indicator
|
|
/// In UAT/Production: Sends to Sentry as error event
|
|
void error(
|
|
String message, {
|
|
String? name,
|
|
Object? error,
|
|
StackTrace? stackTrace,
|
|
Map<String, dynamic>? extras,
|
|
bool isFatal = false,
|
|
}) {
|
|
if (AppEnvironment.isDevelopment) {
|
|
developer.log(
|
|
'❌ ERROR: $message',
|
|
name: name ?? 'App',
|
|
error: error,
|
|
stackTrace: stackTrace,
|
|
level: 1000, // High level for errors
|
|
);
|
|
|
|
if (extras != null && extras.isNotEmpty) {
|
|
developer.log('Extras: $extras', name: name ?? 'App', level: 1000);
|
|
}
|
|
} else {
|
|
// Use Sentry for UAT and Production
|
|
final attributes = <String, SentryLogAttribute>{};
|
|
|
|
// Add extras as attributes
|
|
if (extras != null) {
|
|
extras.forEach((k, v) {
|
|
attributes[k] = SentryLogAttribute.string(v.toString());
|
|
});
|
|
}
|
|
|
|
// Add error and stackTrace as attributes if provided
|
|
if (error != null) {
|
|
attributes['error'] = SentryLogAttribute.string(error.toString());
|
|
}
|
|
if (stackTrace != null) {
|
|
attributes['stackTrace'] = SentryLogAttribute.string(
|
|
stackTrace.toString(),
|
|
);
|
|
}
|
|
|
|
// Add fatal flag as attribute
|
|
if (isFatal) {
|
|
attributes['fatal'] = SentryLogAttribute.string('true');
|
|
}
|
|
|
|
Sentry.logger.error(
|
|
message,
|
|
attributes: attributes.isNotEmpty ? attributes : null,
|
|
);
|
|
|
|
// If debug mode is enabled in UAT, also print to console
|
|
if (kDebugMode) {
|
|
developer.log(
|
|
'❌ ERROR: $message',
|
|
name: name ?? 'App',
|
|
error: error,
|
|
stackTrace: stackTrace,
|
|
level: 1000,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//................................................................................................
|
|
/// Convenience method to log HTTP requests
|
|
void logHttpRequest(
|
|
String method,
|
|
String url, {
|
|
Map<String, dynamic>? headers,
|
|
dynamic body,
|
|
}) {
|
|
log(
|
|
'HTTP $method: $url',
|
|
name: 'HTTP',
|
|
extras: {
|
|
'method': method,
|
|
'url': url,
|
|
if (headers != null) 'headers': headers,
|
|
if (body != null) 'body': body,
|
|
},
|
|
);
|
|
}
|
|
|
|
//................................................................................................
|
|
/// Convenience method to log HTTP responses
|
|
void logHttpResponse(
|
|
String method,
|
|
String url,
|
|
int statusCode, {
|
|
dynamic body,
|
|
}) {
|
|
if (statusCode >= 200 && statusCode < 300) {
|
|
log(
|
|
'HTTP $method Response: $url [$statusCode]',
|
|
name: 'HTTP',
|
|
extras: {
|
|
'method': method,
|
|
'url': url,
|
|
'statusCode': statusCode,
|
|
if (body != null) 'body': body,
|
|
},
|
|
);
|
|
} else {
|
|
error(
|
|
'HTTP $method Error: $url [$statusCode]',
|
|
name: 'HTTP',
|
|
extras: {
|
|
'method': method,
|
|
'url': url,
|
|
'statusCode': statusCode,
|
|
if (body != null) 'body': body,
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
//................................................................................................
|
|
/// Logs navigation events
|
|
void logNavigation(String route, {Map<String, dynamic>? arguments}) {
|
|
log(
|
|
'Navigation to: $route',
|
|
name: 'Navigation',
|
|
extras: {'route': route, if (arguments != null) 'arguments': arguments},
|
|
);
|
|
}
|
|
|
|
//................................................................................................
|
|
/// Logs user actions/events
|
|
void logEvent(String eventName, {Map<String, dynamic>? properties}) {
|
|
log(
|
|
'Event: $eventName',
|
|
name: 'Event',
|
|
extras: {'eventName': eventName, if (properties != null) ...properties},
|
|
);
|
|
}
|
|
}
|