MCPcopy Create free account
hub / github.com/bytebase/bytebase / TestLogAuditToStdoutFormat

Function TestLogAuditToStdoutFormat

backend/api/v1/audit_test.go:22–102  ·  view source on GitHub ↗

TestLogAuditToStdoutFormat is a contract test for the structured JSON fields emitted to stdout when audit log stdout is enabled. Operators run commands like `docker logs | grep '"log_type":"audit"'` — changes to these keys or their values are breaking for downstream log pipelines.

(t *testing.T)

Source from the content-addressed store, hash-verified

20// like `docker logs <container> | grep '"log_type":"audit"'` — changes to
21// these keys or their values are breaking for downstream log pipelines.
22func TestLogAuditToStdoutFormat(t *testing.T) {
23 a := require.New(t)
24
25 // Redirect slog default to a JSON handler writing into a buffer so the
26 // test can inspect the exact structured payload.
27 prev := slog.Default()
28 t.Cleanup(func() { slog.SetDefault(prev) })
29
30 var buf bytes.Buffer
31 slog.SetDefault(slog.New(slog.NewJSONHandler(&buf, &slog.HandlerOptions{
32 Level: slog.LevelInfo,
33 })))
34
35 p := &storepb.AuditLog{
36 Parent: "workspaces/ws-abc",
37 Method: "/bytebase.v1.AuthService/Login",
38 Resource: "alice@example.com",
39 Severity: storepb.AuditLog_INFO,
40 User: "users/alice@example.com",
41 Request: `{"email":"alice@example.com","web":true}`,
42 Response: `{"user":{"name":"users/alice@example.com","email":"alice@example.com"}}`,
43 Status: &spb.Status{Code: 0, Message: ""},
44 Latency: durationpb.New(123_000_000), // 123ms
45 RequestMetadata: &storepb.RequestMetadata{
46 CallerIp: "10.0.1.50",
47 CallerSuppliedUserAgent: "TestAgent/1.0",
48 },
49 }
50
51 logAuditToStdout(context.Background(), p)
52
53 // Every line the handler wrote is an independent JSON object.
54 lines := bytes.Split(bytes.TrimSpace(buf.Bytes()), []byte{'\n'})
55 a.Len(lines, 1, "logAuditToStdout must emit exactly one JSON record")
56
57 var got map[string]any
58 a.NoError(json.Unmarshal(lines[0], &got),
59 "stdout record must be valid JSON: %s", string(lines[0]))
60
61 // Keys the customer explicitly greps for — these form our public contract.
62 // If any of these assertions need to change, it's a breaking change for
63 // everyone consuming audit stdout logs.
64 a.Equal("audit", got["log_type"], `log_type=="audit" is how operators filter audit lines from application logs`)
65 a.Equal("workspaces/ws-abc", got["parent"])
66 a.Equal("/bytebase.v1.AuthService/Login", got["method"])
67 a.Equal("alice@example.com", got["resource"])
68 a.Equal("users/alice@example.com", got["user"])
69 a.Equal("INFO", got["severity"])
70 a.Equal("10.0.1.50", got["client_ip"])
71 a.Equal("TestAgent/1.0", got["user_agent"])
72 a.Equal(float64(123), got["latency_ms"], "latency must be exposed in milliseconds")
73 a.Equal(`{"email":"alice@example.com","web":true}`, got["request"],
74 "request payload must be emitted verbatim (already redacted upstream)")
75 a.Equal(`{"user":{"name":"users/alice@example.com","email":"alice@example.com"}}`, got["response"])
76
77 // Status code 0 (OK) should be reported explicitly so downstream pipelines
78 // can distinguish successful from failed calls.
79 a.Equal(float64(0), got["status_code"])

Callers

nothing calls this directly

Calls 5

logAuditToStdoutFunction · 0.85
LenMethod · 0.80
UnmarshalMethod · 0.80
EqualMethod · 0.65
ResetMethod · 0.45

Tested by

no test coverage detected