fadd
This commit is contained in:
@@ -14,8 +14,6 @@ import (
|
||||
"time"
|
||||
|
||||
"tyapi-server/internal/shared/external_logger"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -39,8 +37,10 @@ type ServiceConfig struct {
|
||||
ClientID string
|
||||
ClientSecret string
|
||||
Timeout time.Duration
|
||||
// Debug 开发环境开启时输出可复现 curl 与完整响应体,便于数据源排查
|
||||
// Debug 开发环境开启时写入单一排查文件(curl + response),不重复打 request/response 日志
|
||||
Debug bool
|
||||
// DebugLogDir 排查日志目录,文件名为 dev_curl.log
|
||||
DebugLogDir string
|
||||
}
|
||||
|
||||
// YuyuechaService 愉悦查 OpenAPI 客户端
|
||||
@@ -127,11 +127,13 @@ func (s *YuyuechaService) doRequest(ctx context.Context, method, path string, bo
|
||||
baseURL := strings.TrimSuffix(s.config.BaseURL, "/")
|
||||
reqURL := baseURL + path
|
||||
|
||||
if s.logger != nil {
|
||||
// dev 排查走单一文件,避免 request/response/info 重复打点
|
||||
if !s.config.Debug && s.logger != nil {
|
||||
s.logger.LogRequest(requestID, transactionID, path, reqURL)
|
||||
}
|
||||
|
||||
signHeaders, err := SignHeaders(s.config.ClientID, s.config.ClientSecret, method, path, bodyBytes)
|
||||
// nonce 与本地 request_id 保持一致,后续仅凭 request_id 即可对接上游排查
|
||||
signHeaders, err := SignHeaders(s.config.ClientID, s.config.ClientSecret, method, path, bodyBytes, requestID)
|
||||
if err != nil {
|
||||
err = errors.Join(ErrSystem, err)
|
||||
s.logError(requestID, transactionID, path, err, map[string]interface{}{"request_params": logParams})
|
||||
@@ -172,11 +174,8 @@ func (s *YuyuechaService) doRequest(ctx context.Context, method, path string, bo
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
err = wrapHTTPError(err)
|
||||
errParams := map[string]interface{}{"request_params": logParams}
|
||||
if curlCmd != "" {
|
||||
errParams["curl"] = curlCmd
|
||||
}
|
||||
s.logError(requestID, transactionID, path, err, errParams)
|
||||
s.logDebugExchange(requestID, transactionID, path, curlCmd, 0, time.Since(startTime), nil, err.Error())
|
||||
s.logError(requestID, transactionID, path, err, map[string]interface{}{"request_params": logParams})
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
@@ -185,45 +184,34 @@ func (s *YuyuechaService) doRequest(ctx context.Context, method, path string, bo
|
||||
raw, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
err = errors.Join(ErrSystem, err)
|
||||
errParams := map[string]interface{}{"request_params": logParams}
|
||||
if curlCmd != "" {
|
||||
errParams["curl"] = curlCmd
|
||||
}
|
||||
s.logError(requestID, transactionID, path, err, errParams)
|
||||
s.logDebugExchange(requestID, transactionID, path, curlCmd, resp.StatusCode, duration, nil, err.Error())
|
||||
s.logError(requestID, transactionID, path, err, map[string]interface{}{"request_params": logParams})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.logDebugCurlAndResponse(requestID, transactionID, path, curlCmd, resp.StatusCode, duration, raw)
|
||||
s.logDebugExchange(requestID, transactionID, path, curlCmd, resp.StatusCode, duration, raw, "")
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
mapped := mapHTTPStatusError(resp.StatusCode, raw)
|
||||
errParams := map[string]interface{}{
|
||||
s.logError(requestID, transactionID, path, mapped, map[string]interface{}{
|
||||
"request_params": logParams,
|
||||
"response_body": truncateForLog(string(raw), maxLogResponseBodyLen),
|
||||
"http_status": resp.StatusCode,
|
||||
}
|
||||
if curlCmd != "" {
|
||||
errParams["curl"] = curlCmd
|
||||
}
|
||||
s.logError(requestID, transactionID, path, mapped, errParams)
|
||||
})
|
||||
return nil, mapped
|
||||
}
|
||||
|
||||
if s.logger != nil {
|
||||
if !s.config.Debug && s.logger != nil {
|
||||
s.logger.LogResponse(requestID, transactionID, path, resp.StatusCode, duration)
|
||||
}
|
||||
|
||||
var outer APIResponse
|
||||
if err := json.Unmarshal(raw, &outer); err != nil {
|
||||
parseErr := errors.Join(ErrSystem, fmt.Errorf("响应解析失败: %w", err))
|
||||
errParams := map[string]interface{}{
|
||||
s.logError(requestID, transactionID, path, parseErr, map[string]interface{}{
|
||||
"request_params": logParams,
|
||||
"response_body": truncateForLog(string(raw), maxLogResponseBodyLen),
|
||||
}
|
||||
if curlCmd != "" {
|
||||
errParams["curl"] = curlCmd
|
||||
}
|
||||
s.logError(requestID, transactionID, path, parseErr, errParams)
|
||||
})
|
||||
return nil, parseErr
|
||||
}
|
||||
|
||||
@@ -235,14 +223,10 @@ func (s *YuyuechaService) doRequest(ctx context.Context, method, path string, bo
|
||||
msg = *outer.ErrCode
|
||||
}
|
||||
mapped := errors.Join(ErrDatasource, errors.New(msg))
|
||||
errParams := map[string]interface{}{
|
||||
s.logError(requestID, transactionID, path, mapped, map[string]interface{}{
|
||||
"request_params": logParams,
|
||||
"response_body": truncateForLog(string(raw), maxLogResponseBodyLen),
|
||||
}
|
||||
if curlCmd != "" {
|
||||
errParams["curl"] = curlCmd
|
||||
}
|
||||
s.logError(requestID, transactionID, path, mapped, errParams)
|
||||
})
|
||||
return nil, mapped
|
||||
}
|
||||
|
||||
@@ -329,18 +313,18 @@ func (s *YuyuechaService) logError(requestID, transactionID, apiCode string, err
|
||||
}
|
||||
}
|
||||
|
||||
// logDebugCurlAndResponse 仅在 Debug(开发环境)输出完整 curl 与响应体
|
||||
func (s *YuyuechaService) logDebugCurlAndResponse(requestID, transactionID, apiCode, curlCmd string, statusCode int, duration time.Duration, raw []byte) {
|
||||
if !s.config.Debug || s.logger == nil || curlCmd == "" {
|
||||
func (s *YuyuechaService) logDebugExchange(requestID, transactionID, apiCode, curlCmd string, statusCode int, duration time.Duration, raw []byte, errMsg string) {
|
||||
if !s.config.Debug {
|
||||
return
|
||||
}
|
||||
s.logger.LogInfo("愉悦查请求响应(dev)",
|
||||
zap.String("request_id", requestID),
|
||||
zap.String("transaction_id", transactionID),
|
||||
zap.String("api_code", apiCode),
|
||||
zap.Int("http_status", statusCode),
|
||||
zap.Duration("duration", duration),
|
||||
zap.String("curl", curlCmd),
|
||||
zap.String("response_body", string(raw)),
|
||||
)
|
||||
writeDebugExchange(s.config.DebugLogDir, debugExchangeRecord{
|
||||
RequestID: requestID,
|
||||
TransactionID: transactionID,
|
||||
API: apiCode,
|
||||
Status: statusCode,
|
||||
Duration: duration,
|
||||
Curl: curlCmd,
|
||||
ResponseBody: raw,
|
||||
Error: errMsg,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user