error_stalker 0.0.12 → 0.0.13
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.
- data/Gemfile +2 -1
- data/README.rdoc +105 -2
- data/lib/error_stalker/exception_report.rb +17 -9
- data/lib/error_stalker/server/public/exception_logger.css +4 -0
- data/lib/error_stalker/server/views/_exception_table.erb +1 -1
- data/lib/error_stalker/server/views/search.erb +3 -3
- data/lib/error_stalker/server/views/show.erb +2 -2
- data/lib/error_stalker/server.rb +11 -13
- data/lib/error_stalker/store/mongoid.rb +33 -20
- data/lib/error_stalker/version.rb +1 -1
- data/lib/error_stalker/will_paginate/mongoid.rb +45 -0
- metadata +4 -6
- data/lib/error_stalker/sinatra_link_renderer.rb +0 -25
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
@@ -1,3 +1,106 @@
|
|
1
|
-
=
|
1
|
+
= ErrorStalker
|
2
2
|
|
3
|
-
|
3
|
+
ErrorStalker is an extensible exception monitor for Ruby apps.
|
4
|
+
|
5
|
+
== Getting Started
|
6
|
+
|
7
|
+
After installing the gem, you should require it:
|
8
|
+
|
9
|
+
require 'error_stalker'
|
10
|
+
|
11
|
+
Afterwards, reporting exceptions is simple:
|
12
|
+
|
13
|
+
ErrorStalker::Client.report(application_name, exception, extra_data)
|
14
|
+
|
15
|
+
This will report an exception to ErrorStalker.
|
16
|
+
|
17
|
+
In Rails, you should be able to put this code in your
|
18
|
+
ApplicationController to report all exceptions:
|
19
|
+
|
20
|
+
rescue_from Exception do |exception|
|
21
|
+
ErrorStalker::Client.report(application_name, exception)
|
22
|
+
raise exception
|
23
|
+
end
|
24
|
+
|
25
|
+
== The ErrorStalker Server
|
26
|
+
|
27
|
+
ErrorStalker has decent defaults for running in development -- when
|
28
|
+
you call ErrorStalker::Client.report, it logs the exception to a
|
29
|
+
logfile. If you're inside a Rails app, it will log to
|
30
|
+
log/exceptions.log, otherwise it will put the logfile in
|
31
|
+
/tmp/exceptions.log.
|
32
|
+
|
33
|
+
This is probably not what you want in production, so ErrorStalker
|
34
|
+
supports different backends, and comes stock with an ErrorStalker
|
35
|
+
Sinatra server that can persist, aggregate, and show the exceptions
|
36
|
+
your app is raising. Switching backends can be done like this:
|
37
|
+
|
38
|
+
require 'error_stalker/backend/server'
|
39
|
+
ErrorStalker::Client.backend = ErrorStalker::Backend::Server.new(:host => "localhost", :port => 8080)
|
40
|
+
|
41
|
+
From that point on, all exceptions will be posted to the ErrorStalker server running on localhost:8080.
|
42
|
+
|
43
|
+
That server is a standard Sinatra app, but you still need to run
|
44
|
+
it. You can do that by pointing your favorite rack-enabled server at a
|
45
|
+
config.ru that looks like this:
|
46
|
+
|
47
|
+
require 'error_stalker/server'
|
48
|
+
|
49
|
+
ErrorStalker::Server.configuration = {
|
50
|
+
... # server config goes here
|
51
|
+
}
|
52
|
+
|
53
|
+
run ErrorStalker::Server
|
54
|
+
|
55
|
+
== Data Stores
|
56
|
+
|
57
|
+
The server takes two main bits of configuration. The most important is
|
58
|
+
the data store. Currently, the server supports an in-memory data store
|
59
|
+
(which will go away when the server does) and a persistent mongodb store (using
|
60
|
+
mongoid). You can configure these with a hash before you start the server:
|
61
|
+
|
62
|
+
ErrorStalker::Server.configuration = {
|
63
|
+
'store' => {
|
64
|
+
'class' => 'ErrorStalker::Store::Mongoid',
|
65
|
+
'parameters' => '/path/to/mongoid.yml'
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
Each data store should call out the parameters it supports in its
|
70
|
+
documentation.
|
71
|
+
|
72
|
+
== Plugins
|
73
|
+
|
74
|
+
The ErrorStalker server also supports a simple plugin
|
75
|
+
architecture. Currently, it supports a simple lighthouse reporter and
|
76
|
+
an automatic email sender. Documentation for these plugins is in the
|
77
|
+
Rdoc for the specific classes. They are configured the same way as the
|
78
|
+
data store:
|
79
|
+
|
80
|
+
ErrorStalker::Server.configuration = {
|
81
|
+
'store' => {
|
82
|
+
'class' => 'ErrorStalker::Store::Mongoid',
|
83
|
+
'parameters' => '/path/to/mongoid.yml'
|
84
|
+
},
|
85
|
+
'plugin' => [
|
86
|
+
{
|
87
|
+
'class' => 'ErrorStalker::Plugin::EmailSender',
|
88
|
+
'parameters' => {
|
89
|
+
'to' => 'to_address@example.com',
|
90
|
+
'from' => 'from_address@example.com'
|
91
|
+
}
|
92
|
+
},
|
93
|
+
...
|
94
|
+
]
|
95
|
+
}
|
96
|
+
|
97
|
+
== Extending ExceptionStalker
|
98
|
+
|
99
|
+
Feel free to write your own backends, stores, or plugins as you need
|
100
|
+
them. As long as you follow the documentation in the ::Base classes,
|
101
|
+
your code should fit right in. Let me know what you come up with!
|
102
|
+
|
103
|
+
== License
|
104
|
+
|
105
|
+
Regardless of what any other file may say about it, this code is
|
106
|
+
licensed under the MIT license.
|
@@ -7,8 +7,8 @@ require 'digest/md5'
|
|
7
7
|
# class, but they should be able to be treated as instances of this
|
8
8
|
# class regardless.
|
9
9
|
class ErrorStalker::ExceptionReport
|
10
|
-
|
11
|
-
# The name of the application that caused this exception.
|
10
|
+
|
11
|
+
# The name of the application that caused this exception.
|
12
12
|
attr_reader :application
|
13
13
|
|
14
14
|
# The name of the machine that raised this exception.
|
@@ -23,9 +23,6 @@ class ErrorStalker::ExceptionReport
|
|
23
23
|
# The exception object (or string message) this report represents
|
24
24
|
attr_reader :exception
|
25
25
|
|
26
|
-
# A hash of extra data logged along with this exception.
|
27
|
-
attr_reader :data
|
28
|
-
|
29
26
|
# The backtrace corresponding to this exception. Should be an array
|
30
27
|
# of strings, each referring to a single stack frame.
|
31
28
|
attr_reader :backtrace
|
@@ -46,15 +43,15 @@ class ErrorStalker::ExceptionReport
|
|
46
43
|
@machine = params[:machine] || machine_name
|
47
44
|
@timestamp = params[:timestamp] || Time.now
|
48
45
|
@type = params[:type] || params[:exception].class.name
|
49
|
-
|
46
|
+
|
50
47
|
if params[:exception].is_a?(Exception)
|
51
48
|
@exception = params[:exception].to_s
|
52
49
|
else
|
53
50
|
@exception = params[:exception]
|
54
51
|
end
|
55
|
-
|
52
|
+
|
56
53
|
@data = params[:data]
|
57
|
-
|
54
|
+
|
58
55
|
if params[:backtrace]
|
59
56
|
@backtrace = params[:backtrace]
|
60
57
|
else
|
@@ -78,6 +75,17 @@ class ErrorStalker::ExceptionReport
|
|
78
75
|
@digest ||= Digest::MD5.hexdigest((backtrace ? backtrace.to_s[0,STACK_DIGEST_LENGTH] : exception.to_s) + type.to_s)
|
79
76
|
end
|
80
77
|
|
78
|
+
# A hash of extra data logged along with this exception.
|
79
|
+
def data
|
80
|
+
@data_with_fixed_encoding ||= JSON.parse(raw_data.to_json.encode('utf-8', 'ascii-8bit', :invalid => :replace, :undef => :replace))
|
81
|
+
end
|
82
|
+
|
83
|
+
# The extra data associated with this object, without fixing any
|
84
|
+
# broken encodings.
|
85
|
+
def raw_data
|
86
|
+
@data
|
87
|
+
end
|
88
|
+
|
81
89
|
# Serialize this object to json, so we can send it over the wire.
|
82
90
|
def to_json
|
83
91
|
{
|
@@ -86,7 +94,7 @@ class ErrorStalker::ExceptionReport
|
|
86
94
|
:timestamp => timestamp,
|
87
95
|
:type => type,
|
88
96
|
:exception => exception,
|
89
|
-
:data =>
|
97
|
+
:data => raw_data,
|
90
98
|
:backtrace => backtrace
|
91
99
|
}.to_json
|
92
100
|
end
|
@@ -26,10 +26,10 @@
|
|
26
26
|
<input id="type" type="text" name="type" value="<%= params[:type] %>" />
|
27
27
|
|
28
28
|
<% if store.supports_extended_searches? %>
|
29
|
-
<label for="data">Extra data
|
30
|
-
<input id="data" type="text" name="data" value="<%= params[:data] %>" />
|
29
|
+
<label for="data">Extra data</label>
|
30
|
+
<input id="data" type="text" name="data" value="<%= params[:data] %>" placeholder="REMOTE_ADDR:127.0.0.1 PATH:/test" />
|
31
31
|
<% end %>
|
32
|
-
|
32
|
+
|
33
33
|
<input type="submit" name="Search" value="Search" />
|
34
34
|
</form>
|
35
35
|
</div>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<dt>First occurred</dt><dd><%= h(@group.first_timestamp) %></dd>
|
8
8
|
<dt>Most recently occurred</dt><dd><%= h(@group.most_recent_timestamp) %></dd>
|
9
9
|
<dt>On machines</dt><dd><%= h(@group.machines.join(', ')) %></dd>
|
10
|
-
<dt>Exception class</dt><dd><%= h(@
|
10
|
+
<dt>Exception class</dt><dd><%= h(@report.type) %></dd>
|
11
11
|
</dl>
|
12
12
|
<p><a href="/similar/<%= @report.digest%>.html">See all</a></p>
|
13
13
|
<% plugins.each do |plugin| %>
|
@@ -28,5 +28,5 @@
|
|
28
28
|
|
29
29
|
<% if @report.data && !@report.data.empty? %>
|
30
30
|
<h3>Additional information</h3>
|
31
|
-
<pre><code><%= h @report.data
|
31
|
+
<pre><code><%= h JSON.pretty_generate(@report.data) %></code></pre>
|
32
32
|
<% end %>
|
data/lib/error_stalker/server.rb
CHANGED
@@ -6,8 +6,6 @@ require 'error_stalker/store'
|
|
6
6
|
require 'error_stalker/plugin'
|
7
7
|
require 'erb'
|
8
8
|
require 'will_paginate'
|
9
|
-
require 'will_paginate/view_helpers/base'
|
10
|
-
require 'error_stalker/sinatra_link_renderer'
|
11
9
|
require 'error_stalker/version'
|
12
10
|
|
13
11
|
module ErrorStalker
|
@@ -24,21 +22,21 @@ module ErrorStalker
|
|
24
22
|
|
25
23
|
# The data store (ErrorStalker::Store instance) to use to store
|
26
24
|
# exception data
|
27
|
-
attr_accessor :store
|
28
|
-
|
25
|
+
attr_accessor :store
|
26
|
+
|
29
27
|
# A list of plugins the server will use.
|
30
28
|
attr_accessor :plugins
|
31
|
-
|
29
|
+
|
32
30
|
set :root, File.dirname(__FILE__)
|
33
31
|
set :public, Proc.new { File.join(root, "server/public") }
|
34
32
|
set :views, Proc.new { File.join(root, "server/views") }
|
35
33
|
|
34
|
+
register WillPaginate::Sinatra
|
35
|
+
|
36
36
|
helpers do
|
37
37
|
include Rack::Utils
|
38
38
|
alias_method :h, :escape_html
|
39
39
|
|
40
|
-
include WillPaginate::ViewHelpers::Base
|
41
|
-
|
42
40
|
# Generates a url from an array of strings representing the
|
43
41
|
# parts of the path.
|
44
42
|
def url(*path_parts)
|
@@ -62,7 +60,7 @@ module ErrorStalker
|
|
62
60
|
class << self
|
63
61
|
# A hash of configuration options, usually read from a
|
64
62
|
# configuration file.
|
65
|
-
attr_accessor :configuration
|
63
|
+
attr_accessor :configuration
|
66
64
|
end
|
67
65
|
self.configuration = {}
|
68
66
|
|
@@ -99,7 +97,7 @@ module ErrorStalker
|
|
99
97
|
end
|
100
98
|
self.store = self.class.store
|
101
99
|
end
|
102
|
-
|
100
|
+
|
103
101
|
get '/' do
|
104
102
|
@records = store.recent.paginate(:page => params[:page], :per_page => PER_PAGE)
|
105
103
|
erb :index
|
@@ -109,7 +107,7 @@ module ErrorStalker
|
|
109
107
|
@results = store.search(params).paginate(:page => params[:page], :per_page => PER_PAGE) if params["Search"]
|
110
108
|
erb :search
|
111
109
|
end
|
112
|
-
|
110
|
+
|
113
111
|
get '/similar/:digest.html' do
|
114
112
|
@group = store.reports_in_group(params[:digest]).paginate(:page => params[:page], :per_page => PER_PAGE)
|
115
113
|
if @group
|
@@ -118,7 +116,7 @@ module ErrorStalker
|
|
118
116
|
404
|
119
117
|
end
|
120
118
|
end
|
121
|
-
|
119
|
+
|
122
120
|
get '/exceptions/:id.html' do
|
123
121
|
@report = store.find(params[:id])
|
124
122
|
if @report
|
@@ -128,7 +126,7 @@ module ErrorStalker
|
|
128
126
|
404
|
129
127
|
end
|
130
128
|
end
|
131
|
-
|
129
|
+
|
132
130
|
get '/stats.json' do
|
133
131
|
timestamp = Time.at(params[:timestamp].to_i) if params[:timestamp]
|
134
132
|
# default to 1 hour ago
|
@@ -147,6 +145,6 @@ module ErrorStalker
|
|
147
145
|
plugins.each {|p| p.after_create(self, report)}
|
148
146
|
200
|
149
147
|
end
|
150
|
-
|
148
|
+
|
151
149
|
end
|
152
150
|
end
|
@@ -1,13 +1,15 @@
|
|
1
1
|
require 'mongoid'
|
2
2
|
require 'error_stalker/store/base'
|
3
|
+
require 'error_stalker/will_paginate/mongoid'
|
4
|
+
require 'will_paginate/array'
|
3
5
|
|
4
6
|
# Store exceptions using MongoDB. This store provides fast storage and
|
5
7
|
# querying of exceptions, and long-term persistence. It also allows
|
6
8
|
# querying based on arbitrary data stored in the +data+ hash of the
|
7
9
|
# exception report, which allows for crazy things like searching
|
8
|
-
# reports by URL or IP address.
|
10
|
+
# reports by URL or IP address.
|
9
11
|
class ErrorStalker::Store::Mongoid < ErrorStalker::Store::Base
|
10
|
-
|
12
|
+
|
11
13
|
# Configure mongoid from the mongoid config file found in
|
12
14
|
# +config_file+. This mongoid config file should be similar to the
|
13
15
|
# one on http://mongoid.org/docs/installation/, and must be indexed
|
@@ -69,7 +71,7 @@ class ErrorStalker::Store::Mongoid < ErrorStalker::Store::Base
|
|
69
71
|
def reports_in_group(digest)
|
70
72
|
ExceptionReport.where(:digest => digest).order_by(:timestamp.desc)
|
71
73
|
end
|
72
|
-
|
74
|
+
|
73
75
|
# returns the ExceptionGroup object corresponding to a particular
|
74
76
|
# digest
|
75
77
|
def group(digest)
|
@@ -80,11 +82,11 @@ class ErrorStalker::Store::Mongoid < ErrorStalker::Store::Base
|
|
80
82
|
def supports_extended_searches?
|
81
83
|
true
|
82
84
|
end
|
83
|
-
|
85
|
+
|
84
86
|
def total
|
85
87
|
ExceptionReport.count()
|
86
88
|
end
|
87
|
-
|
89
|
+
|
88
90
|
def total_since(timestamp)
|
89
91
|
ExceptionReport.where(:timestamp.gte => timestamp).count()
|
90
92
|
end
|
@@ -98,23 +100,24 @@ class ErrorStalker::Store::Mongoid < ErrorStalker::Store::Base
|
|
98
100
|
|
99
101
|
[:application, :machine].each do |param|
|
100
102
|
if params[param] && !params[param].empty?
|
101
|
-
|
103
|
+
puts "HERE: #{params.inspect}"
|
104
|
+
scope = scope.where(param => params[param])
|
102
105
|
end
|
103
106
|
end
|
104
107
|
|
105
108
|
[:exception, :type].each do |param|
|
106
109
|
if params[param] && !params[param].empty?
|
107
|
-
scope.where(param => /#{params[param]}/)
|
110
|
+
scope = scope.where(param => /#{params[param]}/)
|
108
111
|
end
|
109
112
|
end
|
110
113
|
|
111
114
|
if params[:data] && !params[:data].empty?
|
112
115
|
params[:data].split.each do |keyvalue|
|
113
116
|
key, value = keyvalue.split(':')
|
114
|
-
scope.where("data" => {"#{key}" => "#{value}"})
|
117
|
+
scope = scope.where("data" => {"#{key}" => "#{value}"})
|
115
118
|
end
|
116
119
|
end
|
117
|
-
|
120
|
+
|
118
121
|
scope.order_by(:timestamp.desc)
|
119
122
|
end
|
120
123
|
|
@@ -130,7 +133,7 @@ class ErrorStalker::Store::Mongoid < ErrorStalker::Store::Base
|
|
130
133
|
# should eventually be more robust, like the Rails version, but for
|
131
134
|
# now this should be fine.
|
132
135
|
def migrate_data
|
133
|
-
if SchemaMigrations.where(:version => 1).empty?
|
136
|
+
if SchemaMigrations.where(:version => "1").empty?
|
134
137
|
ExceptionGroup.all.order_by(:timestamp).desc.each do |group|
|
135
138
|
exceptions = ExceptionReport.where(:digest => group.digest).order_by(:timestamp)
|
136
139
|
unless exceptions.empty?
|
@@ -142,7 +145,7 @@ class ErrorStalker::Store::Mongoid < ErrorStalker::Store::Base
|
|
142
145
|
group.save
|
143
146
|
end
|
144
147
|
end
|
145
|
-
SchemaMigrations.create(:version => 1)
|
148
|
+
SchemaMigrations.create(:version => "1")
|
146
149
|
end
|
147
150
|
end
|
148
151
|
|
@@ -173,12 +176,12 @@ class ErrorStalker::Store::Mongoid < ErrorStalker::Store::Base
|
|
173
176
|
{:name => report.machine},
|
174
177
|
{:name => report.machine},
|
175
178
|
:upsert => true)
|
176
|
-
|
179
|
+
|
177
180
|
Application.collection.update(
|
178
181
|
{:name => report.application},
|
179
182
|
{:name => report.application},
|
180
183
|
:upsert => true)
|
181
|
-
|
184
|
+
|
182
185
|
report.id
|
183
186
|
end
|
184
187
|
end
|
@@ -239,6 +242,8 @@ class ErrorStalker::Store::Mongoid::ExceptionGroup < ErrorStalker::ExceptionGrou
|
|
239
242
|
# associated exception reports.
|
240
243
|
def paginate(pagination_opts = {})
|
241
244
|
recent = @criteria.paginate(pagination_opts)
|
245
|
+
total_entries = recent.total_entries
|
246
|
+
|
242
247
|
exceptions = ErrorStalker::Store::Mongoid::ExceptionReport.where(:_id.in => recent.map(&:most_recent_report_id))
|
243
248
|
# Fake association preloading
|
244
249
|
id_map = {}.tap do |h|
|
@@ -246,12 +251,20 @@ class ErrorStalker::Store::Mongoid::ExceptionGroup < ErrorStalker::ExceptionGrou
|
|
246
251
|
h[ex.id] = ex
|
247
252
|
end
|
248
253
|
end
|
249
|
-
|
254
|
+
|
255
|
+
# Because all the +recent+ stuff is still a scope at this point,
|
256
|
+
# we somehow lose the most_recent_report information that we try
|
257
|
+
# to assign below the next time we iterate over the
|
258
|
+
# scope. Forcing the scope to turn into an array solves that
|
259
|
+
# problem, although it means we have to 'fake-paginate' the
|
260
|
+
# array before we return it.
|
261
|
+
recent = recent.to_a
|
262
|
+
|
250
263
|
recent.each do |r|
|
251
264
|
r.most_recent_report = id_map[r.most_recent_report_id]
|
252
265
|
end
|
253
|
-
|
254
|
-
recent
|
266
|
+
|
267
|
+
recent.paginate(:per_page => pagination_opts[:per_page], :total_entries => total_entries)
|
255
268
|
end
|
256
269
|
end
|
257
270
|
end
|
@@ -284,16 +297,16 @@ class ErrorStalker::Store::Mongoid::ExceptionReport
|
|
284
297
|
[:id, :application, :machine, :timestamp, :type, :exception, :digest, :backtrace].each do |field|
|
285
298
|
params[field] = send(field)
|
286
299
|
end
|
287
|
-
|
300
|
+
|
288
301
|
if data
|
289
302
|
params[:data] = {}.tap do |h|
|
290
303
|
data.map { |hash| h[hash.keys.first] = hash[hash.keys.first] }
|
291
304
|
end
|
292
305
|
end
|
293
|
-
|
306
|
+
|
294
307
|
ErrorStalker::ExceptionReport.new(params)
|
295
308
|
end
|
296
|
-
|
309
|
+
|
297
310
|
# Create a new mongoid exception report from +exception_report+.
|
298
311
|
def self.create_from_exception_report(exception_report)
|
299
312
|
object = new do |o|
|
@@ -307,7 +320,7 @@ class ErrorStalker::Store::Mongoid::ExceptionReport
|
|
307
320
|
exception_report.data.map {|key, value| array << {key => value}}
|
308
321
|
end
|
309
322
|
end
|
310
|
-
|
323
|
+
|
311
324
|
if exception_report.backtrace
|
312
325
|
o.backtrace = exception_report.backtrace
|
313
326
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Borrowed from
|
2
|
+
# https://raw.github.com/dbackeus/will_paginate/master/lib/will_paginate/mongoid.rb
|
3
|
+
# until it makes it into will_paginate
|
4
|
+
require 'mongoid'
|
5
|
+
require 'will_paginate/collection'
|
6
|
+
|
7
|
+
module WillPaginate
|
8
|
+
module Mongoid
|
9
|
+
module CriteriaMethods
|
10
|
+
def paginate(options = {})
|
11
|
+
extend CollectionMethods
|
12
|
+
@current_page = WillPaginate::PageNumber(options[:page] || @current_page || 1)
|
13
|
+
@page_multiplier = current_page - 1
|
14
|
+
pp = (options[:per_page] || per_page || WillPaginate.per_page).to_i
|
15
|
+
limit(pp).skip(@page_multiplier * pp)
|
16
|
+
end
|
17
|
+
|
18
|
+
def per_page(value = :non_given)
|
19
|
+
value == :non_given ? options[:limit] : limit(value)
|
20
|
+
end
|
21
|
+
|
22
|
+
def page(page)
|
23
|
+
paginate(:page => page)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module CollectionMethods
|
28
|
+
attr_reader :current_page
|
29
|
+
|
30
|
+
def total_entries
|
31
|
+
@total_entries ||= count
|
32
|
+
end
|
33
|
+
|
34
|
+
def total_pages
|
35
|
+
(total_entries / per_page.to_f).ceil
|
36
|
+
end
|
37
|
+
|
38
|
+
def offset
|
39
|
+
@page_multiplier * per_page
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
::Mongoid::Criteria.send(:include, CriteriaMethods)
|
44
|
+
end
|
45
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: error_stalker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.13
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
13
|
-
default_executable:
|
12
|
+
date: 2011-12-23 00:00:00.000000000Z
|
14
13
|
dependencies: []
|
15
14
|
description: Logs exceptions to a pluggable backend. Also provides a server for centralized
|
16
15
|
exception logging using a pluggable data store.
|
@@ -57,12 +56,12 @@ files:
|
|
57
56
|
- lib/error_stalker/server/views/search.erb
|
58
57
|
- lib/error_stalker/server/views/show.erb
|
59
58
|
- lib/error_stalker/server/views/similar.erb
|
60
|
-
- lib/error_stalker/sinatra_link_renderer.rb
|
61
59
|
- lib/error_stalker/store.rb
|
62
60
|
- lib/error_stalker/store/base.rb
|
63
61
|
- lib/error_stalker/store/in_memory.rb
|
64
62
|
- lib/error_stalker/store/mongoid.rb
|
65
63
|
- lib/error_stalker/version.rb
|
64
|
+
- lib/error_stalker/will_paginate/mongoid.rb
|
66
65
|
- test/test_helper.rb
|
67
66
|
- test/unit/backend/base_test.rb
|
68
67
|
- test/unit/backend/in_memory_test.rb
|
@@ -72,7 +71,6 @@ files:
|
|
72
71
|
- test/unit/plugins/email_sender_test.rb
|
73
72
|
- test/unit/server_test.rb
|
74
73
|
- test/unit/stores/in_memory_test.rb
|
75
|
-
has_rdoc: true
|
76
74
|
homepage: ''
|
77
75
|
licenses: []
|
78
76
|
post_install_message:
|
@@ -93,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
91
|
version: '0'
|
94
92
|
requirements: []
|
95
93
|
rubyforge_project: error_stalker
|
96
|
-
rubygems_version: 1.
|
94
|
+
rubygems_version: 1.8.11
|
97
95
|
signing_key:
|
98
96
|
specification_version: 3
|
99
97
|
summary: Logs exceptions to a pluggable backend and/or a pluggable store
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'will_paginate/view_helpers/link_renderer'
|
2
|
-
|
3
|
-
module ErrorStalker
|
4
|
-
# +will_paginate+ doesn't have built-in sinatra support, so this
|
5
|
-
# LinkRenderer subclass implements the +url+ method to work with
|
6
|
-
# sinatra-style request hashes.
|
7
|
-
class SinatraLinkRenderer < WillPaginate::ViewHelpers::LinkRenderer
|
8
|
-
protected
|
9
|
-
|
10
|
-
# Returns the URL for the given +page+
|
11
|
-
def url(page)
|
12
|
-
url = @template.request.url
|
13
|
-
params = @template.request.params.dup
|
14
|
-
if page == 1
|
15
|
-
params.delete("page")
|
16
|
-
else
|
17
|
-
params["page"] = page
|
18
|
-
end
|
19
|
-
|
20
|
-
@template.request.path + "?" + params.map {|k, v| "#{Rack::Utils.escape(k)}=#{Rack::Utils.escape(v)}"}.join("&")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
WillPaginate::ViewHelpers.pagination_options[:renderer] = ErrorStalker::SinatraLinkRenderer
|