panoptic 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7765d548dafa03735d2dc25e0319bb04857aeaff9b4b8394eec1f1f524674eee
4
- data.tar.gz: a2aa9f24af59985caff5c0d4650f474f727819d247964d54175da407fd5fd3dd
3
+ metadata.gz: eaeaa4c54e9017c35ee6093fc0b3d0f57f8281e72dfdb11a4e48a297583bc803
4
+ data.tar.gz: 67409a3a5b05f276654733113cab9ad6c61c39b707dcba9b47caef8e0c6228c8
5
5
  SHA512:
6
- metadata.gz: 0e65e09ed7d09a7e3543e03b04f7c6fb12536b37fab220ce4c5e9170cdcd94093f6dd8105c0f998ee9333817b6ea11372627708c412c9f088e22e1278a14a546
7
- data.tar.gz: a5ad871749df301daf5e13561cfafe05ae5d1bc8f1a67030560f027c92c4ba4d962beb386ce44a2716411673100ff8c2c6f821b4d9be5d66c20ba932a72aa183
6
+ metadata.gz: 5b1eb3f3bc00012b3bf1542037a2e79386bf1e9adf2ca1190bbab33572954ed2a9fd8ca40c96ccc6496133b7f5e723a250456fbeee139c92deceeca41269afb2
7
+ data.tar.gz: 2d3bf8fd70b9432a20ef2826d51a0895c5af449584be8a3807a30906cd0d4ed4821e2c61469f0214997eec95e6a375ab1d8dea4b8ec64ffbfec95cfcce3d94b1
@@ -2,13 +2,16 @@
2
2
 
3
3
  module Panoptic
4
4
  class Jobs::FailedController < ApplicationController
5
+ layout "panoptic/jobs", only: :index
6
+
5
7
  def index
6
- # TODO: use the `failed` scope available in SolidQueue next release
7
8
  @pagy, @jobs = pagy(
8
- SolidQueue::Job.joins(:failed_execution).order(created_at: :asc)
9
+ Panoptic::FailedJob.order(created_at: :asc)
9
10
  )
11
+ end
10
12
 
11
- render "panoptic/jobs/index"
13
+ def show
14
+ @job = Panoptic::FailedJob.find(params[:id])
12
15
  end
13
16
  end
14
17
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Panoptic
4
+ class Jobs::RetriesController < ApplicationController
5
+ def create
6
+ @job = SolidQueue::Job.find(params[:job_id])
7
+
8
+ @job.retry
9
+ redirect_to jobs_path, notice: "Successfully retried Job ##{@job.id}"
10
+ end
11
+ end
12
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Panoptic
4
4
  class Jobs::ScheduledController < ApplicationController
5
+ layout "panoptic/jobs"
6
+
5
7
  def index
6
8
  # TODO: use the `scheduled` scope available in SolidQueue next release
7
9
  @pagy, @jobs = pagy(
@@ -1,6 +1,7 @@
1
1
  module Panoptic
2
2
  module ApplicationHelper
3
3
  include Pagy::Frontend
4
+ include BreadcrumbsHelper
4
5
  include DateTimeHelper
5
6
  end
6
7
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Panoptic
4
+ module BreadcrumbsHelper
5
+ def breadcrumb_items
6
+ @breadcrumb_items ||= []
7
+ end
8
+
9
+ def breadcrumbs
10
+ tag.nav(aria: { label: "breadcrumb" }) do
11
+ tag.ol(class: "breadcrumb") do
12
+ breadcrumb_items.map do |item|
13
+ concat tag.li(item, class: "breadcrumb-item")
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Panoptic
4
+ class FailedJob < SolidQueue::Job
5
+ # TODO: use the `failed` scope available in SolidQueue next release
6
+ default_scope { joins(:failed_execution) }
7
+
8
+ def enqueued_at
9
+ Time.parse(arguments["enqueued_at"])
10
+ end
11
+
12
+ def exception_class
13
+ failed_execution.error["exception_class"]
14
+ end
15
+
16
+ def exception_message
17
+ failed_execution.error["message"]
18
+ end
19
+
20
+ def stacktrace
21
+ failed_execution.error["backtrace"]
22
+ end
23
+ end
24
+ end
@@ -1,19 +1,21 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
- <head>
4
- <title>Panoptic</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
3
+ <head>
4
+ <title>Panoptic</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
7
 
8
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
9
- </head>
10
- <body>
11
- <%= render "shared/navbar" %>
8
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
9
+ </head>
10
+ <body class="pb-4">
12
11
 
13
- <main class="container mt-2">
14
- <%= yield %>
15
- </main>
12
+ <%= render "shared/navbar" %>
16
13
 
17
- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
18
- </body>
14
+ <main class="container mt-2">
15
+ <%= render "shared/flashes" %>
16
+ <%= content_for?(:content) ? yield(:content) : yield %>
17
+ </main>
18
+
19
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
20
+ </body>
19
21
  </html>
@@ -0,0 +1,27 @@
1
+ <% content_for(:content) do %>
2
+ <h1>Jobs</h1>
3
+
4
+ <ul class="nav nav-underline">
5
+ <li class="nav-item">
6
+ <%= link_to "All", jobs_path, class: class_names("nav-link", "active": current_page?(jobs_path)) %>
7
+ </li>
8
+ <li class="nav-item">
9
+ <%= link_to "Scheduled", scheduled_jobs_path, class: class_names("nav-link", "active": current_page?(scheduled_jobs_path)) %>
10
+ </li>
11
+ <li class="nav-item">
12
+ <%= link_to "Failed", failed_jobs_path, class: class_names("nav-link", "active": current_page?(failed_jobs_path)) %>
13
+ </li>
14
+ </ul>
15
+
16
+ <div class="d-flex justify-content-end">
17
+ <%== pagy_info(@pagy) %>
18
+ </div>
19
+
20
+ <%= yield %>
21
+
22
+ <div class="d-flex justify-content-center">
23
+ <%== pagy_bootstrap_nav(@pagy) if @pagy.pages > 1 %>
24
+ </div>
25
+ <% end %>
26
+
27
+ <%= render template: "layouts/panoptic/application" %>
@@ -0,0 +1,13 @@
1
+ <tr>
2
+ <th scope="row"><%= job.id %></th>
3
+ <td scope="col"><%= job.class_name %></td>
4
+ <td scope="col"><%= job.queue_name %></td>
5
+ <td scope="col" class="font-monospace"><%= job.exception_class %></td>
6
+ <td scope="col"><%= safe_time_tag job.enqueued_at %></td>
7
+ <td scope="col">
8
+ <%= link_to "Details", failed_job_path(job), class: "btn btn-link" %>
9
+ <%= button_to "Retry Job", job_retry_path(job),
10
+ class: "btn btn-link",
11
+ form_class: "d-inline" %>
12
+ </td>
13
+ </tr>
@@ -0,0 +1,16 @@
1
+ <table class="table">
2
+ <thead>
3
+ <tr>
4
+ <th scope="col">#</th>
5
+ <th scope="col">Class</th>
6
+ <th scope="col">Queue</th>
7
+ <th scope="col">Exception</th>
8
+ <th scope="col">Enqueued</th>
9
+ <th scope="col"></th>
10
+ </tr>
11
+ </thead>
12
+
13
+ <tbody>
14
+ <%= render partial: "job", collection: @jobs %>
15
+ </tbody>
16
+ </table>
@@ -0,0 +1,26 @@
1
+ <% breadcrumb_items.push link_to("Jobs", jobs_path) %>
2
+ <% breadcrumb_items.push link_to("Failed", failed_jobs_path) %>
3
+ <% breadcrumb_items.push @job.id %>
4
+ <%= breadcrumbs %>
5
+
6
+ <h1><%= @job.class_name %></h1>
7
+
8
+ <%= button_to "Retry Job", job_retry_path(@job), class: "btn btn-primary mb-3" %>
9
+
10
+ <div class="alert alert-danger" role="alert">
11
+ <h4 class="alert-heading"><%= @job.exception_class %></h4>
12
+ <p class="font-monospace mb-0">
13
+ <%= @job.exception_message %>
14
+ </p>
15
+ </div>
16
+
17
+ <div class="card" >
18
+ <div class="card-header">
19
+ Stacktrace
20
+ </div>
21
+ <ul class="list-group list-group-flush font-monospace text-xs">
22
+ <% @job.stacktrace.each do |trace| %>
23
+ <li class="list-group-item"><%= trace %></li>
24
+ <% end %>
25
+ </ul>
26
+ </div>
@@ -1,21 +1,3 @@
1
- <h1>Jobs</h1>
2
-
3
- <ul class="nav nav-underline">
4
- <li class="nav-item">
5
- <%= link_to "All", jobs_path, class: class_names("nav-link", "active": current_page?(jobs_path)) %>
6
- </li>
7
- <li class="nav-item">
8
- <%= link_to "Scheduled", scheduled_jobs_path, class: class_names("nav-link", "active": current_page?(scheduled_jobs_path)) %>
9
- </li>
10
- <li class="nav-item">
11
- <%= link_to "Failed", failed_jobs_path, class: class_names("nav-link", "active": current_page?(failed_jobs_path)) %>
12
- </li>
13
- </ul>
14
-
15
- <div class="d-flex justify-content-end">
16
- <%== pagy_info(@pagy) %>
17
- </div>
18
-
19
1
  <table class="table">
20
2
  <thead>
21
3
  <tr>
@@ -31,7 +13,3 @@
31
13
  <%= render partial: "panoptic/jobs/job", collection: @jobs %>
32
14
  </tbody>
33
15
  </table>
34
-
35
- <div class="d-flex justify-content-center">
36
- <%== pagy_bootstrap_nav(@pagy) if @pagy.pages > 1 %>
37
- </div>
@@ -0,0 +1,7 @@
1
+ <% if flash[:notice] %>
2
+ <div class="alert alert-success" role="alert"><%= flash[:notice] %></div>
3
+ <% end %>
4
+
5
+ <% if flash[:alert] %>
6
+ <div class="alert alert-danger" role="alert"><%= flash[:alert] %></div>
7
+ <% end %>
data/config/routes.rb CHANGED
@@ -3,12 +3,12 @@ Panoptic::Engine.routes.draw do
3
3
 
4
4
  resources :queues, only: [:index]
5
5
 
6
- scope "jobs" do
7
- get "all", to: "jobs#index", as: "jobs"
6
+ resources :jobs, only: :index do
7
+ resource :retry, only: :create, module: :jobs
8
+ end
8
9
 
9
- scope module: "jobs" do
10
- resources :scheduled, only: :index, as: :scheduled_jobs
11
- resources :failed, only: :index, as: :failed_jobs
12
- end
10
+ scope module: :jobs do
11
+ resources :scheduled, only: :index, as: :scheduled_jobs
12
+ resources :failed, only: [:index, :show], as: :failed_jobs
13
13
  end
14
14
  end
@@ -1,3 +1,3 @@
1
1
  module Panoptic
2
- VERSION = "0.2.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: panoptic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vincent Rolea
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-30 00:00:00.000000000 Z
11
+ date: 2024-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,35 +52,43 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '6.2'
55
- description: Web interface for the SoldiQueue queuing backend
55
+ description: Panoptic adds a real time web interface on top of SolidQueue to monitor
56
+ processes, queues and jobs
56
57
  email:
57
58
  - 3525369+virolea@users.noreply.github.com
58
59
  executables: []
59
60
  extensions: []
60
61
  extra_rdoc_files: []
61
62
  files:
62
- - MIT-LICENSE
63
63
  - README.md
64
64
  - Rakefile
65
65
  - app/controllers/panoptic/application_controller.rb
66
66
  - app/controllers/panoptic/jobs/failed_controller.rb
67
+ - app/controllers/panoptic/jobs/retries_controller.rb
67
68
  - app/controllers/panoptic/jobs/scheduled_controller.rb
68
69
  - app/controllers/panoptic/jobs_controller.rb
69
70
  - app/controllers/panoptic/processes_controller.rb
70
71
  - app/controllers/panoptic/queues_controller.rb
71
72
  - app/helpers/panoptic/application_helper.rb
73
+ - app/helpers/panoptic/breadcrumbs_helper.rb
72
74
  - app/helpers/panoptic/date_time_helper.rb
73
75
  - app/jobs/panoptic/application_job.rb
74
76
  - app/mailers/panoptic/application_mailer.rb
75
77
  - app/models/panoptic/application_record.rb
78
+ - app/models/panoptic/failed_job.rb
76
79
  - app/models/panoptic/process.rb
77
80
  - app/views/layouts/panoptic/application.html.erb
81
+ - app/views/layouts/panoptic/jobs.html.erb
78
82
  - app/views/panoptic/jobs/_job.html.erb
83
+ - app/views/panoptic/jobs/failed/_job.html.erb
84
+ - app/views/panoptic/jobs/failed/index.html.erb
85
+ - app/views/panoptic/jobs/failed/show.html.erb
79
86
  - app/views/panoptic/jobs/index.html.erb
80
87
  - app/views/panoptic/processes/_process.html.erb
81
88
  - app/views/panoptic/processes/index.html.erb
82
89
  - app/views/panoptic/queues/_queue.html.erb
83
90
  - app/views/panoptic/queues/index.html.erb
91
+ - app/views/shared/_flashes.html.erb
84
92
  - app/views/shared/_navbar.html.erb
85
93
  - config/initializers/pagy.rb
86
94
  - config/routes.rb
@@ -113,5 +121,5 @@ requirements: []
113
121
  rubygems_version: 3.3.26
114
122
  signing_key:
115
123
  specification_version: 4
116
- summary: Web interface for the SoldiQueue queuing backend
124
+ summary: Web interface for the SolidQueue queuing backend
117
125
  test_files: []
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright Vincent Rolea
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.