Parent

Rackamole::Store::MongoDb

Mongo adapter. Stores mole info to a mongo database.

Public Class Methods

new( options={} ) click to toggle source

Initializes the mongo db store. MongoDb can be used as a persitent store for mole information. This is a preferred store for the mole as it will allow you to gather up reports based on application usage, perf or faults...

Setup rackamole to use the mongodb store as follows:

  config.middleware.use Rack::Mole, { 
    :store => Rackamole::Store::MongoDb.new( 
      :db_name  => 'mole_blee_development_mdb',
      :username => 'fernand',
      :password => 'letmein',
     ) 
  }

NOTE

To use in conjunction with Wackamole your db_name must follow the convention “mole_[app_name]_[environment]_mdb”.

Options

:host

The name of the host running the mongo server. Default: localhost

:port

The port for the mongo server instance. Default: 27017

:db_name

The name of the mole databaase. Default: mole_mdb

:username

username if the mongo db has auth setup. optional

:password

password if the mongo db has auth required. optional

    # File lib/rackamole/store/mongo_db.rb, line 39
39:       def initialize( options={} )
40:         opts = default_options.merge( options )
41:         validate_options( opts )
42:         init_mongo( opts )
43:       end

Private Class Methods

field_map() click to toggle source

Normalize all accessors to 3 chars.

     # File lib/rackamole/store/mongo_db.rb, line 213
213:         def self.field_map
214:           @field_map ||= {
215:             :env          => :env,
216:             :app_name     => :app,
217:             :context      => :ctx,
218:             :controller   => :ctl,
219:             :action       => :act,
220:             :type         => :typ,
221:             :feature_id   => :fid,
222:             :date_id      => :did,
223:             :time_id      => :tid,
224:             :user_id      => :uid,
225:             :user_name    => :una,
226:             :browser      => :bro,
227:             :machine      => :mac,
228:             :host         => :hos,
229:             :software     => :sof,
230:             :request_time => :rti,
231:             :performance  => :per,
232:             :method       => :met,
233:             :path         => :pat,
234:             :session      => :ses,
235:             :params       => :par,
236:             :ruby_version => :ver,
237:             :fault        => :msg,
238:             :stack        => :sta,
239:             :created_at   => :cro,
240:             :status       => :sts,
241:             :headers      => :hdr,
242:             :body         => :bod
243:           }
244:         end

Public Instance Methods

mole( arguments ) click to toggle source

Dump mole info to a mongo database. There are actually 2 collections for mole information. Namely features and logs. The features collection hold application and feature information and is referenced in the mole log. The logs collections holds all information that was gathered during the request such as user, params, session, request time, etc...

    # File lib/rackamole/store/mongo_db.rb, line 60
60:       def mole( arguments )
61:         return if arguments.empty?       
62:         
63:         unless @connection
64:           init_mongo( :host => host, :port => port, :db_name => db_name )
65:         end
66:         
67:         # get a dup of the args since will mock with the original
68:         args = arguments.clone
69: 
70:         # dump request info to mongo
71:         save_log( save_user( args ), save_feature( args ), args )
72:       rescue => mole_boom
73:         $stderr.puts "MOLE STORE CRAPPED OUT -- #{mole_boom}"
74:         $stderr.puts mole_boom.backtrace.join( "\n   " )        
75:       end
to_yaml( opts={} ) click to toggle source
    # File lib/rackamole/store/mongo_db.rb, line 45
45:       def to_yaml( opts={} )
46:         YAML::quick_emit( object_id, opts ) do |out|
47:           out.map( taguri, to_yaml_style ) do |map|
48:             map.add( :host    , host )
49:             map.add( :port    , port )
50:             map.add( :db_name , db_name )
51:           end
52:         end
53:       end

Private Instance Methods

check_hash( value ) click to toggle source

Check

     # File lib/rackamole/store/mongo_db.rb, line 202
202:         def check_hash( value )
203:           return value unless value.is_a?( Hash )
204:           value.keys.inject({}){ |h,k| h[ensure_valid_key(k)] = value[k];h }
205:         end
default_options() click to toggle source

Set up mongo default options ie localhost host, default mongo port and the database being mole_mdb

     # File lib/rackamole/store/mongo_db.rb, line 124
124:         def default_options
125:           {
126:              :host => 'localhost',
127:              :port => Mongo::Connection::DEFAULT_PORT
128:           }
129:         end
ensure_valid_key( key ) click to toggle source

Check for invalid key format - ie something that will choke mongo case a.b.c => a_b_c

     # File lib/rackamole/store/mongo_db.rb, line 197
197:         def ensure_valid_key( key )
198:           key.to_s.index( /\./ ) ? key.to_s.gsub( /\./, '_' ) : key
199:         end
init_mongo( opts ) click to toggle source
     # File lib/rackamole/store/mongo_db.rb, line 87
 87:         def init_mongo( opts )
 88:           @host       = opts[:host]
 89:           @port       = opts[:port]
 90:           @db_name    = opts[:db_name]
 91:           
 92:           @connection = Mongo::Connection.new( @host, @port, :logger => opts[:logger] )          
 93:           @database   = @connection.db( @db_name )
 94:           
 95:           if opts[:username] and opts[:password]
 96:             authenticated = @database.authenticate( opts[:username], opts[:password] )
 97:             raise "Authentication failed for database #{@db_name}. Please check your credentials and try again" unless authenticated
 98:           end
 99:           
100:           @features = database.collection( 'features' )
101:           @logs     = database.collection( 'logs' )
102:           @users    = database.collection( 'users' )
103:         end
min_field( field ) click to toggle source

For storage reason minify the json to save space...

     # File lib/rackamole/store/mongo_db.rb, line 208
208:         def min_field( field )
209:           Rackamole::Store::MongoDb.field_map[field] || field
210:         end
reset!() click to toggle source

Clear out mole database content ( Careful there - testing only! )

    # File lib/rackamole/store/mongo_db.rb, line 81
81:         def reset!
82:           logs.remove
83:           features.remove
84:           users.remove
85:         end
save_feature( args ) click to toggle source

Find or create a mole feature...

     # File lib/rackamole/store/mongo_db.rb, line 154
154:         def save_feature( args )
155:           app_name    = args.delete( :app_name )
156:           route_info  = args.delete( :route_info )
157:           environment = args.delete( :environment )
158:         
159:           row = { min_field(:app_name) => app_name, min_field(:env) => environment.to_s }
160:           if route_info
161:             row[min_field(:controller)] = route_info[:controller]
162:             row[min_field(:action)]     = route_info[:action]
163:           else
164:             row[min_field(:context)] = args.delete( :path )
165:           end
166:           
167:           feature = features.find_one( row, :fields => ['_id'] )
168:           return feature['_id'] if feature
169: 
170:           now = args[:created_at]
171:           row[min_field(:date_id)] = "%4d%02d%02d" %[now.year, now.month, now.day]
172:                     
173:           features.save( row )
174:         end
save_log( user_id, feature_id, args ) click to toggle source

Insert a new feature in the db NOTE : Using min key to reduce storage needs. I know not that great for higher level api’s :-( also saving date and time as ints. same deal...

     # File lib/rackamole/store/mongo_db.rb, line 179
179:         def save_log( user_id, feature_id, args )
180:           now = args.delete( :created_at )
181:           row = {
182:             min_field( :type )       => args[:type],
183:             min_field( :feature_id ) => feature_id,
184:             min_field( :user_id )    => user_id,
185:             min_field( :date_id )    => "%4d%02d%02d" %[now.year, now.month, now.day],
186:             min_field( :time_id )    => "%02d%02d%02d" %[now.hour, now.min, now.sec]
187:           }
188:           
189:           args.each do |k,v|
190:             row[min_field(k)] = check_hash( v ) if v
191:           end
192:           logs.save( row )
193:         end
save_user( args ) click to toggle source

Find or create a moled user... BOZO !! What to do if user name changed ?

     # File lib/rackamole/store/mongo_db.rb, line 133
133:         def save_user( args )
134:           user_id   = args.delete( :user_id ) if args.has_key?( :user_id )
135:           user_name = args.delete( :user_name ) if args.has_key?( :user_name )
136:         
137:           row = {}
138:           if user_id and user_name
139:             row = { min_field( :user_id ) => user_id, min_field( :user_name ) => user_name }
140:           else
141:             row = { min_field( :user_name ) => user_name }
142:           end
143:                     
144:           user = users.find_one( row, :fields => ['_id'] )
145:           return user['_id'] if user
146: 
147:           now = args[:created_at]
148:           row[min_field(:date_id)] = "%4d%02d%02d" % [now.year, now.month, now.day]
149:                     
150:           users.save( row )
151:         end
validate_options( opts ) click to toggle source

Validates option hash.

     # File lib/rackamole/store/mongo_db.rb, line 106
106:         def validate_options( opts )     
107:           ]host port db_name].each do |option|
108:             unless opts[option.to_sym]
109:               raise "[MOle] Mongo store configuration error -- You must specify a value for option `:#{option}" 
110:             end
111:           end
112:           # check for auth
113:           if opts[:username]
114:             %(username password).each do |option|
115:               unless opts[option.to_sym]
116:                 raise "[MOle] Mongo store configuration error -- You must specify a value for auth option `:#{option}" 
117:               end
118:             end
119:           end
120:         end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.