mirror of
https://github.com/amir20/dozzle.git
synced 2026-08-07 11:24:44 +00:00
5f73b41c57
Push container / Push branches and PRs (push) Waiting to run
Deploy VitePress site to Pages / build (push) Waiting to run
Deploy VitePress site to Pages / Deploy (push) Blocked by required conditions
Test / Typecheck (push) Waiting to run
Test / JavaScript Tests (push) Waiting to run
Test / Go Tests (push) Waiting to run
Test / Go Staticcheck (push) Waiting to run
Test / Integration Tests (push) Waiting to run
119 lines
3.3 KiB
Go
119 lines
3.3 KiB
Go
package container
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/amir20/dozzle/internal/utils"
|
|
)
|
|
|
|
// Container represents an internal representation of docker containers
|
|
type Container struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Image string `json:"image"`
|
|
Command string `json:"command"`
|
|
Created time.Time `json:"created"`
|
|
StartedAt time.Time `json:"startedAt"`
|
|
FinishedAt time.Time `json:"finishedAt"`
|
|
State string `json:"state"`
|
|
Health string `json:"health,omitempty"`
|
|
Host string `json:"host,omitempty"`
|
|
Tty bool `json:"-"`
|
|
Labels map[string]string `json:"labels,omitempty"`
|
|
Stats *utils.RingBuffer[ContainerStat] `json:"stats,omitempty"`
|
|
Group string `json:"group,omitempty"`
|
|
}
|
|
|
|
// ContainerStat represent stats instant for a container
|
|
type ContainerStat struct {
|
|
ID string `json:"id"`
|
|
CPUPercent float64 `json:"cpu"`
|
|
MemoryPercent float64 `json:"memory"`
|
|
MemoryUsage float64 `json:"memoryUsage"`
|
|
}
|
|
|
|
// ContainerEvent represents events that are triggered
|
|
type ContainerEvent struct {
|
|
Name string `json:"name"`
|
|
Host string `json:"host"`
|
|
ActorID string `json:"actorId"`
|
|
ActorAttributes map[string]string `json:"actorAttributes,omitempty"`
|
|
Time time.Time `json:"time"`
|
|
}
|
|
|
|
type ContainerFilter map[string][]string
|
|
|
|
func ParseContainerFilter(commaValues string) (ContainerFilter, error) {
|
|
filter := make(ContainerFilter)
|
|
if commaValues == "" {
|
|
return filter, nil
|
|
}
|
|
|
|
for _, val := range strings.Split(commaValues, ",") {
|
|
pos := strings.Index(val, "=")
|
|
if pos == -1 {
|
|
return nil, fmt.Errorf("invalid filter: %s", filter)
|
|
}
|
|
key := val[:pos]
|
|
val := val[pos+1:]
|
|
filter[key] = append(filter[key], val)
|
|
}
|
|
|
|
return filter, nil
|
|
}
|
|
|
|
func (f ContainerFilter) Exists() bool {
|
|
return len(f) > 0
|
|
}
|
|
|
|
type LogPosition string
|
|
|
|
const (
|
|
Beginning LogPosition = "start"
|
|
Middle LogPosition = "middle"
|
|
End LogPosition = "end"
|
|
)
|
|
|
|
type ContainerAction string
|
|
|
|
const (
|
|
Start ContainerAction = "start"
|
|
Stop ContainerAction = "stop"
|
|
Restart ContainerAction = "restart"
|
|
)
|
|
|
|
func ParseContainerAction(input string) (ContainerAction, error) {
|
|
action := ContainerAction(input)
|
|
switch action {
|
|
case Start, Stop, Restart:
|
|
return action, nil
|
|
default:
|
|
return "", fmt.Errorf("unknown action: %s", input)
|
|
}
|
|
}
|
|
|
|
type LogEvent struct {
|
|
Message any `json:"m,omitempty"`
|
|
Timestamp int64 `json:"ts"`
|
|
Id uint32 `json:"id,omitempty"`
|
|
Level string `json:"l,omitempty"`
|
|
Position LogPosition `json:"p,omitempty"`
|
|
Stream string `json:"s,omitempty"`
|
|
ContainerID string `json:"c,omitempty"`
|
|
}
|
|
|
|
func (l *LogEvent) HasLevel() bool {
|
|
return l.Level != "unknown"
|
|
}
|
|
|
|
func (l *LogEvent) IsCloseToTime(other *LogEvent) bool {
|
|
return math.Abs(float64(l.Timestamp-other.Timestamp)) < 10
|
|
}
|
|
|
|
func (l *LogEvent) MessageId() int64 {
|
|
return l.Timestamp
|
|
}
|