Ctrl K
ComunidadGuías…

model/instance.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package model

import (
	"github.com/coroot/coroot/timeseries"
)

type ClusterRole int

const (
	ClusterRoleNone ClusterRole = iota
	ClusterRolePrimary
	ClusterRoleReplica
	ClusterRoleArbiter
	ClusterRolePredictor
	ClusterRoleTransformer
	ClusterRoleExplainer
	ClusterRoleFrontend
	ClusterRoleWorker
	ClusterRolePrefill
	ClusterRoleDecode
	ClusterRolePlanner
	ClusterRoleEPP
)

var clusterRoleNames = map[ClusterRole]string{
	ClusterRolePrimary:     "primary",
	ClusterRoleReplica:     "replica",
	ClusterRoleArbiter:     "arbiter",
	ClusterRolePredictor:   "predictor",
	ClusterRoleTransformer: "transformer",
	ClusterRoleExplainer:   "explainer",
	ClusterRoleFrontend:    "frontend",
	ClusterRoleWorker:      "worker",
	ClusterRolePrefill:     "prefill",
	ClusterRoleDecode:      "decode",
	ClusterRolePlanner:     "planner",
	ClusterRoleEPP:         "epp",
}

var clusterRolesByName = func() map[string]ClusterRole {
	res := make(map[string]ClusterRole, len(clusterRoleNames))
	for r, name := range clusterRoleNames {
		res[name] = r
	}
	return res
}()

func (r ClusterRole) String() string {
	return clusterRoleNames[r]
}

type Instance struct {
	Name  string
	Owner *Application

	Node *Node

	Pod *Pod

	Rds         *Rds
	CloudSQL    *CloudSQL
	Memorystore *Memorystore
	OCIDB       *OCIDB
	OCICache    *OCICache
	Elasticache *Elasticache

	Jvms   map[string]*Jvm
	DotNet map[string]*DotNet
	Python *Python
	Nodejs *Nodejs
	Go     *GoRuntime

	Volumes []*Volume

	GPUUsage map[string]*InstanceGPUUsage

	Upstreams map[ConnectionKey]*Connection

	Requests Requests

	TcpListens map[Listen]bool

	Containers map[string]*Container

	Annotations ApplicationAnnotations

	ClusterName      LabelLastValue
	clusterRole      *timeseries.TimeSeries
	ClusterComponent *Application

	Postgres  *Postgres
	Redis     *Redis
	Mongodb   *Mongodb
	Memcached *Memcached
	Mysql     *Mysql
}

func NewInstance(name string, owner *Application) *Instance {
	return &Instance{
		Name:        name,
		Owner:       owner,
		Annotations: ApplicationAnnotations{},
		Containers:  map[string]*Container{},
		Upstreams:   map[ConnectionKey]*Connection{},
		TcpListens:  map[Listen]bool{},
		GPUUsage:    map[string]*InstanceGPUUsage{},
	}
}

func (instance *Instance) ApplicationTypes() map[ApplicationType]bool {
	res := map[ApplicationType]bool{}
	for _, c := range instance.Containers {
		for t := range c.ApplicationTypes {
			res[t] = true
		}
	}
	if t := instance.Rds.ApplicationType(); t != ApplicationTypeUnknown {
		res[t] = true
	}
	if t := instance.Elasticache.ApplicationType(); t != ApplicationTypeUnknown {
		res[t] = true
	}
	if t := instance.CloudSQL.ApplicationType(); t != ApplicationTypeUnknown {
		res[t] = true
	}
	if t := instance.Memorystore.ApplicationType(); t != ApplicationTypeUnknown {
		res[t] = true
	}
	if t := instance.OCIDB.ApplicationType(); t != ApplicationTypeUnknown {
		res[t] = true
	}
	if t := instance.OCICache.ApplicationType(); t != ApplicationTypeUnknown {
		res[t] = true
	}
	return res
}

func (instance *Instance) IsManagedDatabase() bool {
	return instance.Rds != nil || instance.Elasticache != nil || instance.CloudSQL != nil || instance.Memorystore != nil || instance.OCIDB != nil || instance.OCICache != nil
}

func (instance *Instance) InstrumentedType() ApplicationType {
	switch {
	case instance.Postgres != nil:
		return ApplicationTypePostgres
	case instance.Mysql != nil:
		return ApplicationTypeMysql
	case instance.Redis != nil:
		return ApplicationTypeRedis
	case instance.Mongodb != nil:
		return ApplicationTypeMongodb
	case instance.Memcached != nil:
		return ApplicationTypeMemcached
	}
	return ApplicationTypeUnknown
}

func (instance *Instance) GetOrCreateContainer(id, name string) *Container {
	c := instance.Containers[name]
	if c == nil {
		c = NewContainer(id, name)
		instance.Containers[name] = c
	}
	return c
}

func (instance *Instance) NodeName() string {
	if instance.Node != nil {
		return instance.Node.GetName()
	}
	return ""
}

func (instance *Instance) NodeId() NodeId {
	if instance.Node != nil {
		return instance.Node.Id
	}
	return NodeId{}
}

func (instance *Instance) UpdateClusterRole(role string, v *timeseries.TimeSeries) {
	r, ok := clusterRolesByName[role]
	if !ok {
		return
	}
	v = v.Map(func(t timeseries.Time, v float32) float32 {
		if v == 1 {
			return float32(r)
		}
		return timeseries.NaN
	})
	if instance.clusterRole == nil {
		instance.clusterRole = v
	} else {
		instance.clusterRole = timeseries.NewAggregate(timeseries.Any).Add(instance.clusterRole, v).Get()
	}
}

func (instance *Instance) ClusterRole() *timeseries.TimeSeries {
	if instance.Pod == nil || instance.Pod.Ready.IsEmpty() || instance.clusterRole.IsEmpty() {
		return instance.clusterRole
	}
	return timeseries.Mul(instance.clusterRole, instance.Pod.Ready)
}

func (instance *Instance) ClusterRoleLast() ClusterRole {
	role := instance.ClusterRole()
	if role.IsEmpty() {
		return ClusterRoleNone
	}
	return ClusterRole(role.Last())
}

func (instance *Instance) LifeSpan() *timeseries.TimeSeries {
	if instance.Pod != nil {
		return instance.Pod.LifeSpan
	}
	for _, c := range instance.Containers {
		return c.MemoryRss.Map(timeseries.Defined)
	}
	return nil
}

func (instance *Instance) IsUp() bool {
	for _, c := range instance.Containers {
		if !c.MemoryRss.TailIsEmpty() {
			return true
		}
	}
	return false
}

func (instance *Instance) IsObsolete() bool {
	return instance.Pod != nil && instance.Pod.IsObsolete()
}

func (instance *Instance) IsFailed() bool {
	return instance.Pod != nil && instance.Pod.IsFailed()
}

func (instance *Instance) IsJobPod() bool {
	return instance.Pod != nil &&
		(instance.Pod.OwnerKind == ApplicationKindJob || instance.Pod.OwnerKind == ApplicationKindCronJob)
}

func (instance *Instance) UpAndRunning() *timeseries.TimeSeries {
	mem := timeseries.NewAggregate(timeseries.Any)
	for _, c := range instance.Containers {
		mem.Add(c.MemoryRss)
	}
	memTs := mem.Get()

	if memTs.IsEmpty() {
		return nil
	}
	up := memTs.Map(func(t timeseries.Time, v float32) float32 {
		if v > 0 {
			return 1
		}
		return 0
	})
	if instance.Pod == nil {
		return up
	}
	running := instance.Pod.Running.Map(timeseries.NanToZero)
	ready := instance.Pod.Ready.Map(timeseries.NanToZero)
	return timeseries.NewAggregate(timeseries.Min).Add(running, ready, up).Get()
}

func (instance *Instance) IsListenActive(ip, port string) bool {
	for l, active := range instance.TcpListens {
		if l.IP == ip && (l.Port == port || l.Port == "0") {
			return active
		}
	}
	return false
}

func (instance *Instance) NodeContainerID() *NodeContainerId {
	if instance.Node == nil {
		return nil
	}
	for _, c := range instance.Containers {
		return &NodeContainerId{
			NodeId:      instance.Node.Id,
			ContainerId: c.Id,
		}
	}
	return nil
}

type Listen struct {
	IP      string
	Port    string
	Proxied bool
}

type Requests struct {
	Ok           *timeseries.TimeSeries
	Failed       *timeseries.TimeSeries
	TotalLatency *timeseries.TimeSeries
}