feat(surf): serve startup summary, shutdown report and http request log
- serve prints a startup summary on a terminal (version, environment, URL, admin, database host and name, pending migrations, plugins, drivers) and logs it as a 'startup summary' record plus 'listening on <addr>' - on SIGINT/SIGTERM serve drains, prints and logs a shutdown report and returns nil (exit 0), or the drain errors (exit 1) - the request log is on by default under diary component http with request_id; the route pattern, never the path, is logged - lagoon.PendingMigrations, conga.Worker.Stats, diary.HideOnTTY, bonfire.IsTerminal and bonfire.Details back the summary and report
This commit is contained in:
@@ -33,13 +33,14 @@ func (blogPostsPlugin) Routes(r pact.Router) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// accessLogRouter assembles the blog plugin with http.access_log set to on
|
||||
// and a published JSON logger writing into the returned buffer.
|
||||
// accessLogRouter assembles the blog plugin with http.access_log left at
|
||||
// its default (on) or set to false, and a published JSON logger writing
|
||||
// into the returned buffer.
|
||||
func accessLogRouter(t *testing.T, on bool) (http.Handler, *bytes.Buffer) {
|
||||
t.Helper()
|
||||
y := "body_limits:\n default_bytes: 1024\n upload_bytes: 1024\n"
|
||||
if on {
|
||||
y += "access_log: true\n"
|
||||
if !on {
|
||||
y += "access_log: false\n"
|
||||
}
|
||||
app := backpack.New(writeHTTPConfig(t, y))
|
||||
var buf bytes.Buffer
|
||||
@@ -76,18 +77,23 @@ func TestAccessLogSmoke(t *testing.T) {
|
||||
h, buf := accessLogRouter(t, true)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/blog/posts/7?token=secret", nil))
|
||||
req := httptest.NewRequest(http.MethodGet, "/blog/posts/7?token=secret", nil)
|
||||
req.Header.Set("X-Request-Id", " req-42 ")
|
||||
h.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("GET /blog/posts/7 = %d", rec.Code)
|
||||
}
|
||||
recs := accessRecords(t, buf)
|
||||
if len(recs) != 1 {
|
||||
t.Fatalf("records = %d, want 1:\n%s", len(recs), buf.String())
|
||||
t.Fatalf("records = %d, want 1 (the request log is on by default):\n%s", len(recs), buf.String())
|
||||
}
|
||||
r := recs[0]
|
||||
if r["method"] != "GET" || r["pattern"] != "GET /blog/posts/{id}" || r["status"] != float64(200) || r["level"] != "INFO" {
|
||||
t.Fatalf("matched record = %v", r)
|
||||
}
|
||||
if r["request_id"] != "req-42" {
|
||||
t.Fatalf("request_id = %v, want the trimmed X-Request-Id", r["request_id"])
|
||||
}
|
||||
if _, ok := r["duration_ms"].(float64); !ok {
|
||||
t.Fatalf("matched record has no duration_ms: %v", r)
|
||||
}
|
||||
@@ -112,6 +118,17 @@ func TestAccessLogSmoke(t *testing.T) {
|
||||
if r["pattern"] != "" || r["status"] != float64(404) {
|
||||
t.Fatalf("unmatched record = %v", r)
|
||||
}
|
||||
if _, ok := r["request_id"]; ok {
|
||||
t.Fatalf("a request without X-Request-Id has a request_id: %v", r)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
long := httptest.NewRequest(http.MethodGet, "/blog/posts/7", nil)
|
||||
long.Header.Set("X-Request-Id", strings.Repeat("x", 300))
|
||||
h.ServeHTTP(httptest.NewRecorder(), long)
|
||||
if recs = accessRecords(t, buf); len(recs) != 1 || len(recs[0]["request_id"].(string)) != errorPageMaxRequestID {
|
||||
t.Fatalf("a long X-Request-Id is not cut to %d bytes: %v", errorPageMaxRequestID, recs)
|
||||
}
|
||||
if _, ok := r["path"]; ok {
|
||||
t.Fatalf("unmatched record carries path: %v", r)
|
||||
}
|
||||
@@ -242,6 +259,8 @@ func accessLogEdgesRouter(t *testing.T, on, locale bool, flushErr *error) (http.
|
||||
y := "body_limits:\n default_bytes: 1024\n upload_bytes: 1024\n"
|
||||
if on {
|
||||
y += "access_log: true\n"
|
||||
} else {
|
||||
y += "access_log: false\n"
|
||||
}
|
||||
app := backpack.New(writeHTTPConfig(t, y))
|
||||
var buf bytes.Buffer
|
||||
|
||||
Reference in New Issue
Block a user