feat(logging): add RequestID support in home request logging

- Included `RequestID` field in `homeRequestLogPayload` for better log categorization.
- Updated `forwardRequestLogToHome` and related components to handle `RequestID`.
- Added new test cases to validate `RequestID` propagation in streaming requests.
This commit is contained in:
Luis Pater
2026-05-25 20:44:32 +08:00
parent efa200ec48
commit 412d3442fa
2 changed files with 65 additions and 3 deletions

View File

@@ -166,6 +166,7 @@ type FileRequestLogger struct {
type homeRequestLogPayload struct {
Headers map[string][]string `json:"headers,omitempty"`
RequestID string `json:"request_id,omitempty"`
RequestLog string `json:"request_log,omitempty"`
}
@@ -192,7 +193,7 @@ func cloneHeaders(headers map[string][]string) map[string][]string {
return out
}
func (l *FileRequestLogger) forwardRequestLogToHome(ctx context.Context, headers map[string][]string, logText string) error {
func (l *FileRequestLogger) forwardRequestLogToHome(ctx context.Context, headers map[string][]string, requestID string, logText string) error {
if l == nil || !l.homeEnabled {
return nil
}
@@ -202,6 +203,7 @@ func (l *FileRequestLogger) forwardRequestLogToHome(ctx context.Context, headers
}
payload := homeRequestLogPayload{
Headers: cloneHeaders(headers),
RequestID: strings.TrimSpace(requestID),
RequestLog: logText,
}
raw, errMarshal := json.Marshal(&payload)
@@ -334,7 +336,7 @@ func (l *FileRequestLogger) logRequest(url, method string, requestHeaders map[st
if writeErr != nil {
return fmt.Errorf("failed to build request log content: %w", writeErr)
}
return l.forwardRequestLogToHome(context.Background(), requestHeaders, buf.String())
return l.forwardRequestLogToHome(context.Background(), requestHeaders, requestID, buf.String())
}
// Ensure logs directory exists
@@ -1631,11 +1633,12 @@ type homeStreamingLogWriter struct {
apiRequest []byte
apiResponse []byte
apiWebsocketTime []byte
requestID string
apiResponseTS time.Time
firstChunkTS time.Time
}
func newHomeStreamingLogWriter(url, method string, headers map[string][]string, body []byte, _ string) *homeStreamingLogWriter {
func newHomeStreamingLogWriter(url, method string, headers map[string][]string, body []byte, requestID string) *homeStreamingLogWriter {
requestHeaders := make(map[string][]string, len(headers))
for key, values := range headers {
headerValues := make([]string, len(values))
@@ -1649,6 +1652,7 @@ func newHomeStreamingLogWriter(url, method string, headers map[string][]string,
timestamp: time.Now(),
requestHeaders: requestHeaders,
requestBody: append([]byte(nil), body...),
requestID: strings.TrimSpace(requestID),
chunkChan: make(chan []byte, 100),
doneChan: make(chan struct{}),
}
@@ -1766,6 +1770,7 @@ func (w *homeStreamingLogWriter) Close() error {
payload := homeRequestLogPayload{
Headers: cloneHeaders(w.requestHeaders),
RequestID: w.requestID,
RequestLog: buf.String(),
}
raw, errMarshal := json.Marshal(&payload)

View File

@@ -77,6 +77,7 @@ func TestFileRequestLogger_HomeEnabled_ForwardsWhenRequestLogEnabled(t *testing.
var got struct {
Headers map[string][]string `json:"headers"`
RequestID string `json:"request_id"`
RequestLog string `json:"request_log"`
}
if errUnmarshal := json.Unmarshal(stub.pushed[0], &got); errUnmarshal != nil {
@@ -88,6 +89,62 @@ func TestFileRequestLogger_HomeEnabled_ForwardsWhenRequestLogEnabled(t *testing.
if got.Headers == nil || got.Headers["Authorization"][0] != "Bearer secret" {
t.Fatalf("headers.authorization = %+v, want Bearer secret", got.Headers["Authorization"])
}
if got.RequestID != "req-1" {
t.Fatalf("request_id = %q, want req-1", got.RequestID)
}
if got.RequestLog == "" {
t.Fatalf("request_log empty, want non-empty")
}
}
func TestFileRequestLogger_HomeEnabled_ForwardsStreamingRequestID(t *testing.T) {
original := currentHomeRequestLogClient
defer func() {
currentHomeRequestLogClient = original
}()
stub := &stubHomeRequestLogClient{heartbeatOK: true}
currentHomeRequestLogClient = func() homeRequestLogClient {
return stub
}
logsDir := t.TempDir()
logger := NewFileRequestLogger(true, logsDir, "", 0)
logger.SetHomeEnabled(true)
writer, errLog := logger.LogStreamingRequest(
"/v1/responses",
http.MethodPost,
map[string][]string{"Content-Type": {"application/json"}},
[]byte(`{"input":"hello"}`),
"stream-req-1",
)
if errLog != nil {
t.Fatalf("LogStreamingRequest error: %v", errLog)
}
if errStatus := writer.WriteStatus(http.StatusOK, map[string][]string{"Content-Type": {"text/event-stream"}}); errStatus != nil {
t.Fatalf("WriteStatus error: %v", errStatus)
}
writer.WriteChunkAsync([]byte("data: ok\n\n"))
if errClose := writer.Close(); errClose != nil {
t.Fatalf("Close error: %v", errClose)
}
if len(stub.pushed) != 1 {
t.Fatalf("home pushed records = %d, want 1", len(stub.pushed))
}
var got struct {
RequestID string `json:"request_id"`
RequestLog string `json:"request_log"`
}
if errUnmarshal := json.Unmarshal(stub.pushed[0], &got); errUnmarshal != nil {
t.Fatalf("unmarshal payload: %v payload=%s", errUnmarshal, string(stub.pushed[0]))
}
if got.RequestID != "stream-req-1" {
t.Fatalf("request_id = %q, want stream-req-1", got.RequestID)
}
if got.RequestLog == "" {
t.Fatalf("request_log empty, want non-empty")
}