diff --git a/internal/api/handler.go b/internal/api/handler.go index b64c1ca2..897fd96d 100644 --- a/internal/api/handler.go +++ b/internal/api/handler.go @@ -136,6 +136,7 @@ func NewHandler(requireAuth bool) *gin.Engine { docker.POST("/start", dockerApi.Start) docker.POST("/stop", dockerApi.Stop) docker.POST("/restart", dockerApi.Restart) + docker.GET("/stats/:id", dockerApi.Stats) } } diff --git a/internal/api/v1/docker/stats.go b/internal/api/v1/docker/stats.go new file mode 100644 index 00000000..612346ff --- /dev/null +++ b/internal/api/v1/docker/stats.go @@ -0,0 +1,117 @@ +package dockerapi + +import ( + "context" + "errors" + "io" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" + "github.com/yusing/godoxy/internal/docker" + "github.com/yusing/godoxy/internal/route/routes" + "github.com/yusing/godoxy/internal/types" + apitypes "github.com/yusing/goutils/apitypes" + "github.com/yusing/goutils/http/httpheaders" + "github.com/yusing/goutils/http/websocket" + "github.com/yusing/goutils/synk" + "github.com/yusing/goutils/task" +) + +type ContainerStatsResponse container.StatsResponse // @name ContainerStatsResponse + +// @x-id "stats" +// @BasePath /api/v1 +// @Summary Get container stats +// @Description Get container stats by container id +// @Tags docker,websocket +// @Produce json +// @Param id path string true "Container ID or route alias" +// @Success 200 {object} ContainerStatsResponse +// @Failure 400 {object} apitypes.ErrorResponse "Invalid request: id is required or route is not a docker container" +// @Failure 403 {object} apitypes.ErrorResponse +// @Failure 404 {object} apitypes.ErrorResponse "Container not found" +// @Failure 500 {object} apitypes.ErrorResponse +// @Router /docker/stats/{id} [get] +func Stats(c *gin.Context) { + id := c.Param("id") + if id == "" { + c.JSON(http.StatusBadRequest, apitypes.Error("id is required")) + return + } + + dockerCfg, ok := docker.GetDockerCfgByContainerID(id) + if !ok { + var route types.Route + route, ok = routes.GetIncludeExcluded(id) + if ok { + cont := route.ContainerInfo() + if cont == nil { + c.JSON(http.StatusBadRequest, apitypes.Error("route is not a docker container")) + return + } + dockerCfg = cont.DockerCfg + id = cont.ContainerID + } + } + if !ok { + c.JSON(http.StatusNotFound, apitypes.Error("container or route not found")) + return + } + + dockerClient, err := docker.NewClient(dockerCfg) + if err != nil { + c.Error(apitypes.InternalServerError(err, "failed to create docker client")) + return + } + defer dockerClient.Close() + + if httpheaders.IsWebsocket(c.Request.Header) { + stats, err := dockerClient.ContainerStats(c.Request.Context(), id, client.ContainerStatsOptions{Stream: true}) + if err != nil { + c.Error(apitypes.InternalServerError(err, "failed to get container stats")) + return + } + defer stats.Body.Close() + + manager, err := websocket.NewManagerWithUpgrade(c) + if err != nil { + c.Error(apitypes.InternalServerError(err, "failed to create websocket manager")) + return + } + defer manager.Close() + + buf := synk.GetSizedBytesPool().GetSized(4096) + defer synk.GetSizedBytesPool().Put(buf) + + for { + select { + case <-manager.Done(): + return + default: + _, err = io.CopyBuffer(manager.NewWriter(websocket.TextMessage), stats.Body, buf) + if err != nil { + if errors.Is(err, context.Canceled) || errors.Is(err, task.ErrProgramExiting) { + return + } + c.Error(apitypes.InternalServerError(err, "failed to copy container stats")) + return + } + } + } + } + + stats, err := dockerClient.ContainerStats(c.Request.Context(), id, client.ContainerStatsOptions{Stream: false}) + if err != nil { + c.Error(apitypes.InternalServerError(err, "failed to get container stats")) + return + } + defer stats.Body.Close() + + _, err = io.Copy(c.Writer, stats.Body) + if err != nil { + c.Error(apitypes.InternalServerError(err, "failed to copy container stats")) + return + } +} diff --git a/internal/api/v1/docs/swagger.json b/internal/api/v1/docs/swagger.json index 34cfbfd5..81994556 100644 --- a/internal/api/v1/docs/swagger.json +++ b/internal/api/v1/docs/swagger.json @@ -718,6 +718,62 @@ "operationId": "start" } }, + "/docker/stats/{id}": { + "get": { + "description": "Get container stats by container id", + "produces": [ + "application/json" + ], + "tags": [ + "docker", + "websocket" + ], + "summary": "Get container stats", + "parameters": [ + { + "type": "string", + "description": "Container ID or route alias", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/ContainerStatsResponse" + } + }, + "400": { + "description": "Invalid request: id is required or route is not a docker container", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Container not found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-id": "stats", + "operationId": "stats" + } + }, "/docker/stop": { "post": { "description": "Stop container by container id", @@ -2708,6 +2764,118 @@ "x-nullable": false, "x-omitempty": false }, + "ContainerStatsResponse": { + "type": "object", + "properties": { + "blkio_stats": { + "description": "BlkioStats stores all IO service stats for data read and write.\n\nThis type is Linux-specific and holds many fields that are specific\nto cgroups v1.\n\nOn a cgroup v2 host, all fields other than \"io_service_bytes_recursive\"\nare omitted or \"null\".\n\nThis type is only populated on Linux and omitted for Windows containers.", + "allOf": [ + { + "$ref": "#/definitions/container.BlkioStats" + } + ], + "x-nullable": false, + "x-omitempty": false + }, + "cpu_stats": { + "description": "CPUStats contains CPU related info of the container.", + "allOf": [ + { + "$ref": "#/definitions/container.CPUStats" + } + ], + "x-nullable": false, + "x-omitempty": false + }, + "id": { + "description": "ID is the ID of the container for which the stats were collected.", + "type": "string", + "x-nullable": false, + "x-omitempty": false + }, + "memory_stats": { + "description": "MemoryStats aggregates all memory stats since container inception on Linux.\nWindows returns stats for commit and private working set only.", + "allOf": [ + { + "$ref": "#/definitions/container.MemoryStats" + } + ], + "x-nullable": false, + "x-omitempty": false + }, + "name": { + "description": "Name is the name of the container for which the stats were collected.", + "type": "string", + "x-nullable": false, + "x-omitempty": false + }, + "networks": { + "description": "Networks contains Nntwork statistics for the container per interface.\n\nThis field is omitted if the container has no networking enabled.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/container.NetworkStats" + }, + "x-nullable": false, + "x-omitempty": false + }, + "num_procs": { + "description": "NumProcs is the number of processors on the system.\n\nThis field is Windows-specific and always zero for Linux containers.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "os_type": { + "description": "OSType is the OS of the container (\"linux\" or \"windows\") to allow\nplatform-specific handling of stats.", + "type": "string", + "x-nullable": false, + "x-omitempty": false + }, + "pids_stats": { + "description": "PidsStats contains Linux-specific stats of a container's process-IDs (PIDs).\n\nThis field is Linux-specific and omitted for Windows containers.", + "allOf": [ + { + "$ref": "#/definitions/container.PidsStats" + } + ], + "x-nullable": false, + "x-omitempty": false + }, + "precpu_stats": { + "description": "PreCPUStats contains the CPUStats of the previous sample.", + "allOf": [ + { + "$ref": "#/definitions/container.CPUStats" + } + ], + "x-nullable": false, + "x-omitempty": false + }, + "preread": { + "description": "PreRead is the date and time at which this first sample was collected.\nThis field is not propagated if the \"one-shot\" option is set. If the\n\"one-shot\" option is set, this field may be omitted, empty, or set\nto a default date (`0001-01-01T00:00:00Z`).", + "type": "string", + "x-nullable": false, + "x-omitempty": false + }, + "read": { + "description": "Read is the date and time at which this sample was collected.", + "type": "string", + "x-nullable": false, + "x-omitempty": false + }, + "storage_stats": { + "description": "StorageStats is the disk I/O stats for read/write on Windows.\n\nThis type is Windows-specific and omitted for Linux containers.", + "allOf": [ + { + "$ref": "#/definitions/container.StorageStats" + } + ], + "x-nullable": false, + "x-omitempty": false + } + }, + "x-nullable": false, + "x-omitempty": false + }, "ContainerStopMethod": { "type": "string", "enum": [ @@ -5029,6 +5197,178 @@ "x-nullable": false, "x-omitempty": false }, + "container.BlkioStatEntry": { + "type": "object", + "properties": { + "major": { + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "minor": { + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "op": { + "type": "string", + "x-nullable": false, + "x-omitempty": false + }, + "value": { + "type": "integer", + "x-nullable": false, + "x-omitempty": false + } + }, + "x-nullable": false, + "x-omitempty": false + }, + "container.BlkioStats": { + "type": "object", + "properties": { + "io_merged_recursive": { + "type": "array", + "items": { + "$ref": "#/definitions/container.BlkioStatEntry" + }, + "x-nullable": false, + "x-omitempty": false + }, + "io_queue_recursive": { + "type": "array", + "items": { + "$ref": "#/definitions/container.BlkioStatEntry" + }, + "x-nullable": false, + "x-omitempty": false + }, + "io_service_bytes_recursive": { + "description": "number of bytes transferred to and from the block device", + "type": "array", + "items": { + "$ref": "#/definitions/container.BlkioStatEntry" + }, + "x-nullable": false, + "x-omitempty": false + }, + "io_service_time_recursive": { + "type": "array", + "items": { + "$ref": "#/definitions/container.BlkioStatEntry" + }, + "x-nullable": false, + "x-omitempty": false + }, + "io_serviced_recursive": { + "type": "array", + "items": { + "$ref": "#/definitions/container.BlkioStatEntry" + }, + "x-nullable": false, + "x-omitempty": false + }, + "io_time_recursive": { + "type": "array", + "items": { + "$ref": "#/definitions/container.BlkioStatEntry" + }, + "x-nullable": false, + "x-omitempty": false + }, + "io_wait_time_recursive": { + "type": "array", + "items": { + "$ref": "#/definitions/container.BlkioStatEntry" + }, + "x-nullable": false, + "x-omitempty": false + }, + "sectors_recursive": { + "type": "array", + "items": { + "$ref": "#/definitions/container.BlkioStatEntry" + }, + "x-nullable": false, + "x-omitempty": false + } + }, + "x-nullable": false, + "x-omitempty": false + }, + "container.CPUStats": { + "type": "object", + "properties": { + "cpu_usage": { + "description": "CPU Usage. Linux and Windows.", + "allOf": [ + { + "$ref": "#/definitions/container.CPUUsage" + } + ], + "x-nullable": false, + "x-omitempty": false + }, + "online_cpus": { + "description": "Online CPUs. Linux only.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "system_cpu_usage": { + "description": "System Usage. Linux only.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "throttling_data": { + "description": "Throttling Data. Linux only.", + "allOf": [ + { + "$ref": "#/definitions/container.ThrottlingData" + } + ], + "x-nullable": false, + "x-omitempty": false + } + }, + "x-nullable": false, + "x-omitempty": false + }, + "container.CPUUsage": { + "type": "object", + "properties": { + "percpu_usage": { + "description": "Total CPU time consumed per core (Linux). Not used on Windows.\nUnits: nanoseconds.", + "type": "array", + "items": { + "type": "integer" + }, + "x-nullable": false, + "x-omitempty": false + }, + "total_usage": { + "description": "Total CPU time consumed.\nUnits: nanoseconds (Linux)\nUnits: 100's of nanoseconds (Windows)", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "usage_in_kernelmode": { + "description": "Time spent by tasks of the cgroup in kernel mode (Linux).\nTime spent by all container processes in kernel mode (Windows).\nUnits: nanoseconds (Linux).\nUnits: 100's of nanoseconds (Windows). Not populated for Hyper-V Containers.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "usage_in_usermode": { + "description": "Time spent by tasks of the cgroup in user mode (Linux).\nTime spent by all container processes in user mode (Windows).\nUnits: nanoseconds (Linux).\nUnits: 100's of nanoseconds (Windows). Not populated for Hyper-V Containers", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + } + }, + "x-nullable": false, + "x-omitempty": false + }, "container.ContainerState": { "type": "string", "enum": [ @@ -5070,6 +5410,150 @@ "x-nullable": false, "x-omitempty": false }, + "container.MemoryStats": { + "type": "object", + "properties": { + "commitbytes": { + "description": "committed bytes", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "commitpeakbytes": { + "description": "peak committed bytes", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "failcnt": { + "description": "number of times memory usage hits limits.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "limit": { + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "max_usage": { + "description": "maximum usage ever recorded.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "privateworkingset": { + "description": "private working set", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "stats": { + "description": "TODO(vishh): Export these as stronger types.\nall the stats exported via memory.stat.", + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int64" + }, + "x-nullable": false, + "x-omitempty": false + }, + "usage": { + "description": "current res_counter usage for memory", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + } + }, + "x-nullable": false, + "x-omitempty": false + }, + "container.NetworkStats": { + "type": "object", + "properties": { + "endpoint_id": { + "description": "Endpoint ID. Not used on Linux.", + "type": "string", + "x-nullable": false, + "x-omitempty": false + }, + "instance_id": { + "description": "Instance ID. Not used on Linux.", + "type": "string", + "x-nullable": false, + "x-omitempty": false + }, + "rx_bytes": { + "description": "Bytes received. Windows and Linux.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "rx_dropped": { + "description": "Incoming packets dropped. Windows and Linux.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "rx_errors": { + "description": "Received errors. Not used on Windows. Note that we don't `omitempty` this\nfield as it is expected in the >=v1.21 API stats structure.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "rx_packets": { + "description": "Packets received. Windows and Linux.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "tx_bytes": { + "description": "Bytes sent. Windows and Linux.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "tx_dropped": { + "description": "Outgoing packets dropped. Windows and Linux.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "tx_errors": { + "description": "Sent errors. Not used on Windows. Note that we don't `omitempty` this\nfield as it is expected in the >=v1.21 API stats structure.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "tx_packets": { + "description": "Packets sent. Windows and Linux.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + } + }, + "x-nullable": false, + "x-omitempty": false + }, + "container.PidsStats": { + "type": "object", + "properties": { + "current": { + "description": "Current is the number of pids in the cgroup", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "limit": { + "description": "Limit is the hard limit on the number of pids in the cgroup.\nA \"Limit\" of 0 means that there is no limit.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + } + }, + "x-nullable": false, + "x-omitempty": false + }, "container.PortSummary": { "type": "object", "properties": { @@ -5105,6 +5589,58 @@ "x-nullable": false, "x-omitempty": false }, + "container.StorageStats": { + "type": "object", + "properties": { + "read_count_normalized": { + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "read_size_bytes": { + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "write_count_normalized": { + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "write_size_bytes": { + "type": "integer", + "x-nullable": false, + "x-omitempty": false + } + }, + "x-nullable": false, + "x-omitempty": false + }, + "container.ThrottlingData": { + "type": "object", + "properties": { + "periods": { + "description": "Number of periods with throttling active", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "throttled_periods": { + "description": "Number of periods when the container hits its throttling limit.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + }, + "throttled_time": { + "description": "Aggregate time the container was throttled for in nanoseconds.", + "type": "integer", + "x-nullable": false, + "x-omitempty": false + } + }, + "x-nullable": false, + "x-omitempty": false + }, "disk.IOCountersStat": { "type": "object", "properties": { diff --git a/internal/api/v1/docs/swagger.yaml b/internal/api/v1/docs/swagger.yaml index a7359377..0b1d0377 100644 --- a/internal/api/v1/docs/swagger.yaml +++ b/internal/api/v1/docs/swagger.yaml @@ -180,6 +180,85 @@ definitions: total: type: integer type: object + ContainerStatsResponse: + properties: + blkio_stats: + allOf: + - $ref: '#/definitions/container.BlkioStats' + description: |- + BlkioStats stores all IO service stats for data read and write. + + This type is Linux-specific and holds many fields that are specific + to cgroups v1. + + On a cgroup v2 host, all fields other than "io_service_bytes_recursive" + are omitted or "null". + + This type is only populated on Linux and omitted for Windows containers. + cpu_stats: + allOf: + - $ref: '#/definitions/container.CPUStats' + description: CPUStats contains CPU related info of the container. + id: + description: ID is the ID of the container for which the stats were collected. + type: string + memory_stats: + allOf: + - $ref: '#/definitions/container.MemoryStats' + description: |- + MemoryStats aggregates all memory stats since container inception on Linux. + Windows returns stats for commit and private working set only. + name: + description: Name is the name of the container for which the stats were collected. + type: string + networks: + additionalProperties: + $ref: '#/definitions/container.NetworkStats' + description: |- + Networks contains Nntwork statistics for the container per interface. + + This field is omitted if the container has no networking enabled. + type: object + num_procs: + description: |- + NumProcs is the number of processors on the system. + + This field is Windows-specific and always zero for Linux containers. + type: integer + os_type: + description: |- + OSType is the OS of the container ("linux" or "windows") to allow + platform-specific handling of stats. + type: string + pids_stats: + allOf: + - $ref: '#/definitions/container.PidsStats' + description: |- + PidsStats contains Linux-specific stats of a container's process-IDs (PIDs). + + This field is Linux-specific and omitted for Windows containers. + precpu_stats: + allOf: + - $ref: '#/definitions/container.CPUStats' + description: PreCPUStats contains the CPUStats of the previous sample. + preread: + description: |- + PreRead is the date and time at which this first sample was collected. + This field is not propagated if the "one-shot" option is set. If the + "one-shot" option is set, this field may be omitted, empty, or set + to a default date (`0001-01-01T00:00:00Z`). + type: string + read: + description: Read is the date and time at which this sample was collected. + type: string + storage_stats: + allOf: + - $ref: '#/definitions/container.StorageStats' + description: |- + StorageStats is the disk I/O stats for read/write on Windows. + + This type is Windows-specific and omitted for Linux containers. + type: object ContainerStopMethod: enum: - pause @@ -1288,6 +1367,100 @@ definitions: username: type: string type: object + container.BlkioStatEntry: + properties: + major: + type: integer + minor: + type: integer + op: + type: string + value: + type: integer + type: object + container.BlkioStats: + properties: + io_merged_recursive: + items: + $ref: '#/definitions/container.BlkioStatEntry' + type: array + io_queue_recursive: + items: + $ref: '#/definitions/container.BlkioStatEntry' + type: array + io_service_bytes_recursive: + description: number of bytes transferred to and from the block device + items: + $ref: '#/definitions/container.BlkioStatEntry' + type: array + io_service_time_recursive: + items: + $ref: '#/definitions/container.BlkioStatEntry' + type: array + io_serviced_recursive: + items: + $ref: '#/definitions/container.BlkioStatEntry' + type: array + io_time_recursive: + items: + $ref: '#/definitions/container.BlkioStatEntry' + type: array + io_wait_time_recursive: + items: + $ref: '#/definitions/container.BlkioStatEntry' + type: array + sectors_recursive: + items: + $ref: '#/definitions/container.BlkioStatEntry' + type: array + type: object + container.CPUStats: + properties: + cpu_usage: + allOf: + - $ref: '#/definitions/container.CPUUsage' + description: CPU Usage. Linux and Windows. + online_cpus: + description: Online CPUs. Linux only. + type: integer + system_cpu_usage: + description: System Usage. Linux only. + type: integer + throttling_data: + allOf: + - $ref: '#/definitions/container.ThrottlingData' + description: Throttling Data. Linux only. + type: object + container.CPUUsage: + properties: + percpu_usage: + description: |- + Total CPU time consumed per core (Linux). Not used on Windows. + Units: nanoseconds. + items: + type: integer + type: array + total_usage: + description: |- + Total CPU time consumed. + Units: nanoseconds (Linux) + Units: 100's of nanoseconds (Windows) + type: integer + usage_in_kernelmode: + description: |- + Time spent by tasks of the cgroup in kernel mode (Linux). + Time spent by all container processes in kernel mode (Windows). + Units: nanoseconds (Linux). + Units: 100's of nanoseconds (Windows). Not populated for Hyper-V Containers. + type: integer + usage_in_usermode: + description: |- + Time spent by tasks of the cgroup in user mode (Linux). + Time spent by all container processes in user mode (Windows). + Units: nanoseconds (Linux). + Units: 100's of nanoseconds (Windows). Not populated for Hyper-V Containers + type: integer + type: object container.ContainerState: enum: - created @@ -1325,6 +1498,85 @@ definitions: - StateRemoving - StateExited - StateDead + container.MemoryStats: + properties: + commitbytes: + description: committed bytes + type: integer + commitpeakbytes: + description: peak committed bytes + type: integer + failcnt: + description: number of times memory usage hits limits. + type: integer + limit: + type: integer + max_usage: + description: maximum usage ever recorded. + type: integer + privateworkingset: + description: private working set + type: integer + stats: + additionalProperties: + format: int64 + type: integer + description: |- + TODO(vishh): Export these as stronger types. + all the stats exported via memory.stat. + type: object + usage: + description: current res_counter usage for memory + type: integer + type: object + container.NetworkStats: + properties: + endpoint_id: + description: Endpoint ID. Not used on Linux. + type: string + instance_id: + description: Instance ID. Not used on Linux. + type: string + rx_bytes: + description: Bytes received. Windows and Linux. + type: integer + rx_dropped: + description: Incoming packets dropped. Windows and Linux. + type: integer + rx_errors: + description: |- + Received errors. Not used on Windows. Note that we don't `omitempty` this + field as it is expected in the >=v1.21 API stats structure. + type: integer + rx_packets: + description: Packets received. Windows and Linux. + type: integer + tx_bytes: + description: Bytes sent. Windows and Linux. + type: integer + tx_dropped: + description: Outgoing packets dropped. Windows and Linux. + type: integer + tx_errors: + description: |- + Sent errors. Not used on Windows. Note that we don't `omitempty` this + field as it is expected in the >=v1.21 API stats structure. + type: integer + tx_packets: + description: Packets sent. Windows and Linux. + type: integer + type: object + container.PidsStats: + properties: + current: + description: Current is the number of pids in the cgroup + type: integer + limit: + description: |- + Limit is the hard limit on the number of pids in the cgroup. + A "Limit" of 0 means that there is no limit. + type: integer + type: object container.PortSummary: properties: IP: @@ -1346,6 +1598,29 @@ definitions: Enum: ["tcp","udp","sctp"] type: string type: object + container.StorageStats: + properties: + read_count_normalized: + type: integer + read_size_bytes: + type: integer + write_count_normalized: + type: integer + write_size_bytes: + type: integer + type: object + container.ThrottlingData: + properties: + periods: + description: Number of periods with throttling active + type: integer + throttled_periods: + description: Number of periods when the container hits its throttling limit. + type: integer + throttled_time: + description: Aggregate time the container was throttled for in nanoseconds. + type: integer + type: object disk.IOCountersStat: properties: iops: @@ -2168,6 +2443,43 @@ paths: tags: - docker x-id: start + /docker/stats/{id}: + get: + description: Get container stats by container id + parameters: + - description: Container ID or route alias + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/ContainerStatsResponse' + "400": + description: 'Invalid request: id is required or route is not a docker container' + schema: + $ref: '#/definitions/ErrorResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/ErrorResponse' + "404": + description: Container not found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' + summary: Get container stats + tags: + - docker + - websocket + x-id: stats /docker/stop: post: description: Stop container by container id