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 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