rackamole 0.1.0 → 0.1.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.
- data/HISTORY +8 -0
- data/README.rdoc +20 -5
- data/lib/rackamole.rb +1 -1
- data/lib/rackamole/mole.rb +1 -1
- data/lib/rackamole/store/mongo_db.rb +37 -9
- data/samples/sinatra/moled.rb +13 -9
- data/spec/rackamole/alert/emole_spec.rb +4 -4
- data/spec/rackamole/store/mongo_db_spec.rb +19 -7
- metadata +3 -2
data/HISTORY
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
0.0.1 - 0.1.0
|
2
|
+
* Initial drop and bug fixes. Not that interesting...
|
3
|
+
|
4
|
+
0.1.1
|
5
|
+
* Updated mongo store strategy
|
6
|
+
* Tossed out mongo mapper. Trying to stay closer to the metal
|
7
|
+
* Shortened col names for saving space. Unfortunately lame but necessary
|
8
|
+
* Moved user info into separate collection.
|
data/README.rdoc
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
== RackAMole
|
2
|
-
|
2
|
+
Observe your web applications in the wild!
|
3
3
|
|
4
4
|
== DESCRIPTION:
|
5
5
|
|
@@ -27,7 +27,7 @@ interactions and leverage these findings for the next iteration of your applicat
|
|
27
27
|
|
28
28
|
== FEATURES:
|
29
29
|
|
30
|
-
* Monitors Rails
|
30
|
+
* Monitors any rack based framework such as Rails and Sinatra
|
31
31
|
* Captures the essence of the request as well as user information
|
32
32
|
* Tracks performance issues based on your latency threshold
|
33
33
|
* Tracks exceptions that might occurred during a request
|
@@ -36,14 +36,13 @@ interactions and leverage these findings for the next iteration of your applicat
|
|
36
36
|
|
37
37
|
* Logging
|
38
38
|
* Hitimes
|
39
|
-
* MongoDb
|
39
|
+
* MongoDb + mongo ruby adapter
|
40
40
|
|
41
41
|
== INSTALL:
|
42
42
|
|
43
43
|
* sudo gem install rackamole
|
44
44
|
|
45
|
-
NOTE: The gem is hosted on gemcutter.
|
46
|
-
already specified
|
45
|
+
NOTE: The gem is hosted on gemcutter.org
|
47
46
|
|
48
47
|
== USAGE:
|
49
48
|
|
@@ -78,6 +77,22 @@ interactions and leverage these findings for the next iteration of your applicat
|
|
78
77
|
This assumes that you have session enabled to identify a user if not the mole will log the user
|
79
78
|
as 'Unknown'
|
80
79
|
|
80
|
+
=== Storing moled information
|
81
|
+
|
82
|
+
Rackamole currently comes with a single storage strategy. More will come in the near future, but
|
83
|
+
currently we are using MongoDb as our default storage. The idea here is to create a database for
|
84
|
+
a given moled app per environment. For instance, for application 'Fred', you will need to use a
|
85
|
+
separate store for Fred running in alpha mode and Fred running in production mode.
|
86
|
+
|
87
|
+
In order to use a store, you will need to pass in the :store option. There currently 2 store
|
88
|
+
types a logger and a mongo adapter. By default the store is set to log moled information to the console.
|
89
|
+
To change to a mongo store simply add the following options:
|
90
|
+
|
91
|
+
use Rack::Mole, { :app_name => "Fred", :store => Rackamole::Store::MongoDb.new( :database => 'mole_fred_alpha_mdb' ) }
|
92
|
+
|
93
|
+
This expect a local mongo instance to be running on the default port. You can change the
|
94
|
+
location by adding :host and :port options.
|
95
|
+
|
81
96
|
== LICENSE:
|
82
97
|
|
83
98
|
(The MIT License)
|
data/lib/rackamole.rb
CHANGED
data/lib/rackamole/mole.rb
CHANGED
@@ -22,7 +22,7 @@ module Rack
|
|
22
22
|
# :perf_threshold :: Any request taking longer than this value will get moled. Default: 10secs
|
23
23
|
# :moleable :: Enable/Disable the MOle (Default:true)
|
24
24
|
# :store :: The storage instance ie log file or mongodb [Default:stdout]
|
25
|
-
# :expiration :: Number of seconds to expiration. The mole will not keep sending alert if a particular
|
25
|
+
# :expiration :: Number of seconds to alert expiration. The mole will not keep sending alert if a particular
|
26
26
|
# mole type has been reported in the past. This threshold specifies the limit at which
|
27
27
|
# the previously sent alerts will expire and thus will be sent again.
|
28
28
|
# For instance, it might be the case that the app is consistently slow for a particular action.
|
@@ -7,7 +7,7 @@ module Rackamole
|
|
7
7
|
# Mongo adapter. Stores mole info to a mongo database.
|
8
8
|
class MongoDb
|
9
9
|
|
10
|
-
attr_reader :database, :logs, :features #:nodoc:
|
10
|
+
attr_reader :database, :logs, :features, :users #:nodoc:
|
11
11
|
|
12
12
|
# Initializes the mongo db store. MongoDb can be used as a persitent store for
|
13
13
|
# mole information. This is a preferred store for the mole as it will allow you
|
@@ -41,7 +41,7 @@ module Rackamole
|
|
41
41
|
args = arguments.clone
|
42
42
|
|
43
43
|
# dump request info to mongo
|
44
|
-
save_log( save_feature( args ), args )
|
44
|
+
save_log( save_user( args ), save_feature( args ), args )
|
45
45
|
rescue => mole_boom
|
46
46
|
$stderr.puts "MOLE STORE CRAPPED OUT -- #{mole_boom}"
|
47
47
|
$stderr.puts mole_boom.backtrace.join( "\n " )
|
@@ -54,6 +54,7 @@ module Rackamole
|
|
54
54
|
def reset!
|
55
55
|
logs.remove
|
56
56
|
features.remove
|
57
|
+
users.remove
|
57
58
|
end
|
58
59
|
|
59
60
|
def init_mongo( opts )
|
@@ -61,6 +62,7 @@ module Rackamole
|
|
61
62
|
@database = @connection.db( opts[:database] )
|
62
63
|
@features = database.collection( 'features' )
|
63
64
|
@logs = database.collection( 'logs' )
|
65
|
+
@users = database.collection( 'users' )
|
64
66
|
end
|
65
67
|
|
66
68
|
# Validates option hash.
|
@@ -77,12 +79,34 @@ module Rackamole
|
|
77
79
|
def default_options
|
78
80
|
{
|
79
81
|
:host => 'localhost',
|
80
|
-
:port =>
|
82
|
+
:port => Mongo::Connection::DEFAULT_PORT,
|
81
83
|
:database => 'mole_mdb'
|
82
84
|
}
|
83
85
|
end
|
84
86
|
|
85
|
-
# Find or create a
|
87
|
+
# Find or create a moled user...
|
88
|
+
# BOZO !! What to do if user name changed ?
|
89
|
+
def save_user( args )
|
90
|
+
user_id = args.delete( :user_id ) if args.has_key?( :user_id )
|
91
|
+
user_name = args.delete( :user_name ) if args.has_key?( :user_name )
|
92
|
+
|
93
|
+
row = {}
|
94
|
+
if user_id and user_name
|
95
|
+
row = { min_field( :user_id ) => user_id, min_field( :user_name ) => user_name }
|
96
|
+
else
|
97
|
+
row = { min_field( :user_name ) => user_name }
|
98
|
+
end
|
99
|
+
|
100
|
+
user = users.find_one( row, :fields => ['_id'] )
|
101
|
+
return user['_id'] if user
|
102
|
+
|
103
|
+
now = args[:created_at]
|
104
|
+
row[min_field(:date_id)] = "%4d%02d%02d" % [now.year, now.month, now.day]
|
105
|
+
|
106
|
+
users.save( row )
|
107
|
+
end
|
108
|
+
|
109
|
+
# Find or create a mole feature...
|
86
110
|
def save_feature( args )
|
87
111
|
app_name = args.delete( :app_name )
|
88
112
|
route_info = args.delete( :route_info )
|
@@ -99,7 +123,8 @@ module Rackamole
|
|
99
123
|
feature = features.find_one( row, :fields => ['_id'] )
|
100
124
|
return feature['_id'] if feature
|
101
125
|
|
102
|
-
|
126
|
+
now = args[:created_at]
|
127
|
+
row[min_field(:date_id)] = "%4d%02d%02d" %[now.year, now.month, now.day]
|
103
128
|
|
104
129
|
features.save( row )
|
105
130
|
end
|
@@ -107,13 +132,16 @@ module Rackamole
|
|
107
132
|
# Insert a new feature in the db
|
108
133
|
# NOTE : Using min key to reduce storage needs. I know not that great for higher level api's :-(
|
109
134
|
# also saving date and time as ints. same deal...
|
110
|
-
def save_log( feature_id, args )
|
135
|
+
def save_log( user_id, feature_id, args )
|
136
|
+
puts "Saving LOG for #{feature_id} -- #{user_id}"
|
137
|
+
puts caller.inspect
|
111
138
|
now = args.delete( :created_at )
|
112
139
|
row = {
|
113
140
|
min_field( :type ) => args[:type],
|
114
|
-
min_field( :feature_id ) => feature_id
|
115
|
-
min_field( :
|
116
|
-
min_field( :
|
141
|
+
min_field( :feature_id ) => feature_id,
|
142
|
+
min_field( :user_id ) => user_id,
|
143
|
+
min_field( :date_id ) => "%4d%02d%02d" %[now.year, now.month, now.day],
|
144
|
+
min_field( :time_id ) => "%02d%02d%02d" %[now.hour, now.min, now.sec]
|
117
145
|
}
|
118
146
|
|
119
147
|
args.each do |k,v|
|
data/samples/sinatra/moled.rb
CHANGED
@@ -2,20 +2,25 @@ require 'rubygems'
|
|
2
2
|
require 'sinatra'
|
3
3
|
require 'rackamole'
|
4
4
|
|
5
|
-
set :environment, :production
|
6
5
|
|
7
|
-
configure
|
8
|
-
set :sessions,
|
6
|
+
configure do
|
7
|
+
set :sessions, true
|
8
|
+
|
9
|
+
puts "mole_sinatra_#{Sinatra::Application.environment}_mdb"
|
10
|
+
|
9
11
|
use Rack::Lint
|
10
12
|
use Rack::Session::Cookie
|
11
13
|
use Rack::Mole, {
|
12
|
-
:app_name => "Moled Franky",
|
14
|
+
:app_name => "Moled Franky",
|
15
|
+
:environment => Sinatra::Application.environment,
|
13
16
|
:log_level => :debug,
|
14
17
|
:user_key => :user_name,
|
18
|
+
# :store => Rackamole::Store::MongoDb.new( :database => "mole_sinatra_dev_mdb" ),
|
19
|
+
:store => Rackamole::Store::MongoDb.new( :database => "mole_sinatra_#{Sinatra::Application.environment}_mdb" ),
|
15
20
|
:expiration => 10,
|
16
21
|
:perf_threshold => 0.2,
|
17
22
|
:twitter => { :username => 'moled', :password => 'fernand~1', :alert_on => [Rackamole.perf, Rackamole.fault] },
|
18
|
-
:excluded_paths => [ /.+?\.css/, /.+?\.png/ ]
|
23
|
+
:excluded_paths => [ /.+?\.css/, /.+?\.js/, /.+?\.png/ ]
|
19
24
|
}
|
20
25
|
end
|
21
26
|
|
@@ -24,25 +29,24 @@ before do
|
|
24
29
|
end
|
25
30
|
|
26
31
|
get '/' do
|
27
|
-
puts "Yo"
|
28
32
|
erb :index
|
29
33
|
end
|
30
34
|
|
31
35
|
get '/normal' do
|
32
36
|
@blee = "Hello World!"
|
33
|
-
session[:
|
34
|
-
|
37
|
+
session[:normal] = "something normal"
|
35
38
|
erb :normal
|
36
39
|
end
|
37
40
|
|
38
41
|
post '/post' do
|
39
42
|
@post = params[:blee]
|
43
|
+
session[:post] = "something posted"
|
40
44
|
erb :post
|
41
45
|
end
|
42
46
|
|
43
47
|
get '/params/:id' do
|
44
48
|
@blee = params[:id]
|
45
|
-
session[:
|
49
|
+
session[:param] = "something param"
|
46
50
|
|
47
51
|
erb :params
|
48
52
|
end
|
@@ -23,8 +23,8 @@ describe Rackamole::Alert::Emole do
|
|
23
23
|
|
24
24
|
it "should send a feature email correctly" do
|
25
25
|
@expected.subject = "[M()le] (Feature) -Test@Fred- for user Fernand"
|
26
|
-
@expected.body = feature_body
|
27
|
-
Rackamole::Alert::Emole.create_alert( @from, @to, @args ).
|
26
|
+
@expected.body = feature_body
|
27
|
+
Rackamole::Alert::Emole.create_alert( @from, @to, @args ).body_port.to_s.should == @expected.body_port.to_s
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should send a perf email correctly" do
|
@@ -32,7 +32,7 @@ describe Rackamole::Alert::Emole do
|
|
32
32
|
@args[:request_time] = 10.0
|
33
33
|
@expected.subject = "[M()le] (Performance:10.0) -Test@Fred- for user Fernand"
|
34
34
|
@expected.body = perf_body
|
35
|
-
Rackamole::Alert::Emole.create_alert( @from, @to, @args ).
|
35
|
+
Rackamole::Alert::Emole.create_alert( @from, @to, @args ).body_port.to_s.should == @expected.body_port.to_s
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should send a fault email correctly" do
|
@@ -42,7 +42,7 @@ describe Rackamole::Alert::Emole do
|
|
42
42
|
@args[:params] = { :id => 10 }
|
43
43
|
@expected.subject = "[M()le] (Fault) -Test@Fred- for user Fernand"
|
44
44
|
@expected.body = fault_body
|
45
|
-
Rackamole::Alert::Emole.create_alert( @from, @to, @args ).
|
45
|
+
Rackamole::Alert::Emole.create_alert( @from, @to, @args ).body_port.to_s.should == @expected.body_port.to_s
|
46
46
|
end
|
47
47
|
|
48
48
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
|
2
|
+
require 'chronic'
|
2
3
|
|
3
4
|
describe Rackamole::Store::MongoDb do
|
4
5
|
|
5
6
|
describe "#mole" do
|
6
7
|
before( :all ) do
|
8
|
+
@now = Chronic.parse( "11/27/2009" )
|
7
9
|
@store = Rackamole::Store::MongoDb.new(
|
8
10
|
:host => 'localhost',
|
9
11
|
:port => 27017,
|
@@ -30,7 +32,7 @@ describe Rackamole::Store::MongoDb do
|
|
30
32
|
@args[:method] = 'GET'
|
31
33
|
@args[:params] = { :blee => "duh".to_json }
|
32
34
|
@args[:session] = { :fred => 10.to_json }
|
33
|
-
@args[:created_at] =
|
35
|
+
@args[:created_at] = @now.utc
|
34
36
|
end
|
35
37
|
|
36
38
|
it "should mole a context based feature correctly" do
|
@@ -46,7 +48,7 @@ describe Rackamole::Store::MongoDb do
|
|
46
48
|
|
47
49
|
log = @store.logs.find_one()
|
48
50
|
log.should_not be_nil
|
49
|
-
log['typ'].should
|
51
|
+
log['typ'].should == Rackamole.feature
|
50
52
|
log['fid'].should_not be_nil
|
51
53
|
log['par'].should == { 'blee' => 'duh'.to_json }
|
52
54
|
log['ip'].should == '1.1.1.1'
|
@@ -54,13 +56,23 @@ describe Rackamole::Store::MongoDb do
|
|
54
56
|
log['url'].should == 'http://test_me/'
|
55
57
|
log['met'].should == 'GET'
|
56
58
|
log['ses'].should == { 'fred' => '10' }
|
57
|
-
log['
|
58
|
-
log['uid'].should == 100
|
59
|
+
log['uid'].should_not be_nil
|
59
60
|
log['rti'].should == 1.0
|
60
|
-
log['did'].
|
61
|
-
log['tid'].
|
61
|
+
log['did'].should == '20091127'
|
62
|
+
log['tid'].should == '190000'
|
62
63
|
|
63
|
-
@store.features.find_one(
|
64
|
+
feature = @store.features.find_one( log['fid'] )
|
65
|
+
feature.should_not be_nil
|
66
|
+
feature['app'].should == 'Test app'
|
67
|
+
feature['env'].should == 'test'
|
68
|
+
feature['ctx'].should == '/fred'
|
69
|
+
feature['did'].should == '20091127'
|
70
|
+
|
71
|
+
user = @store.users.find_one( log['uid'] )
|
72
|
+
user.should_not be_nil
|
73
|
+
user['una'].should == "Fernand"
|
74
|
+
user['uid'].should == 100
|
75
|
+
user['did'].should == '20091127'
|
64
76
|
end
|
65
77
|
|
66
78
|
it "should mole a rails feature correctly" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rackamole
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fernand Galiana
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-12-09 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -105,6 +105,7 @@ extra_rdoc_files:
|
|
105
105
|
- samples/rails/moled/public/robots.txt
|
106
106
|
files:
|
107
107
|
- ...
|
108
|
+
- HISTORY
|
108
109
|
- README.rdoc
|
109
110
|
- Rakefile
|
110
111
|
- aaa.txt
|