mirror of
https://github.com/fankes/beszel.git
synced 2025-10-19 17:59:28 +08:00
refactor: alerts / emails
This commit is contained in:
@@ -25,8 +25,5 @@ func main() {
|
|||||||
Run: func(_ *cobra.Command, _ []string) { update.UpdateBeszel() },
|
Run: func(_ *cobra.Command, _ []string) { update.UpdateBeszel() },
|
||||||
})
|
})
|
||||||
|
|
||||||
hubApp := hub.NewHub(app)
|
hub.NewHub(app).Run()
|
||||||
|
|
||||||
hubApp.Run()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package alerts
|
package alerts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"beszel/internal/entities/email"
|
|
||||||
"beszel/internal/entities/system"
|
"beszel/internal/entities/system"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
@@ -72,12 +71,12 @@ func (am *AlertManager) handleSlidingValueAlert(newRecord *models.Record, alertR
|
|||||||
if !triggered && curValue > threshold {
|
if !triggered && curValue > threshold {
|
||||||
alertRecord.Set("triggered", true)
|
alertRecord.Set("triggered", true)
|
||||||
systemName := newRecord.GetString("name")
|
systemName := newRecord.GetString("name")
|
||||||
subject = fmt.Sprintf("%s usage threshold exceeded on %s", name, systemName)
|
subject = fmt.Sprintf("%s usage above threshold on %s", name, systemName)
|
||||||
body = fmt.Sprintf("%s usage on %s is %.1f%%.\n\n%s\n\n- Beszel", name, systemName, curValue, am.app.Settings().Meta.AppUrl+"/system/"+systemName)
|
body = fmt.Sprintf("%s usage on %s is %.1f%%.\n\n%s\n\n- Beszel", name, systemName, curValue, am.app.Settings().Meta.AppUrl+"/system/"+systemName)
|
||||||
} else if triggered && curValue <= threshold {
|
} else if triggered && curValue <= threshold {
|
||||||
alertRecord.Set("triggered", false)
|
alertRecord.Set("triggered", false)
|
||||||
systemName := newRecord.GetString("name")
|
systemName := newRecord.GetString("name")
|
||||||
subject = fmt.Sprintf("%s usage returned below threshold on %s", name, systemName)
|
subject = fmt.Sprintf("%s usage below threshold on %s", name, systemName)
|
||||||
body = fmt.Sprintf("%s usage on %s is below threshold at %.1f%%.\n\n%s\n\n- Beszel", name, systemName, curValue, am.app.Settings().Meta.AppUrl+"/system/"+systemName)
|
body = fmt.Sprintf("%s usage on %s is below threshold at %.1f%%.\n\n%s\n\n- Beszel", name, systemName, curValue, am.app.Settings().Meta.AppUrl+"/system/"+systemName)
|
||||||
} else {
|
} else {
|
||||||
// fmt.Println(name, "not triggered")
|
// fmt.Println(name, "not triggered")
|
||||||
@@ -93,11 +92,11 @@ func (am *AlertManager) handleSlidingValueAlert(newRecord *models.Record, alertR
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if user := alertRecord.ExpandedOne("user"); user != nil {
|
if user := alertRecord.ExpandedOne("user"); user != nil {
|
||||||
am.sendAlert(email.NewEmailData(
|
am.sendAlert(&mailer.Message{
|
||||||
user.GetString("email"),
|
To: []mail.Address{{Address: user.GetString("email")}},
|
||||||
subject,
|
Subject: subject,
|
||||||
body,
|
Text: body,
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,24 +129,20 @@ func (am *AlertManager) handleStatusAlerts(newStatus string, oldRecord *models.R
|
|||||||
}
|
}
|
||||||
// send alert
|
// send alert
|
||||||
systemName := oldRecord.GetString("name")
|
systemName := oldRecord.GetString("name")
|
||||||
am.sendAlert(email.NewEmailData(
|
am.sendAlert(&mailer.Message{
|
||||||
user.GetString("email"),
|
To: []mail.Address{{Address: user.GetString("email")}},
|
||||||
fmt.Sprintf("Connection to %s is %s %v", systemName, alertStatus, emoji),
|
Subject: fmt.Sprintf("Connection to %s is %s %v", systemName, alertStatus, emoji),
|
||||||
fmt.Sprintf("Connection to %s is %s\n\n- Beszel", systemName, alertStatus),
|
Text: fmt.Sprintf("Connection to %s is %s\n\n- Beszel", systemName, alertStatus),
|
||||||
))
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *AlertManager) sendAlert(data *email.EmailData) {
|
func (am *AlertManager) sendAlert(message *mailer.Message) {
|
||||||
// fmt.Println("sending alert", "to", data.to, "subj", data.subj, "body", data.body)
|
// fmt.Println("sending alert", "to", message.To, "subj", message.Subject, "body", message.Text)
|
||||||
message := &mailer.Message{
|
message.From = mail.Address{
|
||||||
From: mail.Address{
|
|
||||||
Address: am.app.Settings().Meta.SenderAddress,
|
Address: am.app.Settings().Meta.SenderAddress,
|
||||||
Name: am.app.Settings().Meta.SenderName,
|
Name: am.app.Settings().Meta.SenderName,
|
||||||
},
|
|
||||||
To: []mail.Address{{Address: data.To()}},
|
|
||||||
Subject: data.Subject(),
|
|
||||||
Text: data.Body(),
|
|
||||||
}
|
}
|
||||||
if err := am.mailClient.Send(message); err != nil {
|
if err := am.mailClient.Send(message); err != nil {
|
||||||
am.app.Logger().Error("Failed to send alert: ", "err", err.Error())
|
am.app.Logger().Error("Failed to send alert: ", "err", err.Error())
|
||||||
|
@@ -2,6 +2,7 @@ package container
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
|
// Docker container resources info from /containers/id/stats
|
||||||
type Container struct {
|
type Container struct {
|
||||||
Id string
|
Id string
|
||||||
IdShort string
|
IdShort string
|
||||||
@@ -24,6 +25,7 @@ type Container struct {
|
|||||||
// Mounts []MountPoint
|
// Mounts []MountPoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stats to return to the hub
|
||||||
type ContainerStats struct {
|
type ContainerStats struct {
|
||||||
Name string `json:"n"`
|
Name string `json:"n"`
|
||||||
Cpu float64 `json:"c"`
|
Cpu float64 `json:"c"`
|
||||||
@@ -32,6 +34,7 @@ type ContainerStats struct {
|
|||||||
NetworkRecv float64 `json:"nr"`
|
NetworkRecv float64 `json:"nr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keeps track of container stats from previous run
|
||||||
type PrevContainerStats struct {
|
type PrevContainerStats struct {
|
||||||
Cpu [2]uint64
|
Cpu [2]uint64
|
||||||
Net struct {
|
Net struct {
|
||||||
|
@@ -1,27 +0,0 @@
|
|||||||
package email
|
|
||||||
|
|
||||||
type EmailData struct {
|
|
||||||
to string
|
|
||||||
subj string
|
|
||||||
body string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEmailData(to, subj, body string) *EmailData {
|
|
||||||
return &EmailData{
|
|
||||||
to: to,
|
|
||||||
subj: subj,
|
|
||||||
body: body,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EmailData) To() string {
|
|
||||||
return e.to
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EmailData) Subject() string {
|
|
||||||
return e.subj
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EmailData) Body() string {
|
|
||||||
return e.body
|
|
||||||
}
|
|
@@ -46,9 +46,8 @@ func NewHub(app *pocketbase.PocketBase) *Hub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hub) Run() {
|
func (h *Hub) Run() {
|
||||||
|
var rm *records.RecordManager
|
||||||
rm := records.NewRecordManager(h.app)
|
var am *alerts.AlertManager
|
||||||
am := alerts.NewAlertManager(h.app)
|
|
||||||
|
|
||||||
// loosely check if it was executed using "go run"
|
// loosely check if it was executed using "go run"
|
||||||
isGoRun := strings.HasPrefix(os.Args[0], os.TempDir())
|
isGoRun := strings.HasPrefix(os.Args[0], os.TempDir())
|
||||||
@@ -60,6 +59,13 @@ func (h *Hub) Run() {
|
|||||||
Dir: "../../migrations",
|
Dir: "../../migrations",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// set up record manager and alert manager
|
||||||
|
h.app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||||
|
rm = records.NewRecordManager(h.app)
|
||||||
|
am = alerts.NewAlertManager(h.app)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
// set auth settings
|
// set auth settings
|
||||||
h.app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
h.app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||||
usersCollection, err := h.app.Dao().FindCollectionByNameOrId("users")
|
usersCollection, err := h.app.Dao().FindCollectionByNameOrId("users")
|
||||||
|
@@ -46,6 +46,7 @@ export default function MemChart({
|
|||||||
<YAxis
|
<YAxis
|
||||||
// use "ticks" instead of domain / tickcount if need more control
|
// use "ticks" instead of domain / tickcount if need more control
|
||||||
domain={[0, totalMem]}
|
domain={[0, totalMem]}
|
||||||
|
tickCount={9}
|
||||||
className="tracking-tighter"
|
className="tracking-tighter"
|
||||||
width={yAxisWidth}
|
width={yAxisWidth}
|
||||||
tickLine={false}
|
tickLine={false}
|
||||||
|
Reference in New Issue
Block a user