mirror of https://github.com/coder/coder.git
refactor(coderd/healthcheck): make Warnings an object with { Code, Message } (#10950)
- Adds health.Message { code string, mesasge string } - Refactors existing warnings []string to be of type []health.Message instead
This commit is contained in:
parent
4f9292859d
commit
07895006d9
|
@ -12258,7 +12258,7 @@ const docTemplate = `{
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12297,7 +12297,7 @@ const docTemplate = `{
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12348,7 +12348,7 @@ const docTemplate = `{
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12367,6 +12367,56 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"health.Code": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"EUNKNOWN",
|
||||
"EWP01",
|
||||
"EWP02",
|
||||
"EWP03",
|
||||
"EWP04",
|
||||
"EDB01",
|
||||
"EDB02",
|
||||
"EWS01",
|
||||
"EWS02",
|
||||
"EWS03",
|
||||
"EACS01",
|
||||
"EACS02",
|
||||
"EACS03",
|
||||
"EACS04",
|
||||
"EDERP01",
|
||||
"EDERP02"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"CodeUnknown",
|
||||
"CodeProxyUpdate",
|
||||
"CodeProxyFetch",
|
||||
"CodeProxyVersionMismatch",
|
||||
"CodeProxyUnhealthy",
|
||||
"CodeDatabasePingFailed",
|
||||
"CodeDatabasePingSlow",
|
||||
"CodeWebsocketDial",
|
||||
"CodeWebsocketEcho",
|
||||
"CodeWebsocketMsg",
|
||||
"CodeAccessURLNotSet",
|
||||
"CodeAccessURLInvalid",
|
||||
"CodeAccessURLFetch",
|
||||
"CodeAccessURLNotOK",
|
||||
"CodeDERPNodeUsesWebsocket",
|
||||
"CodeDERPOneNodeUnhealthy"
|
||||
]
|
||||
},
|
||||
"health.Message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"$ref": "#/definitions/health.Code"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"health.Severity": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
@ -12420,7 +12470,7 @@ const docTemplate = `{
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12465,7 +12515,7 @@ const docTemplate = `{
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12579,7 +12629,7 @@ const docTemplate = `{
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
},
|
||||
"workspace_proxies": {
|
||||
|
|
|
@ -11163,7 +11163,7 @@
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11198,7 +11198,7 @@
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11245,7 +11245,7 @@
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11264,6 +11264,56 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"health.Code": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"EUNKNOWN",
|
||||
"EWP01",
|
||||
"EWP02",
|
||||
"EWP03",
|
||||
"EWP04",
|
||||
"EDB01",
|
||||
"EDB02",
|
||||
"EWS01",
|
||||
"EWS02",
|
||||
"EWS03",
|
||||
"EACS01",
|
||||
"EACS02",
|
||||
"EACS03",
|
||||
"EACS04",
|
||||
"EDERP01",
|
||||
"EDERP02"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"CodeUnknown",
|
||||
"CodeProxyUpdate",
|
||||
"CodeProxyFetch",
|
||||
"CodeProxyVersionMismatch",
|
||||
"CodeProxyUnhealthy",
|
||||
"CodeDatabasePingFailed",
|
||||
"CodeDatabasePingSlow",
|
||||
"CodeWebsocketDial",
|
||||
"CodeWebsocketEcho",
|
||||
"CodeWebsocketMsg",
|
||||
"CodeAccessURLNotSet",
|
||||
"CodeAccessURLInvalid",
|
||||
"CodeAccessURLFetch",
|
||||
"CodeAccessURLNotOK",
|
||||
"CodeDERPNodeUsesWebsocket",
|
||||
"CodeDERPOneNodeUnhealthy"
|
||||
]
|
||||
},
|
||||
"health.Message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"$ref": "#/definitions/health.Code"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"health.Severity": {
|
||||
"type": "string",
|
||||
"enum": ["ok", "warning", "error"],
|
||||
|
@ -11305,7 +11355,7 @@
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11346,7 +11396,7 @@
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11452,7 +11502,7 @@
|
|||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/health.Message"
|
||||
}
|
||||
},
|
||||
"workspace_proxies": {
|
||||
|
|
|
@ -8,16 +8,15 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/healthcheck/health"
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
)
|
||||
|
||||
// @typescript-generate AccessURLReport
|
||||
type AccessURLReport struct {
|
||||
// Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity" enums:"ok,warning,error"`
|
||||
Warnings []string `json:"warnings"`
|
||||
Dismissed bool `json:"dismissed"`
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity" enums:"ok,warning,error"`
|
||||
Warnings []health.Message `json:"warnings"`
|
||||
Dismissed bool `json:"dismissed"`
|
||||
|
||||
AccessURL string `json:"access_url"`
|
||||
Reachable bool `json:"reachable"`
|
||||
|
@ -38,11 +37,11 @@ func (r *AccessURLReport) Run(ctx context.Context, opts *AccessURLReportOptions)
|
|||
defer cancel()
|
||||
|
||||
r.Severity = health.SeverityOK
|
||||
r.Warnings = []string{}
|
||||
r.Warnings = []health.Message{}
|
||||
r.Dismissed = opts.Dismissed
|
||||
|
||||
if opts.AccessURL == nil {
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeAccessURLNotSet, "Access URL not set"))
|
||||
r.Error = health.Errorf(health.CodeAccessURLNotSet, "Access URL not set")
|
||||
r.Severity = health.SeverityError
|
||||
return
|
||||
}
|
||||
|
@ -54,21 +53,21 @@ func (r *AccessURLReport) Run(ctx context.Context, opts *AccessURLReportOptions)
|
|||
|
||||
accessURL, err := opts.AccessURL.Parse("/healthz")
|
||||
if err != nil {
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeAccessURLInvalid, "parse healthz endpoint: %s", err))
|
||||
r.Error = health.Errorf(health.CodeAccessURLInvalid, "parse healthz endpoint: %s", err)
|
||||
r.Severity = health.SeverityError
|
||||
return
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", accessURL.String(), nil)
|
||||
if err != nil {
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeAccessURLFetch, "create healthz request: %s", err))
|
||||
r.Error = health.Errorf(health.CodeAccessURLFetch, "create healthz request: %s", err)
|
||||
r.Severity = health.SeverityError
|
||||
return
|
||||
}
|
||||
|
||||
res, err := opts.Client.Do(req)
|
||||
if err != nil {
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeAccessURLFetch, "get healthz endpoint: %s", err))
|
||||
r.Error = health.Errorf(health.CodeAccessURLFetch, "get healthz endpoint: %s", err)
|
||||
r.Severity = health.SeverityError
|
||||
return
|
||||
}
|
||||
|
@ -76,7 +75,7 @@ func (r *AccessURLReport) Run(ctx context.Context, opts *AccessURLReportOptions)
|
|||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeAccessURLFetch, "read healthz response: %s", err))
|
||||
r.Error = health.Errorf(health.CodeAccessURLFetch, "read healthz response: %s", err)
|
||||
r.Severity = health.SeverityError
|
||||
return
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ func TestAccessURL(t *testing.T) {
|
|||
assert.Equal(t, string(resp), report.HealthzResponse)
|
||||
assert.Nil(t, report.Error)
|
||||
if assert.NotEmpty(t, report.Warnings) {
|
||||
assert.Contains(t, report.Warnings[0], health.CodeAccessURLNotOK)
|
||||
assert.Equal(t, report.Warnings[0].Code, health.CodeAccessURLNotOK)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -4,11 +4,10 @@ import (
|
|||
"context"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/healthcheck/health"
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -18,10 +17,10 @@ const (
|
|||
// @typescript-generate DatabaseReport
|
||||
type DatabaseReport struct {
|
||||
// Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity" enums:"ok,warning,error"`
|
||||
Warnings []string `json:"warnings"`
|
||||
Dismissed bool `json:"dismissed"`
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity" enums:"ok,warning,error"`
|
||||
Warnings []health.Message `json:"warnings"`
|
||||
Dismissed bool `json:"dismissed"`
|
||||
|
||||
Reachable bool `json:"reachable"`
|
||||
Latency string `json:"latency"`
|
||||
|
@ -38,7 +37,7 @@ type DatabaseReportOptions struct {
|
|||
}
|
||||
|
||||
func (r *DatabaseReport) Run(ctx context.Context, opts *DatabaseReportOptions) {
|
||||
r.Warnings = []string{}
|
||||
r.Warnings = []health.Message{}
|
||||
r.Severity = health.SeverityOK
|
||||
r.Dismissed = opts.Dismissed
|
||||
|
||||
|
@ -55,7 +54,7 @@ func (r *DatabaseReport) Run(ctx context.Context, opts *DatabaseReportOptions) {
|
|||
for i := 0; i < pingCount; i++ {
|
||||
pong, err := opts.DB.Ping(ctx)
|
||||
if err != nil {
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeDatabasePingFailed, "ping database: %s", err))
|
||||
r.Error = health.Errorf(health.CodeDatabasePingFailed, "ping database: %s", err)
|
||||
r.Severity = health.SeverityError
|
||||
|
||||
return
|
||||
|
|
|
@ -143,7 +143,7 @@ func TestDatabase(t *testing.T) {
|
|||
assert.Equal(t, time.Second.Milliseconds(), report.ThresholdMS)
|
||||
assert.Nil(t, report.Error)
|
||||
if assert.NotEmpty(t, report.Warnings) {
|
||||
assert.Contains(t, report.Warnings[0], health.CodeDatabasePingSlow)
|
||||
assert.Equal(t, report.Warnings[0].Code, health.CodeDatabasePingSlow)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -36,10 +36,10 @@ const (
|
|||
// @typescript-generate Report
|
||||
type Report struct {
|
||||
// Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity" enums:"ok,warning,error"`
|
||||
Warnings []string `json:"warnings"`
|
||||
Dismissed bool `json:"dismissed"`
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity" enums:"ok,warning,error"`
|
||||
Warnings []health.Message `json:"warnings"`
|
||||
Dismissed bool `json:"dismissed"`
|
||||
|
||||
Regions map[int]*RegionReport `json:"regions"`
|
||||
|
||||
|
@ -55,9 +55,9 @@ type RegionReport struct {
|
|||
mu sync.Mutex
|
||||
|
||||
// Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity" enums:"ok,warning,error"`
|
||||
Warnings []string `json:"warnings"`
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity" enums:"ok,warning,error"`
|
||||
Warnings []health.Message `json:"warnings"`
|
||||
|
||||
Region *tailcfg.DERPRegion `json:"region"`
|
||||
NodeReports []*NodeReport `json:"node_reports"`
|
||||
|
@ -70,9 +70,9 @@ type NodeReport struct {
|
|||
clientCounter int
|
||||
|
||||
// Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity" enums:"ok,warning,error"`
|
||||
Warnings []string `json:"warnings"`
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity" enums:"ok,warning,error"`
|
||||
Warnings []health.Message `json:"warnings"`
|
||||
|
||||
Node *tailcfg.DERPNode `json:"node"`
|
||||
|
||||
|
@ -104,7 +104,7 @@ type ReportOptions struct {
|
|||
func (r *Report) Run(ctx context.Context, opts *ReportOptions) {
|
||||
r.Healthy = true
|
||||
r.Severity = health.SeverityOK
|
||||
r.Warnings = []string{}
|
||||
r.Warnings = []health.Message{}
|
||||
r.Dismissed = opts.Dismissed
|
||||
|
||||
r.Regions = map[int]*RegionReport{}
|
||||
|
@ -168,7 +168,7 @@ func (r *RegionReport) Run(ctx context.Context) {
|
|||
r.Healthy = true
|
||||
r.Severity = health.SeverityOK
|
||||
r.NodeReports = []*NodeReport{}
|
||||
r.Warnings = []string{}
|
||||
r.Warnings = []health.Message{}
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
var unhealthyNodes int // atomic.Int64 is not mandatory as we depend on RegionReport mutex.
|
||||
|
@ -263,7 +263,7 @@ func (r *NodeReport) Run(ctx context.Context) {
|
|||
r.Severity = health.SeverityOK
|
||||
r.ClientLogs = [][]string{}
|
||||
r.ClientErrs = [][]string{}
|
||||
r.Warnings = []string{}
|
||||
r.Warnings = []health.Message{}
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ func TestDERP(t *testing.T) {
|
|||
assert.Equal(t, health.SeverityWarning, report.Severity)
|
||||
assert.True(t, report.Dismissed)
|
||||
if assert.NotEmpty(t, report.Warnings) {
|
||||
assert.Contains(t, report.Warnings[0], health.CodeDERPOneNodeUnhealthy)
|
||||
assert.Contains(t, report.Warnings[0].Code, health.CodeDERPOneNodeUnhealthy)
|
||||
}
|
||||
for _, region := range report.Regions {
|
||||
assert.True(t, region.Healthy)
|
||||
|
@ -236,7 +236,7 @@ func TestDERP(t *testing.T) {
|
|||
assert.True(t, report.Healthy)
|
||||
assert.Equal(t, health.SeverityWarning, report.Severity)
|
||||
if assert.NotEmpty(t, report.Warnings) {
|
||||
assert.Contains(t, report.Warnings[0], health.CodeDERPNodeUsesWebsocket)
|
||||
assert.Equal(t, report.Warnings[0].Code, health.CodeDERPNodeUsesWebsocket)
|
||||
}
|
||||
for _, region := range report.Regions {
|
||||
assert.True(t, region.Healthy)
|
||||
|
|
|
@ -3,6 +3,8 @@ package health
|
|||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -47,16 +49,34 @@ func (s Severity) Value() int {
|
|||
return severityRank[s]
|
||||
}
|
||||
|
||||
// @typescript-generate Message
|
||||
type Message struct {
|
||||
Code Code `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (m Message) String() string {
|
||||
var sb strings.Builder
|
||||
_, _ = sb.WriteString(string(m.Code))
|
||||
_, _ = sb.WriteRune(':')
|
||||
_, _ = sb.WriteRune(' ')
|
||||
_, _ = sb.WriteString(m.Message)
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// Code is a stable identifier used to link to documentation.
|
||||
// @typescript-generate Code
|
||||
type Code string
|
||||
|
||||
// Messagef is a convenience function for formatting a healthcheck error message.
|
||||
func Messagef(code Code, msg string, args ...any) string {
|
||||
var sb strings.Builder
|
||||
_, _ = sb.WriteString(string(code))
|
||||
_, _ = sb.WriteRune(':')
|
||||
_, _ = sb.WriteRune(' ')
|
||||
_, _ = sb.WriteString(fmt.Sprintf(msg, args...))
|
||||
return sb.String()
|
||||
// Messagef is a convenience function for returning a health.Message
|
||||
func Messagef(code Code, msg string, args ...any) Message {
|
||||
return Message{
|
||||
Code: code,
|
||||
Message: fmt.Sprintf(msg, args...),
|
||||
}
|
||||
}
|
||||
|
||||
// Errorf is a convenience function for returning a stringly-typed version of a Message.
|
||||
func Errorf(code Code, msg string, args ...any) *string {
|
||||
return ptr.Ref(Messagef(code, msg, args...).String())
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ func Run(ctx context.Context, opts *ReportOptions) *Report {
|
|||
defer wg.Done()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
report.DERP.Error = ptr.Ref(health.Messagef(health.CodeUnknown, "derp report panic: %s", err))
|
||||
report.DERP.Error = health.Errorf(health.CodeUnknown, "derp report panic: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -115,7 +115,7 @@ func Run(ctx context.Context, opts *ReportOptions) *Report {
|
|||
defer wg.Done()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
report.AccessURL.Error = ptr.Ref(health.Messagef(health.CodeUnknown, "access url report panic: %s", err))
|
||||
report.AccessURL.Error = health.Errorf(health.CodeUnknown, "access url report panic: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -127,7 +127,7 @@ func Run(ctx context.Context, opts *ReportOptions) *Report {
|
|||
defer wg.Done()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
report.Websocket.Error = ptr.Ref(health.Messagef(health.CodeUnknown, "websocket report panic: %s", err))
|
||||
report.Websocket.Error = health.Errorf(health.CodeUnknown, "websocket report panic: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -139,7 +139,7 @@ func Run(ctx context.Context, opts *ReportOptions) *Report {
|
|||
defer wg.Done()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
report.Database.Error = ptr.Ref(health.Messagef(health.CodeUnknown, "database report panic: %s", err))
|
||||
report.Database.Error = health.Errorf(health.CodeUnknown, "database report panic: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -151,7 +151,7 @@ func Run(ctx context.Context, opts *ReportOptions) *Report {
|
|||
defer wg.Done()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
report.WorkspaceProxy.Error = ptr.Ref(health.Messagef(health.CodeUnknown, "proxy report panic: %s", err))
|
||||
report.WorkspaceProxy.Error = health.Errorf(health.CodeUnknown, "proxy report panic: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ func TestHealthcheck(t *testing.T) {
|
|||
checker: &testChecker{
|
||||
DERPReport: derphealth.Report{
|
||||
Healthy: true,
|
||||
Warnings: []string{"foobar"},
|
||||
Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}},
|
||||
Severity: health.SeverityWarning,
|
||||
},
|
||||
AccessURLReport: healthcheck.AccessURLReport{
|
||||
|
@ -259,7 +259,7 @@ func TestHealthcheck(t *testing.T) {
|
|||
},
|
||||
WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{
|
||||
Healthy: true,
|
||||
Warnings: []string{"foobar"},
|
||||
Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}},
|
||||
Severity: health.SeverityWarning,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
"nhooyr.io/websocket"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/healthcheck/health"
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
)
|
||||
|
||||
// @typescript-generate WebsocketReport
|
||||
|
@ -76,7 +75,7 @@ func (r *WebsocketReport) Run(ctx context.Context, opts *WebsocketReportOptions)
|
|||
}
|
||||
if err != nil {
|
||||
r.Error = convertError(xerrors.Errorf("websocket dial: %w", err))
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeWebsocketDial, "websocket dial: %s", err))
|
||||
r.Error = health.Errorf(health.CodeWebsocketDial, "websocket dial: %s", err)
|
||||
r.Severity = health.SeverityError
|
||||
return
|
||||
}
|
||||
|
@ -86,26 +85,26 @@ func (r *WebsocketReport) Run(ctx context.Context, opts *WebsocketReportOptions)
|
|||
msg := strconv.Itoa(i)
|
||||
err := c.Write(ctx, websocket.MessageText, []byte(msg))
|
||||
if err != nil {
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeWebsocketEcho, "write message: %s", err))
|
||||
r.Error = health.Errorf(health.CodeWebsocketEcho, "write message: %s", err)
|
||||
r.Severity = health.SeverityError
|
||||
return
|
||||
}
|
||||
|
||||
ty, got, err := c.Read(ctx)
|
||||
if err != nil {
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeWebsocketEcho, "read message: %s", err))
|
||||
r.Error = health.Errorf(health.CodeWebsocketEcho, "read message: %s", err)
|
||||
r.Severity = health.SeverityError
|
||||
return
|
||||
}
|
||||
|
||||
if ty != websocket.MessageText {
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeWebsocketMsg, "received incorrect message type: %v", ty))
|
||||
r.Error = health.Errorf(health.CodeWebsocketMsg, "received incorrect message type: %v", ty)
|
||||
r.Severity = health.SeverityError
|
||||
return
|
||||
}
|
||||
|
||||
if string(got) != msg {
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeWebsocketMsg, "received incorrect message: wanted %q, got %q", msg, string(got)))
|
||||
r.Error = health.Errorf(health.CodeWebsocketMsg, "received incorrect message: wanted %q, got %q", msg, string(got))
|
||||
r.Severity = health.SeverityError
|
||||
return
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@ import (
|
|||
|
||||
// @typescript-generate WorkspaceProxyReport
|
||||
type WorkspaceProxyReport struct {
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity"`
|
||||
Warnings []string `json:"warnings"`
|
||||
Dismissed bool `json:"dismissed"`
|
||||
Error *string `json:"error"`
|
||||
Healthy bool `json:"healthy"`
|
||||
Severity health.Severity `json:"severity"`
|
||||
Warnings []health.Message `json:"warnings"`
|
||||
Dismissed bool `json:"dismissed"`
|
||||
Error *string `json:"error"`
|
||||
|
||||
WorkspaceProxies codersdk.RegionsResponse[codersdk.WorkspaceProxy] `json:"workspace_proxies"`
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ func (*AGPLWorkspaceProxiesFetchUpdater) Update(context.Context) error {
|
|||
func (r *WorkspaceProxyReport) Run(ctx context.Context, opts *WorkspaceProxyReportOptions) {
|
||||
r.Healthy = true
|
||||
r.Severity = health.SeverityOK
|
||||
r.Warnings = []string{}
|
||||
r.Warnings = []health.Message{}
|
||||
r.Dismissed = opts.Dismissed
|
||||
|
||||
if opts.WorkspaceProxiesFetchUpdater == nil {
|
||||
|
@ -72,7 +72,7 @@ func (r *WorkspaceProxyReport) Run(ctx context.Context, opts *WorkspaceProxyRepo
|
|||
if err != nil {
|
||||
r.Healthy = false
|
||||
r.Severity = health.SeverityError
|
||||
r.Error = ptr.Ref(health.Messagef(health.CodeProxyFetch, "fetch workspace proxies: %s", err))
|
||||
r.Error = health.Errorf(health.CodeProxyFetch, "fetch workspace proxies: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ func (r *WorkspaceProxyReport) Run(ctx context.Context, opts *WorkspaceProxyRepo
|
|||
case health.SeverityWarning, health.SeverityOK:
|
||||
r.Warnings = append(r.Warnings, health.Messagef(health.CodeProxyUnhealthy, err))
|
||||
case health.SeverityError:
|
||||
r.appendError(health.Messagef(health.CodeProxyUnhealthy, err))
|
||||
r.appendError(*health.Errorf(health.CodeProxyUnhealthy, err))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ func (r *WorkspaceProxyReport) Run(ctx context.Context, opts *WorkspaceProxyRepo
|
|||
if vErr := checkVersion(proxy, opts.CurrentVersion); vErr != nil {
|
||||
r.Healthy = false
|
||||
r.Severity = health.SeverityError
|
||||
r.appendError(health.Messagef(health.CodeProxyVersionMismatch, vErr.Error()))
|
||||
r.appendError(*health.Errorf(health.CodeProxyVersionMismatch, vErr.Error()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package healthcheck_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -27,7 +26,7 @@ func TestWorkspaceProxies(t *testing.T) {
|
|||
updateProxyHealth func(context.Context) error
|
||||
expectedHealthy bool
|
||||
expectedError string
|
||||
expectedWarning string
|
||||
expectedWarningCode health.Code
|
||||
expectedSeverity health.Severity
|
||||
}{
|
||||
{
|
||||
|
@ -103,10 +102,10 @@ func TestWorkspaceProxies(t *testing.T) {
|
|||
fakeWorkspaceProxy("alpha", false, currentVersion),
|
||||
fakeWorkspaceProxy("beta", true, currentVersion),
|
||||
),
|
||||
updateProxyHealth: fakeUpdateProxyHealth(nil),
|
||||
expectedHealthy: true,
|
||||
expectedSeverity: health.SeverityWarning,
|
||||
expectedWarning: string(health.CodeProxyUnhealthy),
|
||||
updateProxyHealth: fakeUpdateProxyHealth(nil),
|
||||
expectedHealthy: true,
|
||||
expectedSeverity: health.SeverityWarning,
|
||||
expectedWarningCode: health.CodeProxyUnhealthy,
|
||||
},
|
||||
{
|
||||
name: "Enabled/AllUnhealthy",
|
||||
|
@ -163,7 +162,7 @@ func TestWorkspaceProxies(t *testing.T) {
|
|||
updateProxyHealth: fakeUpdateProxyHealth(assert.AnError),
|
||||
expectedHealthy: true,
|
||||
expectedSeverity: health.SeverityWarning,
|
||||
expectedWarning: string(health.CodeProxyUpdate),
|
||||
expectedWarningCode: health.CodeProxyUpdate,
|
||||
},
|
||||
} {
|
||||
tt := tt
|
||||
|
@ -190,15 +189,15 @@ func TestWorkspaceProxies(t *testing.T) {
|
|||
} else {
|
||||
assert.Nil(t, rpt.Error)
|
||||
}
|
||||
if tt.expectedWarning != "" && assert.NotEmpty(t, rpt.Warnings) {
|
||||
if tt.expectedWarningCode != "" && assert.NotEmpty(t, rpt.Warnings) {
|
||||
var found bool
|
||||
for _, w := range rpt.Warnings {
|
||||
if strings.Contains(w, tt.expectedWarning) {
|
||||
if w.Code == tt.expectedWarningCode {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found, "expected warning %s not found in %v", tt.expectedWarning, rpt.Warnings)
|
||||
assert.True(t, found, "expected warning %s not found in %v", tt.expectedWarningCode, rpt.Warnings)
|
||||
} else {
|
||||
assert.Empty(t, rpt.Warnings)
|
||||
}
|
||||
|
|
|
@ -54,7 +54,12 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \
|
|||
"reachable": true,
|
||||
"severity": "ok",
|
||||
"status_code": 0,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"coder_version": "string",
|
||||
"database": {
|
||||
|
@ -66,7 +71,12 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \
|
|||
"reachable": true,
|
||||
"severity": "ok",
|
||||
"threshold_ms": 0,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"derp": {
|
||||
"dismissed": true,
|
||||
|
@ -143,7 +153,12 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \
|
|||
"error": "string"
|
||||
},
|
||||
"uses_websocket": true,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"region": {
|
||||
|
@ -171,7 +186,12 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \
|
|||
"regionName": "string"
|
||||
},
|
||||
"severity": "ok",
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"property2": {
|
||||
"error": "string",
|
||||
|
@ -211,7 +231,12 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \
|
|||
"error": "string"
|
||||
},
|
||||
"uses_websocket": true,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"region": {
|
||||
|
@ -239,11 +264,21 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \
|
|||
"regionName": "string"
|
||||
},
|
||||
"severity": "ok",
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"severity": "ok",
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"failing_sections": ["string"],
|
||||
"healthy": true,
|
||||
|
@ -263,7 +298,12 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \
|
|||
"error": "string",
|
||||
"healthy": true,
|
||||
"severity": "ok",
|
||||
"warnings": ["string"],
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
],
|
||||
"workspace_proxies": {
|
||||
"regions": [
|
||||
{
|
||||
|
|
|
@ -7176,7 +7176,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"error": "string"
|
||||
},
|
||||
"uses_websocket": true,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -7196,7 +7201,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
| `severity` | [health.Severity](#healthseverity) | false | | |
|
||||
| `stun` | [derphealth.StunReport](#derphealthstunreport) | false | | |
|
||||
| `uses_websocket` | boolean | false | | |
|
||||
| `warnings` | array of string | false | | |
|
||||
| `warnings` | array of [health.Message](#healthmessage) | false | | |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
|
@ -7247,7 +7252,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"error": "string"
|
||||
},
|
||||
"uses_websocket": true,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"region": {
|
||||
|
@ -7275,7 +7285,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"regionName": "string"
|
||||
},
|
||||
"severity": "ok",
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -7288,7 +7303,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
| `node_reports` | array of [derphealth.NodeReport](#derphealthnodereport) | false | | |
|
||||
| `region` | [tailcfg.DERPRegion](#tailcfgderpregion) | false | | |
|
||||
| `severity` | [health.Severity](#healthseverity) | false | | |
|
||||
| `warnings` | array of string | false | | |
|
||||
| `warnings` | array of [health.Message](#healthmessage) | false | | |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
|
@ -7376,7 +7391,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"error": "string"
|
||||
},
|
||||
"uses_websocket": true,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"region": {
|
||||
|
@ -7404,7 +7424,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"regionName": "string"
|
||||
},
|
||||
"severity": "ok",
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"property2": {
|
||||
"error": "string",
|
||||
|
@ -7444,7 +7469,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"error": "string"
|
||||
},
|
||||
"uses_websocket": true,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"region": {
|
||||
|
@ -7472,11 +7502,21 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"regionName": "string"
|
||||
},
|
||||
"severity": "ok",
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"severity": "ok",
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -7493,7 +7533,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
| `regions` | object | false | | |
|
||||
| » `[any property]` | [derphealth.RegionReport](#derphealthregionreport) | false | | |
|
||||
| `severity` | [health.Severity](#healthseverity) | false | | |
|
||||
| `warnings` | array of string | false | | |
|
||||
| `warnings` | array of [health.Message](#healthmessage) | false | | |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
|
@ -7521,6 +7561,51 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
| `enabled` | boolean | false | | |
|
||||
| `error` | string | false | | |
|
||||
|
||||
## health.Code
|
||||
|
||||
```json
|
||||
"EUNKNOWN"
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
| Value |
|
||||
| ---------- |
|
||||
| `EUNKNOWN` |
|
||||
| `EWP01` |
|
||||
| `EWP02` |
|
||||
| `EWP03` |
|
||||
| `EWP04` |
|
||||
| `EDB01` |
|
||||
| `EDB02` |
|
||||
| `EWS01` |
|
||||
| `EWS02` |
|
||||
| `EWS03` |
|
||||
| `EACS01` |
|
||||
| `EACS02` |
|
||||
| `EACS03` |
|
||||
| `EACS04` |
|
||||
| `EDERP01` |
|
||||
| `EDERP02` |
|
||||
|
||||
## health.Message
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| --------- | -------------------------- | -------- | ------------ | ----------- |
|
||||
| `code` | [health.Code](#healthcode) | false | | |
|
||||
| `message` | string | false | | |
|
||||
|
||||
## health.Severity
|
||||
|
||||
```json
|
||||
|
@ -7549,23 +7634,28 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"reachable": true,
|
||||
"severity": "ok",
|
||||
"status_code": 0,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| ------------------ | ---------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- |
|
||||
| `access_url` | string | false | | |
|
||||
| `dismissed` | boolean | false | | |
|
||||
| `error` | string | false | | |
|
||||
| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
|
||||
| `healthz_response` | string | false | | |
|
||||
| `reachable` | boolean | false | | |
|
||||
| `severity` | [health.Severity](#healthseverity) | false | | |
|
||||
| `status_code` | integer | false | | |
|
||||
| `warnings` | array of string | false | | |
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| ------------------ | ----------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- |
|
||||
| `access_url` | string | false | | |
|
||||
| `dismissed` | boolean | false | | |
|
||||
| `error` | string | false | | |
|
||||
| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
|
||||
| `healthz_response` | string | false | | |
|
||||
| `reachable` | boolean | false | | |
|
||||
| `severity` | [health.Severity](#healthseverity) | false | | |
|
||||
| `status_code` | integer | false | | |
|
||||
| `warnings` | array of [health.Message](#healthmessage) | false | | |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
|
@ -7587,23 +7677,28 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"reachable": true,
|
||||
"severity": "ok",
|
||||
"threshold_ms": 0,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| -------------- | ---------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- |
|
||||
| `dismissed` | boolean | false | | |
|
||||
| `error` | string | false | | |
|
||||
| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
|
||||
| `latency` | string | false | | |
|
||||
| `latency_ms` | integer | false | | |
|
||||
| `reachable` | boolean | false | | |
|
||||
| `severity` | [health.Severity](#healthseverity) | false | | |
|
||||
| `threshold_ms` | integer | false | | |
|
||||
| `warnings` | array of string | false | | |
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| -------------- | ----------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- |
|
||||
| `dismissed` | boolean | false | | |
|
||||
| `error` | string | false | | |
|
||||
| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
|
||||
| `latency` | string | false | | |
|
||||
| `latency_ms` | integer | false | | |
|
||||
| `reachable` | boolean | false | | |
|
||||
| `severity` | [health.Severity](#healthseverity) | false | | |
|
||||
| `threshold_ms` | integer | false | | |
|
||||
| `warnings` | array of [health.Message](#healthmessage) | false | | |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
|
@ -7626,7 +7721,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"reachable": true,
|
||||
"severity": "ok",
|
||||
"status_code": 0,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"coder_version": "string",
|
||||
"database": {
|
||||
|
@ -7638,7 +7738,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"reachable": true,
|
||||
"severity": "ok",
|
||||
"threshold_ms": 0,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"derp": {
|
||||
"dismissed": true,
|
||||
|
@ -7715,7 +7820,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"error": "string"
|
||||
},
|
||||
"uses_websocket": true,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"region": {
|
||||
|
@ -7743,7 +7853,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"regionName": "string"
|
||||
},
|
||||
"severity": "ok",
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"property2": {
|
||||
"error": "string",
|
||||
|
@ -7783,7 +7898,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"error": "string"
|
||||
},
|
||||
"uses_websocket": true,
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"region": {
|
||||
|
@ -7811,11 +7931,21 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"regionName": "string"
|
||||
},
|
||||
"severity": "ok",
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"severity": "ok",
|
||||
"warnings": ["string"]
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"failing_sections": ["string"],
|
||||
"healthy": true,
|
||||
|
@ -7835,7 +7965,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"error": "string",
|
||||
"healthy": true,
|
||||
"severity": "ok",
|
||||
"warnings": ["string"],
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
],
|
||||
"workspace_proxies": {
|
||||
"regions": [
|
||||
{
|
||||
|
@ -7932,7 +8067,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
"error": "string",
|
||||
"healthy": true,
|
||||
"severity": "ok",
|
||||
"warnings": ["string"],
|
||||
"warnings": [
|
||||
{
|
||||
"code": "EUNKNOWN",
|
||||
"message": "string"
|
||||
}
|
||||
],
|
||||
"workspace_proxies": {
|
||||
"regions": [
|
||||
{
|
||||
|
@ -7971,7 +8111,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
|||
| `error` | string | false | | |
|
||||
| `healthy` | boolean | false | | |
|
||||
| `severity` | [health.Severity](#healthseverity) | false | | |
|
||||
| `warnings` | array of string | false | | |
|
||||
| `warnings` | array of [health.Message](#healthmessage) | false | | |
|
||||
| `workspace_proxies` | [codersdk.RegionsResponse-codersdk_WorkspaceProxy](#codersdkregionsresponse-codersdk_workspaceproxy) | false | | |
|
||||
|
||||
## netcheck.Report
|
||||
|
|
|
@ -2099,7 +2099,7 @@ export type RegionTypes = Region | WorkspaceProxy;
|
|||
export interface HealthcheckAccessURLReport {
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: string[];
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly dismissed: boolean;
|
||||
readonly access_url: string;
|
||||
readonly reachable: boolean;
|
||||
|
@ -2112,7 +2112,7 @@ export interface HealthcheckAccessURLReport {
|
|||
export interface HealthcheckDatabaseReport {
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: string[];
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly dismissed: boolean;
|
||||
readonly reachable: boolean;
|
||||
readonly latency: string;
|
||||
|
@ -2150,7 +2150,7 @@ export interface HealthcheckWebsocketReport {
|
|||
export interface HealthcheckWorkspaceProxyReport {
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: string[];
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly dismissed: boolean;
|
||||
readonly error?: string;
|
||||
readonly workspace_proxies: RegionsResponse<WorkspaceProxy>;
|
||||
|
@ -2203,6 +2203,12 @@ export const ClibaseValueSources: ClibaseValueSource[] = [
|
|||
|
||||
// The code below is generated from coderd/healthcheck/health.
|
||||
|
||||
// From health/model.go
|
||||
export interface HealthMessage {
|
||||
readonly code: HealthCode;
|
||||
readonly message: string;
|
||||
}
|
||||
|
||||
// From health/model.go
|
||||
export type HealthCode =
|
||||
| "EACS01"
|
||||
|
@ -2251,7 +2257,9 @@ export interface DerphealthNodeReport {
|
|||
readonly healthy: boolean;
|
||||
// This is likely an enum in an external package ("github.com/coder/coder/v2/coderd/healthcheck/health.Severity")
|
||||
readonly severity: string;
|
||||
readonly warnings: string[];
|
||||
// Named type "github.com/coder/coder/v2/coderd/healthcheck/health.Message" unknown, using "any"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type
|
||||
readonly warnings: any[];
|
||||
// Named type "tailscale.com/tailcfg.DERPNode" unknown, using "any"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type
|
||||
readonly node?: any;
|
||||
|
@ -2273,7 +2281,9 @@ export interface DerphealthRegionReport {
|
|||
readonly healthy: boolean;
|
||||
// This is likely an enum in an external package ("github.com/coder/coder/v2/coderd/healthcheck/health.Severity")
|
||||
readonly severity: string;
|
||||
readonly warnings: string[];
|
||||
// Named type "github.com/coder/coder/v2/coderd/healthcheck/health.Message" unknown, using "any"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type
|
||||
readonly warnings: any[];
|
||||
// Named type "tailscale.com/tailcfg.DERPRegion" unknown, using "any"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type
|
||||
readonly region?: any;
|
||||
|
@ -2286,7 +2296,9 @@ export interface DerphealthReport {
|
|||
readonly healthy: boolean;
|
||||
// This is likely an enum in an external package ("github.com/coder/coder/v2/coderd/healthcheck/health.Severity")
|
||||
readonly severity: string;
|
||||
readonly warnings: string[];
|
||||
// Named type "github.com/coder/coder/v2/coderd/healthcheck/health.Message" unknown, using "any"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type
|
||||
readonly warnings: any[];
|
||||
readonly dismissed: boolean;
|
||||
readonly regions: Record<number, DerphealthRegionReport>;
|
||||
// Named type "tailscale.com/net/netcheck.Report" unknown, using "any"
|
||||
|
|
|
@ -43,7 +43,7 @@ export const AccessURLWarning: Story = {
|
|||
access_url: {
|
||||
...MockHealth.access_url,
|
||||
healthy: true,
|
||||
warnings: ["foobar"],
|
||||
warnings: [{ code: "EUNKNOWN", message: "foobar" }],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -73,7 +73,7 @@ export const DatabaseWarning: Story = {
|
|||
database: {
|
||||
...MockHealth.database,
|
||||
healthy: true,
|
||||
warnings: ["foobar"],
|
||||
warnings: [{ code: "EUNKNOWN", message: "foobar" }],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -159,7 +159,7 @@ export const ProxyWarning: Story = {
|
|||
severity: "warning",
|
||||
workspace_proxy: {
|
||||
...MockHealth.workspace_proxy,
|
||||
warnings: ["foobar"],
|
||||
warnings: [{ code: "EUNKNOWN", message: "foobar" }],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue