rackamole 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
- Your web application observer...
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 or Sinatra applications
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.com - please update your gem sources if not
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
@@ -1,7 +1,7 @@
1
1
  module Rackamole
2
2
 
3
3
  # :stopdoc:
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
6
6
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
7
7
  # :startdoc:
@@ -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 => 27017,
82
+ :port => Mongo::Connection::DEFAULT_PORT,
81
83
  :database => 'mole_mdb'
82
84
  }
83
85
  end
84
86
 
85
- # Find or create a mole feature
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
- row[min_field(:created_at)] = args[:created_at]
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.to_s,
115
- min_field( :date_id ) => ("%4d%02d%02d" %[now.year, now.month, now.day]).to_i,
116
- min_field( :time_id ) => ("%02d%02d%02d" %[now.hour, now.min, now.sec] ).to_i
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|
@@ -2,20 +2,25 @@ require 'rubygems'
2
2
  require 'sinatra'
3
3
  require 'rackamole'
4
4
 
5
- set :environment, :production
6
5
 
7
- configure :production do
8
- set :sessions, true
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[:fred] = "oh dear"
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[:blee] = "something interesting"
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 ).encoded.should == @expected.encoded
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 ).encoded.should == @expected.encoded
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 ).encoded.should == @expected.encoded
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] = Time.now.utc
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 == Rackamole.feature
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['una'].should == 'Fernand'
58
- log['uid'].should == 100
59
+ log['uid'].should_not be_nil
59
60
  log['rti'].should == 1.0
60
- log['did'].should_not be_nil
61
- log['tid'].should_not be_nil
61
+ log['did'].should == '20091127'
62
+ log['tid'].should == '190000'
62
63
 
63
- @store.features.find_one( Mongo::ObjectID.from_string( log['fid'] ) )['app'].should == 'Test app'
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.0
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-11-28 00:00:00 -07:00
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