refactor: replace hardcoded log messages with constants for better maintainability

This commit is contained in:
lilong.129
2025-06-18 17:08:50 +08:00
parent 1f3366453e
commit a3f2ff37bc
5 changed files with 51 additions and 45 deletions

View File

@@ -206,6 +206,6 @@ func SendGA4Event(name string, params map[string]interface{}) {
} }
err := ga4Client.SendEvent(event) err := ga4Client.SendEvent(event)
if err != nil { if err != nil {
log.Error().Err(err).Msg("send GA4 event failed") log.Warn().Err(err).Msg("send GA4 event failed")
} }
} }

View File

@@ -1 +1 @@
v5.0.0-beta-2506181659 v5.0.0-beta-2506181717

View File

@@ -14,6 +14,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/uixt" "github.com/httprunner/httprunner/v5/uixt"
"github.com/httprunner/httprunner/v5/uixt/ai"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
@@ -262,11 +263,11 @@ func (g *HTMLReportGenerator) getStepLogs(stepName string, startTime int64, elap
} }
// Track AI conversation patterns // Track AI conversation patterns
if strings.Contains(logEntry.Message, "log request messages") { if strings.Contains(logEntry.Message, ai.LOG_REQUEST_MESSAGES) {
if logTime >= actualStartTime && logTime <= actualEndTime+30000 { // 30s buffer for AI requests if logTime >= actualStartTime && logTime <= actualEndTime+30000 { // 30s buffer for AI requests
inAIConversation = true inAIConversation = true
} }
} else if strings.Contains(logEntry.Message, "log response message") && inAIConversation { } else if strings.Contains(logEntry.Message, ai.LOG_RESPONSE_MESSAGE) && inAIConversation {
// Extend end time to include complete AI conversation, but respect next step boundary // Extend end time to include complete AI conversation, but respect next step boundary
extendedEndTime := logTime extendedEndTime := logTime
if nextStepStartTime > 0 && extendedEndTime >= nextStepStartTime { if nextStepStartTime > 0 && extendedEndTime >= nextStepStartTime {

View File

@@ -73,6 +73,11 @@ func (h *ConversationHistory) Clear() {
log.Warn().Msg("conversation history cleared completely") log.Warn().Msg("conversation history cleared completely")
} }
const (
LOG_REQUEST_MESSAGES = "log request messages"
LOG_RESPONSE_MESSAGE = "log response message"
)
func logRequest(messages ConversationHistory) { func logRequest(messages ConversationHistory) {
msgs := make(ConversationHistory, 0, len(messages)) msgs := make(ConversationHistory, 0, len(messages))
for _, message := range messages { for _, message := range messages {
@@ -99,7 +104,7 @@ func logRequest(messages ConversationHistory) {
} }
msgs = append(msgs, msg) msgs = append(msgs, msg)
} }
log.Debug().Interface("messages", msgs).Msg("log request messages") log.Debug().Interface("messages", msgs).Msg(LOG_REQUEST_MESSAGES)
} }
func logResponse(message *schema.Message) { func logResponse(message *schema.Message) {
@@ -126,5 +131,5 @@ func logResponse(message *schema.Message) {
if message.Extra != nil { if message.Extra != nil {
logger = logger.Interface("extra", message.Extra) logger = logger.Interface("extra", message.Extra)
} }
logger.Msg("log response message") logger.Msg(LOG_RESPONSE_MESSAGE)
} }

View File

@@ -24,6 +24,45 @@ type PlanningJSONResponse struct {
Error string `json:"error"` Error string `json:"error"`
} }
// parseStructuredResponse parses model response into structured format with error recovery
func parseStructuredResponse(content string, result interface{}) error {
// Clean and validate UTF-8 content first
cleanContent := sanitizeUTF8Content(content)
// Extract JSON content from response
jsonContent := extractJSONFromContent(cleanContent)
if jsonContent == "" {
// If JSON extraction failed, try parsing the content directly as a fallback
jsonContent = cleanContent
}
// Parse JSON response with error recovery
return parseJSONWithFallback(jsonContent, result)
}
// sanitizeUTF8Content cleans invalid UTF-8 characters from content
func sanitizeUTF8Content(content string) string {
if utf8.ValidString(content) {
return content
}
// Convert to bytes and filter out invalid UTF-8 sequences
bytes := []byte(content)
var validBytes []byte
for len(bytes) > 0 {
r, size := utf8.DecodeRune(bytes)
if r != utf8.RuneError {
// Valid rune, keep it
validBytes = append(validBytes, bytes[:size]...)
}
// Skip invalid bytes (including RuneError)
bytes = bytes[size:]
}
return string(validBytes)
}
// extractJSONFromContent extracts JSON content from various formats in the response // extractJSONFromContent extracts JSON content from various formats in the response
// This function handles multiple formats: // This function handles multiple formats:
// 1. ```json ... ``` markdown code blocks // 1. ```json ... ``` markdown code blocks
@@ -121,29 +160,6 @@ func extractJSONFromContent(content string) string {
return "" return ""
} }
// sanitizeUTF8Content cleans invalid UTF-8 characters from content
func sanitizeUTF8Content(content string) string {
if utf8.ValidString(content) {
return content
}
// Convert to bytes and filter out invalid UTF-8 sequences
bytes := []byte(content)
var validBytes []byte
for len(bytes) > 0 {
r, size := utf8.DecodeRune(bytes)
if r != utf8.RuneError {
// Valid rune, keep it
validBytes = append(validBytes, bytes[:size]...)
}
// Skip invalid bytes (including RuneError)
bytes = bytes[size:]
}
return string(validBytes)
}
// parseJSONWithFallback attempts to parse JSON with multiple strategies for any struct type // parseJSONWithFallback attempts to parse JSON with multiple strategies for any struct type
func parseJSONWithFallback(jsonContent string, result interface{}) error { func parseJSONWithFallback(jsonContent string, result interface{}) error {
// Strategy 1: Direct JSON unmarshaling // Strategy 1: Direct JSON unmarshaling
@@ -432,22 +448,6 @@ func extractPlanningFieldsManually(content string) (*PlanningJSONResponse, error
return result, nil return result, nil
} }
// parseStructuredResponse parses model response into structured format with error recovery
func parseStructuredResponse(content string, result interface{}) error {
// Clean and validate UTF-8 content first
cleanContent := sanitizeUTF8Content(content)
// Extract JSON content from response
jsonContent := extractJSONFromContent(cleanContent)
if jsonContent == "" {
// If JSON extraction failed, try parsing the content directly as a fallback
jsonContent = cleanContent
}
// Parse JSON response with error recovery
return parseJSONWithFallback(jsonContent, result)
}
// callModelWithLogging is a common function to call model with logging and timing // callModelWithLogging is a common function to call model with logging and timing
// It handles the common pattern of: // It handles the common pattern of:
// 1. Log request // 1. Log request