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:
@@ -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
|
||||
|
||||
37
backend/app/controllers/admin/ops_controller.rb
Normal file
37
backend/app/controllers/admin/ops_controller.rb
Normal 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
|
||||
28
backend/app/controllers/ops/health_controller.rb
Normal file
28
backend/app/controllers/ops/health_controller.rb
Normal 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
|
||||
Reference in New Issue
Block a user