solid_stack_web 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/solid_stack_web/application_controller.rb +23 -1
- data/app/controllers/solid_stack_web/audit_controller.rb +49 -0
- data/app/controllers/solid_stack_web/failed_jobs/selections_controller.rb +2 -0
- data/app/controllers/solid_stack_web/failed_jobs_controller.rb +4 -0
- data/app/controllers/solid_stack_web/jobs/selections_controller.rb +1 -0
- data/app/controllers/solid_stack_web/jobs_controller.rb +4 -0
- data/app/controllers/solid_stack_web/queues/pauses_controller.rb +2 -0
- data/app/helpers/solid_stack_web/application_helper.rb +9 -0
- data/app/models/solid_stack_web/audit_event.rb +17 -0
- data/app/views/layouts/solid_stack_web/application.html.erb +2 -0
- data/app/views/solid_stack_web/audit/index.html.erb +86 -0
- data/config/importmap.rb +1 -0
- data/config/routes.rb +1 -0
- data/lib/generators/solid_stack_web/install/migrations_generator.rb +24 -0
- data/lib/generators/solid_stack_web/install/templates/create_solid_stack_web_audit_events.rb.tt +16 -0
- data/lib/generators/solid_stack_web/install/templates/initializer.rb +7 -0
- data/lib/solid_stack_web/version.rb +1 -1
- data/lib/solid_stack_web.rb +5 -0
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f5c82dfa829278df1d7fe7b59637d2b7c7b2ef31ea8ec9fb7ff2fe1234133658
|
|
4
|
+
data.tar.gz: eb1e7519de019b3921c5ef3536b806b902790a51eac340d94084e59e1ef4650c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 33821254738d6f8c2ee5cc177ef01f600988d905ccf7020285b4a3368b29db7c5f19811aabaf45ade463a433304e70639047bf8120bc0718ee2c9442a93686a7
|
|
7
|
+
data.tar.gz: 780cbf594e35533f5ee0374e41945a6a1319c22151c6fb2b9b7a82f1aaf256651b6e836777e3939b305bcff510144a5d3d84de014f6e8bc67cab67959f761725
|
|
@@ -22,7 +22,7 @@ module SolidStackWeb
|
|
|
22
22
|
|
|
23
23
|
def current_section
|
|
24
24
|
case controller_name
|
|
25
|
-
when "jobs", "failed_jobs", "queues", "processes", "history", "scheduled_jobs", "recurring_tasks" then :queue
|
|
25
|
+
when "jobs", "failed_jobs", "queues", "processes", "history", "scheduled_jobs", "recurring_tasks", "audit" then :queue
|
|
26
26
|
when "cache", "cache_entries" then :cache
|
|
27
27
|
when "cable" then :cable
|
|
28
28
|
else :overview
|
|
@@ -51,6 +51,28 @@ module SolidStackWeb
|
|
|
51
51
|
request_http_basic_authentication("Solid Stack Dashboard")
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
def record_audit(action, job_class: nil, queue_name: nil, item_count: 1)
|
|
55
|
+
AuditEvent.create!(
|
|
56
|
+
action: action,
|
|
57
|
+
actor: resolve_current_actor,
|
|
58
|
+
job_class: job_class,
|
|
59
|
+
queue_name: queue_name,
|
|
60
|
+
item_count: item_count
|
|
61
|
+
)
|
|
62
|
+
rescue => e
|
|
63
|
+
Rails.logger.error("[SolidStackWeb] Audit log failed: #{e.message}")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def resolve_current_actor
|
|
67
|
+
block = SolidStackWeb.current_actor
|
|
68
|
+
return nil unless block
|
|
69
|
+
|
|
70
|
+
instance_exec(&block)
|
|
71
|
+
rescue => e
|
|
72
|
+
Rails.logger.error("[SolidStackWeb] current_actor resolution failed: #{e.message}")
|
|
73
|
+
nil
|
|
74
|
+
end
|
|
75
|
+
|
|
54
76
|
def render_not_found
|
|
55
77
|
render "solid_stack_web/errors/not_found", status: :not_found
|
|
56
78
|
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module SolidStackWeb
|
|
2
|
+
class AuditController < ApplicationController
|
|
3
|
+
def index
|
|
4
|
+
unless AuditEvent.table_exists?
|
|
5
|
+
redirect_to root_path,
|
|
6
|
+
alert: "Audit log requires running `rails solid_stack_web:install:migrations && rails db:migrate`."
|
|
7
|
+
return
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
set_filters
|
|
11
|
+
scope = audit_scope
|
|
12
|
+
|
|
13
|
+
respond_to do |format|
|
|
14
|
+
format.html { @pagy, @events = pagy(scope) }
|
|
15
|
+
format.csv do
|
|
16
|
+
send_data audit_csv(scope),
|
|
17
|
+
filename: "audit-log-#{Date.today}.csv",
|
|
18
|
+
type: "text/csv", disposition: "attachment"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def set_filters
|
|
26
|
+
@action_filter = params[:audit_action].presence_in(AuditEvent::ACTIONS)
|
|
27
|
+
@actor_filter = params[:actor].presence
|
|
28
|
+
@queue_filter = params[:queue].presence
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def audit_scope
|
|
32
|
+
scope = AuditEvent.recent
|
|
33
|
+
scope = scope.where(action: @action_filter) if @action_filter
|
|
34
|
+
scope = scope.where(actor: @actor_filter) if @actor_filter
|
|
35
|
+
scope = scope.where(queue_name: @queue_filter) if @queue_filter
|
|
36
|
+
scope
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def audit_csv(scope)
|
|
40
|
+
CSV.generate(headers: true) do |csv|
|
|
41
|
+
csv << %w[id action actor job_class queue_name item_count created_at]
|
|
42
|
+
scope.each do |event|
|
|
43
|
+
csv << [event.id, event.action, event.actor, event.job_class,
|
|
44
|
+
event.queue_name, event.item_count, event.created_at.iso8601]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -6,6 +6,7 @@ module SolidStackWeb
|
|
|
6
6
|
def create
|
|
7
7
|
count = @ids.size
|
|
8
8
|
SolidQueue::FailedExecution.where(id: @ids).each(&:retry)
|
|
9
|
+
record_audit("failed_jobs_retried", item_count: count)
|
|
9
10
|
redirect_to failed_jobs_path, notice: "#{count} #{count == 1 ? "job" : "jobs"} retried."
|
|
10
11
|
rescue => e
|
|
11
12
|
redirect_to failed_jobs_path, alert: "Could not retry jobs: #{e.message}"
|
|
@@ -14,6 +15,7 @@ module SolidStackWeb
|
|
|
14
15
|
def destroy
|
|
15
16
|
job_ids = SolidQueue::FailedExecution.where(id: @ids).pluck(:job_id)
|
|
16
17
|
count = SolidQueue::Job.where(id: job_ids).destroy_all.size
|
|
18
|
+
record_audit("failed_jobs_discarded", item_count: count)
|
|
17
19
|
redirect_to failed_jobs_path, notice: "#{count} #{count == 1 ? "job" : "jobs"} discarded."
|
|
18
20
|
rescue => e
|
|
19
21
|
redirect_to failed_jobs_path, alert: "Could not discard jobs: #{e.message}"
|
|
@@ -28,7 +28,10 @@ module SolidStackWeb
|
|
|
28
28
|
|
|
29
29
|
def destroy
|
|
30
30
|
@execution = ::SolidQueue::FailedExecution.find(params[:id])
|
|
31
|
+
job_class = @execution.job.class_name
|
|
32
|
+
queue_name = @execution.job.queue_name
|
|
31
33
|
@execution.job.destroy!
|
|
34
|
+
record_audit("failed_job_discarded", job_class: job_class, queue_name: queue_name)
|
|
32
35
|
@executions_remain = ::SolidQueue::FailedExecution.exists?
|
|
33
36
|
@notice = "Job discarded."
|
|
34
37
|
|
|
@@ -40,6 +43,7 @@ module SolidStackWeb
|
|
|
40
43
|
|
|
41
44
|
def retry
|
|
42
45
|
execution = ::SolidQueue::FailedExecution.find(params[:id])
|
|
46
|
+
record_audit("failed_job_retried", job_class: execution.job.class_name, queue_name: execution.job.queue_name)
|
|
43
47
|
execution.retry
|
|
44
48
|
redirect_to failed_jobs_path, notice: "Job retried."
|
|
45
49
|
end
|
|
@@ -8,6 +8,7 @@ module SolidStackWeb
|
|
|
8
8
|
ids = Array(params[:job_ids]).map(&:to_i).reject(&:zero?)
|
|
9
9
|
job_ids = Job::EXECUTION_MODELS[status].where(id: ids).pluck(:job_id)
|
|
10
10
|
count = SolidQueue::Job.where(id: job_ids).destroy_all.size
|
|
11
|
+
record_audit("jobs_discarded", item_count: count)
|
|
11
12
|
|
|
12
13
|
redirect_to jobs_path(
|
|
13
14
|
status: status,
|
|
@@ -31,7 +31,10 @@ module SolidStackWeb
|
|
|
31
31
|
def destroy
|
|
32
32
|
if params[:id]
|
|
33
33
|
@execution = Job::EXECUTION_MODELS[@status].find(params[:id])
|
|
34
|
+
job_class = @execution.job.class_name
|
|
35
|
+
queue_name = @execution.job.queue_name
|
|
34
36
|
@execution.job.destroy!
|
|
37
|
+
record_audit("job_discarded", job_class: job_class, queue_name: queue_name)
|
|
35
38
|
@executions_remain = Job::EXECUTION_MODELS[@status].exists?
|
|
36
39
|
@notice = "Job discarded."
|
|
37
40
|
|
|
@@ -42,6 +45,7 @@ module SolidStackWeb
|
|
|
42
45
|
else
|
|
43
46
|
job_ids = filtered_scope.pluck(:job_id)
|
|
44
47
|
count = SolidQueue::Job.where(id: job_ids).destroy_all.size
|
|
48
|
+
record_audit("jobs_discarded", item_count: count)
|
|
45
49
|
redirect_to jobs_path(status: @status, q: @search, queue: @queue, period: @period, priority: @priority, sort: @sort, direction: @direction),
|
|
46
50
|
notice: "#{count} #{count == 1 ? "job" : "jobs"} discarded."
|
|
47
51
|
end
|
|
@@ -2,11 +2,13 @@ module SolidStackWeb
|
|
|
2
2
|
class Queues::PausesController < ApplicationController
|
|
3
3
|
def create
|
|
4
4
|
::SolidQueue::Pause.find_or_create_by!(queue_name: params[:queue_id])
|
|
5
|
+
record_audit("queue_paused", queue_name: params[:queue_id])
|
|
5
6
|
redirect_back_or_to queues_path
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
def destroy
|
|
9
10
|
::SolidQueue::Pause.find_by(queue_name: params[:queue_id])&.destroy
|
|
11
|
+
record_audit("queue_resumed", queue_name: params[:queue_id])
|
|
10
12
|
redirect_back_or_to queues_path
|
|
11
13
|
end
|
|
12
14
|
end
|
|
@@ -87,6 +87,15 @@ module SolidStackWeb
|
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
+
def audit_action_badge_class(action)
|
|
91
|
+
case action
|
|
92
|
+
when /discard/ then "sqw-badge--failed"
|
|
93
|
+
when /retry/ then "sqw-badge--scheduled"
|
|
94
|
+
when "queue_paused" then "sqw-badge--blocked"
|
|
95
|
+
when "queue_resumed" then "sqw-badge--ready"
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
90
99
|
def sort_header_th(label, col, url_proc, current_sort:, current_dir:)
|
|
91
100
|
is_active = current_sort == col
|
|
92
101
|
next_dir = (is_active && current_dir == "desc") ? "asc" : "desc"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module SolidStackWeb
|
|
2
|
+
class AuditEvent < ActiveRecord::Base
|
|
3
|
+
self.table_name = "solid_stack_web_audit_events"
|
|
4
|
+
|
|
5
|
+
ACTIONS = %w[
|
|
6
|
+
job_discarded jobs_discarded
|
|
7
|
+
failed_job_retried failed_jobs_retried
|
|
8
|
+
failed_job_discarded failed_jobs_discarded
|
|
9
|
+
queue_paused queue_resumed
|
|
10
|
+
].freeze
|
|
11
|
+
|
|
12
|
+
validates :action, presence: true, inclusion: { in: ACTIONS }
|
|
13
|
+
validates :item_count, numericality: { greater_than: 0 }
|
|
14
|
+
|
|
15
|
+
scope :recent, -> { order(created_at: :desc) }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -65,6 +65,8 @@
|
|
|
65
65
|
class: "sqw-subnav__link#{" sqw-subnav__link--active" if controller_name == "history"}" %>
|
|
66
66
|
<%= link_to "Processes", processes_path,
|
|
67
67
|
class: "sqw-subnav__link#{" sqw-subnav__link--active" if controller_name == "processes"}" %>
|
|
68
|
+
<%= link_to "Audit", audit_path,
|
|
69
|
+
class: "sqw-subnav__link#{" sqw-subnav__link--active" if controller_name == "audit"}" %>
|
|
68
70
|
</div>
|
|
69
71
|
</nav>
|
|
70
72
|
<% end %>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<div class="sqw-page-header sqw-page-header--split">
|
|
2
|
+
<h1 class="sqw-page-title">Audit Log</h1>
|
|
3
|
+
<% if @events&.any? %>
|
|
4
|
+
<%= link_to "Export CSV",
|
|
5
|
+
audit_path(format: :csv, audit_action: @action_filter, actor: @actor_filter, queue: @queue_filter),
|
|
6
|
+
class: "sqw-btn sqw-btn--muted sqw-btn--sm", data: { turbo: false } %>
|
|
7
|
+
<% end %>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<form class="sqw-filters" action="<%= audit_path %>" method="get">
|
|
11
|
+
<select name="audit_action" class="sqw-select" aria-label="Filter by action"
|
|
12
|
+
onchange="this.form.submit()">
|
|
13
|
+
<option value="">All actions</option>
|
|
14
|
+
<% SolidStackWeb::AuditEvent::ACTIONS.each do |action| %>
|
|
15
|
+
<option value="<%= action %>" <%= "selected" if @action_filter == action %>><%= action.tr("_", " ") %></option>
|
|
16
|
+
<% end %>
|
|
17
|
+
</select>
|
|
18
|
+
|
|
19
|
+
<% if @actor_filter.present? %>
|
|
20
|
+
<span class="sqw-badge">
|
|
21
|
+
Actor: <%= @actor_filter %>
|
|
22
|
+
<%= link_to "×", audit_path(audit_action: @action_filter, queue: @queue_filter), class: "sqw-muted", aria: { label: "Clear actor filter" } %>
|
|
23
|
+
</span>
|
|
24
|
+
<% end %>
|
|
25
|
+
|
|
26
|
+
<% if @queue_filter.present? %>
|
|
27
|
+
<span class="sqw-badge">
|
|
28
|
+
Queue: <%= @queue_filter %>
|
|
29
|
+
<%= link_to "×", audit_path(audit_action: @action_filter, actor: @actor_filter), class: "sqw-muted", aria: { label: "Clear queue filter" } %>
|
|
30
|
+
</span>
|
|
31
|
+
<% end %>
|
|
32
|
+
|
|
33
|
+
<% if @action_filter.present? || @actor_filter.present? || @queue_filter.present? %>
|
|
34
|
+
<%= link_to "Clear all", audit_path, class: "sqw-btn sqw-btn--muted sqw-btn--sm" %>
|
|
35
|
+
<% end %>
|
|
36
|
+
</form>
|
|
37
|
+
|
|
38
|
+
<% if @events.any? %>
|
|
39
|
+
<table class="sqw-table">
|
|
40
|
+
<thead>
|
|
41
|
+
<tr>
|
|
42
|
+
<th scope="col">Time</th>
|
|
43
|
+
<th scope="col">Action</th>
|
|
44
|
+
<th scope="col">Actor</th>
|
|
45
|
+
<th scope="col">Job Class</th>
|
|
46
|
+
<th scope="col">Queue</th>
|
|
47
|
+
<th scope="col">Count</th>
|
|
48
|
+
</tr>
|
|
49
|
+
</thead>
|
|
50
|
+
<tbody>
|
|
51
|
+
<% @events.each do |event| %>
|
|
52
|
+
<tr>
|
|
53
|
+
<td class="sqw-muted"><%= local_time(event.created_at, format: :long) %></td>
|
|
54
|
+
<td>
|
|
55
|
+
<span class="sqw-badge <%= audit_action_badge_class(event.action) %>">
|
|
56
|
+
<%= event.action.tr("_", " ") %>
|
|
57
|
+
</span>
|
|
58
|
+
</td>
|
|
59
|
+
<td>
|
|
60
|
+
<% if event.actor.present? %>
|
|
61
|
+
<%= link_to event.actor, audit_path(audit_action: @action_filter, actor: event.actor, queue: @queue_filter) %>
|
|
62
|
+
<% else %>
|
|
63
|
+
<span class="sqw-muted">—</span>
|
|
64
|
+
<% end %>
|
|
65
|
+
</td>
|
|
66
|
+
<td class="sqw-monospace"><%= event.job_class.presence || content_tag(:span, "—", class: "sqw-muted") %></td>
|
|
67
|
+
<td>
|
|
68
|
+
<% if event.queue_name.present? %>
|
|
69
|
+
<span class="sqw-badge sqw-badge--queue">
|
|
70
|
+
<%= link_to event.queue_name, audit_path(audit_action: @action_filter, actor: @actor_filter, queue: event.queue_name) %>
|
|
71
|
+
</span>
|
|
72
|
+
<% else %>
|
|
73
|
+
<span class="sqw-muted">—</span>
|
|
74
|
+
<% end %>
|
|
75
|
+
</td>
|
|
76
|
+
<td><%= event.item_count %></td>
|
|
77
|
+
</tr>
|
|
78
|
+
<% end %>
|
|
79
|
+
</tbody>
|
|
80
|
+
</table>
|
|
81
|
+
<%== @pagy.series_nav(aria_label: "Pagination") if @pagy.pages > 1 %>
|
|
82
|
+
<% else %>
|
|
83
|
+
<div class="sqw-empty" id="sqd-empty">
|
|
84
|
+
<p class="sqw-muted">No audit events recorded yet.</p>
|
|
85
|
+
</div>
|
|
86
|
+
<% end %>
|
data/config/importmap.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
pin "@hotwired/turbo", to: "https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.23/dist/turbo.es2017-esm.js"
|
|
2
2
|
pin "@hotwired/stimulus", to: "https://cdn.jsdelivr.net/npm/@hotwired/stimulus@3.2.2/dist/stimulus.js"
|
|
3
3
|
pin "solid_stack_web", to: "solid_stack_web/application.js"
|
|
4
|
+
pin "solid_stack_web/filter_persist_controller", to: "solid_stack_web/filter_persist_controller.js"
|
|
4
5
|
pin "solid_stack_web/refresh_controller", to: "solid_stack_web/refresh_controller.js"
|
|
5
6
|
pin "solid_stack_web/search_controller", to: "solid_stack_web/search_controller.js"
|
|
6
7
|
pin "solid_stack_web/selection_controller", to: "solid_stack_web/selection_controller.js"
|
data/config/routes.rb
CHANGED
|
@@ -36,6 +36,7 @@ SolidStackWeb::Engine.routes.draw do
|
|
|
36
36
|
get "metrics", to: "metrics#index", as: :metrics
|
|
37
37
|
get "stats", to: "stats#index", as: :stats
|
|
38
38
|
get "history", to: "history#index", as: :history
|
|
39
|
+
get "audit", to: "audit#index", as: :audit
|
|
39
40
|
get "cache", to: "cache#index", as: :cache
|
|
40
41
|
resources :cache_entries, only: [:index, :show, :destroy], path: "cache/entries"
|
|
41
42
|
resource :cache_flush, only: [:destroy], path: "cache/flush", controller: "cache/flushes"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require "rails/generators/base"
|
|
2
|
+
require "rails/generators/migration"
|
|
3
|
+
|
|
4
|
+
module SolidStackWeb
|
|
5
|
+
module Generators
|
|
6
|
+
class MigrationsGenerator < Rails::Generators::Base
|
|
7
|
+
include Rails::Generators::Migration
|
|
8
|
+
|
|
9
|
+
source_root File.expand_path("templates", __dir__)
|
|
10
|
+
|
|
11
|
+
desc "Generates the solid_stack_web_audit_events migration"
|
|
12
|
+
|
|
13
|
+
def self.next_migration_number(dirname)
|
|
14
|
+
next_migration_number = current_migration_number(dirname) + 1
|
|
15
|
+
ActiveRecord::Migration.next_migration_number(next_migration_number)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_migration_file
|
|
19
|
+
migration_template "create_solid_stack_web_audit_events.rb.tt",
|
|
20
|
+
"db/migrate/create_solid_stack_web_audit_events.rb"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/generators/solid_stack_web/install/templates/create_solid_stack_web_audit_events.rb.tt
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class CreateSolidStackWebAuditEvents < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
|
2
|
+
def change
|
|
3
|
+
create_table :solid_stack_web_audit_events do |t|
|
|
4
|
+
t.string :action, null: false
|
|
5
|
+
t.string :actor
|
|
6
|
+
t.string :job_class
|
|
7
|
+
t.string :queue_name
|
|
8
|
+
t.integer :item_count, null: false, default: 1
|
|
9
|
+
t.datetime :created_at, null: false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
add_index :solid_stack_web_audit_events, :created_at
|
|
13
|
+
add_index :solid_stack_web_audit_events, :action
|
|
14
|
+
add_index :solid_stack_web_audit_events, :actor
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -47,6 +47,13 @@ SolidStackWeb.configure do |config|
|
|
|
47
47
|
# "critical" => 50,
|
|
48
48
|
# "default" => 500
|
|
49
49
|
# }
|
|
50
|
+
# Audit log actor — block runs in controller context, return a string identifying the current user.
|
|
51
|
+
# Requires running `rails solid_stack_web:install:migrations && rails db:migrate` first.
|
|
52
|
+
#
|
|
53
|
+
# config.current_actor do
|
|
54
|
+
# current_user&.email
|
|
55
|
+
# end
|
|
56
|
+
|
|
50
57
|
# config.alert_slow_job_count_threshold = 3 # fire when N+ claimed jobs exceed slow_job_threshold duration
|
|
51
58
|
# config.alert_stale_process_threshold = 1 # fire when N+ workers have a stale heartbeat (>5 min old)
|
|
52
59
|
# config.alert_webhook_cooldown = 3600 # seconds between repeat alerts
|
data/lib/solid_stack_web.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: solid_stack_web
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chuck Smith
|
|
@@ -151,6 +151,7 @@ files:
|
|
|
151
151
|
- app/assets/stylesheets/solid_stack_web/_12_dark_mode.css
|
|
152
152
|
- app/assets/stylesheets/solid_stack_web/application.css
|
|
153
153
|
- app/controllers/solid_stack_web/application_controller.rb
|
|
154
|
+
- app/controllers/solid_stack_web/audit_controller.rb
|
|
154
155
|
- app/controllers/solid_stack_web/cable/channel_purges_controller.rb
|
|
155
156
|
- app/controllers/solid_stack_web/cable/purges_controller.rb
|
|
156
157
|
- app/controllers/solid_stack_web/cable_controller.rb
|
|
@@ -184,6 +185,7 @@ files:
|
|
|
184
185
|
- app/javascript/solid_stack_web/theme_controller.js
|
|
185
186
|
- app/javascript/solid_stack_web/timestamp_controller.js
|
|
186
187
|
- app/models/solid_stack_web/alert_webhook.rb
|
|
188
|
+
- app/models/solid_stack_web/audit_event.rb
|
|
187
189
|
- app/models/solid_stack_web/cable_stats.rb
|
|
188
190
|
- app/models/solid_stack_web/cable_timeline.rb
|
|
189
191
|
- app/models/solid_stack_web/cache_size_stats.rb
|
|
@@ -196,6 +198,7 @@ files:
|
|
|
196
198
|
- app/models/solid_stack_web/queue_stats.rb
|
|
197
199
|
- app/models/solid_stack_web/throughput_sparkline.rb
|
|
198
200
|
- app/views/layouts/solid_stack_web/application.html.erb
|
|
201
|
+
- app/views/solid_stack_web/audit/index.html.erb
|
|
199
202
|
- app/views/solid_stack_web/cable/index.html.erb
|
|
200
203
|
- app/views/solid_stack_web/cable_messages/index.html.erb
|
|
201
204
|
- app/views/solid_stack_web/cache/index.html.erb
|
|
@@ -224,6 +227,8 @@ files:
|
|
|
224
227
|
- config/routes.rb
|
|
225
228
|
- docs/screenshots/demo.gif
|
|
226
229
|
- lib/generators/solid_stack_web/install/install_generator.rb
|
|
230
|
+
- lib/generators/solid_stack_web/install/migrations_generator.rb
|
|
231
|
+
- lib/generators/solid_stack_web/install/templates/create_solid_stack_web_audit_events.rb.tt
|
|
227
232
|
- lib/generators/solid_stack_web/install/templates/initializer.rb
|
|
228
233
|
- lib/solid_stack_web.rb
|
|
229
234
|
- lib/solid_stack_web/engine.rb
|