Fix
This commit is contained in:
parent
e1ddd0b656
commit
f28ccce6a0
1 changed files with 52 additions and 11 deletions
|
|
@ -36,6 +36,7 @@ const (
|
||||||
dcKindStatusChanged dcChangeKind = "status_changed"
|
dcKindStatusChanged dcChangeKind = "status_changed"
|
||||||
dcKindHealthChanged dcChangeKind = "health_changed"
|
dcKindHealthChanged dcChangeKind = "health_changed"
|
||||||
dcKindDisappeared dcChangeKind = "disappeared"
|
dcKindDisappeared dcChangeKind = "disappeared"
|
||||||
|
dcKindAppeared dcChangeKind = "appeared"
|
||||||
)
|
)
|
||||||
|
|
||||||
type dcStateChange struct {
|
type dcStateChange struct {
|
||||||
|
|
@ -58,6 +59,10 @@ func (ch dcStateChange) isProblem() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ch dcStateChange) isNew() bool {
|
||||||
|
return ch.Kind == dcKindAppeared
|
||||||
|
}
|
||||||
|
|
||||||
func (ch dcStateChange) isRecovery() bool {
|
func (ch dcStateChange) isRecovery() bool {
|
||||||
switch ch.Kind {
|
switch ch.Kind {
|
||||||
case dcKindStatusChanged:
|
case dcKindStatusChanged:
|
||||||
|
|
@ -108,6 +113,7 @@ func runDockerCheck() error {
|
||||||
|
|
||||||
// Загружаем предыдущее состояние
|
// Загружаем предыдущее состояние
|
||||||
prevState := dcLoadState()
|
prevState := dcLoadState()
|
||||||
|
isFirstRun := len(prevState.Containers) == 0
|
||||||
|
|
||||||
// Строим map текущего состояния
|
// Строим map текущего состояния
|
||||||
current := make(map[string]dcContainerInfo, len(containers))
|
current := make(map[string]dcContainerInfo, len(containers))
|
||||||
|
|
@ -116,7 +122,7 @@ func runDockerCheck() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сравниваем
|
// Сравниваем
|
||||||
changes := dcCompareStates(prevState.Containers, current)
|
changes := dcCompareStates(prevState.Containers, current, isFirstRun)
|
||||||
|
|
||||||
// Статистика
|
// Статистика
|
||||||
runningCount := 0
|
runningCount := 0
|
||||||
|
|
@ -140,6 +146,8 @@ func runDockerCheck() error {
|
||||||
for _, ch := range changes {
|
for _, ch := range changes {
|
||||||
arrow := dcChangeArrow(ch)
|
arrow := dcChangeArrow(ch)
|
||||||
switch ch.Kind {
|
switch ch.Kind {
|
||||||
|
case dcKindAppeared:
|
||||||
|
log.Printf(" %s %-30s | появился (%s) | %s", arrow, ch.Name, ch.CurrState.Status, ch.Image)
|
||||||
case dcKindDisappeared:
|
case dcKindDisappeared:
|
||||||
log.Printf(" %s %-30s | исчез (был: %s)", arrow, ch.Name, ch.PrevState.Status)
|
log.Printf(" %s %-30s | исчез (был: %s)", arrow, ch.Name, ch.PrevState.Status)
|
||||||
case dcKindStatusChanged:
|
case dcKindStatusChanged:
|
||||||
|
|
@ -265,7 +273,7 @@ func dcNormalizeStatus(raw string) string {
|
||||||
|
|
||||||
// ── Сравнение состояний ──────────────────────────────────────────────────────
|
// ── Сравнение состояний ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
func dcCompareStates(prev map[string]dcContainerState, curr map[string]dcContainerInfo) []dcStateChange {
|
func dcCompareStates(prev map[string]dcContainerState, curr map[string]dcContainerInfo, isFirstRun bool) []dcStateChange {
|
||||||
var changes []dcStateChange
|
var changes []dcStateChange
|
||||||
|
|
||||||
// Проверяем текущие контейнеры
|
// Проверяем текущие контейнеры
|
||||||
|
|
@ -273,7 +281,16 @@ func dcCompareStates(prev map[string]dcContainerState, curr map[string]dcContain
|
||||||
prevInfo, existed := prev[name]
|
prevInfo, existed := prev[name]
|
||||||
|
|
||||||
if !existed {
|
if !existed {
|
||||||
// Новый контейнер — не алертим, просто добавится в state
|
if !isFirstRun {
|
||||||
|
// Новый контейнер появился после первого запуска — алертим
|
||||||
|
changes = append(changes, dcStateChange{
|
||||||
|
Name: name,
|
||||||
|
Kind: dcKindAppeared,
|
||||||
|
PrevState: dcContainerState{},
|
||||||
|
CurrState: dcContainerState{Status: currInfo.Status, Health: currInfo.Health},
|
||||||
|
Image: currInfo.Image,
|
||||||
|
})
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -365,29 +382,34 @@ func dcSaveState(current map[string]dcContainerInfo) {
|
||||||
// ── Отправка алерта ──────────────────────────────────────────────────────────
|
// ── Отправка алерта ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
func dcSendAlert(hostname string, changes []dcStateChange) {
|
func dcSendAlert(hostname string, changes []dcStateChange) {
|
||||||
var problems, recoveries []dcStateChange
|
var problems, recoveries, appeared []dcStateChange
|
||||||
for _, ch := range changes {
|
for _, ch := range changes {
|
||||||
if ch.isRecovery() {
|
switch {
|
||||||
|
case ch.isNew():
|
||||||
|
appeared = append(appeared, ch)
|
||||||
|
case ch.isRecovery():
|
||||||
recoveries = append(recoveries, ch)
|
recoveries = append(recoveries, ch)
|
||||||
} else if ch.isProblem() {
|
case ch.isProblem():
|
||||||
problems = append(problems, ch)
|
problems = append(problems, ch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Если нет ни проблем, ни восстановлений — молчим
|
// Если нет никаких изменений — молчим
|
||||||
if len(problems) == 0 && len(recoveries) == 0 {
|
if len(problems) == 0 && len(recoveries) == 0 && len(appeared) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Заголовок по наиболее критичному событию
|
// Заголовок по наиболее критичному событию
|
||||||
var header string
|
var header string
|
||||||
switch {
|
switch {
|
||||||
case len(problems) > 0 && len(recoveries) > 0:
|
|
||||||
header = "⚠️ <b>Изменения в состоянии контейнеров</b>"
|
|
||||||
case len(problems) > 0:
|
case len(problems) > 0:
|
||||||
header = "🚨 <b>АЛЕРТ: Проблемы с контейнерами!</b>"
|
header = "🚨 <b>АЛЕРТ: Проблемы с контейнерами!</b>"
|
||||||
default:
|
case len(recoveries) > 0 && len(appeared) > 0:
|
||||||
|
header = "⚠️ <b>Изменения в состоянии контейнеров</b>"
|
||||||
|
case len(recoveries) > 0:
|
||||||
header = "✅ <b>Контейнеры восстановлены</b>"
|
header = "✅ <b>Контейнеры восстановлены</b>"
|
||||||
|
default:
|
||||||
|
header = "ℹ️ <b>Новые контейнеры</b>"
|
||||||
}
|
}
|
||||||
|
|
||||||
message := fmt.Sprintf(
|
message := fmt.Sprintf(
|
||||||
|
|
@ -458,6 +480,20 @@ func dcSendAlert(hostname string, changes []dcStateChange) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Новые контейнеры
|
||||||
|
if len(appeared) > 0 {
|
||||||
|
message += "━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
|
||||||
|
message += fmt.Sprintf("🆕 <b>Появились (%d):</b>\n\n", len(appeared))
|
||||||
|
for _, ch := range appeared {
|
||||||
|
message += fmt.Sprintf(
|
||||||
|
"🆕 <b>%s</b>\n"+
|
||||||
|
" 📌 Статус: <code>%s</code>\n"+
|
||||||
|
" 🐳 <code>%s</code>\n\n",
|
||||||
|
ch.Name, ch.CurrState.Status, ch.Image,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
message += "━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
|
message += "━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
|
||||||
message += "💡 <i>docker ps -a | docker logs <имя> --tail 50</i>"
|
message += "💡 <i>docker ps -a | docker logs <имя> --tail 50</i>"
|
||||||
|
|
||||||
|
|
@ -492,6 +528,8 @@ func dcStatusEmoji(status, health string) string {
|
||||||
|
|
||||||
func dcChangeEmoji(ch dcStateChange) string {
|
func dcChangeEmoji(ch dcStateChange) string {
|
||||||
switch ch.Kind {
|
switch ch.Kind {
|
||||||
|
case dcKindAppeared:
|
||||||
|
return "🆕"
|
||||||
case dcKindDisappeared:
|
case dcKindDisappeared:
|
||||||
return "👻"
|
return "👻"
|
||||||
case dcKindHealthChanged:
|
case dcKindHealthChanged:
|
||||||
|
|
@ -510,6 +548,9 @@ func dcChangeEmoji(ch dcStateChange) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func dcChangeArrow(ch dcStateChange) string {
|
func dcChangeArrow(ch dcStateChange) string {
|
||||||
|
if ch.isNew() {
|
||||||
|
return "🆕"
|
||||||
|
}
|
||||||
if ch.isRecovery() {
|
if ch.isRecovery() {
|
||||||
return "✅"
|
return "✅"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue