mongodb_logger 0.3.3 → 0.4.0

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