You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
HMG_Patient_App/lib/dev_tools/api_logger_service.dart

134 lines
4.7 KiB
Dart

// filepath: lib/core/service/client/api_logger_service.dart
import 'dart:convert';
import 'package:flutter/foundation.dart';
/// Holds the details of a single API call.
class ApiLogEntry {
final String id;
final DateTime timestamp;
final String method;
final String url;
final String endpoint;
final String environment;
final Map<String, String> headers;
final Map<String, dynamic>? requestBody;
final dynamic responseBody;
final int statusCode;
final bool isSuccess;
final Duration? duration;
ApiLogEntry({
required this.id,
required this.timestamp,
required this.method,
required this.url,
required this.endpoint,
this.environment = '',
required this.headers,
this.requestBody,
this.responseBody,
required this.statusCode,
required this.isSuccess,
this.duration,
});
/// Derives a short environment label from a full URL string.
static String envFromUrl(String url) {
if (url.contains('vidamergeuat')) return 'VidaMerge';
if (url.contains('vidauat')) return 'VidaPlus';
if (url.contains('orash')) return 'Orash';
if (url.contains('uat.hmgwebservices')) return 'UAT';
if (url.contains('rc.hmg.com') && url.contains('/test')) return 'RC-Test';
if (url.contains('ms.hmg.com/rc')) return 'MS-RC';
if (url.contains('rc.hmg.com')) return 'RC';
if (url.contains('mdlaboratories.com/exacartapitest')) return 'Pharmacy-Test';
if (url.contains('mdlaboratories.com')) return 'Pharmacy';
if (url.contains('hmgwebservices.com')) return 'Production';
// External / other
final uri = Uri.tryParse(url);
return uri?.host.isNotEmpty == true ? uri!.host.split('.').first : 'External';
}
/// Returns a pretty-printed JSON string of the request body.
String get prettyRequestBody {
if (requestBody == null) return '(none)';
try {
return const JsonEncoder.withIndent(' ').convert(requestBody);
} catch (_) {
return requestBody.toString();
}
}
/// Returns a pretty-printed JSON string of the response body.
String get prettyResponseBody {
if (responseBody == null) return '(none)';
try {
if (responseBody is String) {
final decoded = json.decode(responseBody as String);
return const JsonEncoder.withIndent(' ').convert(decoded);
}
return const JsonEncoder.withIndent(' ').convert(responseBody);
} catch (_) {
return responseBody.toString();
}
}
/// Returns formatted text report (headers + request + response sectioned).
String toFormattedText() {
final buf = StringBuffer();
buf.writeln('═══════════════════════════════════');
buf.writeln('[$method] $url');
buf.writeln('Status : $statusCode | ${isSuccess ? '✅ Success' : '❌ Failed'}');
if (environment.isNotEmpty) buf.writeln('Env : $environment');
buf.writeln('Time : ${timestamp.toIso8601String()}');
if (duration != null) buf.writeln('Duration: ${duration!.inMilliseconds}ms');
buf.writeln('───────────────── HEADERS ─────────────────');
headers.forEach((k, v) => buf.writeln('$k: $v'));
buf.writeln('───────────────── REQUEST ─────────────────');
buf.writeln(prettyRequestBody);
buf.writeln('──────────────── RESPONSE ─────────────────');
buf.writeln(prettyResponseBody);
buf.writeln('═══════════════════════════════════');
return buf.toString();
}
/// Returns a cURL command equivalent.
String toCurl() {
final buf = StringBuffer();
buf.write("curl -X $method \\\n");
buf.write(" '${url.trim()}' \\\n");
headers.forEach((k, v) {
buf.write(" -H '$k: $v' \\\n");
});
if (requestBody != null && method != 'GET') {
final bodyStr = json.encode(requestBody).replaceAll("'", "\\'");
buf.write(" -d '$bodyStr'");
}
return buf.toString();
}
}
/// Singleton service that collects API call logs in-memory.
class ApiLoggerService extends ChangeNotifier {
ApiLoggerService._internal();
static final ApiLoggerService instance = ApiLoggerService._internal();
final List<ApiLogEntry> _logs = [];
List<ApiLogEntry> get logs => List.unmodifiable(_logs.reversed.toList());
void addLog(ApiLogEntry entry) {
_logs.add(entry);
// Keep last 500 entries to avoid huge memory usage
if (_logs.length > 500) _logs.removeAt(0);
notifyListeners();
}
void clear() {
_logs.clear();
notifyListeners();
}
}