Aggiunge monitoraggio ops: health check, log scanner, dashboard e notifiche.
Introduce incidenti con dedup, job Sidekiq ogni 3 min, scan log cron, /up/deep, dashboard /admin/ops e push ntfy; include Sentry opzionale e fix test suite. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
43
backend/app/models/ops/incident.rb
Normal file
43
backend/app/models/ops/incident.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
module Ops
|
||||
class Incident < ApplicationRecord
|
||||
self.table_name = "ops_incidents"
|
||||
|
||||
KINDS = %w[
|
||||
disk_space recordings_size service_down http_public sidekiq_stale sidekiq_dead
|
||||
log_pattern garage_storage
|
||||
].freeze
|
||||
SEVERITIES = %w[critical warning info].freeze
|
||||
STATUSES = %w[open acknowledged resolved].freeze
|
||||
|
||||
validates :kind, :severity, :status, :title, :fingerprint, presence: true
|
||||
validates :severity, inclusion: { in: SEVERITIES }
|
||||
validates :status, inclusion: { in: STATUSES }
|
||||
validates :occurrence_count, numericality: { greater_than: 0 }
|
||||
|
||||
scope :open, -> { where(status: %w[open acknowledged]) }
|
||||
scope :unresolved, -> { where.not(status: "resolved") }
|
||||
scope :critical_open, -> { open.where(severity: "critical") }
|
||||
scope :recent, -> { order(last_seen_at: :desc) }
|
||||
scope :since, ->(time) { where("last_seen_at >= ?", time) }
|
||||
|
||||
def open?
|
||||
status.in?(%w[open acknowledged])
|
||||
end
|
||||
|
||||
def muted?
|
||||
muted_until.present? && muted_until.future?
|
||||
end
|
||||
|
||||
def acknowledge!
|
||||
update!(status: "acknowledged", acknowledged_at: Time.current)
|
||||
end
|
||||
|
||||
def resolve!
|
||||
update!(status: "resolved")
|
||||
end
|
||||
|
||||
def mute!(duration: 24.hours)
|
||||
update!(muted_until: duration.from_now)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user