error_stalker 0.0.12 → 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|