catpm 0.6.0 → 0.6.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72b1f8ad18b14d62b8ace369a8d064396ff4fc2988f1dc4eb911c71278c05766
4
- data.tar.gz: f6153a851adc6ff5dd810cf648b069b512117bd25ae87f6e7715382ea6c43960
3
+ metadata.gz: 77d3e9a9e80a64c61ba1cbc9f400f9b53cb774c2eee0cf1fc807952bf1b81c39
4
+ data.tar.gz: 3364e29476e9a6f77494f86c0fb00932c70a84eb90067df86e8455a00608930b
5
5
  SHA512:
6
- metadata.gz: 485696711db8a1ed56901065ee90b151292a466c4a21bf6585e63e36a0ee6f873a14584b229f1963bd9fa14ac5143d4fbc3641763177dec0ec2fc5c5421ba11d
7
- data.tar.gz: c6e0dd6391af5921e4fa79ad77a69fe7d637adf77f714cf19eb66182dbac128c7c45d75ee1ac7365620824afc34d6672d788169c230c72d8ac0af27460167eff
6
+ metadata.gz: 52c5cb2542feabdb2a493390e1fd0c42bef5e5ea8c8d89bb71115f774b790e88b8c8f253402e47835da8190a4113d3ed7302398f59a2ce2841df2576018a20cb
7
+ data.tar.gz: be688f7c4ce207e04d09fb1ac30b390bc7f2ea8b050120bc46929a952a632d17e63ffc110950907ee37e60aa62f8f7400a3d982acfc568dd2392d01fe9841c91
Binary file
@@ -28,7 +28,7 @@ module Catpm
28
28
 
29
29
  @total_count = scope.count
30
30
  @page = [params[:page].to_i, 1].max
31
- @errors = scope.order(@sort => @dir).offset((@page - 1) * PER_PAGE).limit(PER_PAGE)
31
+ @errors = scope.order(pinned: :desc, @sort => @dir).offset((@page - 1) * PER_PAGE).limit(PER_PAGE)
32
32
  end
33
33
 
34
34
  def show
@@ -106,19 +106,41 @@ module Catpm
106
106
  def resolve
107
107
  error = Catpm::ErrorRecord.find(params[:id])
108
108
  error.resolve!
109
- redirect_to catpm.error_path(error), notice: 'Marked as resolved'
109
+ if request.xhr?
110
+ render json: { resolved: true }
111
+ else
112
+ redirect_to catpm.error_path(error), notice: 'Marked as resolved'
113
+ end
110
114
  end
111
115
 
112
116
  def unresolve
113
117
  error = Catpm::ErrorRecord.find(params[:id])
114
118
  error.unresolve!
115
- redirect_to catpm.error_path(error), notice: 'Reopened'
119
+ if request.xhr?
120
+ render json: { resolved: false }
121
+ else
122
+ redirect_to catpm.error_path(error), notice: 'Reopened'
123
+ end
124
+ end
125
+
126
+ def toggle_pin
127
+ error = Catpm::ErrorRecord.find(params[:id])
128
+ error.update!(pinned: !error.pinned)
129
+ if request.xhr?
130
+ render json: { pinned: error.pinned }
131
+ else
132
+ redirect_back fallback_location: catpm.error_path(error)
133
+ end
116
134
  end
117
135
 
118
136
  def destroy
119
137
  error = Catpm::ErrorRecord.find(params[:id])
120
138
  error.destroy!
121
- redirect_to catpm.errors_path, notice: 'Error deleted'
139
+ if request.xhr?
140
+ render json: { deleted: true }
141
+ else
142
+ redirect_to catpm.errors_path, notice: 'Error deleted'
143
+ end
122
144
  end
123
145
 
124
146
  def resolve_all
@@ -64,9 +64,10 @@ module Catpm
64
64
  # Sort (pinned always on top)
65
65
  @sort = %w[name total_count last_seen].include?(params[:sort]) ? params[:sort] : 'total_count'
66
66
  @dir = params[:dir] == 'asc' ? 'asc' : 'desc'
67
- events_list = events_list.sort_by { |e| e[@sort.to_sym] || '' }
68
- events_list = events_list.reverse if @dir == 'desc'
69
- events_list = events_list.sort_by { |e| e[:pinned] ? 0 : 1 }
67
+ sorted = events_list.sort_by { |e| e[@sort.to_sym] || '' }
68
+ sorted = sorted.reverse if @dir == 'desc'
69
+ pinned, unpinned = sorted.partition { |e| e[:pinned] }
70
+ events_list = pinned + unpinned
70
71
 
71
72
  @total_event_names = events_list.size
72
73
 
@@ -153,6 +154,16 @@ module Catpm
153
154
  end
154
155
  end
155
156
 
157
+ def destroy_sample
158
+ sample = Catpm::EventSample.find(params[:sample_id])
159
+ sample.destroy
160
+ if request.xhr?
161
+ render json: { deleted: true }
162
+ else
163
+ redirect_back fallback_location: catpm.events_path, notice: 'Sample deleted'
164
+ end
165
+ end
166
+
156
167
  def ignored
157
168
  @range, period, _bucket_seconds = helpers.parse_range(remembered_range)
158
169
  ignored_prefs = Catpm::EventPref.ignored
@@ -17,7 +17,9 @@ module Catpm
17
17
  sample = Catpm::Sample.find(params[:id])
18
18
  bucket = sample.bucket
19
19
  sample.destroy
20
- if bucket
20
+ if request.xhr?
21
+ render json: { deleted: true }
22
+ elsif bucket
21
23
  redirect_to catpm.endpoint_path(kind: bucket.kind, target: bucket.target, operation: bucket.operation), notice: 'Sample deleted'
22
24
  else
23
25
  redirect_to catpm.status_index_path, notice: 'Sample deleted'
@@ -85,9 +85,10 @@ module Catpm
85
85
  # Server-side sort (pinned always on top)
86
86
  @sort = %w[target total_count avg_duration max_duration total_failures last_seen].include?(params[:sort]) ? params[:sort] : 'last_seen'
87
87
  @dir = params[:dir] == 'asc' ? 'asc' : 'desc'
88
- endpoints = endpoints.sort_by { |e| e[@sort.to_sym] || '' }
89
- endpoints = endpoints.reverse if @dir == 'desc'
90
- endpoints = endpoints.sort_by { |e| e[:pinned] ? 0 : 1 }
88
+ sorted = endpoints.sort_by { |e| e[@sort.to_sym] || '' }
89
+ sorted = sorted.reverse if @dir == 'desc'
90
+ pinned, unpinned = sorted.partition { |e| e[:pinned] }
91
+ endpoints = pinned + unpinned
91
92
 
92
93
  @total_endpoint_count = endpoints.size
93
94
 
@@ -10,6 +10,7 @@ module Catpm
10
10
  scope :by_kind, ->(kind) { where(kind: kind) }
11
11
  scope :unresolved, -> { where(resolved_at: nil) }
12
12
  scope :resolved, -> { where.not(resolved_at: nil) }
13
+ scope :pinned, -> { where(pinned: true) }
13
14
  scope :recent, ->(period = 24.hours) { where(last_occurred_at: period.ago..) }
14
15
 
15
16
  def resolved?
@@ -7,6 +7,7 @@
7
7
  <th>Duration</th>
8
8
  <th>Segments</th>
9
9
  <th>Time</th>
10
+ <th></th>
10
11
  </tr>
11
12
  </thead>
12
13
  <tbody>
@@ -24,6 +25,12 @@
24
25
  <% end %>
25
26
  </td>
26
27
  <td><%= time_with_tooltip(s.recorded_at) %></td>
28
+ <td style="position:relative; z-index:2; width:28px; padding:4px 2px; text-align:center">
29
+ <button class="action-menu-btn">&#x22EE;</button>
30
+ <div class="action-menu">
31
+ <button class="menu-danger" data-action="delete" data-url="<%= catpm.sample_path(s) %>">Delete</button>
32
+ </div>
33
+ </td>
27
34
  </tr>
28
35
  <% end %>
29
36
  </tbody>
@@ -27,6 +27,7 @@
27
27
  <table id="errors-table">
28
28
  <thead>
29
29
  <tr>
30
+ <th></th>
30
31
  <th>Kind</th>
31
32
  <th><%= sort_header("Error Class", "error_class", @sort, @dir, extra_params: extra) %></th>
32
33
  <th>Message</th>
@@ -34,11 +35,13 @@
34
35
  <th>Trend</th>
35
36
  <th><%= sort_header("Last Seen", "last_occurred_at", @sort, @dir, extra_params: extra) %></th>
36
37
  <% if @tab == "resolved" %><th>Resolved</th><% end %>
38
+ <th></th>
37
39
  </tr>
38
40
  </thead>
39
41
  <tbody>
40
42
  <% @errors.each do |e| %>
41
43
  <tr class="linked">
44
+ <td style="position:relative; z-index:1; width:28px; padding:4px 2px; text-align:center"><button class="star-btn<%= ' pinned' if e.pinned %>" data-pin-url="<%= catpm.toggle_pin_error_path(e) %>"><%= e.pinned ? "&#x2605;".html_safe : "&#x2606;".html_safe %></button></td>
42
45
  <td><a href="<%= catpm.error_path(e) %>" class="row-link"><%= type_badge(e.kind) %></a></td>
43
46
  <td class="mono"><%= e.error_class %></td>
44
47
  <td style="color:var(--text-1)"><%= truncate(e.message, length: 60) %></td>
@@ -46,6 +49,17 @@
46
49
  <td><%= trend_indicator(e) %></td>
47
50
  <td><%= time_with_tooltip(e.last_occurred_at) %></td>
48
51
  <% if @tab == "resolved" %><td><%= time_with_tooltip(e.resolved_at) %></td><% end %>
52
+ <td style="position:relative; z-index:2; width:28px; padding:4px 2px; text-align:center">
53
+ <button class="action-menu-btn">&#x22EE;</button>
54
+ <div class="action-menu">
55
+ <% if e.resolved? %>
56
+ <button data-action="unresolve" data-url="<%= catpm.unresolve_error_path(e) %>">Reopen</button>
57
+ <% else %>
58
+ <button data-action="resolve" data-url="<%= catpm.resolve_error_path(e) %>">Resolve</button>
59
+ <% end %>
60
+ <button class="menu-danger" data-action="delete" data-url="<%= catpm.error_path(e) %>">Delete</button>
61
+ </div>
62
+ </td>
49
63
  </tr>
50
64
  <% end %>
51
65
  </tbody>
@@ -106,17 +106,24 @@
106
106
  <th>Status</th>
107
107
  <th>Target</th>
108
108
  <th>Segments</th>
109
+ <th></th>
109
110
  </tr>
110
111
  </thead>
111
112
  <tbody>
112
113
  <% @samples.each do |sample| %>
113
114
  <% ctx = sample.parsed_context %>
114
- <tr class="clickable-row" onclick="window.location='<%= catpm.sample_path(sample) %>';" style="cursor:pointer">
115
- <td><%= time_with_tooltip(sample.recorded_at) %></td>
115
+ <tr class="linked">
116
+ <td><a href="<%= catpm.sample_path(sample) %>" class="row-link"><%= time_with_tooltip(sample.recorded_at) %></a></td>
116
117
  <td class="mono"><%= format_duration(sample.duration) %></td>
117
118
  <td><%= status_badge(ctx["status"] || ctx[:status]) %></td>
118
119
  <td class="mono"><%= sample.bucket&.target || "—" %></td>
119
120
  <td class="mono text-muted"><%= segment_count_summary(ctx["segment_summary"] || ctx[:segment_summary]).presence || "—" %></td>
121
+ <td style="position:relative; z-index:2; width:28px; padding:4px 2px; text-align:center">
122
+ <button class="action-menu-btn">&#x22EE;</button>
123
+ <div class="action-menu">
124
+ <button class="menu-danger" data-action="delete" data-url="<%= catpm.sample_path(sample) %>">Delete</button>
125
+ </div>
126
+ </td>
120
127
  </tr>
121
128
  <% end %>
122
129
  </tbody>
@@ -63,11 +63,13 @@
63
63
  <colgroup>
64
64
  <col style="width:120px">
65
65
  <col>
66
+ <col style="width:36px">
66
67
  </colgroup>
67
68
  <thead>
68
69
  <tr>
69
70
  <th>Recorded At</th>
70
71
  <th>Payload</th>
72
+ <th></th>
71
73
  </tr>
72
74
  </thead>
73
75
  <tbody>
@@ -87,6 +89,12 @@
87
89
  <span class="text-muted">—</span>
88
90
  <% end %>
89
91
  </td>
92
+ <td style="position:relative; z-index:2; width:28px; padding:4px 2px; text-align:center; vertical-align:top">
93
+ <button class="action-menu-btn">&#x22EE;</button>
94
+ <div class="action-menu">
95
+ <button class="menu-danger" data-action="delete" data-url="<%= catpm.destroy_sample_events_path(sample_id: sample.id) %>">Delete</button>
96
+ </div>
97
+ </td>
90
98
  </tr>
91
99
  <% end %>
92
100
  </tbody>
@@ -3,6 +3,10 @@
3
3
  <head>
4
4
  <title>catpm<%= " — #{yield :title}" if content_for?(:title) %></title>
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <link rel="icon" type="image/png" sizes="32x32" href="<%= image_path('catpm/favicon-32.png') %>">
7
+ <link rel="icon" type="image/png" sizes="512x512" href="<%= image_path('catpm/favicon-512.png') %>">
8
+ <link rel="icon" type="image/x-icon" href="<%= image_path('catpm/favicon.ico') %>">
9
+ <link rel="apple-touch-icon" href="<%= image_path('catpm/favicon-512.png') %>">
6
10
  <%= csrf_meta_tags %>
7
11
  <%= yield :head_extra if content_for?(:head_extra) %>
8
12
  <style>
@@ -541,10 +545,14 @@
541
545
  if (action === 'ignore') {
542
546
  apiRequest(url, 'PATCH').then(function(data) { if (data.ignored && row) fadeOutRow(row); });
543
547
  } else if (action === 'delete') {
544
- if (!confirm('Delete this endpoint and all its data?')) return;
548
+ if (!confirm('Delete this and all its data?')) return;
545
549
  apiRequest(url, 'DELETE').then(function(data) { if (data.deleted && row) fadeOutRow(row); });
546
550
  } else if (action === 'unignore') {
547
551
  apiRequest(url, 'PATCH').then(function(data) { if (!data.ignored && row) fadeOutRow(row); });
552
+ } else if (action === 'resolve') {
553
+ apiRequest(url, 'PATCH').then(function(data) { if (data.resolved && row) fadeOutRow(row); });
554
+ } else if (action === 'unresolve') {
555
+ apiRequest(url, 'PATCH').then(function(data) { if (!data.resolved && row) fadeOutRow(row); });
548
556
  }
549
557
  return;
550
558
  }
data/config/routes.rb CHANGED
@@ -10,7 +10,11 @@ Catpm::Engine.routes.draw do
10
10
  patch 'endpoint/ignore', to: 'endpoints#toggle_ignore', as: :endpoint_ignore
11
11
  get 'endpoints/ignored', to: 'endpoints#ignored', as: :ignored_endpoints
12
12
  resources :samples, only: [:show, :destroy]
13
- resources :events, only: [:index, :show, :destroy], param: :name
13
+ resources :events, only: [:index, :show, :destroy], param: :name do
14
+ collection do
15
+ delete 'samples/:sample_id', to: 'events#destroy_sample', as: :destroy_sample
16
+ end
17
+ end
14
18
  patch 'events/:name/pin', to: 'events#toggle_pin', as: :event_pin
15
19
  patch 'events/:name/ignore', to: 'events#toggle_ignore', as: :event_ignore
16
20
  get 'events_ignored', to: 'events#ignored', as: :ignored_events
@@ -21,6 +25,7 @@ Catpm::Engine.routes.draw do
21
25
  member do
22
26
  patch :resolve
23
27
  patch :unresolve
28
+ patch :toggle_pin
24
29
  end
25
30
  end
26
31
  end
@@ -50,6 +50,7 @@ class CreateCatpmTables < ActiveRecord::Migration[8.0]
50
50
  t.json :contexts
51
51
  t.json :occurrence_buckets
52
52
  t.datetime :resolved_at
53
+ t.boolean :pinned, null: false, default: false
53
54
  end
54
55
 
55
56
  add_index :catpm_errors, :fingerprint, unique: true, name: 'idx_catpm_errors_fingerprint'
@@ -53,6 +53,7 @@ module Catpm
53
53
  duration: elapsed_ms(env),
54
54
  started_at: Time.current,
55
55
  status: 500,
56
+ sample_type: 'error',
56
57
  error_class: exception.class.name,
57
58
  error_message: exception.message,
58
59
  backtrace: exception.backtrace,
data/lib/catpm/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Catpm
4
- VERSION = '0.6.0'
4
+ VERSION = '0.6.1'
5
5
  end
@@ -35,6 +35,13 @@ namespace :catpm do
35
35
  puts '[catpm] catpm_endpoint_prefs table already exists, skipping'
36
36
  end
37
37
 
38
+ unless connection.column_exists?(:catpm_errors, :pinned)
39
+ connection.add_column :catpm_errors, :pinned, :boolean, null: false, default: false
40
+ puts '[catpm] Added pinned column to catpm_errors'
41
+ else
42
+ puts '[catpm] catpm_errors.pinned already exists, skipping'
43
+ end
44
+
38
45
  unless connection.table_exists?(:catpm_event_prefs)
39
46
  connection.create_table :catpm_event_prefs do |t|
40
47
  t.string :name, null: false
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: catpm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
@@ -33,6 +33,9 @@ files:
33
33
  - MIT-LICENSE
34
34
  - README.md
35
35
  - Rakefile
36
+ - app/assets/images/catpm/favicon-32.png
37
+ - app/assets/images/catpm/favicon-512.png
38
+ - app/assets/images/catpm/favicon.ico
36
39
  - app/assets/stylesheets/catpm/application.css
37
40
  - app/controllers/catpm/application_controller.rb
38
41
  - app/controllers/catpm/endpoints_controller.rb