diff --git a/internal/api/v1/docs/swagger.json b/internal/api/v1/docs/swagger.json index 3ab3464a..da35ecc3 100644 --- a/internal/api/v1/docs/swagger.json +++ b/internal/api/v1/docs/swagger.json @@ -2956,43 +2956,6 @@ "x-nullable": false, "x-omitempty": false }, - "HealthInfo": { - "type": "object", - "properties": { - "detail": { - "type": "string", - "x-nullable": false, - "x-omitempty": false - }, - "latency": { - "description": "latency in microseconds", - "type": "number", - "x-nullable": false, - "x-omitempty": false - }, - "status": { - "type": "string", - "enum": [ - "healthy", - "unhealthy", - "napping", - "starting", - "error", - "unknown" - ], - "x-nullable": false, - "x-omitempty": false - }, - "uptime": { - "description": "uptime in milliseconds", - "type": "number", - "x-nullable": false, - "x-omitempty": false - } - }, - "x-nullable": false, - "x-omitempty": false - }, "HealthInfoWithoutDetail": { "type": "object", "properties": { @@ -3047,22 +3010,14 @@ "x-nullable": true }, "lastSeen": { + "description": "unix timestamp in seconds", "type": "integer", "x-nullable": false, "x-omitempty": false }, - "lastSeenStr": { - "type": "string", - "x-nullable": false, - "x-omitempty": false - }, "latency": { - "type": "number", - "x-nullable": false, - "x-omitempty": false - }, - "latencyStr": { - "type": "string", + "description": "latency in milliseconds", + "type": "integer", "x-nullable": false, "x-omitempty": false }, @@ -3072,30 +3027,22 @@ "x-omitempty": false }, "started": { + "description": "unix timestamp in seconds", "type": "integer", "x-nullable": false, "x-omitempty": false }, - "startedStr": { - "type": "string", - "x-nullable": false, - "x-omitempty": false - }, "status": { - "type": "string", + "$ref": "#/definitions/HealthStatusString", "x-nullable": false, "x-omitempty": false }, "uptime": { + "description": "uptime in seconds", "type": "number", "x-nullable": false, "x-omitempty": false }, - "uptimeStr": { - "type": "string", - "x-nullable": false, - "x-omitempty": false - }, "url": { "type": "string", "x-nullable": false, @@ -3108,11 +3055,32 @@ "HealthMap": { "type": "object", "additionalProperties": { - "$ref": "#/definitions/HealthInfo" + "$ref": "#/definitions/HealthStatusString" }, "x-nullable": false, "x-omitempty": false }, + "HealthStatusString": { + "type": "string", + "enum": [ + "unknown", + "healthy", + "napping", + "starting", + "unhealthy", + "error" + ], + "x-enum-varnames": [ + "StatusUnknownStr", + "StatusHealthyStr", + "StatusNappingStr", + "StatusStartingStr", + "StatusUnhealthyStr", + "StatusErrorStr" + ], + "x-nullable": false, + "x-omitempty": false + }, "HomepageCategory": { "type": "object", "properties": { diff --git a/internal/api/v1/docs/swagger.yaml b/internal/api/v1/docs/swagger.yaml index 23ebc20c..1865cedd 100644 --- a/internal/api/v1/docs/swagger.yaml +++ b/internal/api/v1/docs/swagger.yaml @@ -302,26 +302,6 @@ definitions: additionalProperties: {} type: object type: object - HealthInfo: - properties: - detail: - type: string - latency: - description: latency in microseconds - type: number - status: - enum: - - healthy - - unhealthy - - napping - - starting - - error - - unknown - type: string - uptime: - description: uptime in milliseconds - type: number - type: object HealthInfoWithoutDetail: properties: latency: @@ -351,32 +331,44 @@ definitions: - $ref: '#/definitions/HealthExtra' x-nullable: true lastSeen: + description: unix timestamp in seconds type: integer - lastSeenStr: - type: string latency: - type: number - latencyStr: - type: string + description: latency in milliseconds + type: integer name: type: string started: + description: unix timestamp in seconds type: integer - startedStr: - type: string status: - type: string + $ref: '#/definitions/HealthStatusString' uptime: + description: uptime in seconds type: number - uptimeStr: - type: string url: type: string type: object HealthMap: additionalProperties: - $ref: '#/definitions/HealthInfo' + $ref: '#/definitions/HealthStatusString' type: object + HealthStatusString: + enum: + - unknown + - healthy + - napping + - starting + - unhealthy + - error + type: string + x-enum-varnames: + - StatusUnknownStr + - StatusHealthyStr + - StatusNappingStr + - StatusStartingStr + - StatusUnhealthyStr + - StatusErrorStr HomepageCategory: properties: items: diff --git a/internal/api/v1/health.go b/internal/api/v1/health.go index 7bc35618..6fc19bfa 100644 --- a/internal/api/v1/health.go +++ b/internal/api/v1/health.go @@ -12,8 +12,6 @@ import ( _ "github.com/yusing/goutils/apitypes" ) -type HealthMap = map[string]routes.HealthInfo // @name HealthMap - // @x-id "health" // @BasePath /api/v1 // @Summary Get routes health info @@ -21,16 +19,16 @@ type HealthMap = map[string]routes.HealthInfo // @name HealthMap // @Tags v1,websocket // @Accept json // @Produce json -// @Success 200 {object} HealthMap "Health info by route name" +// @Success 200 {object} routes.HealthMap "Health info by route name" // @Failure 403 {object} apitypes.ErrorResponse // @Failure 500 {object} apitypes.ErrorResponse // @Router /health [get] func Health(c *gin.Context) { if httpheaders.IsWebsocket(c.Request.Header) { websocket.PeriodicWrite(c, 1*time.Second, func() (any, error) { - return routes.GetHealthInfo(), nil + return routes.GetHealthInfoSimple(), nil }) } else { - c.JSON(http.StatusOK, routes.GetHealthInfo()) + c.JSON(http.StatusOK, routes.GetHealthInfoSimple()) } } diff --git a/internal/route/routes/query.go b/internal/route/routes/query.go index 51d9c98a..50849c9a 100644 --- a/internal/route/routes/query.go +++ b/internal/route/routes/query.go @@ -17,6 +17,8 @@ type HealthInfoWithoutDetail struct { Latency time.Duration `json:"latency" swaggertype:"number"` // latency in microseconds } // @name HealthInfoWithoutDetail +type HealthMap = map[string]types.HealthStatusString // @name HealthMap + // GetHealthInfo returns a map of route name to health info. // // The health info is for all routes, including excluded routes. @@ -39,6 +41,14 @@ func GetHealthInfoWithoutDetail() map[string]HealthInfoWithoutDetail { return healthMap } +func GetHealthInfoSimple() map[string]types.HealthStatus { + healthMap := make(map[string]types.HealthStatus, NumAllRoutes()) + for r := range IterAll { + healthMap[r.Name()] = getHealthInfoSimple(r) + } + return healthMap +} + func getHealthInfo(r types.Route) HealthInfo { mon := r.HealthMonitor() if mon == nil { @@ -73,6 +83,14 @@ func getHealthInfoWithoutDetail(r types.Route) HealthInfoWithoutDetail { } } +func getHealthInfoSimple(r types.Route) types.HealthStatus { + mon := r.HealthMonitor() + if mon == nil { + return types.StatusUnknown + } + return mon.Status() +} + // ByProvider returns a map of provider name to routes. // // The routes are all routes, including excluded routes. diff --git a/internal/types/health.go b/internal/types/health.go index 797c08f3..be45b3f5 100644 --- a/internal/types/health.go +++ b/internal/types/health.go @@ -8,12 +8,12 @@ import ( "time" "github.com/bytedance/sonic" - strutils "github.com/yusing/goutils/strings" "github.com/yusing/goutils/task" ) type ( - HealthStatus uint8 + HealthStatus uint8 // @name HealthStatus + HealthStatusString string // @name HealthStatusString HealthCheckResult struct { Healthy bool `json:"healthy"` @@ -45,20 +45,16 @@ type ( HealthChecker } HealthJSON struct { - Name string `json:"name"` - Config *HealthCheckConfig `json:"config"` - Started int64 `json:"started"` - StartedStr string `json:"startedStr"` - Status string `json:"status"` - Uptime float64 `json:"uptime"` - UptimeStr string `json:"uptimeStr"` - Latency float64 `json:"latency"` - LatencyStr string `json:"latencyStr"` - LastSeen int64 `json:"lastSeen"` - LastSeenStr string `json:"lastSeenStr"` - Detail string `json:"detail"` - URL string `json:"url"` - Extra *HealthExtra `json:"extra,omitempty" extensions:"x-nullable"` + Name string `json:"name"` + Config *HealthCheckConfig `json:"config"` + Started int64 `json:"started"` // unix timestamp in seconds + Status HealthStatusString `json:"status"` + Uptime float64 `json:"uptime"` // uptime in seconds + Latency int64 `json:"latency"` // latency in milliseconds + LastSeen int64 `json:"lastSeen"` // unix timestamp in seconds + Detail string `json:"detail"` + URL string `json:"url"` + Extra *HealthExtra `json:"extra,omitempty" extensions:"x-nullable"` } // @name HealthJSON HealthJSONRepr struct { @@ -88,12 +84,12 @@ const ( StatusUnhealthy StatusError - StatusUnknownStr = "unknown" - StatusHealthyStr = "healthy" - StatusNappingStr = "napping" - StatusStartingStr = "starting" - StatusUnhealthyStr = "unhealthy" - StatusErrorStr = "error" + StatusUnknownStr HealthStatusString = "unknown" + StatusHealthyStr HealthStatusString = "healthy" + StatusNappingStr HealthStatusString = "napping" + StatusStartingStr HealthStatusString = "starting" + StatusUnhealthyStr HealthStatusString = "unhealthy" + StatusErrorStr HealthStatusString = "error" NumStatuses int = iota - 1 @@ -102,15 +98,15 @@ const ( ) var ( - StatusHealthyStr2 = strconv.Itoa(int(StatusHealthy)) - StatusNappingStr2 = strconv.Itoa(int(StatusNapping)) - StatusStartingStr2 = strconv.Itoa(int(StatusStarting)) - StatusUnhealthyStr2 = strconv.Itoa(int(StatusUnhealthy)) - StatusErrorStr2 = strconv.Itoa(int(StatusError)) + StatusHealthyStr2 HealthStatusString = HealthStatusString(strconv.Itoa(int(StatusHealthy))) + StatusNappingStr2 HealthStatusString = HealthStatusString(strconv.Itoa(int(StatusNapping))) + StatusStartingStr2 HealthStatusString = HealthStatusString(strconv.Itoa(int(StatusStarting))) + StatusUnhealthyStr2 HealthStatusString = HealthStatusString(strconv.Itoa(int(StatusUnhealthy))) + StatusErrorStr2 HealthStatusString = HealthStatusString(strconv.Itoa(int(StatusError))) ) func NewHealthStatusFromString(s string) HealthStatus { - switch s { + switch HealthStatusString(s) { case StatusHealthyStr, StatusHealthyStr2: return StatusHealthy case StatusUnhealthyStr, StatusUnhealthyStr2: @@ -126,7 +122,7 @@ func NewHealthStatusFromString(s string) HealthStatus { } } -func (s HealthStatus) String() string { +func (s HealthStatus) StatusString() HealthStatusString { switch s { case StatusHealthy: return StatusHealthyStr @@ -143,6 +139,11 @@ func (s HealthStatus) String() string { } } +// String implements fmt.Stringer. +func (s HealthStatus) String() string { + return string(s.StatusString()) +} + func (s HealthStatus) Good() bool { return s&HealthyMask != 0 } @@ -178,19 +179,15 @@ func (jsonRepr *HealthJSONRepr) MarshalJSON() ([]byte, error) { url = "" } return sonic.Marshal(HealthJSON{ - Name: jsonRepr.Name, - Config: jsonRepr.Config, - Started: jsonRepr.Started.Unix(), - StartedStr: strutils.FormatTime(jsonRepr.Started), - Status: jsonRepr.Status.String(), - Uptime: jsonRepr.Uptime.Seconds(), - UptimeStr: strutils.FormatDuration(jsonRepr.Uptime), - Latency: jsonRepr.Latency.Seconds(), - LatencyStr: strconv.Itoa(int(jsonRepr.Latency.Milliseconds())) + " ms", - LastSeen: jsonRepr.LastSeen.Unix(), - LastSeenStr: strutils.FormatLastSeen(jsonRepr.LastSeen), - Detail: jsonRepr.Detail, - URL: url, - Extra: jsonRepr.Extra, + Name: jsonRepr.Name, + Config: jsonRepr.Config, + Started: jsonRepr.Started.Unix(), + Status: HealthStatusString(jsonRepr.Status.String()), + Uptime: jsonRepr.Uptime.Seconds(), + Latency: jsonRepr.Latency.Milliseconds(), + LastSeen: jsonRepr.LastSeen.Unix(), + Detail: jsonRepr.Detail, + URL: url, + Extra: jsonRepr.Extra, }) }