feat(go): add realtime pipeline observability

This commit is contained in:
lingniu
2026-07-03 15:06:27 +08:00
parent 28c81611a1
commit b8299faefa
10 changed files with 636 additions and 6 deletions

View File

@@ -79,6 +79,7 @@ func TestTCPServerRecordsFrameMetrics(t *testing.T) {
text := registry.Render()
for _, want := range []string{
`vehicle_gateway_frames_total{protocol="JT808",status="OK"} 1`,
`vehicle_gateway_identity_total{protocol="JT808",status="unresolved"} 1`,
`vehicle_gateway_publish_total{kind="raw",protocol="JT808",status="ok"} 1`,
} {
if !strings.Contains(text, want) {
@@ -139,12 +140,14 @@ func TestTCPServerPublishesBadFrameOnlyToRaw(t *testing.T) {
good := buildGBFrame(0x02, 0xfe, "LNBSCB3D4R1234567", nil)
good[len(good)-1] ^= 0xff
sink := &recordingSink{}
registry := metrics.NewRegistry()
server := newTestServer(t, TCPProtocol{
Protocol: envelope.ProtocolGB32960,
Addr: ":0",
Extract: gb32960.ExtractFrames,
Parse: gb32960.ParseFrame,
}, sink)
server.metrics = registry
client, done := runPipe(t, server)
if _, err := client.Write(good); err != nil {
@@ -162,6 +165,41 @@ func TestTCPServerPublishesBadFrameOnlyToRaw(t *testing.T) {
if sink.raw[0].ParseError == "" {
t.Fatal("parse error should be recorded")
}
if text := registry.Render(); !strings.Contains(text, `vehicle_gateway_parse_errors_total{protocol="GB32960",reason="checksum"} 1`) {
t.Fatalf("parse error metric missing:\n%s", text)
}
}
func TestTCPServerAnnotatesUnresolvedIdentity(t *testing.T) {
sink := &recordingSink{}
server := newTestServer(t, TCPProtocol{
Protocol: envelope.ProtocolJT808,
Addr: ":0",
Extract: func(raw []byte) ([][]byte, []byte, error) {
return [][]byte{raw}, nil, nil
},
Parse: func(_ []byte, receivedAtMS int64, sourceEndpoint string) (envelope.FrameEnvelope, error) {
return envelope.FrameEnvelope{
Protocol: envelope.ProtocolJT808,
MessageID: "0x0200",
Phone: "13307795425",
SourceEndpoint: sourceEndpoint,
ReceivedAtMS: receivedAtMS,
EventTimeMS: receivedAtMS,
ParseStatus: envelope.ParseOK,
}, nil
},
}, sink)
server.handleFrame(context.Background(), nil, []byte{0x01}, "127.0.0.1:808", &connectionState{})
if len(sink.raw) != 1 {
t.Fatalf("raw count = %d", len(sink.raw))
}
identity, ok := sink.raw[0].Parsed["identity"].(map[string]any)
if !ok || identity["resolved"] != false || identity["reason"] != "no_binding" {
t.Fatalf("identity metadata = %#v", sink.raw[0].Parsed["identity"])
}
}
func TestTCPServerWritesProtocolResponseAfterPublish(t *testing.T) {