MotorSignal-App/lib/services/alerts/road_alert_diagnostics.dart

84 lines
2.9 KiB
Dart

import 'road_alert_models.dart';
/// Comprehensive diagnostics telemetry for the road alert pipeline.
/// Tracks upstream provider status, ingestion rates, stage-by-stage rejection reasons,
/// and map/audio dispatch metrics without leaking credentials or sensitive user data.
class RoadAlertDiagnostics {
final RoadAlertProviderStatus providerStatus;
final String? statusMessage;
final DateTime? lastFetchTime;
final DateTime? lastSuccessfulFetchTime;
final String? lastRequestedArea;
final double? lastRequestedRadiusMeters;
final bool isLive;
final int rawReportsCount;
final int normalizedAcceptedCount;
final Map<String, int> rejectedReasons;
final int displayedOnMapCount;
final int audioCandidateCount;
final String? lastError;
const RoadAlertDiagnostics({
this.providerStatus = RoadAlertProviderStatus.notConfigured,
this.statusMessage,
this.lastFetchTime,
this.lastSuccessfulFetchTime,
this.lastRequestedArea,
this.lastRequestedRadiusMeters,
this.isLive = true,
this.rawReportsCount = 0,
this.normalizedAcceptedCount = 0,
this.rejectedReasons = const {},
this.displayedOnMapCount = 0,
this.audioCandidateCount = 0,
this.lastError,
});
int get totalRejectedCount =>
rejectedReasons.values.fold(0, (sum, count) => sum + count);
bool get hasQuotaError =>
providerStatus == RoadAlertProviderStatus.rateLimited;
bool get hasAuthError =>
providerStatus == RoadAlertProviderStatus.authError;
bool get isOperational =>
providerStatus == RoadAlertProviderStatus.connected;
RoadAlertDiagnostics copyWith({
RoadAlertProviderStatus? providerStatus,
String? statusMessage,
DateTime? lastFetchTime,
DateTime? lastSuccessfulFetchTime,
String? lastRequestedArea,
double? lastRequestedRadiusMeters,
bool? isLive,
int? rawReportsCount,
int? normalizedAcceptedCount,
Map<String, int>? rejectedReasons,
int? displayedOnMapCount,
int? audioCandidateCount,
String? lastError,
}) {
return RoadAlertDiagnostics(
providerStatus: providerStatus ?? this.providerStatus,
statusMessage: statusMessage ?? this.statusMessage,
lastFetchTime: lastFetchTime ?? this.lastFetchTime,
lastSuccessfulFetchTime:
lastSuccessfulFetchTime ?? this.lastSuccessfulFetchTime,
lastRequestedArea: lastRequestedArea ?? this.lastRequestedArea,
lastRequestedRadiusMeters:
lastRequestedRadiusMeters ?? this.lastRequestedRadiusMeters,
isLive: isLive ?? this.isLive,
rawReportsCount: rawReportsCount ?? this.rawReportsCount,
normalizedAcceptedCount:
normalizedAcceptedCount ?? this.normalizedAcceptedCount,
rejectedReasons: rejectedReasons ?? this.rejectedReasons,
displayedOnMapCount: displayedOnMapCount ?? this.displayedOnMapCount,
audioCandidateCount: audioCandidateCount ?? this.audioCandidateCount,
lastError: lastError ?? this.lastError,
);
}
}