19205: Report longest-running active and abandoned reqs in metrics.
[arvados.git] / sdk / go / httpserver / inspect_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 package httpserver
6
7 import (
8         "context"
9         "encoding/json"
10         "net/http"
11         "net/http/httptest"
12
13         "github.com/prometheus/client_golang/prometheus"
14         "github.com/prometheus/client_golang/prometheus/promhttp"
15         check "gopkg.in/check.v1"
16 )
17
18 func (s *Suite) TestInspect(c *check.C) {
19         reg := prometheus.NewRegistry()
20         h := newTestHandler()
21         mh := Inspect(reg, "abcd", h)
22         handlerReturned := make(chan struct{})
23         reqctx, reqcancel := context.WithCancel(context.Background())
24         longreq := httptest.NewRequest("GET", "/test", nil).WithContext(reqctx)
25         go func() {
26                 mh.ServeHTTP(httptest.NewRecorder(), longreq)
27                 close(handlerReturned)
28         }()
29         <-h.inHandler
30
31         resp := httptest.NewRecorder()
32         req := httptest.NewRequest("GET", "/_inspect/requests", nil)
33         mh.ServeHTTP(resp, req)
34         c.Check(resp.Code, check.Equals, http.StatusUnauthorized)
35         c.Check(resp.Body.String(), check.Equals, `{"errors":["unauthorized"]}`+"\n")
36
37         resp = httptest.NewRecorder()
38         req.Header.Set("Authorization", "Bearer abcde")
39         mh.ServeHTTP(resp, req)
40         c.Check(resp.Code, check.Equals, http.StatusUnauthorized)
41
42         resp = httptest.NewRecorder()
43         req.Header.Set("Authorization", "Bearer abcd")
44         mh.ServeHTTP(resp, req)
45         c.Check(resp.Code, check.Equals, http.StatusOK)
46         reqs := []map[string]interface{}{}
47         err := json.NewDecoder(resp.Body).Decode(&reqs)
48         c.Check(err, check.IsNil)
49         c.Check(reqs, check.HasLen, 1)
50         c.Check(reqs[0]["URL"], check.Equals, "/test")
51
52         // Request is active, so we should see active request age > 0
53         resp = httptest.NewRecorder()
54         mreq := httptest.NewRequest("GET", "/metrics", nil)
55         promhttp.HandlerFor(reg, promhttp.HandlerOpts{}).ServeHTTP(resp, mreq)
56         c.Check(resp.Code, check.Equals, http.StatusOK)
57         c.Check(resp.Body.String(), check.Matches, `(?ms).*\narvados_max_active_request_age_seconds [0\.]*[1-9][-\d\.e]*\n.*`)
58         c.Check(resp.Body.String(), check.Matches, `(?ms).*\narvados_max_abandoned_request_age_seconds 0\n.*`)
59
60         reqcancel()
61
62         // Request context is canceled but handler hasn't returned, so
63         // we should see max abandoned request age > 0
64         resp = httptest.NewRecorder()
65         promhttp.HandlerFor(reg, promhttp.HandlerOpts{}).ServeHTTP(resp, mreq)
66         c.Check(resp.Code, check.Equals, http.StatusOK)
67         c.Check(resp.Body.String(), check.Matches, `(?ms).*\narvados_max_active_request_age_seconds 0\n.*`)
68         c.Check(resp.Body.String(), check.Matches, `(?ms).*\narvados_max_abandoned_request_age_seconds [0\.]*[1-9][-\d\.e]*\n.*`)
69
70         h.okToProceed <- struct{}{}
71         <-handlerReturned
72
73         // Handler has returned, so we should see max abandoned
74         // request age == max active request age == 0
75         resp = httptest.NewRecorder()
76         promhttp.HandlerFor(reg, promhttp.HandlerOpts{}).ServeHTTP(resp, mreq)
77         c.Check(resp.Code, check.Equals, http.StatusOK)
78         c.Check(resp.Body.String(), check.Matches, `(?ms).*\narvados_max_active_request_age_seconds 0\n.*`)
79         c.Check(resp.Body.String(), check.Matches, `(?ms).*\narvados_max_abandoned_request_age_seconds 0\n.*`)
80
81         // ...and no active requests at the /_monitor endpoint
82         resp = httptest.NewRecorder()
83         mh.ServeHTTP(resp, req)
84         c.Check(resp.Code, check.Equals, http.StatusOK)
85         reqs = nil
86         err = json.NewDecoder(resp.Body).Decode(&reqs)
87         c.Check(err, check.IsNil)
88         c.Assert(reqs, check.HasLen, 0)
89 }