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:
2026-06-12 08:16:47 +02:00
parent ce8939fffb
commit 52cfffb83f
44 changed files with 1396 additions and 24 deletions

View File

@@ -13,7 +13,22 @@ module Admin
def metrics
host = HostMetrics.new.sample!
stats = DashboardStats.new.call
render json: { host: host, stats: stats, at: Time.current.iso8601 }
render json: {
host: host,
stats: stats,
ops_summary: ops_summary,
at: Time.current.iso8601
}
end
private
def ops_summary
{
open_critical: Ops::Incident.critical_open.count,
open_warning: Ops::Incident.open.where(severity: "warning").count,
open_total: Ops::Incident.open.count
}
end
end
end

View File

@@ -0,0 +1,37 @@
module Admin
class OpsController < Admin::BaseController
def index
@open_incidents = Ops::Incident.open.recent.limit(50)
@resolved_incidents = Ops::Incident.where(status: "resolved").since(30.days.ago).recent.limit(30)
@summary = ops_summary
end
def acknowledge
incident = Ops::Incident.find(params[:id])
incident.acknowledge!
redirect_to admin_ops_path, notice: "Incidente preso in carico"
end
def resolve
incident = Ops::Incident.find(params[:id])
incident.resolve!
redirect_to admin_ops_path, notice: "Incidente risolto"
end
def mute
incident = Ops::Incident.find(params[:id])
incident.mute!(duration: 24.hours)
redirect_to admin_ops_path, notice: "Notifiche sospese per 24 ore"
end
private
def ops_summary
{
open_critical: Ops::Incident.critical_open.count,
open_warning: Ops::Incident.open.where(severity: "warning").count,
open_total: Ops::Incident.open.count
}
end
end
end

View File

@@ -0,0 +1,28 @@
module Ops
class HealthController < ActionController::API
before_action :authorize_deep_health!
def show
summary = Ops::HealthChecks.new.summary
status_code = case summary[:status]
when "ok" then :ok
when "degraded" then :service_unavailable
else :service_unavailable
end
render json: summary, status: status_code
end
private
def authorize_deep_health!
token = ENV["OPS_HEALTH_TOKEN"].presence
return if token.blank?
provided = request.headers["X-Ops-Token"].presence || params[:token].presence
return head :unauthorized if provided.blank?
head :unauthorized unless ActiveSupport::SecurityUtils.secure_compare(provided, token)
end
end
end