mongodb_logger 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.rvmrc +1 -1
  2. data/.travis.yml +13 -7
  3. data/Gemfile +1 -7
  4. data/README.md +128 -117
  5. data/Rakefile +11 -40
  6. data/SUPPORTED_RAILS_VERSIONS +3 -1
  7. data/app/assets/javascripts/analytics.js.coffee +66 -0
  8. data/app/assets/javascripts/logs.js.coffee +107 -164
  9. data/app/assets/javascripts/mongodb_logger.js +11 -2
  10. data/app/assets/javascripts/vendors/jquery-1.8.3.min.js +2 -0
  11. data/app/assets/javascripts/vendors/jquery-ui-1.9.2.min.js +6 -0
  12. data/app/assets/javascripts/vendors/jquery.pjax.min.js +13 -6
  13. data/app/assets/javascripts/vendors/rickshaw/d3.layout.min.js +1 -0
  14. data/app/assets/javascripts/vendors/rickshaw/d3.min.js +2 -0
  15. data/app/assets/javascripts/vendors/rickshaw/rickshaw.js +2637 -0
  16. data/app/assets/stylesheets/humanity/{jquery-ui-1.8.16.custom.css → jquery-ui-1.9.2.custom.css} +0 -0
  17. data/app/assets/stylesheets/layout.css +1 -1
  18. data/app/assets/stylesheets/library.css.erb +2 -2
  19. data/app/assets/stylesheets/mongodb_logger.css +2 -1
  20. data/app/assets/stylesheets/rickshaw/rickshaw.css +307 -0
  21. data/bin/mongodb_logger_web +1 -2
  22. data/config.ru +8 -1
  23. data/examples/server_config.yml +1 -2
  24. data/features/mongodb_logger_web.feature +1 -1
  25. data/features/step_definitions/mongodb_logger_web_steps.rb +18 -12
  26. data/lib/mongodb_logger.rb +6 -2
  27. data/lib/mongodb_logger/adapters.rb +3 -0
  28. data/lib/mongodb_logger/adapters/base.rb +45 -0
  29. data/lib/mongodb_logger/adapters/mongo.rb +91 -0
  30. data/lib/mongodb_logger/adapters/moped.rb +95 -0
  31. data/lib/mongodb_logger/logger.rb +39 -71
  32. data/lib/mongodb_logger/replica_set_helper.rb +11 -2
  33. data/lib/mongodb_logger/server.rb +15 -36
  34. data/lib/mongodb_logger/server/model/analytic.rb +54 -37
  35. data/lib/mongodb_logger/server/view_helpers.rb +5 -1
  36. data/lib/mongodb_logger/server/views/analytics.erb +8 -7
  37. data/lib/mongodb_logger/server/views/layout.erb +4 -11
  38. data/lib/mongodb_logger/server/views/overview.erb +6 -6
  39. data/lib/mongodb_logger/server/views/shared/_collection_stats.erb +4 -4
  40. data/lib/mongodb_logger/server/views/shared/_dynamic_filter.erb +1 -1
  41. data/lib/mongodb_logger/server/views/shared/_log_info.erb +1 -1
  42. data/lib/mongodb_logger/server/views/shared/_tabs.erb +2 -2
  43. data/lib/mongodb_logger/server/views/shared/_tail_panel.erb +4 -4
  44. data/lib/mongodb_logger/server/views/shared/_top_panel.erb +1 -1
  45. data/lib/mongodb_logger/server/views/show_log.erb +11 -1
  46. data/lib/mongodb_logger/server_config.rb +17 -66
  47. data/lib/mongodb_logger/version.rb +1 -1
  48. data/mongodb_logger.gemspec +19 -20
  49. data/spec/javascripts/MongodbLoggerMainSpec.js +2 -2
  50. data/spec/javascripts/support/jasmine.yml +5 -5
  51. data/test/Gemfile_tests +2 -1
  52. data/test/config/samples/database.yml +3 -1
  53. data/test/config/samples/database_no_file_logging.yml +3 -1
  54. data/test/shoulda_macros/log_macros.rb +1 -1
  55. data/test/test.sh +5 -5
  56. data/test/test_helper.rb +26 -18
  57. data/test/unit/mongodb_logger_test.rb +21 -20
  58. metadata +70 -88
  59. data/app/assets/javascripts/vendors/jquery-1.7.1.min.js +0 -4
  60. data/app/assets/javascripts/vendors/jquery-ui-1.8.16.min.js +0 -791
  61. data/mongodb_logger.java.gemspec +0 -43
@@ -1,6 +1,5 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
- require 'mongo'
4
3
  require 'mongodb_logger/config'
5
4
  require 'mongodb_logger/logger'
6
5
  require 'mongodb_logger/railtie' if defined?(Rails::Railtie)
@@ -21,6 +20,10 @@ module MongodbLogger
21
20
  when request.respond_to?(:filtered_parameters) then request.filtered_parameters
22
21
  else params
23
22
  end
23
+ f_session = case
24
+ when request.respond_to?(:session) then request.session
25
+ else session
26
+ end
24
27
  Rails.logger.mongoize({
25
28
  :method => request.method,
26
29
  :action => action_name,
@@ -28,8 +31,9 @@ module MongodbLogger
28
31
  :path => request.path,
29
32
  :url => request.url,
30
33
  :params => f_params,
34
+ :session => f_session,
31
35
  :ip => request.remote_ip
32
36
  }) { yield }
33
37
  end
34
38
  end
35
- end
39
+ end
@@ -0,0 +1,3 @@
1
+ require 'mongodb_logger/adapters/base'
2
+ require 'mongodb_logger/adapters/mongo'
3
+ require 'mongodb_logger/adapters/moped'
@@ -0,0 +1,45 @@
1
+ module MongodbLogger
2
+ module Adapers
3
+ class Base
4
+
5
+ attr_reader :configuration, :connection, :connection_type, :collection, :authenticated
6
+
7
+ def collection_name
8
+ @configuration['collection']
9
+ end
10
+
11
+ def authenticated?
12
+ @authenticated
13
+ end
14
+
15
+ def check_for_collection
16
+ # setup the capped collection if it doesn't already exist
17
+ create_collection unless @connection.collection_names.include?(@configuration['collection'])
18
+ @collection = @connection[@configuration['collection']]
19
+ end
20
+
21
+ def reset_collection
22
+ if @connection && @collection
23
+ @collection.drop
24
+ create_collection
25
+ end
26
+ end
27
+
28
+ def collection_stats_hash(stats)
29
+ {
30
+ :is_capped => (stats["capped"] && ([1, true].include?(stats["capped"]))),
31
+ :count => stats["count"].to_i,
32
+ :size => stats["size"].to_f,
33
+ :storageSize => stats["storageSize"].to_f,
34
+ :db_name => @configuration["database"],
35
+ :collection => collection_name
36
+ }
37
+ end
38
+
39
+ def create_collection
40
+ raise "Not implemented"
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,91 @@
1
+ module MongodbLogger
2
+ module Adapers
3
+ class Mongo < Base
4
+
5
+ def initialize(options = {})
6
+ @authenticated = false
7
+ @configuration = options
8
+ if @configuration['url']
9
+ uri = URI.parse(@configuration['url'])
10
+ @configuration['database'] = uri.path.gsub(/^\//, '')
11
+ @connection ||= mongo_connection_object.db(@configuration['database'])
12
+ @authenticated = true
13
+ else
14
+ @connection ||= mongo_connection_object.db(@configuration['database'])
15
+ if @configuration['username'] && @configuration['password']
16
+ # the driver stores credentials in case reconnection is required
17
+ @authenticated = @connection.authenticate(@configuration['username'],
18
+ @configuration['password'])
19
+ end
20
+ end
21
+ end
22
+
23
+ def create_collection
24
+ @connection.create_collection(collection_name,
25
+ {:capped => true, :size => @configuration['capsize'].to_i})
26
+ end
27
+
28
+ def insert_log_record(record, options = {})
29
+ @collection.insert(record, options[:write_options])
30
+ end
31
+
32
+ def collection_stats
33
+ collection_stats_hash(@collection.stats)
34
+ end
35
+
36
+ # filter
37
+ def filter_by_conditions(filter)
38
+ @collection.find(filter.get_mongo_conditions).sort('$natural', -1).limit(filter.get_mongo_limit)
39
+ end
40
+
41
+ def find_by_id(id)
42
+ @collection.find_one(::BSON::ObjectId(id))
43
+ end
44
+
45
+ def tail_log_from_params(params = {})
46
+ logs = []
47
+ last_id = nil
48
+ if params[:log_last_id] && !params[:log_last_id].blank?
49
+ log_last_id = params[:log_last_id]
50
+ @collection.find({'_id' => { '$gt' => ::BSON::ObjectId(log_last_id) }}).sort('$natural', -1).each do |log|
51
+ logs << log
52
+ log_last_id = log["_id"].to_s
53
+ end
54
+ logs.reverse!
55
+ else
56
+ log = @collection.find_one({}, {:sort => ['$natural', -1]})
57
+ log_last_id = log["_id"].to_s unless log.blank?
58
+ end
59
+ {
60
+ :log_last_id => log_last_id,
61
+ :time => Time.now.strftime("%F %T"),
62
+ :logs => logs
63
+ }
64
+ end
65
+
66
+ def calculate_mapreduce(map, reduce, params = {})
67
+ @collection.map_reduce(map, reduce, {:query => params[:conditions], :sort => ['$natural', -1], :out => {:inline => true}, :raw => true}).find()
68
+ end
69
+
70
+ private
71
+
72
+ def mongo_connection_object
73
+ if @configuration['hosts']
74
+ conn = ::Mongo::ReplSetConnection.new(*(@configuration['hosts'] <<
75
+ {:connect => true, :pool_timeout => 6}))
76
+ @configuration['replica_set'] = true
77
+ elsif @configuration['url']
78
+ conn = ::Mongo::Connection.from_uri(@configuration['url'])
79
+ else
80
+ conn = ::Mongo::Connection.new(@configuration['host'],
81
+ @configuration['port'],
82
+ :connect => true,
83
+ :pool_timeout => 6)
84
+ end
85
+ @connection_type = conn.class
86
+ conn
87
+ end
88
+
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,95 @@
1
+ module MongodbLogger
2
+ module Adapers
3
+ class Moped < Base
4
+
5
+ def initialize(options = {})
6
+ @configuration = options
7
+ if @configuration['url']
8
+ uri = URI.parse(@configuration['url'])
9
+ @configuration['database'] = uri.path.gsub(/^\//, '')
10
+ @connection ||= mongo_connection_object
11
+ @connection.use @configuration['database']
12
+ @authenticated = true
13
+ else
14
+ @connection ||= mongo_connection_object
15
+ @connection.use @configuration['database']
16
+ if @configuration['username'] && @configuration['password']
17
+ # the driver stores credentials in case reconnection is required
18
+ @authenticated = @connection.login(@configuration['username'],
19
+ @configuration['password'])
20
+ end
21
+ end
22
+ end
23
+
24
+ def create_collection
25
+ @connection.command(create: collection_name, capped: true, size: @configuration['capsize'].to_i)
26
+ end
27
+
28
+ def insert_log_record(record, options = {})
29
+ record[:_id] = ::Moped::BSON::ObjectId.new
30
+ @connection.with(safe: options[:write_options])[collection_name].insert(record)
31
+ end
32
+
33
+ def collection_stats
34
+ collection_stats_hash(@connection.command(collStats: collection_name))
35
+ end
36
+
37
+ # filter
38
+ def filter_by_conditions(filter)
39
+ @collection.find(filter.get_mongo_conditions).sort('$natural' => -1).limit(filter.get_mongo_limit)
40
+ end
41
+
42
+ def find_by_id(id)
43
+ @collection.find("_id" => ::Moped::BSON::ObjectId.from_string(id)).first
44
+ end
45
+
46
+ def tail_log_from_params(params = {})
47
+ logs = []
48
+ last_id = nil
49
+ if params[:log_last_id] && !params[:log_last_id].blank?
50
+ log_last_id = params[:log_last_id]
51
+ @collection.find({'_id' => { '$gt' => ::Moped::BSON::ObjectId.from_string(log_last_id) }}).sort('$natural' => -1).each do |log|
52
+ logs << log
53
+ log_last_id = log["_id"].to_s
54
+ end
55
+ logs.reverse!
56
+ else
57
+ log = @collection.find.sort('$natural' => -1).first
58
+ log_last_id = log["_id"].to_s unless log.blank?
59
+ end
60
+ {
61
+ :log_last_id => log_last_id,
62
+ :time => Time.now.strftime("%F %T"),
63
+ :logs => logs
64
+ }
65
+ end
66
+
67
+ def calculate_mapreduce(map, reduce, params = {})
68
+ @connection.command(
69
+ mapreduce: collection_name,
70
+ map: map,
71
+ reduce: reduce,
72
+ query: params[:conditions],
73
+ out: { inline: true },
74
+ raw: true
75
+ ).find()
76
+ end
77
+
78
+ private
79
+
80
+ def mongo_connection_object
81
+ if @configuration['hosts']
82
+ conn = ::Moped::Session.new(@configuration['hosts'].map{|(host,port)| "#{host}:#{port}"}, :timeout => 6)
83
+ @configuration['replica_set'] = true
84
+ elsif @configuration['url']
85
+ conn = ::Moped::Session.connect(@configuration['url'])
86
+ else
87
+ conn = ::Moped::Session.new(["#{@configuration['host']}:#{@configuration['port']}"], :timeout => 6)
88
+ end
89
+ @connection_type = conn.class
90
+ conn
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -1,10 +1,10 @@
1
1
  require 'erb'
2
2
  require 'uri'
3
- require 'mongo'
4
3
  require 'active_support'
5
4
  require 'active_support/core_ext'
6
5
  require 'active_support/core_ext/logger'
7
6
  require 'action_dispatch/http/upload'
7
+ require 'mongodb_logger/adapters'
8
8
  require 'mongodb_logger/replica_set_helper'
9
9
 
10
10
  module MongodbLogger
@@ -15,16 +15,21 @@ module MongodbLogger
15
15
  # Looks for configuration files in this order
16
16
  CONFIGURATION_FILES = ["mongodb_logger.yml", "mongoid.yml", "database.yml"]
17
17
  LOG_LEVEL_SYM = [:debug, :info, :warn, :error, :fatal, :unknown]
18
+
19
+ ADAPTERS = [
20
+ ["mongo", Adapers::Mongo],
21
+ ["moped", Adapers::Moped]
22
+ ]
18
23
 
19
- attr_reader :db_configuration, :mongo_connection, :mongo_collection_name, :mongo_collection, :mongo_connection_type
24
+ attr_reader :db_configuration, :mongo_adapter
20
25
 
21
- def initialize(options={})
26
+ def initialize(options = {})
22
27
  path = options[:path] || File.join(Rails.root, "log/#{Rails.env}.log")
23
28
  @level = options[:level] || DEBUG
24
29
  internal_initialize
25
30
  rescue => e
26
31
  # should use a config block for this
27
- Rails.env.production? ? (raise e) : (puts "MongodbLogger WARNING: Using BufferedLogger due to exception: " + e.message)
32
+ Rails.env.production? ? (raise e) : (puts "MongodbLogger WARNING: Using BufferedLogger due to exception: #{e.message}")
28
33
  ensure
29
34
  if disable_file_logging?
30
35
  @log = ::Logger.new(STDOUT)
@@ -34,9 +39,9 @@ module MongodbLogger
34
39
  end
35
40
  end
36
41
 
37
- def add_metadata(options={})
42
+ def add_metadata(options = {})
38
43
  options.each do |key, value|
39
- unless [:messages, :request_time, :ip, :runtime, :application_name, :is_exception, :params, :method].include?(key.to_sym)
44
+ unless [:messages, :request_time, :ip, :runtime, :application_name, :is_exception, :params, :session, :method].include?(key.to_sym)
40
45
  @mongo_record[key] = value
41
46
  else
42
47
  raise ArgumentError, ":#{key} is a reserved key for the mongodb logger. Please choose a different key"
@@ -55,19 +60,11 @@ module MongodbLogger
55
60
  disable_file_logging? ? message : (@level ? super : message)
56
61
  end
57
62
 
58
- # Drop the capped_collection and recreate it
59
- def reset_collection
60
- if @mongo_connection && @mongo_collection
61
- @mongo_collection.drop
62
- create_collection
63
- end
64
- end
65
-
66
- def mongoize(options={})
63
+ def mongoize(options = {})
67
64
  @mongo_record = options.merge({
68
65
  :messages => Hash.new { |hash, key| hash[key] = Array.new },
69
66
  :request_time => Time.now.getutc,
70
- :application_name => @application_name
67
+ :application_name => @db_configuration['application_name']
71
68
  })
72
69
 
73
70
  runtime = Benchmark.measure{ yield }.real if block_given?
@@ -97,12 +94,8 @@ module MongodbLogger
97
94
  end
98
95
  end
99
96
 
100
- def authenticated?
101
- @authenticated
102
- end
103
-
104
97
  private
105
- # facilitate testing
98
+
106
99
  def internal_initialize
107
100
  configure
108
101
  connect
@@ -115,26 +108,21 @@ module MongodbLogger
115
108
 
116
109
  def configure
117
110
  default_capsize = DEFAULT_COLLECTION_SIZE
118
- @authenticated = false
119
111
  @db_configuration = {
120
112
  'host' => 'localhost',
121
113
  'port' => 27017,
122
114
  'capsize' => default_capsize}.merge(resolve_config)
123
- @mongo_collection_name = @db_configuration['collection'] || "#{Rails.env}_log"
124
- @application_name = resolve_application_name
125
- @safe_insert = @db_configuration['safe_insert'] || false
115
+ @db_configuration['collection'] ||= defined?(Rails) ? "#{Rails.env}_log" : "production_log"
116
+ @db_configuration['application_name'] ||= resolve_application_name
117
+ @db_configuration['write_options'] ||= { w: 0, wtimeout: 200 }
126
118
 
127
119
  @insert_block = @db_configuration.has_key?('replica_set') && @db_configuration['replica_set'] ?
128
- lambda { rescue_connection_failure{ insert_log_record(@safe_insert) } } :
129
- lambda { insert_log_record }
120
+ lambda { rescue_connection_failure{ insert_log_record(@db_configuration['write_options']) } } :
121
+ lambda { insert_log_record(@db_configuration['write_options']) }
130
122
  end
131
123
 
132
124
  def resolve_application_name
133
- if @db_configuration.has_key?('application_name')
134
- @db_configuration['application_name']
135
- else
136
- Rails.application.class.to_s.split("::").first
137
- end
125
+ Rails.application.class.to_s.split("::").first if defined?(Rails)
138
126
  end
139
127
 
140
128
  def resolve_config
@@ -149,52 +137,32 @@ module MongodbLogger
149
137
  end
150
138
  config
151
139
  end
152
-
153
- def mongo_connection_object
154
- if @db_configuration['hosts']
155
- conn = Mongo::ReplSetConnection.new(*(@db_configuration['hosts'] <<
156
- {:connect => true, :pool_timeout => 6}))
157
- @db_configuration['replica_set'] = true
158
- elsif @db_configuration['url']
159
- conn = Mongo::Connection.from_uri(@db_configuration['url'])
160
- else
161
- conn = Mongo::Connection.new(@db_configuration['host'],
162
- @db_configuration['port'],
163
- :connect => true,
164
- :pool_timeout => 6)
165
- end
166
- @mongo_connection_type = conn.class
167
- conn
168
- end
169
-
170
- def connect
171
- if @db_configuration['url']
172
- uri = URI.parse(@db_configuration['url'])
173
- @mongo_connection ||= mongo_connection_object.db(uri.path.gsub(/^\//, ''))
174
- @authenticated = true
175
- else
176
- @mongo_connection ||= mongo_connection_object.db(@db_configuration['database'])
177
- if @db_configuration['username'] && @db_configuration['password']
178
- # the driver stores credentials in case reconnection is required
179
- @authenticated = @mongo_connection.authenticate(@db_configuration['username'],
180
- @db_configuration['password'])
140
+
141
+ def find_adapter
142
+ ADAPTERS.each do |(library, adapter)|
143
+ begin
144
+ require library
145
+ return adapter
146
+ rescue LoadError
147
+ next
181
148
  end
182
149
  end
150
+ return nil
183
151
  end
184
152
 
185
- def create_collection
186
- @mongo_connection.create_collection(@mongo_collection_name,
187
- {:capped => true, :size => @db_configuration['capsize'].to_i})
153
+ def connect
154
+ adapter = find_adapter
155
+ raise "!!! MongodbLogger not found supported adapter. Please, add mongo with bson_ext gems or moped gem into Gemfile !!!" if adapter.nil?
156
+ @mongo_adapter ||= adapter.new(@db_configuration)
157
+ @db_configuration = @mongo_adapter.configuration
188
158
  end
189
159
 
190
160
  def check_for_collection
191
- # setup the capped collection if it doesn't already exist
192
- create_collection unless @mongo_connection.collection_names.include?(@mongo_collection_name)
193
- @mongo_collection = @mongo_connection[@mongo_collection_name]
161
+ @mongo_adapter.check_for_collection
194
162
  end
195
163
 
196
- def insert_log_record(safe = false)
197
- @mongo_collection.insert(@mongo_record, :safe => safe)
164
+ def insert_log_record(write_options)
165
+ @mongo_adapter.insert_log_record(@mongo_record, write_options: write_options)
198
166
  end
199
167
 
200
168
  def logging_colorized?
@@ -228,8 +196,8 @@ module MongodbLogger
228
196
  data.map{|v| nice_serialize_object(v) }
229
197
  when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile # uploaded files
230
198
  hvalues = {
231
- :original_filename => data.original_filename,
232
- :content_type => data.content_type
199
+ original_filename: data.original_filename,
200
+ content_type: data.content_type
233
201
  }
234
202
  else
235
203
  data.inspect