mirror of
https://github.com/amir20/dozzle.git
synced 2026-06-23 04:10:12 +00:00
chore: cleans up types for notificaitons (#4367)
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/amir20/dozzle/internal/notification"
|
||||
"github.com/amir20/dozzle/internal/notification/dispatcher"
|
||||
"github.com/amir20/dozzle/internal/releases"
|
||||
"github.com/amir20/dozzle/types"
|
||||
"github.com/expr-lang/expr"
|
||||
"github.com/expr-lang/expr/vm"
|
||||
)
|
||||
@@ -195,7 +196,7 @@ func (r *mutationResolver) PreviewExpression(ctx context.Context, input model.Pr
|
||||
// Compile and test container expression
|
||||
var containerProgram *vm.Program
|
||||
if input.ContainerExpression != "" {
|
||||
program, err := expr.Compile(input.ContainerExpression, expr.Env(notification.Container{}))
|
||||
program, err := expr.Compile(input.ContainerExpression, expr.Env(types.NotificationContainer{}))
|
||||
if err != nil {
|
||||
errStr := err.Error()
|
||||
result.ContainerError = &errStr
|
||||
@@ -207,7 +208,7 @@ func (r *mutationResolver) PreviewExpression(ctx context.Context, input model.Pr
|
||||
// Compile and test log expression
|
||||
var logProgram *vm.Program
|
||||
if input.LogExpression != nil && *input.LogExpression != "" {
|
||||
program, err := expr.Compile(*input.LogExpression, expr.Env(notification.Log{}))
|
||||
program, err := expr.Compile(*input.LogExpression, expr.Env(types.NotificationLog{}))
|
||||
if err != nil {
|
||||
errStr := err.Error()
|
||||
result.LogError = &errStr
|
||||
|
||||
@@ -2,10 +2,12 @@ package dispatcher
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/amir20/dozzle/types"
|
||||
)
|
||||
|
||||
// Dispatcher is responsible for sending notifications to external systems
|
||||
type Dispatcher interface {
|
||||
// Send sends a notification to the configured destination
|
||||
Send(ctx context.Context, notification any) error
|
||||
Send(ctx context.Context, notification types.Notification) error
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/amir20/dozzle/types"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
@@ -46,7 +47,7 @@ func NewWebhookDispatcher(name, url, templateStr string) (*WebhookDispatcher, er
|
||||
}
|
||||
|
||||
// Send sends a notification to the webhook URL
|
||||
func (w *WebhookDispatcher) Send(ctx context.Context, notification any) error {
|
||||
func (w *WebhookDispatcher) Send(ctx context.Context, notification types.Notification) error {
|
||||
var payload []byte
|
||||
var err error
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/amir20/dozzle/internal/container"
|
||||
"github.com/amir20/dozzle/internal/notification/dispatcher"
|
||||
"github.com/amir20/dozzle/types"
|
||||
"github.com/expr-lang/expr"
|
||||
"github.com/puzpuzpuz/xsync/v4"
|
||||
"github.com/rs/zerolog/log"
|
||||
@@ -75,7 +76,7 @@ func (m *Manager) AddSubscription(sub *Subscription) error {
|
||||
|
||||
// Compile container expression if provided
|
||||
if sub.ContainerExpression != "" {
|
||||
program, err := expr.Compile(sub.ContainerExpression, expr.Env(Container{}))
|
||||
program, err := expr.Compile(sub.ContainerExpression, expr.Env(types.NotificationContainer{}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to compile container expression: %w", err)
|
||||
}
|
||||
@@ -84,7 +85,7 @@ func (m *Manager) AddSubscription(sub *Subscription) error {
|
||||
|
||||
// Compile log expression if provided
|
||||
if sub.LogExpression != "" {
|
||||
program, err := expr.Compile(sub.LogExpression, expr.Env(Log{}))
|
||||
program, err := expr.Compile(sub.LogExpression, expr.Env(types.NotificationLog{}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to compile log expression: %w", err)
|
||||
}
|
||||
@@ -122,7 +123,7 @@ func (m *Manager) RemoveSubscription(id int) {
|
||||
func (m *Manager) ReplaceSubscription(sub *Subscription) error {
|
||||
// Compile container expression if provided
|
||||
if sub.ContainerExpression != "" {
|
||||
program, err := expr.Compile(sub.ContainerExpression, expr.Env(Container{}))
|
||||
program, err := expr.Compile(sub.ContainerExpression, expr.Env(types.NotificationContainer{}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to compile container expression: %w", err)
|
||||
}
|
||||
@@ -131,7 +132,7 @@ func (m *Manager) ReplaceSubscription(sub *Subscription) error {
|
||||
|
||||
// Compile log expression if provided
|
||||
if sub.LogExpression != "" {
|
||||
program, err := expr.Compile(sub.LogExpression, expr.Env(Log{}))
|
||||
program, err := expr.Compile(sub.LogExpression, expr.Env(types.NotificationLog{}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to compile log expression: %w", err)
|
||||
}
|
||||
@@ -196,7 +197,7 @@ func (m *Manager) UpdateSubscription(id int, updates map[string]any) error {
|
||||
}
|
||||
case "containerExpression":
|
||||
if exprStr, ok := value.(string); ok {
|
||||
program, err := expr.Compile(exprStr, expr.Env(Container{}))
|
||||
program, err := expr.Compile(exprStr, expr.Env(types.NotificationContainer{}))
|
||||
if err != nil {
|
||||
updateErr = fmt.Errorf("failed to compile container expression: %w", err)
|
||||
return nil, xsync.CancelOp
|
||||
@@ -207,7 +208,7 @@ func (m *Manager) UpdateSubscription(id int, updates map[string]any) error {
|
||||
case "logExpression":
|
||||
if exprStr, ok := value.(string); ok {
|
||||
if exprStr != "" {
|
||||
program, err := expr.Compile(exprStr, expr.Env(Log{}))
|
||||
program, err := expr.Compile(exprStr, expr.Env(types.NotificationLog{}))
|
||||
if err != nil {
|
||||
updateErr = fmt.Errorf("failed to compile log expression: %w", err)
|
||||
return nil, xsync.CancelOp
|
||||
@@ -354,7 +355,7 @@ func (m *Manager) processLogEvent(logEvent *container.LogEvent) {
|
||||
log.Debug().Str("containerID", notificationContainer.ID).Interface("log", notificationLog.Message).Msg("Matched subscription")
|
||||
|
||||
// Create notification
|
||||
notification := Notification{
|
||||
notification := types.Notification{
|
||||
ID: fmt.Sprintf("%s-%d", c.ID, time.Now().UnixNano()),
|
||||
Container: notificationContainer,
|
||||
Log: notificationLog,
|
||||
@@ -370,7 +371,7 @@ func (m *Manager) processLogEvent(logEvent *container.LogEvent) {
|
||||
}
|
||||
|
||||
// sendNotification sends a notification using the dispatcher
|
||||
func (m *Manager) sendNotification(d dispatcher.Dispatcher, notification Notification, id int) {
|
||||
func (m *Manager) sendNotification(d dispatcher.Dispatcher, notification types.Notification, id int) {
|
||||
ctx, cancel := context.WithTimeout(m.ctx, 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -454,7 +455,7 @@ func (m *Manager) LoadConfig(r io.Reader) error {
|
||||
func (m *Manager) loadSubscription(sub *Subscription) error {
|
||||
// Compile container expression if provided
|
||||
if sub.ContainerExpression != "" {
|
||||
program, err := expr.Compile(sub.ContainerExpression, expr.Env(Container{}))
|
||||
program, err := expr.Compile(sub.ContainerExpression, expr.Env(types.NotificationContainer{}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to compile container expression: %w", err)
|
||||
}
|
||||
@@ -463,7 +464,7 @@ func (m *Manager) loadSubscription(sub *Subscription) error {
|
||||
|
||||
// Compile log expression if provided
|
||||
if sub.LogExpression != "" {
|
||||
program, err := expr.Compile(sub.LogExpression, expr.Env(Log{}))
|
||||
program, err := expr.Compile(sub.LogExpression, expr.Env(types.NotificationLog{}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to compile log expression: %w", err)
|
||||
}
|
||||
|
||||
@@ -6,33 +6,15 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/amir20/dozzle/internal/container"
|
||||
"github.com/amir20/dozzle/types"
|
||||
"github.com/expr-lang/expr"
|
||||
"github.com/expr-lang/expr/vm"
|
||||
"github.com/puzpuzpuz/xsync/v4"
|
||||
)
|
||||
|
||||
// Notification represents a notification event that can be filtered and sent
|
||||
type Notification struct {
|
||||
ID string `json:"id"`
|
||||
Container Container `json:"container"`
|
||||
Log Log `json:"log"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// Container represents a simplified container structure optimized for expr filtering
|
||||
type Container struct {
|
||||
ID string `json:"id" expr:"id"`
|
||||
Name string `json:"name" expr:"name"`
|
||||
Image string `json:"image" expr:"image"`
|
||||
State string `json:"state" expr:"state"`
|
||||
Health string `json:"health" expr:"health"`
|
||||
Host string `json:"host" expr:"host"`
|
||||
Labels map[string]string `json:"labels" expr:"labels"`
|
||||
}
|
||||
|
||||
// FromContainerModel converts internal container.Container to notification.Container
|
||||
func FromContainerModel(c container.Container) Container {
|
||||
return Container{
|
||||
// FromContainerModel converts internal container.Container to types.NotificationContainer
|
||||
func FromContainerModel(c container.Container) types.NotificationContainer {
|
||||
return types.NotificationContainer{
|
||||
ID: c.ID,
|
||||
Name: c.Name,
|
||||
Image: c.Image,
|
||||
@@ -43,21 +25,11 @@ func FromContainerModel(c container.Container) Container {
|
||||
}
|
||||
}
|
||||
|
||||
// Log represents a log entry with message that can be string or object
|
||||
type Log struct {
|
||||
ID uint32 `json:"id" expr:"id"`
|
||||
Message any `json:"message" expr:"message"` // string for simple/grouped logs, map for complex logs
|
||||
Timestamp int64 `json:"timestamp" expr:"timestamp"`
|
||||
Level string `json:"level" expr:"level"`
|
||||
Stream string `json:"stream" expr:"stream"`
|
||||
Type string `json:"type" expr:"type"`
|
||||
}
|
||||
|
||||
// FromLogEvent converts container.LogEvent to notification.Log
|
||||
func FromLogEvent(l container.LogEvent) Log {
|
||||
// FromLogEvent converts container.LogEvent to types.NotificationLog
|
||||
func FromLogEvent(l container.LogEvent) types.NotificationLog {
|
||||
message := extractMessage(l)
|
||||
|
||||
return Log{
|
||||
return types.NotificationLog{
|
||||
ID: l.Id,
|
||||
Message: message,
|
||||
Timestamp: l.Timestamp,
|
||||
@@ -138,7 +110,7 @@ type Config struct {
|
||||
}
|
||||
|
||||
// MatchesContainer checks if a container matches this subscription's container filter
|
||||
func (s *Subscription) MatchesContainer(c Container) bool {
|
||||
func (s *Subscription) MatchesContainer(c types.NotificationContainer) bool {
|
||||
if s.ContainerProgram == nil {
|
||||
return false
|
||||
}
|
||||
@@ -153,7 +125,7 @@ func (s *Subscription) MatchesContainer(c Container) bool {
|
||||
}
|
||||
|
||||
// MatchesLog checks if a log matches this subscription's log filter
|
||||
func (s *Subscription) MatchesLog(l Log) bool {
|
||||
func (s *Subscription) MatchesLog(l types.NotificationLog) bool {
|
||||
if s.LogProgram == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
// Notification represents a notification event that can be filtered and sent
|
||||
type Notification struct {
|
||||
ID string `json:"id"`
|
||||
Container NotificationContainer `json:"container"`
|
||||
Log NotificationLog `json:"log"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// NotificationContainer represents a simplified container structure for notifications
|
||||
type NotificationContainer struct {
|
||||
ID string `json:"id" expr:"id"`
|
||||
Name string `json:"name" expr:"name"`
|
||||
Image string `json:"image" expr:"image"`
|
||||
State string `json:"state" expr:"state"`
|
||||
Health string `json:"health" expr:"health"`
|
||||
Host string `json:"host" expr:"host"`
|
||||
Labels map[string]string `json:"labels" expr:"labels"`
|
||||
}
|
||||
|
||||
// NotificationLog represents a log entry with message that can be string or object
|
||||
type NotificationLog struct {
|
||||
ID uint32 `json:"id" expr:"id"`
|
||||
Message any `json:"message" expr:"message"` // string for simple/grouped logs, map for complex logs
|
||||
Timestamp int64 `json:"timestamp" expr:"timestamp"`
|
||||
Level string `json:"level" expr:"level"`
|
||||
Stream string `json:"stream" expr:"stream"`
|
||||
Type string `json:"type" expr:"type"`
|
||||
}
|
||||
Reference in New Issue
Block a user