rscratch 0.1.3 → 0.1.4
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 +5 -13
- data/README.md +2 -6
- data/app/assets/javascripts/rscratch/exceptions.js +107 -12
- data/app/assets/javascripts/rscratch/templates/exception_overview.jst.ejs +9 -1
- data/app/assets/stylesheets/rscratch/style.css +5 -2
- data/app/controllers/rscratch/exceptions_controller.rb +27 -2
- data/app/helpers/rscratch/exceptions_helper.rb +9 -0
- data/app/models/rscratch/exception.rb +63 -22
- data/app/models/rscratch/exception_log.rb +31 -7
- data/app/views/rscratch/exceptions/_exception_smartlist.html.haml +2 -2
- data/app/views/rscratch/exceptions/index.html.haml +59 -20
- data/app/views/rscratch/exceptions/resolve.json.jbuilder +7 -0
- data/app/views/rscratch/exceptions/show.json.jbuilder +1 -1
- data/app/views/rscratch/exceptions/toggle_ignore.json.jbuilder +7 -0
- data/config/routes.rb +9 -1
- data/lib/generators/rscratch/install/templates/migration.rb +32 -25
- data/lib/rscratch/version.rb +1 -1
- metadata +16 -14
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NzdhNTQ0NjI2OGY2Yjg3MmU1Mjk2MjY5MDJhNGQyOTYyYjE3MjBmNw==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 676517b649abb56d47e1a082529497f3f8c36d16
|
4
|
+
data.tar.gz: edc162e44f9a79ddf8b0be16a028619778267db4
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ZTE5MDJjY2IyMTliNGIwYjBhZTRmM2UzOTRjZWE2ZDNhY2U3ZDAxNTBlYjll
|
11
|
-
NjBhZGI2NTU2MjM5YTU3Y2UzNWYyMWVhYjM4ZDI1Zjg0YjQ0ZmQ=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YTM4MWVjODNhMDJhNzA1MjMwN2RjZDg1ZjM3YzhiYjlkMGVjZTJkNjE3ZGIx
|
14
|
-
MjM3MGUxZmU0ZWZhN2RhNTg1YzU5NzRhMjljZTQ3OWJjZTk1MmI1MTAwM2Y5
|
15
|
-
ZjhlMzZiNGQxYjVhZmNjNWNkOWRhZGY0Y2RkZTgxODkxMzA4NDI=
|
6
|
+
metadata.gz: 8aaf9492970cc937350ed1f1ef06fb73f10a54776c92e5d158adda4d132b88b78e2371b590eedec8f70119ebc902a262a72923f80b485d04d5078b64925e785b
|
7
|
+
data.tar.gz: e30dab1e112a060e633c48f97355145512cddf1d7c0e7263ed1170362c63291633dff3fa5e48ed933905f62a7623d932e8b77520bdb3abfcd818c155891cd62e
|
data/README.md
CHANGED
@@ -24,10 +24,6 @@ And then execute:
|
|
24
24
|
```ruby
|
25
25
|
$ bundle install
|
26
26
|
```
|
27
|
-
Or install it yourself as:
|
28
|
-
```ruby
|
29
|
-
$ gem install rscratch
|
30
|
-
```
|
31
27
|
After you install RScratch, you need to run the generator:
|
32
28
|
```ruby
|
33
29
|
$ rails g rscratch:install
|
@@ -71,12 +67,12 @@ Now everything looks sparky. Rscratch comes bundled with a web UI to track excep
|
|
71
67
|
|
72
68
|
http://{YOUR_APP_URL}/rscratch/
|
73
69
|
|
74
|
-
Ohh!! you may be asked for username and password once you visit this page.
|
70
|
+
Ohh!! you may be asked for username and password once you visit this page. Default credentials are given below.
|
75
71
|
```ruby
|
76
72
|
username: admin
|
77
73
|
password: admin123
|
78
74
|
```
|
79
|
-
To change this credentials check rsctarch initializer file
|
75
|
+
To change this credentials check rsctarch initializer file.
|
80
76
|
```ruby
|
81
77
|
#config/initializers/rscratch.rb
|
82
78
|
Rscratch.configure do |config|
|
@@ -2,10 +2,15 @@ $(document).ready(function() {
|
|
2
2
|
var get_exception_data, load_log_summary_bar_chart, logCountBarChart;
|
3
3
|
$(".exception-info").hide();
|
4
4
|
logCountBarChart = void 0;
|
5
|
+
|
6
|
+
// Getting exception details
|
5
7
|
$(document).on("click", ".exception-item", function() {
|
6
8
|
var e_action, e_controller, e_date, e_id, e_message, e_new_count, e_raw, e_total_count, loader;
|
7
9
|
$(".exception-info").show();
|
8
10
|
$(".no-exception").hide();
|
11
|
+
$("#mark-resolve-btn").hide();
|
12
|
+
$("#resolved-btn").hide();
|
13
|
+
// Getting data attributes
|
9
14
|
e_id = $(this).data("exception-id");
|
10
15
|
e_message = $(this).data("exception-message");
|
11
16
|
e_raw = $(this).data("exception-raw");
|
@@ -14,18 +19,86 @@ $(document).ready(function() {
|
|
14
19
|
e_new_count = $(this).data("exception-new-count");
|
15
20
|
e_controller = $(this).data("exception-controller");
|
16
21
|
e_action = $(this).data("exception-action");
|
22
|
+
e_status = $(this).data("exception-status");
|
23
|
+
e_ignore = $(this).data("exception-ignore");
|
24
|
+
// Setting data
|
17
25
|
$('.exception-message').html(e_message);
|
18
26
|
$('.exception-raw').html(e_raw);
|
19
27
|
$('.exception-total-count').html(e_total_count);
|
20
28
|
$('.exception-new-count').html(e_new_count);
|
21
29
|
$('.exception-date').html("Last occured on: " + e_date);
|
22
|
-
$('.ex-controller').html("Controller & Action: " + e_controller + "#" + e_action);
|
23
30
|
$(".exception-item").removeClass("selected");
|
24
31
|
$(".excp-item-" + e_id).addClass("selected");
|
32
|
+
|
25
33
|
loader = JST['rscratch/templates/loader'];
|
26
34
|
$('.progress-loader').html(loader);
|
27
35
|
get_exception_data(e_id, 1);
|
28
36
|
});
|
37
|
+
|
38
|
+
// Log pagination
|
39
|
+
$(document).on("click", ".log-navigator", function() {
|
40
|
+
current_page = parseFloat($("#current_page_num").val());
|
41
|
+
total_page = parseFloat($("#total_page_count").val());
|
42
|
+
e_id = parseFloat($("#exception_entry_id").val());
|
43
|
+
nav = $(this).data("navigate");
|
44
|
+
page = get_page_number(nav,current_page,total_page)
|
45
|
+
get_exception_data(e_id, page);
|
46
|
+
});
|
47
|
+
|
48
|
+
// Resolve issue
|
49
|
+
$(document).on("click", "#mark-resolve-btn", function() {
|
50
|
+
exception_id = $("#exception_entry_id").val();
|
51
|
+
var request;
|
52
|
+
request = $.ajax({
|
53
|
+
type: 'POST',
|
54
|
+
url: "/rscratch/exceptions/" + exception_id + "/resolve.json",
|
55
|
+
dataType: "json"
|
56
|
+
});
|
57
|
+
request.done(function(rData, textStatus, jqXHR) {
|
58
|
+
$("#mark-resolve-btn").hide();
|
59
|
+
$("#resolved-btn").show();
|
60
|
+
});
|
61
|
+
request.error(function(jqXHR, textStatus, errorThrown) {
|
62
|
+
alert("AJAX Error:" + textStatus);
|
63
|
+
});
|
64
|
+
});
|
65
|
+
|
66
|
+
// ignore toggle issue
|
67
|
+
$(document).on("click", "#ignore-issue-box", function() {
|
68
|
+
exception_id = $("#exception_entry_id").val();
|
69
|
+
var request;
|
70
|
+
request = $.ajax({
|
71
|
+
type: 'POST',
|
72
|
+
url: "/rscratch/exceptions/" + exception_id + "/toggle_ignore.json",
|
73
|
+
dataType: "json"
|
74
|
+
});
|
75
|
+
request.done(function(rData, textStatus, jqXHR) {
|
76
|
+
if(rData.status == "ok"){
|
77
|
+
Materialize.toast("Issue successfully updated", 5000)
|
78
|
+
}
|
79
|
+
});
|
80
|
+
request.error(function(jqXHR, textStatus, errorThrown) {
|
81
|
+
alert("AJAX Error:" + textStatus);
|
82
|
+
});
|
83
|
+
});
|
84
|
+
|
85
|
+
|
86
|
+
// Getting page number
|
87
|
+
get_page_number = function(nav,current_page,total_page){
|
88
|
+
var page = 0;
|
89
|
+
if(nav == "first"){ page = 1; }
|
90
|
+
else if(nav == "last"){ page = total_page; }
|
91
|
+
else if(nav == "next"){
|
92
|
+
if(current_page == total_page){ page = total_page; }
|
93
|
+
else{ page = current_page + 1; }
|
94
|
+
} else if(nav == "previous"){
|
95
|
+
if(current_page == 1){ page = 1; }
|
96
|
+
else{ page = current_page - 1; }
|
97
|
+
}
|
98
|
+
return page
|
99
|
+
}
|
100
|
+
|
101
|
+
// Getting exception details
|
29
102
|
get_exception_data = function(exception_id, page) {
|
30
103
|
var request;
|
31
104
|
request = $.ajax({
|
@@ -38,6 +111,28 @@ $(document).ready(function() {
|
|
38
111
|
if (page === 1) {
|
39
112
|
load_log_summary_bar_chart(rData.data.log_summary);
|
40
113
|
}
|
114
|
+
// Checking resolve status
|
115
|
+
if(rData.data.status == "new") {
|
116
|
+
$("#mark-resolve-btn").show();
|
117
|
+
$("#resolved-btn").hide();
|
118
|
+
}else {
|
119
|
+
$("#mark-resolve-btn").hide();
|
120
|
+
$("#resolved-btn").show();
|
121
|
+
}
|
122
|
+
|
123
|
+
// Checking toggle status
|
124
|
+
if(rData.data.is_ignored == false) {
|
125
|
+
$("#ignore-issue-box").prop('checked', false);
|
126
|
+
}else {
|
127
|
+
$("#ignore-issue-box").prop('checked', true);
|
128
|
+
}
|
129
|
+
// Setting pagination values
|
130
|
+
$("#current_page_num").val(page);
|
131
|
+
$("#total_page_count").val(rData.data.total_occurance_count);
|
132
|
+
$("#exception_entry_id").val(exception_id);
|
133
|
+
$(".current-log").html(page);
|
134
|
+
|
135
|
+
// Setting log data
|
41
136
|
$(".ex-backtrace").html(rData.data.log.backtrace);
|
42
137
|
$(".ex-params").html(rData.data.log.parameters);
|
43
138
|
rData.response = rData.data;
|
@@ -48,6 +143,8 @@ $(document).ready(function() {
|
|
48
143
|
alert("AJAX Error:" + textStatus);
|
49
144
|
});
|
50
145
|
};
|
146
|
+
|
147
|
+
// Load bar chart
|
51
148
|
load_log_summary_bar_chart = function(data) {
|
52
149
|
var countBarChart, count_array, dataBarChart, empty, i, j, label_array;
|
53
150
|
count_array = [];
|
@@ -58,11 +155,12 @@ $(document).ready(function() {
|
|
58
155
|
label_array.push(data[i].date);
|
59
156
|
i++;
|
60
157
|
}
|
61
|
-
if (label_array.length <
|
62
|
-
empty =
|
158
|
+
if (label_array.length < 30) {
|
159
|
+
empty = 30 - label_array.length;
|
63
160
|
j = 0;
|
64
161
|
while (j < empty) {
|
65
|
-
|
162
|
+
count_array.unshift('');
|
163
|
+
label_array.unshift('-');
|
66
164
|
j++;
|
67
165
|
}
|
68
166
|
}
|
@@ -74,10 +172,10 @@ $(document).ready(function() {
|
|
74
172
|
datasets: [
|
75
173
|
{
|
76
174
|
label: 'Exception count, group by date',
|
77
|
-
fillColor: 'rgba(
|
78
|
-
strokeColor: 'rgba(
|
79
|
-
highlightFill: 'rgba(
|
80
|
-
highlightStroke: 'rgba(
|
175
|
+
fillColor: 'rgba(158, 158, 158, 0.8)',
|
176
|
+
strokeColor: 'rgba(158, 158, 158, 1)',
|
177
|
+
highlightFill: 'rgba(158, 158, 158, 0.3)',
|
178
|
+
highlightStroke: 'rgba(158, 158, 158, 0.7)',
|
81
179
|
data: count_array
|
82
180
|
}
|
83
181
|
]
|
@@ -88,10 +186,7 @@ $(document).ready(function() {
|
|
88
186
|
showScale: false,
|
89
187
|
animationSteps: 15,
|
90
188
|
barValueSpacing: 1,
|
91
|
-
responsive:
|
189
|
+
responsive: false
|
92
190
|
});
|
93
191
|
};
|
94
192
|
});
|
95
|
-
|
96
|
-
// ---
|
97
|
-
// generated by coffee-script 1.9.2
|
@@ -16,7 +16,7 @@
|
|
16
16
|
var created_at = new Date(response.created_at);
|
17
17
|
var created_at = created_at.format("dd-mm-yyyy hh:MM TT","GMT");
|
18
18
|
|
19
|
-
var updated_at = new Date(response.
|
19
|
+
var updated_at = new Date(response.log.created_at);
|
20
20
|
var updated_at = updated_at.format("dd-mm-yyyy hh:MM TT","GMT");
|
21
21
|
%>
|
22
22
|
<div class="row">
|
@@ -47,6 +47,14 @@
|
|
47
47
|
<div class="col s3">Request Method</div>
|
48
48
|
<div class="col s9"><%= response.log.request_method %></div>
|
49
49
|
</div>
|
50
|
+
<div class="row">
|
51
|
+
<div class="col s3">Controller</div>
|
52
|
+
<div class="col s9"><%= response.controller %></div>
|
53
|
+
</div>
|
54
|
+
<div class="row">
|
55
|
+
<div class="col s3">Action</div>
|
56
|
+
<div class="col s9"><%= response.action %></div>
|
57
|
+
</div>
|
50
58
|
<div class="row">
|
51
59
|
<div class="col s3">Client IP</div>
|
52
60
|
<div class="col s9"><%= response.log.client_ip %></div>
|
@@ -22,9 +22,12 @@ h1 span.logo-text {
|
|
22
22
|
.p5{ padding: 5px !important; }
|
23
23
|
.p10{ padding: 10px !important; }
|
24
24
|
.p20{ padding: 20px; }
|
25
|
+
.padding-r10{ padding-right:10px !important; }
|
25
26
|
|
26
27
|
.margin-t-0{ margin-top:0px !important; }
|
27
28
|
.margin-t-5{ margin-top:5px !important; }
|
29
|
+
.margin-t-10{ margin-top:10px !important; }
|
30
|
+
.margin-b-0{ margin-bottom:0px !important; }
|
28
31
|
.margin-0{ margin:0px !important; }
|
29
32
|
|
30
33
|
.font-10{ font-size: 10px; }
|
@@ -85,10 +88,10 @@ span.label {
|
|
85
88
|
background-color: #b2ebf2 !important;
|
86
89
|
will-change: left, right; }
|
87
90
|
#log-page-header .card-image {
|
88
|
-
height:
|
91
|
+
height: 180px;
|
89
92
|
}
|
90
93
|
#log-page-header .card-content {
|
91
|
-
margin-top: -
|
94
|
+
/*margin-top: -10px;*/
|
92
95
|
}
|
93
96
|
#log-page-header .card-profile-image {
|
94
97
|
width: 110px;
|
@@ -3,6 +3,9 @@ module Rscratch
|
|
3
3
|
class ExceptionsController < ApplicationController
|
4
4
|
include SmartListing::Helper::ControllerExtensions
|
5
5
|
helper SmartListing::Helper
|
6
|
+
|
7
|
+
before_filter :set_exception, :only => [:show, :toggle_ignore, :resolve]
|
8
|
+
|
6
9
|
def index
|
7
10
|
@exceptions = Rscratch::Exception.order("updated_at desc")
|
8
11
|
smart_listing_create :exceptions, @exceptions.by_status('new'), partial: "rscratch/exceptions/exception_smartlist"
|
@@ -13,11 +16,33 @@ module Rscratch
|
|
13
16
|
format.json { render json: @exceptions }
|
14
17
|
end
|
15
18
|
end
|
19
|
+
|
16
20
|
def show
|
17
|
-
@excp = Rscratch::Exception.find(params[:id])
|
18
21
|
@log = @excp.exception_logs.order("created_at desc").page(params[:page]).per(1)
|
19
|
-
@historical_data = @excp.exception_logs.select("count(id) as exception_count, date(created_at) as date").group("date(created_at)").order("date(created_at)").last(30)
|
22
|
+
@historical_data = @excp.exception_logs.select("count(id) as exception_count, date(created_at) as date").group("date(created_at)").order("date(created_at)").last(30) if params[:page] == "1"
|
23
|
+
rescue Exception => @error
|
24
|
+
end
|
25
|
+
|
26
|
+
def log
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def toggle_ignore
|
31
|
+
@excp.toggle_ignore!
|
32
|
+
@excp.reload
|
33
|
+
rescue Exception => @error
|
34
|
+
end
|
35
|
+
|
36
|
+
def resolve
|
37
|
+
@excp.resolve!
|
38
|
+
@excp.reload
|
20
39
|
rescue Exception => @error
|
21
40
|
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def set_exception
|
45
|
+
@excp = Rscratch::Exception.find(params[:id])
|
46
|
+
end
|
22
47
|
end
|
23
48
|
end
|
@@ -2,7 +2,7 @@ module Rscratch
|
|
2
2
|
class Exception < ActiveRecord::Base
|
3
3
|
|
4
4
|
if Rails::VERSION::MAJOR == 3
|
5
|
-
attr_accessible :action, :app_environment, :controller, :exception, :message, :new_occurance_count, :total_occurance_count, :status
|
5
|
+
attr_accessible :action, :app_environment, :controller, :exception, :message, :new_occurance_count, :total_occurance_count, :status, :is_ignored
|
6
6
|
end
|
7
7
|
|
8
8
|
STATUS = %w(new under_development resolved)
|
@@ -26,6 +26,9 @@ module Rscratch
|
|
26
26
|
scope :by_environment, lambda {|env|where(["app_environment=?", env])}
|
27
27
|
scope :by_status, lambda {|status|where(["status=?", status])}
|
28
28
|
|
29
|
+
### => Model Callbacks
|
30
|
+
before_validation :set_default_attributes
|
31
|
+
|
29
32
|
# => Dynamic methods for exception statuses
|
30
33
|
STATUS.each do |status|
|
31
34
|
define_method "#{status}?" do
|
@@ -34,35 +37,73 @@ module Rscratch
|
|
34
37
|
end
|
35
38
|
|
36
39
|
# Log an exception
|
37
|
-
def self.log(
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
40
|
+
def self.log(_exception,_request)
|
41
|
+
_exc = self.find_or_create(_exception,_request.filtered_parameters["controller"].camelize,_request.filtered_parameters["action"],Rails.env.camelize)
|
42
|
+
if _exc.is_ignored == false
|
43
|
+
@log = ExceptionLog.new
|
44
|
+
@log.set_attributes_for _exception,_request
|
45
|
+
_exc.exception_logs << @log
|
46
|
+
else
|
47
|
+
@log = _exc.exception_logs.last
|
48
|
+
end
|
49
|
+
_hash = { :exception_id => _exc.id,
|
50
|
+
:log_serial => @log.id,
|
51
|
+
:log_url => "#{_request.base_url}#{Rscratch::Engine.routes.url_helpers.log_exceptions_path(@log)}"
|
52
|
+
}
|
53
|
+
return _hash
|
50
54
|
end
|
51
55
|
|
52
56
|
# Log unique exceptions
|
53
|
-
def self.
|
57
|
+
def self.find_or_create exc,_controller,_action,_env
|
54
58
|
_excp = Exception.by_exception(exc.class).by_message(exc.message).by_controller(_controller).by_action(_action).by_environment(_env)
|
55
59
|
if _excp.present?
|
56
60
|
return _excp.first
|
57
61
|
else
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
:app_environment => _env,
|
63
|
-
:status => "new")
|
64
|
-
return _new_excp
|
62
|
+
_excp = Exception.new
|
63
|
+
_excp.set_attributes_for exc, _controller, _action, _env
|
64
|
+
_excp.save!
|
65
|
+
_excp
|
65
66
|
end
|
66
67
|
end
|
68
|
+
|
69
|
+
# Sets Exception instance attributes.
|
70
|
+
def set_attributes_for _exception, _controller, _action, _env
|
71
|
+
self.exception = _exception.class
|
72
|
+
self.message = _exception.message
|
73
|
+
self.controller = _controller
|
74
|
+
self.action = _action
|
75
|
+
self.app_environment = _env
|
76
|
+
end
|
77
|
+
|
78
|
+
# Setting new default attributes
|
79
|
+
def set_default_attributes
|
80
|
+
self.status = "new"
|
81
|
+
end
|
82
|
+
|
83
|
+
def resolve!
|
84
|
+
update_attribute(:status, 'resolved')
|
85
|
+
self.exception_logs.last.resolve!
|
86
|
+
reset_counter!
|
87
|
+
end
|
88
|
+
|
89
|
+
def ignored?
|
90
|
+
self.is_ignored == true
|
91
|
+
end
|
92
|
+
|
93
|
+
def dont_ignore!
|
94
|
+
update_attribute(:is_ignored, false)
|
95
|
+
end
|
96
|
+
|
97
|
+
def ignore!
|
98
|
+
update_attribute(:is_ignored, true)
|
99
|
+
end
|
100
|
+
|
101
|
+
def toggle_ignore!
|
102
|
+
ignored? ? dont_ignore! : ignore!
|
103
|
+
end
|
104
|
+
|
105
|
+
def reset_counter!
|
106
|
+
update_attribute(:new_occurance_count, 0)
|
107
|
+
end
|
67
108
|
end
|
68
109
|
end
|
@@ -15,7 +15,7 @@ module Rscratch
|
|
15
15
|
validates :status, presence: true, :inclusion => {:in => STATUS}
|
16
16
|
|
17
17
|
### => Model Callbacks
|
18
|
-
after_create :
|
18
|
+
after_create :calculate_log_count
|
19
19
|
|
20
20
|
# => Dynamic methods for log statuses
|
21
21
|
STATUS.each do |status|
|
@@ -29,7 +29,7 @@ module Rscratch
|
|
29
29
|
scope :unresolved_exceptions, lambda {|last_id|where(["id >?", last_id])}
|
30
30
|
scope :resolved, lambda {where(["status=?", "resolved"])}
|
31
31
|
|
32
|
-
def
|
32
|
+
def start_development!
|
33
33
|
update_attribute(:status, 'under_development')
|
34
34
|
end
|
35
35
|
|
@@ -37,13 +37,37 @@ module Rscratch
|
|
37
37
|
update_attribute(:status, 'resolved')
|
38
38
|
end
|
39
39
|
|
40
|
+
# Sets Log instance attributes.
|
41
|
+
def set_attributes_for exc, request
|
42
|
+
self.description = exc.inspect,
|
43
|
+
self.backtrace = exc.backtrace.join("\n"),
|
44
|
+
self.request_url = request.original_url,
|
45
|
+
self.request_method = request.request_method,
|
46
|
+
self.parameters = request.filtered_parameters,
|
47
|
+
self.user_agent = request.user_agent,
|
48
|
+
self.client_ip = request.remote_ip,
|
49
|
+
self.status = "new"
|
50
|
+
end
|
51
|
+
|
52
|
+
def log_count exception_id
|
53
|
+
ExceptionLog.by_exception(exception_id).count
|
54
|
+
end
|
55
|
+
|
56
|
+
def last_resolved exception_id
|
57
|
+
ExceptionLog.by_exception(exception_id).resolved.last
|
58
|
+
end
|
59
|
+
|
60
|
+
def new_log_count exception_id
|
61
|
+
_last_resolved = last_resolved exception_id
|
62
|
+
_new_count = _last_resolved.present? ? ExceptionLog.by_exception(exception_id).unresolved_exceptions(_last_resolved.id).count : log_count(exception_id)
|
63
|
+
end
|
64
|
+
|
40
65
|
private
|
41
66
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
self.exception.update_attributes(:total_occurance_count=>_exception_logs.count, :new_occurance_count=>_new_logs.count)
|
67
|
+
def calculate_log_count
|
68
|
+
_log_count = log_count self.exception_id
|
69
|
+
_new_count = new_log_count self.exception_id
|
70
|
+
self.exception.update_attributes(:total_occurance_count=>_log_count, :new_occurance_count=>_new_count)
|
47
71
|
end
|
48
72
|
end
|
49
73
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
- unless smart_listing.empty?
|
2
2
|
%ul.collection.margin-t-0
|
3
3
|
- smart_listing.collection.each do |object|
|
4
|
-
%li.collection-item.avatar.min-height-70.waves-effect.width-100.exception-item{:class=>"excp-item-#{object.id}","data-exception-id"=>object.id, "data-exception-message"=>object.message, "data-exception-date"=>object.updated_at.strftime("%d-%m-%Y, %I:%M %p"), "data-exception-total-count"=>object.total_occurance_count, "data-exception-new-count"=>object.new_occurance_count, "data-exception-controller"=>object.controller, "data-exception-action"=>object.action, "data-exception-raw"=>object.exception}
|
5
|
-
%i.margin-t-5.material-icons.circle.
|
4
|
+
%li.collection-item.avatar.min-height-70.waves-effect.width-100.exception-item{:class=>"excp-item-#{object.id}","data-exception-id"=>object.id, "data-exception-message"=>object.message, "data-exception-date"=>object.updated_at.strftime("%d-%m-%Y, %I:%M %p"), "data-exception-total-count"=>object.total_occurance_count, "data-exception-new-count"=>object.new_occurance_count, "data-exception-controller"=>object.controller, "data-exception-action"=>object.action, "data-exception-raw"=>object.exception, "data-exception-status"=>object.status, "data-exception-ignore"=>"#{object.is_ignored}"}
|
5
|
+
%i.margin-t-5.material-icons.circle.font-24{:class=>"#{get_issue_color(object)}"} bug_report
|
6
6
|
%span.secondary-content.label=object.total_occurance_count
|
7
7
|
%h6.grey-text.text-darken-4.margin-t-0.truncate=object.message
|
8
8
|
%h6.grey-text.text-darken-3.margin-t-0.truncate.font-11=object.exception
|
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
.row
|
7
7
|
.col.s4.p0.fixed-sidebar.z-depth-1
|
8
|
-
%ul.tabs.
|
8
|
+
%ul.tabs.teal
|
9
9
|
%li.tab.col.s6
|
10
10
|
%a.white-text.waves-effect.waves-light.active{:href => "#new-ex"} New
|
11
11
|
%li.tab.col.s6
|
@@ -17,28 +17,67 @@
|
|
17
17
|
#resolved-ex.p0
|
18
18
|
= smart_listing_render :resolved_exceptions
|
19
19
|
|
20
|
-
.col.s8.p0
|
21
|
-
.card#log-page-header.exception-info.margin-0
|
22
|
-
.card-
|
23
|
-
%canvas#log-count-canvas{:height => "89","chart-legend" => "true"}
|
24
|
-
.card-content
|
20
|
+
.col.s8.p0.right
|
21
|
+
.card#log-page-header.exception-info.margin-0.waves-effect.waves-block.waves-light
|
22
|
+
.card-content.p0.blue.border-radius-0
|
25
23
|
.row.margin-0
|
26
|
-
.col.
|
27
|
-
%h6.
|
28
|
-
%p.medium-small
|
29
|
-
%h6.margin-t-0.
|
30
|
-
%h6.margin-t-0.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
24
|
+
.col.l8.s12
|
25
|
+
%h6.font-18.white-text.exception-message
|
26
|
+
%p.medium-small
|
27
|
+
%h6.margin-t-0.blue-text.text-lighten-4.font-12.exception-raw
|
28
|
+
%h6.margin-t-0.blue-text.text-lighten-4.font-12.exception-date
|
29
|
+
.col.l4.s12.margin-t-10
|
30
|
+
%a.white#mark-resolve-btn.blue-text.waves-effect.waves-green.btn.margin-t-10
|
31
|
+
%i.material-icons.left> golf_course
|
32
|
+
Mark as resolved
|
33
|
+
%a.white#resolved-btn.blue-text.waves-effect.waves-green.btn.margin-t-10
|
34
|
+
%i.material-icons.left> done
|
35
|
+
Issue Resolved
|
36
|
+
.card-action.p0.grey.lighten-3
|
37
|
+
.row.margin-0
|
38
|
+
.col.l2.s6.center-align
|
39
|
+
%h3.margin-b-0.margin-t-10.orange-text.exception-total-count
|
40
|
+
%p.margin-t-0.medium-small.orange-text.text-lighten-1.font-12 Total Occurrences
|
41
|
+
.col.l2.s6.center-align
|
42
|
+
%h3.margin-b-0.margin-t-10.teal-text.exception-new-count
|
43
|
+
%p.margin-t-0.medium-small.teal-text.text-lighten-1.font-12 Since Last Resolved
|
44
|
+
.col.l3.s12.p10
|
45
|
+
.font-12.grey-text You can ingore this issue and from next time it won't be reported again.
|
46
|
+
%input#ignore-issue-box.filled-in{:checked => false, :type => "checkbox"}
|
47
|
+
%label.margin-t-10{:for => "ignore-issue-box"} Ignore this issue
|
48
|
+
.col.l5.s12.hide-on-small-only
|
49
|
+
%canvas#log-count-canvas.right{:height => "93",:style=>"margin-bottom:-2px;"}
|
39
50
|
.col.s12.exception-info
|
51
|
+
|
52
|
+
|
40
53
|
.card
|
41
|
-
|
54
|
+
%ul.pagination.right
|
55
|
+
%li
|
56
|
+
%a{:href => "#!"}
|
57
|
+
%i.material-icons bug_report
|
58
|
+
%li
|
59
|
+
%a.font-12{:href => "#!"}
|
60
|
+
%span.current-log 1
|
61
|
+
of
|
62
|
+
%span.exception-total-count
|
63
|
+
%li.waves-effect
|
64
|
+
%a.exception-data.log-navigator.arrow-first{:href => "#!", "data-navigate"=>"first"}
|
65
|
+
%i.material-icons fast_rewind
|
66
|
+
%li.waves-effect
|
67
|
+
%a.exception-data.log-navigator.arrow-previous{:href => "#!", "data-navigate"=>"previous"}
|
68
|
+
%i.material-icons chevron_left
|
69
|
+
%li.active
|
70
|
+
%a.current-log{:href => "#!"} 1
|
71
|
+
%input#current_page_num{:type=>"hidden"}
|
72
|
+
%input#total_page_count{:type=>"hidden"}
|
73
|
+
%input#exception_entry_id{:type=>"hidden"}
|
74
|
+
%li.waves-effect
|
75
|
+
%a.exception-data.log-navigator.arrow-next{:href => "#!", "data-navigate"=>"next"}
|
76
|
+
%i.material-icons chevron_right
|
77
|
+
%li.waves-effect
|
78
|
+
%a.exception-data.log-navigator.arrow-last{:href => "#!", "data-navigate"=>"last"}
|
79
|
+
%i.material-icons fast_forward
|
80
|
+
|
42
81
|
%ul.tabs.tab-profile.z-depth-1.red
|
43
82
|
%li.tab
|
44
83
|
%a.white-text.waves-effect.waves-light.active{:href => "#overview"}
|
@@ -4,7 +4,7 @@ if @error.present?
|
|
4
4
|
json.data Array.new
|
5
5
|
else
|
6
6
|
json.data do
|
7
|
-
json.extract! @excp, :action, :app_environment, :controller, :exception, :message, :new_occurance_count, :total_occurance_count, :created_at, :updated_at
|
7
|
+
json.extract! @excp, :action, :app_environment, :controller, :exception, :message, :new_occurance_count, :total_occurance_count, :created_at, :updated_at, :status, :is_ignored
|
8
8
|
json.log do
|
9
9
|
json.extract! @log.first, :backtrace, :client_ip, :description, :exception_id, :parameters, :request_method, :request_url, :status, :user_agent, :created_at, :updated_at
|
10
10
|
end
|
data/config/routes.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
Rscratch::Engine.routes.draw do
|
2
2
|
|
3
|
-
resources :exceptions
|
3
|
+
resources :exceptions do
|
4
|
+
member do
|
5
|
+
post "toggle_ignore"
|
6
|
+
post "resolve"
|
7
|
+
end
|
8
|
+
collection do
|
9
|
+
get "log/:id", to: "exceptions#log", as: "log"
|
10
|
+
end
|
11
|
+
end
|
4
12
|
|
5
13
|
get "dashboard/index"
|
6
14
|
|
@@ -1,40 +1,47 @@
|
|
1
1
|
class RscratchSchemaMigration < ActiveRecord::Migration
|
2
2
|
def change
|
3
3
|
# Exception table
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
unless table_exists?("rscratch_exceptions")
|
5
|
+
create_table :rscratch_exceptions do |t|
|
6
|
+
t.text :exception
|
7
|
+
t.text :message
|
8
|
+
t.string :controller
|
9
|
+
t.string :action
|
10
|
+
t.string :app_environment
|
11
|
+
t.integer :total_occurance_count
|
12
|
+
t.integer :new_occurance_count
|
13
|
+
t.string :status
|
14
|
+
t.boolean :is_ignored, default: false
|
13
15
|
|
14
|
-
|
16
|
+
t.timestamps
|
17
|
+
end
|
15
18
|
end
|
16
19
|
|
17
20
|
# Exception log table
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
unless table_exists?("rscratch_exception_logs")
|
22
|
+
create_table :rscratch_exception_logs do |t|
|
23
|
+
t.integer :exception_id
|
24
|
+
t.text :description
|
25
|
+
t.text :backtrace
|
26
|
+
t.text :request_url
|
27
|
+
t.string :request_method
|
28
|
+
t.text :parameters
|
29
|
+
t.string :user_agent
|
30
|
+
t.string :client_ip
|
31
|
+
t.string :status
|
28
32
|
|
29
|
-
|
33
|
+
t.timestamps
|
34
|
+
end
|
30
35
|
end
|
31
36
|
|
32
37
|
# Config table
|
33
|
-
|
34
|
-
tc
|
35
|
-
|
38
|
+
unless table_exists?("rscratch_configurations")
|
39
|
+
create_table :rscratch_configurations do |tc|
|
40
|
+
tc.string :config_key
|
41
|
+
tc.string :config_value
|
36
42
|
|
37
|
-
|
43
|
+
tc.timestamps
|
44
|
+
end
|
38
45
|
end
|
39
46
|
end
|
40
47
|
end
|
data/lib/rscratch/version.rb
CHANGED
metadata
CHANGED
@@ -1,83 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rscratch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Avishek Jana
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: smart_listing
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: haml
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: ejs
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: jbuilder
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: haml-rails
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
description: RScratch - Exception and log processing solution for Ruby on Rails application
|
@@ -111,7 +111,9 @@ files:
|
|
111
111
|
- app/views/rscratch/exceptions/_exception_smartlist.html.haml
|
112
112
|
- app/views/rscratch/exceptions/index.html.haml
|
113
113
|
- app/views/rscratch/exceptions/index.js.erb
|
114
|
+
- app/views/rscratch/exceptions/resolve.json.jbuilder
|
114
115
|
- app/views/rscratch/exceptions/show.json.jbuilder
|
116
|
+
- app/views/rscratch/exceptions/toggle_ignore.json.jbuilder
|
115
117
|
- app/views/smart_listing/_action_custom.html.erb
|
116
118
|
- app/views/smart_listing/_action_delete.html.erb
|
117
119
|
- app/views/smart_listing/_action_edit.html.erb
|
@@ -179,12 +181,12 @@ require_paths:
|
|
179
181
|
- lib
|
180
182
|
required_ruby_version: !ruby/object:Gem::Requirement
|
181
183
|
requirements:
|
182
|
-
- -
|
184
|
+
- - ">="
|
183
185
|
- !ruby/object:Gem::Version
|
184
186
|
version: '0'
|
185
187
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
188
|
requirements:
|
187
|
-
- -
|
189
|
+
- - ">="
|
188
190
|
- !ruby/object:Gem::Version
|
189
191
|
version: '0'
|
190
192
|
requirements: []
|