whoops 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
data/README.asciidoc
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
Whoops
|
2
|
+
======
|
3
|
+
Daniel Higginbotham <daniel@flyingmachinestudios.com>
|
4
|
+
2011-07-09
|
5
|
+
|
6
|
+
== Overview
|
7
|
+
|
8
|
+
=== Purpose
|
9
|
+
|
10
|
+
whoops was originally conceived as an alternative to Hoptoad. Its allows you to:
|
11
|
+
|
12
|
+
* *Log arbitrary events.* Whoops events use an event_type field which can be any string - exception, notification, warning, etc.
|
13
|
+
* *Log arbitrary details.* Events are stored in http://www.mongodb.org[mongodb], giving you the flexibility of a document database.
|
14
|
+
* *Search event details.* The search parser maps text to mongoid conditions, allowing you to do queries like +details.current_user_id#in [123, 423]+
|
15
|
+
* *Extend the app.* Since it's a rails engine, you can make changes to your base rails app without worrying about merge difficulties when you upgrade whoops.
|
16
|
+
|
17
|
+
If you find yourself bumping up against limitations in Hoptoad, whoops might be right for you.
|
18
|
+
|
19
|
+
=== Design
|
20
|
+
|
21
|
+
whoops consists of two main components: the rails 3 engine and the notifier. Hosting is up to you. The engine provides the following:
|
22
|
+
|
23
|
+
* Controllers and views for viewing, filtering, and searching events.
|
24
|
+
* An end point for receiving event notifications
|
25
|
+
* A mailer for sending email notifications
|
26
|
+
* http://www.mongoid.org[Mongoid] models
|
27
|
+
|
28
|
+
The notifier is documented separately. Briefly, it allows you to create strategies for building an event notification. It also allows you to modify existing strategies.
|
29
|
+
|
30
|
+
For example, you could use the https://github.com/flyingmachine/whoops_rails_notifier[rails 3 notifier] , but modify it to include the ID of the currently logged in user. If your app ran background processes, you could create a notification strategy specific to your processes. Both strategies can coexist in the same app.
|
31
|
+
|
32
|
+
=== Terms / Models
|
33
|
+
|
34
|
+
* _Event_ A specific occurrence of an event. The Event model stores details specific to an event.
|
35
|
+
* _Event Group_ All Events are associated with an Event Group. Event Groups store details common to all events in the group.
|
36
|
+
* _Notification_ The whoops notifier sends Notifications to whoops. A notification contains both Event and Event Group information; whoops sorts it out when it receives a Notification.
|
37
|
+
|
38
|
+
== Usage
|
39
|
+
|
40
|
+
=== Installation
|
41
|
+
|
42
|
+
. create a new rails app
|
43
|
+
. add +gem "whoops"+ to your Gemfile
|
44
|
+
. run +bundle+
|
45
|
+
. run +bundle exec rails g whoops:assets+ - this copies assets to your public directory (whoops isn't 3.1 compatible yet)
|
46
|
+
. _optional_ add `root :to => "event_groups#index"` to your routes file to make the event group listing your home page
|
47
|
+
. add https://github.com/flyingmachine/whoops_notifier[notifiers] to the code you want to monitor
|
48
|
+
|
49
|
+
=== Filtering
|
50
|
+
|
51
|
+
.Filters
|
52
|
+
image::https://github.com/flyingmachine/whoops/raw/master/doc/images/dash-filters.png[Filters]
|
53
|
+
|
54
|
+
When viewing the Event Group list, you can filter by service, environment, and event type.
|
55
|
+
|
56
|
+
When you set a filter, its value is stored in a session and won't be changed until you click "reset". This is so that you won't lose your filter after, for example, viewing a specific event.
|
57
|
+
|
58
|
+
=== Searching
|
59
|
+
|
60
|
+
.Search
|
61
|
+
image::https://github.com/flyingmachine/whoops/raw/master/doc/images/details-search.png[Search]
|
62
|
+
|
63
|
+
For now, you need to enter your queries into the textarea shown above. Currently, searches only apply to the events within the current event group.
|
64
|
+
|
65
|
+
.Search Syntax
|
66
|
+
----
|
67
|
+
key[#method] query
|
68
|
+
----
|
69
|
+
|
70
|
+
* *key* the Event field to search.
|
71
|
+
* *method* _(optional)_ a http://mongoid.org/docs/querying/criteria.html#where[Mongoid] where criteria method
|
72
|
+
* *query* a YAML string
|
73
|
+
|
74
|
+
.Examples
|
75
|
+
|
76
|
+
Below is the text you would write, and below that is essentially the ruby code that ends up getting run by the server
|
77
|
+
|
78
|
+
----
|
79
|
+
details.current_user_id#in [3, 54, 532] <1>
|
80
|
+
details.num_failures#gt 3 <2>
|
81
|
+
details.current_user.first_name Voldemort <3>
|
82
|
+
message#in !r/(yesterday|today)/ <4>
|
83
|
+
----
|
84
|
+
|
85
|
+
<1> `Event.where( {:"details.current_user_id".in => [3, 54, 532]} )`
|
86
|
+
<2> `Event.where( {:"details.num_failure".gt => 3} )`
|
87
|
+
<3> `Event.where( {:"details.current_user.first_name" => "Voldemort"} )`
|
88
|
+
<4> `Event.where( {:message.in /(yesterday|today/)} )` Note that regular expressions must start with !r.
|
89
|
+
|
90
|
+
This syntax is kind of goofy, but it lets you enter constant numbers, strings, arrays, hashes, and regular expressions, just like you could if you were typing in the code directly.
|
91
|
+
|
92
|
+
== TODO
|
93
|
+
|
94
|
+
* finish notifications
|
95
|
+
* site-wide search
|
96
|
+
* graphing
|
97
|
+
|
98
|
+
== License
|
99
|
+
|
100
|
+
This project uses MIT-LICENSE.
|
File without changes
|
data/app/models/whoops/event.rb
CHANGED
@@ -18,7 +18,12 @@ class Whoops::Event
|
|
18
18
|
event_group_params[:last_recorded_at] = params[:event_time]
|
19
19
|
|
20
20
|
event_group = Whoops::EventGroup.first(:conditions => event_group_params.slice(*Whoops::EventGroup.identifying_fields))
|
21
|
-
event_group
|
21
|
+
if event_group
|
22
|
+
event_group.attributes = event_group_params
|
23
|
+
event_group.save
|
24
|
+
else
|
25
|
+
event_group = Whoops::EventGroup.create(event_group_params)
|
26
|
+
end
|
22
27
|
|
23
28
|
event_params = params.slice(*Whoops::Event.field_names)
|
24
29
|
event_group.events.create(event_params)
|
@@ -7,6 +7,7 @@ class Whoops::EventGroup
|
|
7
7
|
field string_field, :type => String
|
8
8
|
end
|
9
9
|
field :last_recorded_at, :type => DateTime
|
10
|
+
field :notify_on_next_occurrence, :type => Boolean, :default => true
|
10
11
|
|
11
12
|
has_many :events, :class_name => "Whoops::Event"
|
12
13
|
|
@@ -29,4 +30,6 @@ class Whoops::EventGroup
|
|
29
30
|
end
|
30
31
|
services
|
31
32
|
end
|
33
|
+
|
34
|
+
|
32
35
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class Whoops::NotificationRule
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :email, :type => String
|
5
|
+
field :matchers, :type => Array
|
6
|
+
|
7
|
+
# This might come in handy in the future?
|
8
|
+
# class << self.fields["matchers"]
|
9
|
+
# def set(object)
|
10
|
+
# object = object.split("\n").collect{ |m| m.strip } if object.is_a?(String)
|
11
|
+
# object
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
|
15
|
+
before_save :downcase_email
|
16
|
+
|
17
|
+
def downcase_email
|
18
|
+
self.email.downcase!
|
19
|
+
end
|
20
|
+
|
21
|
+
def matchers=(matchers)
|
22
|
+
write_attribute(:matchers, matchers.split("\n").collect{ |m| m.strip })
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.matches(event)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class Matcher
|
30
|
+
attr_accessor :event_group
|
31
|
+
|
32
|
+
# @param [ Whoops::EventGroup ]
|
33
|
+
def initialize(event_group)
|
34
|
+
self.event_group = event_group
|
35
|
+
end
|
36
|
+
|
37
|
+
def matching_emails
|
38
|
+
matches.collect{|m| m.email}.uniq
|
39
|
+
end
|
40
|
+
|
41
|
+
def matches
|
42
|
+
Whoops::NotificationRule.where(:matchers => /^#{event_group.service}/)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -34,7 +34,7 @@ class Whoops::SearchParser
|
|
34
34
|
def parse_value(value)
|
35
35
|
value = value.strip
|
36
36
|
# value = "!ruby/regexp \"#{value}\"" if value =~ /^\/.*\/$/
|
37
|
-
value.gsub!(
|
37
|
+
value.gsub!(/!r(\/.*?\/)/, %Q{!ruby/regexp "\\1"})
|
38
38
|
return YAML.load(value)
|
39
39
|
end
|
40
40
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whoops
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Daniel Higginbotham
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-09 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -251,9 +251,11 @@ files:
|
|
251
251
|
- app/helpers/events_helper.rb
|
252
252
|
- app/helpers/notifications_helper.rb
|
253
253
|
- app/lib/field_names.rb
|
254
|
+
- app/mailers/whoops/notification_mailer.rb
|
254
255
|
- app/models/whoops/event.rb
|
255
256
|
- app/models/whoops/event_group.rb
|
256
257
|
- app/models/whoops/filter.rb
|
258
|
+
- app/models/whoops/notification_rule.rb
|
257
259
|
- app/models/whoops/search_parser.rb
|
258
260
|
- app/views/event_groups/_list.html.haml
|
259
261
|
- app/views/event_groups/index.html.haml
|
@@ -318,7 +320,7 @@ files:
|
|
318
320
|
- MIT-LICENSE
|
319
321
|
- Rakefile
|
320
322
|
- Gemfile
|
321
|
-
- README.
|
323
|
+
- README.asciidoc
|
322
324
|
has_rdoc: true
|
323
325
|
homepage:
|
324
326
|
licenses: []
|
data/README.rdoc
DELETED