fix: generate typescript types for healthcheck pkg (#8846)

This commit is contained in:
Colin Adler
2023-08-03 16:20:46 -05:00
committed by GitHub
parent 72780c8031
commit 8ee500c59d
21 changed files with 333 additions and 204 deletions

30
coderd/apidoc/docs.go generated
View File

@ -11248,6 +11248,9 @@ const docTemplate = `{
"$ref": "#/definitions/derp.ServerInfoMessage"
},
"round_trip_ping": {
"type": "string"
},
"round_trip_ping_ms": {
"type": "integer"
},
"stun": {
@ -11316,7 +11319,9 @@ const docTemplate = `{
"enabled": {
"type": "boolean"
},
"error": {}
"error": {
"type": "string"
}
}
},
"healthcheck.DatabaseReport": {
@ -11329,6 +11334,9 @@ const docTemplate = `{
"type": "boolean"
},
"latency": {
"type": "string"
},
"latency_ms": {
"type": "integer"
},
"reachable": {
@ -11373,20 +11381,6 @@ const docTemplate = `{
}
},
"healthcheck.WebsocketReport": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"healthy": {
"type": "boolean"
},
"response": {
"$ref": "#/definitions/healthcheck.WebsocketResponse"
}
}
},
"healthcheck.WebsocketResponse": {
"type": "object",
"properties": {
"body": {
@ -11394,6 +11388,12 @@ const docTemplate = `{
},
"code": {
"type": "integer"
},
"error": {
"type": "string"
},
"healthy": {
"type": "boolean"
}
}
},

View File

@ -10232,6 +10232,9 @@
"$ref": "#/definitions/derp.ServerInfoMessage"
},
"round_trip_ping": {
"type": "string"
},
"round_trip_ping_ms": {
"type": "integer"
},
"stun": {
@ -10300,7 +10303,9 @@
"enabled": {
"type": "boolean"
},
"error": {}
"error": {
"type": "string"
}
}
},
"healthcheck.DatabaseReport": {
@ -10313,6 +10318,9 @@
"type": "boolean"
},
"latency": {
"type": "string"
},
"latency_ms": {
"type": "integer"
},
"reachable": {
@ -10357,20 +10365,6 @@
}
},
"healthcheck.WebsocketReport": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"healthy": {
"type": "boolean"
},
"response": {
"$ref": "#/definitions/healthcheck.WebsocketResponse"
}
}
},
"healthcheck.WebsocketResponse": {
"type": "object",
"properties": {
"body": {
@ -10378,6 +10372,12 @@
},
"code": {
"type": "integer"
},
"error": {
"type": "string"
},
"healthy": {
"type": "boolean"
}
}
},

View File

@ -12,6 +12,7 @@ import (
"github.com/coder/coder/coderd/util/ptr"
)
// @typescript-generate AccessURLReport
type AccessURLReport struct {
AccessURL string `json:"access_url"`
Healthy bool `json:"healthy"`

View File

@ -10,11 +10,13 @@ import (
"github.com/coder/coder/coderd/database"
)
// @typescript-generate DatabaseReport
type DatabaseReport struct {
Healthy bool `json:"healthy"`
Reachable bool `json:"reachable"`
Latency time.Duration `json:"latency"`
Error *string `json:"error"`
Healthy bool `json:"healthy"`
Reachable bool `json:"reachable"`
Latency string `json:"latency"`
LatencyMs int `json:"latency_ms"`
Error *string `json:"error"`
}
type DatabaseReportOptions struct {
@ -39,10 +41,12 @@ func (r *DatabaseReport) Run(ctx context.Context, opts *DatabaseReportOptions) {
slices.Sort(pings)
// Take the median ping.
r.Latency = pings[pingCount/2]
latency := pings[pingCount/2]
r.Latency = latency.String()
r.LatencyMs = int(latency.Milliseconds())
// Somewhat arbitrary, but if the latency is over 15ms, we consider it
// unhealthy.
if r.Latency < 15*time.Millisecond {
if latency < 15*time.Millisecond {
r.Healthy = true
}
r.Reachable = true

View File

@ -35,7 +35,8 @@ func TestDatabase(t *testing.T) {
assert.True(t, report.Healthy)
assert.True(t, report.Reachable)
assert.Equal(t, ping, report.Latency)
assert.Equal(t, ping.String(), report.Latency)
assert.Equal(t, int(ping.Milliseconds()), report.LatencyMs)
assert.Nil(t, report.Error)
})
@ -81,7 +82,8 @@ func TestDatabase(t *testing.T) {
assert.True(t, report.Healthy)
assert.True(t, report.Reachable)
assert.Equal(t, time.Millisecond, report.Latency)
assert.Equal(t, time.Millisecond.String(), report.Latency)
assert.Equal(t, 1, report.LatencyMs)
assert.Nil(t, report.Error)
})
}

View File

@ -24,6 +24,7 @@ import (
"github.com/coder/coder/coderd/util/ptr"
)
// @typescript-generate DERPReport
type DERPReport struct {
Healthy bool `json:"healthy"`
@ -36,6 +37,7 @@ type DERPReport struct {
Error *string `json:"error"`
}
// @typescript-generate DERPRegionReport
type DERPRegionReport struct {
mu sync.Mutex
Healthy bool `json:"healthy"`
@ -44,6 +46,8 @@ type DERPRegionReport struct {
NodeReports []*DERPNodeReport `json:"node_reports"`
Error *string `json:"error"`
}
// @typescript-generate DERPNodeReport
type DERPNodeReport struct {
mu sync.Mutex
clientCounter int
@ -53,7 +57,8 @@ type DERPNodeReport struct {
ServerInfo derp.ServerInfoMessage `json:"node_info"`
CanExchangeMessages bool `json:"can_exchange_messages"`
RoundTripPing time.Duration `json:"round_trip_ping"`
RoundTripPing string `json:"round_trip_ping"`
RoundTripPingMs int `json:"round_trip_ping_ms"`
UsesWebsocket bool `json:"uses_websocket"`
ClientLogs [][]string `json:"client_logs"`
ClientErrs [][]string `json:"client_errs"`
@ -62,10 +67,11 @@ type DERPNodeReport struct {
STUN DERPStunReport `json:"stun"`
}
// @typescript-generate DERPStunReport
type DERPStunReport struct {
Enabled bool
CanSTUN bool
Error error
Error *string
}
type DERPReportOptions struct {
@ -251,7 +257,9 @@ func (r *DERPNodeReport) doExchangeMessage(ctx context.Context) {
r.mu.Lock()
r.CanExchangeMessages = true
r.RoundTripPing = time.Since(*t)
rtt := time.Since(*t)
r.RoundTripPing = rtt.String()
r.RoundTripPingMs = int(rtt.Milliseconds())
r.mu.Unlock()
cancel()
@ -301,20 +309,20 @@ func (r *DERPNodeReport) doSTUNTest(ctx context.Context) {
addr, port, err := r.stunAddr(ctx)
if err != nil {
r.STUN.Error = xerrors.Errorf("get stun addr: %w", err)
r.STUN.Error = convertError(xerrors.Errorf("get stun addr: %w", err))
return
}
// We only create a prober to call ProbeUDP manually.
p, err := prober.DERP(prober.New(), "", time.Second, time.Second, time.Second)
if err != nil {
r.STUN.Error = xerrors.Errorf("create prober: %w", err)
r.STUN.Error = convertError(xerrors.Errorf("create prober: %w", err))
return
}
err = p.ProbeUDP(addr, port)(ctx)
if err != nil {
r.STUN.Error = xerrors.Errorf("probe stun: %w", err)
r.STUN.Error = convertError(xerrors.Errorf("probe stun: %w", err))
return
}

View File

@ -67,7 +67,7 @@ func TestDERP(t *testing.T) {
for _, node := range region.NodeReports {
assert.True(t, node.Healthy)
assert.True(t, node.CanExchangeMessages)
assert.Positive(t, node.RoundTripPing)
assert.NotEmpty(t, node.RoundTripPing)
assert.Len(t, node.ClientLogs, 2)
assert.Len(t, node.ClientLogs[0], 1)
assert.Len(t, node.ClientErrs[0], 0)
@ -76,7 +76,7 @@ func TestDERP(t *testing.T) {
assert.False(t, node.STUN.Enabled)
assert.False(t, node.STUN.CanSTUN)
assert.NoError(t, node.STUN.Error)
assert.Nil(t, node.STUN.Error)
}
}
})
@ -111,7 +111,7 @@ func TestDERP(t *testing.T) {
for _, node := range region.NodeReports {
assert.True(t, node.Healthy)
assert.True(t, node.CanExchangeMessages)
assert.Positive(t, node.RoundTripPing)
assert.NotEmpty(t, node.RoundTripPing)
assert.Len(t, node.ClientLogs, 2)
assert.Len(t, node.ClientLogs[0], 1)
assert.Len(t, node.ClientErrs[0], 0)
@ -120,7 +120,7 @@ func TestDERP(t *testing.T) {
assert.True(t, node.STUN.Enabled)
assert.True(t, node.STUN.CanSTUN)
assert.NoError(t, node.STUN.Error)
assert.Nil(t, node.STUN.Error)
}
}
})
@ -174,7 +174,7 @@ func TestDERP(t *testing.T) {
for _, node := range region.NodeReports {
assert.False(t, node.Healthy)
assert.True(t, node.CanExchangeMessages)
assert.Positive(t, node.RoundTripPing)
assert.NotEmpty(t, node.RoundTripPing)
assert.Len(t, node.ClientLogs, 2)
assert.Len(t, node.ClientLogs[0], 3)
assert.Len(t, node.ClientLogs[1], 3)
@ -185,7 +185,7 @@ func TestDERP(t *testing.T) {
assert.False(t, node.STUN.Enabled)
assert.False(t, node.STUN.CanSTUN)
assert.NoError(t, node.STUN.Error)
assert.Nil(t, node.STUN.Error)
}
}
})
@ -227,7 +227,7 @@ func TestDERP(t *testing.T) {
assert.True(t, node.STUN.Enabled)
assert.True(t, node.STUN.CanSTUN)
assert.NoError(t, node.STUN.Error)
assert.Nil(t, node.STUN.Error)
}
}
})

View File

@ -29,6 +29,7 @@ type Checker interface {
Database(ctx context.Context, opts *DatabaseReportOptions) DatabaseReport
}
// @typescript-generate Report
type Report struct {
// Time is the time the report was generated at.
Time time.Time `json:"time"`

View File

@ -2,6 +2,7 @@ package healthcheck
import (
"context"
"fmt"
"io"
"net/http"
"net/url"
@ -10,8 +11,6 @@ import (
"golang.org/x/xerrors"
"nhooyr.io/websocket"
"github.com/coder/coder/coderd/httpapi"
)
type WebsocketReportOptions struct {
@ -20,15 +19,12 @@ type WebsocketReportOptions struct {
HTTPClient *http.Client
}
// @typescript-generate WebsocketReport
type WebsocketReport struct {
Healthy bool `json:"healthy"`
Response WebsocketResponse `json:"response"`
Error *string `json:"error"`
}
type WebsocketResponse struct {
Body string `json:"body"`
Code int `json:"code"`
Healthy bool `json:"healthy"`
Body string `json:"body"`
Code int `json:"code"`
Error *string `json:"error"`
}
func (r *WebsocketReport) Run(ctx context.Context, opts *WebsocketReportOptions) {
@ -60,10 +56,8 @@ func (r *WebsocketReport) Run(ctx context.Context, opts *WebsocketReportOptions)
}
}
r.Response = WebsocketResponse{
Body: body,
Code: res.StatusCode,
}
r.Body = body
r.Code = res.StatusCode
}
if err != nil {
r.Error = convertError(xerrors.Errorf("websocket dial: %w", err))
@ -115,7 +109,8 @@ func (s *WebsocketEchoServer) ServeHTTP(rw http.ResponseWriter, r *http.Request)
ctx := r.Context()
c, err := websocket.Accept(rw, r, &websocket.AcceptOptions{})
if err != nil {
httpapi.Write(ctx, rw, http.StatusBadRequest, "unable to accept: "+err.Error())
rw.WriteHeader(http.StatusBadRequest)
_, _ = rw.Write([]byte(fmt.Sprint("unable to accept:", err)))
return
}
defer c.Close(websocket.StatusGoingAway, "goodbye")

View File

@ -63,7 +63,7 @@ func TestWebsocket(t *testing.T) {
})
require.NotNil(t, wsReport.Error)
assert.Equal(t, wsReport.Response.Body, "test error")
assert.Equal(t, wsReport.Response.Code, http.StatusBadRequest)
assert.Equal(t, wsReport.Body, "test error")
assert.Equal(t, wsReport.Code, http.StatusBadRequest)
})
}