Files
heartbeat/internal/app/app.go
todor 93ae9b66b3
Some checks failed
Build heartbeat / build (push) Failing after 1m18s
init
2026-05-03 21:09:59 +02:00

83 lines
1.9 KiB
Go

package app
import (
"context"
"log"
"time"
"heartbeat/internal/alerts"
"heartbeat/internal/config"
"heartbeat/internal/discord"
"heartbeat/internal/metrics"
)
type Runner struct {
cfg config.Config
sampler *metrics.Sampler
evaluator *alerts.Evaluator
discord *discord.Client
}
func New(cfg config.Config) (*Runner, error) {
return &Runner{
cfg: cfg,
sampler: metrics.NewSampler(cfg.RequestTimeout),
evaluator: alerts.NewEvaluator(),
discord: discord.New(cfg.ServerName, cfg.DiscordWebhookURL, cfg.NotifyRoleID, cfg.RequestTimeout),
}, nil
}
func (r *Runner) Run(ctx context.Context) error {
if err := r.tick(ctx, true); err != nil {
log.Printf("initial tick failed: %v", err)
}
sampleTicker := time.NewTicker(r.cfg.SampleInterval)
defer sampleTicker.Stop()
summaryTicker := time.NewTicker(r.cfg.SummaryInterval)
defer summaryTicker.Stop()
for {
select {
case <-ctx.Done():
return nil
case <-sampleTicker.C:
if err := r.tick(ctx, false); err != nil {
log.Printf("sample tick failed: %v", err)
}
case <-summaryTicker.C:
if err := r.sendSummary(ctx); err != nil {
log.Printf("summary failed: %v", err)
}
}
}
}
func (r *Runner) tick(ctx context.Context, sendSummary bool) error {
sample, err := r.sampler.Collect(ctx, r.cfg)
if err != nil {
return err
}
if sendSummary {
if err := r.discord.SendSummary(ctx, sample, r.cfg.SummaryInterval); err != nil {
log.Printf("summary send failed: %v", err)
}
}
for _, event := range r.evaluator.Evaluate(r.cfg, sample) {
if err := r.discord.SendEvent(ctx, sample, event); err != nil {
log.Printf("event send failed for %s: %v", event.Key, err)
}
}
return nil
}
func (r *Runner) sendSummary(ctx context.Context) error {
sample, err := r.sampler.Collect(ctx, r.cfg)
if err != nil {
return err
}
return r.discord.SendSummary(ctx, sample, r.cfg.SummaryInterval)
}