Fix Container Health Status Not Displayed Correctly in Dashboard #12319 (#12828)

pull/12833/head
dergreg 2025-08-26 22:59:33 +02:00 committed by GitHub
parent 3a727d24ce
commit daf97624b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 30 additions and 56 deletions

View File

@ -1,6 +1,11 @@
package docker package stats
import "github.com/docker/docker/api/types" import (
"strings"
"github.com/docker/docker/api/types"
"github.com/rs/zerolog/log"
)
type ContainerStats struct { type ContainerStats struct {
Running int `json:"running"` Running int `json:"running"`
@ -13,18 +18,20 @@ type ContainerStats struct {
func CalculateContainerStats(containers []types.Container) ContainerStats { func CalculateContainerStats(containers []types.Container) ContainerStats {
var running, stopped, healthy, unhealthy int var running, stopped, healthy, unhealthy int
for _, container := range containers { for _, container := range containers {
log.Debug().Str("containerId", container.ID).Str("state", container.State).Str("status", container.Status).Msg("Container info")
switch container.State { switch container.State {
case "running": case "running":
running++ running++
case "healthy":
running++
healthy++
case "unhealthy":
running++
unhealthy++
case "exited", "stopped": case "exited", "stopped":
stopped++ stopped++
} }
if strings.Contains(container.Status, "(healthy)") {
healthy++
} else if strings.Contains(container.Status, "(unhealthy)") {
unhealthy++
}
} }
return ContainerStats{ return ContainerStats{

View File

@ -1,4 +1,4 @@
package docker package stats
import ( import (
"testing" "testing"
@ -10,11 +10,11 @@ import (
func TestCalculateContainerStats(t *testing.T) { func TestCalculateContainerStats(t *testing.T) {
containers := []types.Container{ containers := []types.Container{
{State: "running"}, {State: "running"},
{State: "running"}, {State: "running", Status: "Up 5 minutes (healthy)"},
{State: "exited"}, {State: "exited"},
{State: "stopped"}, {State: "stopped"},
{State: "healthy"}, {State: "running", Status: "Up 10 minutes"},
{State: "unhealthy"}, {State: "running", Status: "Up about an hour (unhealthy)"},
} }
stats := CalculateContainerStats(containers) stats := CalculateContainerStats(containers)

View File

@ -11,7 +11,7 @@ import (
"github.com/docker/docker/api/types/volume" "github.com/docker/docker/api/types/volume"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices" "github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/docker" "github.com/portainer/portainer/api/docker/stats"
"github.com/portainer/portainer/api/http/errors" "github.com/portainer/portainer/api/http/errors"
"github.com/portainer/portainer/api/http/handler/docker/utils" "github.com/portainer/portainer/api/http/handler/docker/utils"
"github.com/portainer/portainer/api/http/middlewares" "github.com/portainer/portainer/api/http/middlewares"
@ -26,12 +26,12 @@ type imagesCounters struct {
} }
type dashboardResponse struct { type dashboardResponse struct {
Containers docker.ContainerStats `json:"containers"` Containers stats.ContainerStats `json:"containers"`
Services int `json:"services"` Services int `json:"services"`
Images imagesCounters `json:"images"` Images imagesCounters `json:"images"`
Volumes int `json:"volumes"` Volumes int `json:"volumes"`
Networks int `json:"networks"` Networks int `json:"networks"`
Stacks int `json:"stacks"` Stacks int `json:"stacks"`
} }
// @id dockerDashboard // @id dockerDashboard
@ -150,7 +150,7 @@ func (h *Handler) dashboard(w http.ResponseWriter, r *http.Request) *httperror.H
Size: totalSize, Size: totalSize,
}, },
Services: len(services), Services: len(services),
Containers: docker.CalculateContainerStats(containers), Containers: stats.CalculateContainerStats(containers),
Networks: len(networks), Networks: len(networks),
Volumes: len(volumes), Volumes: len(volumes),
Stacks: stackCount, Stacks: stackCount,

View File

@ -30,7 +30,7 @@ export function ContainerStatus({ stats }: Props) {
{stats.healthy} healthy {stats.healthy} healthy
</div> </div>
<div className="vertical-center space-right"> <div className="vertical-center space-right">
<Icon icon={Heart} mode="danger" size="sm" /> <Icon icon={Heart} mode="warning" size="sm" />
{stats.unhealthy} unhealthy {stats.unhealthy} unhealthy
</div> </div>
</div> </div>

View File

@ -10,6 +10,7 @@ import (
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/docker/consts" "github.com/portainer/portainer/api/docker/consts"
"github.com/portainer/portainer/api/docker/stats"
edgeutils "github.com/portainer/portainer/pkg/edge" edgeutils "github.com/portainer/portainer/pkg/edge"
networkingutils "github.com/portainer/portainer/pkg/networking" networkingutils "github.com/portainer/portainer/pkg/networking"
@ -207,7 +208,7 @@ func dockerSnapshotContainers(snapshot *portainer.DockerSnapshot, cli *client.Cl
snapshot.GpuUseAll = gpuUseAll snapshot.GpuUseAll = gpuUseAll
snapshot.GpuUseList = gpuUseList snapshot.GpuUseList = gpuUseList
stats := calculateContainerStats(containers) stats := stats.CalculateContainerStats(containers)
snapshot.ContainerCount = stats.Total snapshot.ContainerCount = stats.Total
snapshot.RunningContainerCount = stats.Running snapshot.RunningContainerCount = stats.Running
@ -344,37 +345,3 @@ func isPodman(version types.Version) bool {
return false return false
} }
type ContainerStats struct {
Running int
Stopped int
Healthy int
Unhealthy int
Total int
}
func calculateContainerStats(containers []types.Container) ContainerStats {
var running, stopped, healthy, unhealthy int
for _, container := range containers {
switch container.State {
case "running":
running++
case "healthy":
running++
healthy++
case "unhealthy":
running++
unhealthy++
case "exited", "stopped":
stopped++
}
}
return ContainerStats{
Running: running,
Stopped: stopped,
Healthy: healthy,
Unhealthy: unhealthy,
Total: len(containers),
}
}