import 'package:EasyDartModule/base/logger/Logger.dart'; import 'package:dio/dio.dart'; import 'package:shelf/shelf.dart' as sf; import 'package:uuid/uuid.dart'; class TraceDio { final Dio _dio; final Logger? _logger; final Uuid uuid = Uuid(); static late TraceDio _traceDio; String? token; TraceDio(Logger? logger) : _dio = Dio(), _logger = logger { // 配置 Dio // 设置连接超时 _dio.options.connectTimeout = Duration(seconds: 60); // 设置接收超时 _dio.options.receiveTimeout = Duration(seconds: 5 * 60); //保留原始大小写 _dio.options.preserveHeaderCase = true; // 设置拦截器,自动添加 traceId 和 spanId,并记录日志 _dio.interceptors.add(InterceptorsWrapper( onRequest: (options, handler) { // 获取请求中的 traceId(如果没有则生成) String? traceId = options.headers['X-Trace-ID']; String? spanId = options.headers['X-Span-ID']; if (traceId == null) { // 在请求头中添加 traceId 和 spanId traceId = uuid.v4(); spanId = uuid.v4(); options.headers['X-Trace-ID'] = traceId; options.headers['X-Span-ID'] = spanId; } // 记录请求日志 _logger?.info('发送请求: ${options.method} ${options.uri}', tag: "DIO", traceId: traceId, spanId: spanId); return handler.next(options); // 继续请求 }, onResponse: (response, handler) { // 记录响应日志 String? traceId = response.headers.value('X-Trace-ID'); String? spanId = response.headers.value('X-Span-ID'); _logger?.info('接收数据: ${response.statusCode} ${response.statusMessage}', tag: "DIO", traceId: traceId, spanId: spanId); //自动更新token if (response.headers["token"] != null) { token = response.headers["token"]?[0]; } return handler.next(response); // 继续处理响应 }, onError: (DioException e, handler) { // 记录错误日志 String? traceId = e.requestOptions.headers['X-Trace-ID']; String? spanId = e.requestOptions.headers['X-Span-ID']; String errMsg; if (e.response != null) { errMsg = "请求错误: url:${e.requestOptions.path} 请求方法:${e.requestOptions.method} 请求数据:${e.requestOptions.data} 响应代码:${e.response?.statusCode} 响应消息:${e.response?.statusMessage} 响应内容:${e.response?.data}"; } else { errMsg = "请求错误: url:${e.requestOptions.path} 请求方法:${e.requestOptions.method} 请求数据:${e.requestOptions.data} 错误消息:${e.message ?? e.error}"; } print(errMsg); _logger?.error(errMsg, tag: "DIO", traceId: traceId, spanId: spanId); return handler.next(e); // 继续处理错误 }, )); } static TraceDio getInstance() { return _traceDio; } static void setInstance(TraceDio traceDio) { _traceDio = traceDio; } Map? getHeader( {Map? headers, sf.Request? request}) { headers ??= {}; if (request != null) { return { ...headers, "X-Trace-ID": request.context['request_trace_id'] as String, "X-Span-ID": request.context['request_span_id'] as String }; } if (token != null) { headers["token"] = token; } return headers; } // 发起 GET 请求 Future get(String url, {Map? queryParameters, sf.Request? request, ResponseType? responseType, Duration? receiveTimeout}) async { return await _dio.get(url, queryParameters: queryParameters, options: Options( receiveTimeout: receiveTimeout, headers: getHeader(request: request), responseType: responseType)); } // 发起 POST 请求 Future post(String url, {Object? data, Map? queryParameters, sf.Request? request, Duration? receiveTimeout}) async { return await _dio.post(url, data: data, queryParameters: queryParameters, options: Options( receiveTimeout: receiveTimeout, headers: getHeader(request: request))); } // 发起 PUT 请求 Future put(String url, {Object? data, Map? queryParameters, sf.Request? request, Duration? receiveTimeout}) async { return await _dio.put(url, data: data, queryParameters: queryParameters, options: Options( receiveTimeout: receiveTimeout, headers: getHeader(request: request))); } // 发起 DELETE 请求 Future delete(String url, {Object? data, Map? queryParameters, sf.Request? request, Duration? receiveTimeout}) async { return await _dio.delete( url, data: data, queryParameters: queryParameters, options: Options( receiveTimeout: receiveTimeout, headers: getHeader(request: request)), ); } }