The example keeps the two modules decoupled and checks that one trace id appears on both sides. Co-authored-by: Cursor <cursoragent@cursor.com>
54 lines
1.5 KiB
Go
54 lines
1.5 KiB
Go
package trace
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"error-code-system/domains"
|
|
"error-code-system/errcode"
|
|
"error-code-system/httpx"
|
|
"logging-system/logsys"
|
|
"logging-system/sink"
|
|
)
|
|
|
|
func TestErrorCodeReachesLogAndHTTP(t *testing.T) {
|
|
reg := errcode.NewRegistry()
|
|
domains.RegisterAll(reg)
|
|
mem := &sink.Memory{}
|
|
log := logsys.New(logsys.Options{Service: "agent-squad", Level: logsys.LevelInfo, Sinks: []logsys.Sink{mem}})
|
|
|
|
cause := errors.New("dial tcp: connection refused")
|
|
err := errcode.Wrap(cause, errcode.AgentProviderUnavailable, "模型不可达", "model", "glm-4")
|
|
const traceID = "trace-loop-0001"
|
|
log.WithTraceID(traceID).Error("provider down", err)
|
|
|
|
got := mem.Snapshot()
|
|
if len(got) != 1 {
|
|
t.Fatalf("logs %d", len(got))
|
|
}
|
|
if got[0].TraceID != traceID || got[0].Code != string(errcode.AgentProviderUnavailable) {
|
|
t.Fatalf("entry %+v", got[0])
|
|
}
|
|
if got[0].Fields["model"] != "glm-4" {
|
|
t.Fatalf("fields %+v", got[0].Fields)
|
|
}
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/runs", nil)
|
|
req.Header.Set(httpx.TraceHeader, traceID)
|
|
rec := httptest.NewRecorder()
|
|
httpx.WriteError(reg, rec, req, err)
|
|
if rec.Code != http.StatusServiceUnavailable {
|
|
t.Fatalf("status %d", rec.Code)
|
|
}
|
|
var env httpx.Envelope
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &env); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if env.Error.Code != got[0].Code || env.Error.TraceID != got[0].TraceID {
|
|
t.Fatalf("envelope %+v log code %s trace %s", env.Error, got[0].Code, got[0].TraceID)
|
|
}
|
|
}
|