Ctrl K
ComunidadGuías…

auditor/auditor.go

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

Archivo original ↗Preguntar a KiBot
package auditor

import (
	"sort"
	"time"

	"github.com/coroot/coroot/db"
	"github.com/coroot/coroot/model"
	"k8s.io/klog"
)

type appAuditor struct {
	w        *model.World
	p        *db.Project
	app      *model.Application
	reports  []*model.AuditReport
	detailed bool
}

type Profile struct {
	Stages map[string]float32 `json:"stages"`
}

type Stages map[string]time.Duration

func (ss Stages) stage(name string, f func()) {
	if ss == nil {
		f()
		return
	}
	t := time.Now()
	f()
	ss[name] += time.Since(t)
}

func Audit(w *model.World, p *db.Project, generateDetailedReportFor *model.Application, prof *Profile) {
	start := time.Now()
	ncs := nodeConsumersByNode{}

	var stages Stages
	if prof != nil {
		stages = Stages{}
	}
	for _, app := range w.Applications {
		a := &appAuditor{
			w:        w,
			p:        p,
			app:      app,
			detailed: app == generateDetailedReportFor,
		}
		stages.stage("slo", a.slo)
		stages.stage("instances", a.instances)
		stages.stage("cpu", func() { a.cpu(ncs) })
		stages.stage("memory", func() { a.memory(ncs) })
		stages.stage("storage", a.storage)
		stages.stage("gpu", a.gpu)
		stages.stage("network", a.network)
		stages.stage("dns", a.dns)
		stages.stage("postgres", a.postgres)
		stages.stage("mysql", a.mysql)
		stages.stage("redis", a.redis)
		stages.stage("mongodb", a.mongodb)
		stages.stage("memcached", a.memcached)
		stages.stage("jvm", a.jvm)
		stages.stage("dotnet", a.dotnet)
		stages.stage("python", a.python)
		stages.stage("nodejs", a.nodejs)
		stages.stage("logs", a.logs)
		stages.stage("deployments", a.deployments)

		for _, r := range a.reports {
			widgets := a.enrichWidgets(r.Widgets, app.Events)
			sort.SliceStable(widgets, func(i, j int) bool {
				return widgets[i].Table != nil && widgets[j].Table == nil
			})
			r.Widgets = widgets
			r.ArrangeWidgets()

			for _, ch := range r.Checks {
				ch.Calc()
				if ch.Status > r.Status {
					r.Status = ch.Status
				}
			}
			switch r.Name {
			case model.AuditReportPostgres, model.AuditReportMongodb, model.AuditReportMysql, model.AuditReportRedis, model.AuditReportInstances, model.AuditReportSLO:
				if app.Status < r.Status {
					app.Status = r.Status
				}
			}
			app.Reports = append(app.Reports, r)
		}
	}

	if prof != nil {
		prof.Stages = map[string]float32{}
		for name, duration := range stages {
			d := float32(duration.Seconds())
			if d > prof.Stages[name] {
				prof.Stages[name] = d
			}
		}
	}

	klog.Infof("%s: audited %d apps in %s", p.Id, len(w.Applications), time.Since(start).Truncate(time.Millisecond))
}

func (a *appAuditor) addReport(name model.AuditReportName) *model.AuditReport {
	r := model.NewAuditReport(a.app, a.w.Ctx, a.w.CheckConfigs, name, a.detailed)
	a.reports = append(a.reports, r)
	return r
}

func (a *appAuditor) delReport(name model.AuditReportName) {
	for i, r := range a.reports {
		if r.Name == name {
			a.reports = append(a.reports[:i], a.reports[i+1:]...)
			return
		}
	}
}

func (a *appAuditor) enrichWidgets(widgets []*model.Widget, events []*model.ApplicationEvent) []*model.Widget {
	annotations := model.EventsToAnnotations(events, a.w.Ctx)
	var res []*model.Widget
	for _, w := range widgets {
		if w.Chart != nil {
			if w.Chart.IsEmpty() {
				continue
			}
		}
		if w.Heatmap != nil {
			if w.Heatmap.IsEmpty() {
				continue
			}
		}
		if w.ChartGroup != nil {
			var charts []*model.Chart
			for _, ch := range w.ChartGroup.Charts {
				if ch.IsEmpty() {
					continue
				}
				charts = append(charts, ch)
			}
			if len(charts) == 0 {
				continue
			}
			w.ChartGroup.Charts = charts
		}
		w.AddAnnotation(annotations...)
		res = append(res, w)
	}
	return res
}