mongo 1.10.0-java

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 (116) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/LICENSE +190 -0
  5. data/README.md +149 -0
  6. data/Rakefile +31 -0
  7. data/VERSION +1 -0
  8. data/bin/mongo_console +43 -0
  9. data/ext/jsasl/target/jsasl.jar +0 -0
  10. data/lib/mongo.rb +90 -0
  11. data/lib/mongo/bulk_write_collection_view.rb +380 -0
  12. data/lib/mongo/collection.rb +1164 -0
  13. data/lib/mongo/collection_writer.rb +364 -0
  14. data/lib/mongo/connection.rb +19 -0
  15. data/lib/mongo/connection/node.rb +239 -0
  16. data/lib/mongo/connection/pool.rb +347 -0
  17. data/lib/mongo/connection/pool_manager.rb +325 -0
  18. data/lib/mongo/connection/sharding_pool_manager.rb +67 -0
  19. data/lib/mongo/connection/socket.rb +18 -0
  20. data/lib/mongo/connection/socket/socket_util.rb +37 -0
  21. data/lib/mongo/connection/socket/ssl_socket.rb +95 -0
  22. data/lib/mongo/connection/socket/tcp_socket.rb +86 -0
  23. data/lib/mongo/connection/socket/unix_socket.rb +39 -0
  24. data/lib/mongo/cursor.rb +719 -0
  25. data/lib/mongo/db.rb +735 -0
  26. data/lib/mongo/exception.rb +88 -0
  27. data/lib/mongo/functional.rb +21 -0
  28. data/lib/mongo/functional/authentication.rb +318 -0
  29. data/lib/mongo/functional/logging.rb +85 -0
  30. data/lib/mongo/functional/read_preference.rb +174 -0
  31. data/lib/mongo/functional/sasl_java.rb +48 -0
  32. data/lib/mongo/functional/uri_parser.rb +374 -0
  33. data/lib/mongo/functional/write_concern.rb +66 -0
  34. data/lib/mongo/gridfs.rb +18 -0
  35. data/lib/mongo/gridfs/grid.rb +112 -0
  36. data/lib/mongo/gridfs/grid_ext.rb +53 -0
  37. data/lib/mongo/gridfs/grid_file_system.rb +163 -0
  38. data/lib/mongo/gridfs/grid_io.rb +484 -0
  39. data/lib/mongo/legacy.rb +140 -0
  40. data/lib/mongo/mongo_client.rb +702 -0
  41. data/lib/mongo/mongo_replica_set_client.rb +523 -0
  42. data/lib/mongo/mongo_sharded_client.rb +159 -0
  43. data/lib/mongo/networking.rb +370 -0
  44. data/lib/mongo/utils.rb +19 -0
  45. data/lib/mongo/utils/conversions.rb +110 -0
  46. data/lib/mongo/utils/core_ext.rb +70 -0
  47. data/lib/mongo/utils/server_version.rb +69 -0
  48. data/lib/mongo/utils/support.rb +80 -0
  49. data/lib/mongo/utils/thread_local_variable_manager.rb +25 -0
  50. data/mongo.gemspec +36 -0
  51. data/test/functional/authentication_test.rb +35 -0
  52. data/test/functional/bulk_api_stress_test.rb +133 -0
  53. data/test/functional/bulk_write_collection_view_test.rb +1129 -0
  54. data/test/functional/client_test.rb +565 -0
  55. data/test/functional/collection_test.rb +2073 -0
  56. data/test/functional/collection_writer_test.rb +83 -0
  57. data/test/functional/conversions_test.rb +163 -0
  58. data/test/functional/cursor_fail_test.rb +63 -0
  59. data/test/functional/cursor_message_test.rb +57 -0
  60. data/test/functional/cursor_test.rb +625 -0
  61. data/test/functional/db_api_test.rb +819 -0
  62. data/test/functional/db_connection_test.rb +27 -0
  63. data/test/functional/db_test.rb +344 -0
  64. data/test/functional/grid_file_system_test.rb +285 -0
  65. data/test/functional/grid_io_test.rb +252 -0
  66. data/test/functional/grid_test.rb +273 -0
  67. data/test/functional/pool_test.rb +62 -0
  68. data/test/functional/safe_test.rb +98 -0
  69. data/test/functional/ssl_test.rb +29 -0
  70. data/test/functional/support_test.rb +62 -0
  71. data/test/functional/timeout_test.rb +58 -0
  72. data/test/functional/uri_test.rb +330 -0
  73. data/test/functional/write_concern_test.rb +118 -0
  74. data/test/helpers/general.rb +50 -0
  75. data/test/helpers/test_unit.rb +317 -0
  76. data/test/replica_set/authentication_test.rb +35 -0
  77. data/test/replica_set/basic_test.rb +174 -0
  78. data/test/replica_set/client_test.rb +341 -0
  79. data/test/replica_set/complex_connect_test.rb +77 -0
  80. data/test/replica_set/connection_test.rb +138 -0
  81. data/test/replica_set/count_test.rb +64 -0
  82. data/test/replica_set/cursor_test.rb +212 -0
  83. data/test/replica_set/insert_test.rb +140 -0
  84. data/test/replica_set/max_values_test.rb +145 -0
  85. data/test/replica_set/pinning_test.rb +55 -0
  86. data/test/replica_set/query_test.rb +73 -0
  87. data/test/replica_set/read_preference_test.rb +214 -0
  88. data/test/replica_set/refresh_test.rb +175 -0
  89. data/test/replica_set/replication_ack_test.rb +94 -0
  90. data/test/replica_set/ssl_test.rb +32 -0
  91. data/test/sharded_cluster/basic_test.rb +197 -0
  92. data/test/shared/authentication/basic_auth_shared.rb +286 -0
  93. data/test/shared/authentication/bulk_api_auth_shared.rb +259 -0
  94. data/test/shared/authentication/gssapi_shared.rb +164 -0
  95. data/test/shared/authentication/sasl_plain_shared.rb +96 -0
  96. data/test/shared/ssl_shared.rb +235 -0
  97. data/test/test_helper.rb +56 -0
  98. data/test/threading/basic_test.rb +120 -0
  99. data/test/tools/mongo_config.rb +608 -0
  100. data/test/tools/mongo_config_test.rb +160 -0
  101. data/test/unit/client_test.rb +347 -0
  102. data/test/unit/collection_test.rb +166 -0
  103. data/test/unit/connection_test.rb +325 -0
  104. data/test/unit/cursor_test.rb +299 -0
  105. data/test/unit/db_test.rb +136 -0
  106. data/test/unit/grid_test.rb +76 -0
  107. data/test/unit/mongo_sharded_client_test.rb +48 -0
  108. data/test/unit/node_test.rb +93 -0
  109. data/test/unit/pool_manager_test.rb +142 -0
  110. data/test/unit/read_pref_test.rb +115 -0
  111. data/test/unit/read_test.rb +159 -0
  112. data/test/unit/safe_test.rb +158 -0
  113. data/test/unit/sharding_pool_manager_test.rb +84 -0
  114. data/test/unit/write_concern_test.rb +175 -0
  115. metadata +260 -0
  116. metadata.gz.sig +0 -0
@@ -0,0 +1,88 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ # Generic Mongo Ruby Driver exception class.
17
+ class MongoRubyError < StandardError; end
18
+
19
+ # Raised when MongoDB itself has returned an error.
20
+ class MongoDBError < RuntimeError
21
+
22
+ # @return The entire failed command's response object, if available.
23
+ attr_reader :result
24
+
25
+ # @return The failed command's error code, if availab.e
26
+ attr_reader :error_code
27
+
28
+ def initialize(message=nil, error_code=nil, result=nil)
29
+ @error_code = error_code
30
+ @result = result
31
+ super(message)
32
+ end
33
+ end
34
+
35
+ # Raised on fatal errors to GridFS.
36
+ class GridError < MongoRubyError; end
37
+
38
+ # Raised on fatal errors to GridFS.
39
+ class GridFileNotFound < GridError; end
40
+
41
+ # Raised on fatal errors to GridFS.
42
+ class GridMD5Failure < GridError; end
43
+
44
+ # Raised when invalid arguments are sent to Mongo Ruby methods.
45
+ class MongoArgumentError < MongoRubyError; end
46
+
47
+ # Raised on failures in connection to the database server.
48
+ class ConnectionError < MongoRubyError; end
49
+
50
+ # Raised on failures in connection to the database server.
51
+ class ReplicaSetConnectionError < ConnectionError; end
52
+
53
+ # Raised on failures in connection to the database server.
54
+ class ConnectionTimeoutError < MongoRubyError; end
55
+
56
+ # Raised when no tags in a read preference maps to a given connection.
57
+ class NodeWithTagsNotFound < MongoRubyError; end
58
+
59
+ # Raised when a connection operation fails.
60
+ class ConnectionFailure < MongoDBError; end
61
+
62
+ # Raised when authentication fails.
63
+ class AuthenticationError < MongoDBError; end
64
+
65
+ # Raised when a database operation fails.
66
+ class OperationFailure < MongoDBError; end
67
+
68
+ # Raised when a database operation exceeds maximum specified time.
69
+ class ExecutionTimeout < OperationFailure; end
70
+
71
+ # Raised when a database operation has a write concern error.
72
+ class WriteConcernError < OperationFailure; end
73
+
74
+ # Raised when a socket read operation times out.
75
+ class OperationTimeout < SocketError; end
76
+
77
+ # Raised when a client attempts to perform an invalid operation.
78
+ class InvalidOperation < MongoDBError; end
79
+
80
+ # Raised when an invalid collection or database name is used (invalid namespace name).
81
+ class InvalidNSName < RuntimeError; end
82
+
83
+ # Raised when the client supplies an invalid value to sort by.
84
+ class InvalidSortValueError < MongoRubyError; end
85
+
86
+ # Raised for bulk write errors.
87
+ class BulkWriteError < OperationFailure; end
88
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'mongo/functional/authentication'
16
+ require 'mongo/functional/logging'
17
+ require 'mongo/functional/read_preference'
18
+ require 'mongo/functional/write_concern'
19
+ require 'mongo/functional/uri_parser'
20
+
21
+ require 'mongo/functional/sasl_java' if RUBY_PLATFORM =~ /java/
@@ -0,0 +1,318 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'digest/md5'
16
+
17
+ module Mongo
18
+ module Authentication
19
+
20
+ DEFAULT_MECHANISM = 'MONGODB-CR'
21
+ MECHANISMS = ['GSSAPI', 'MONGODB-CR', 'MONGODB-X509', 'PLAIN']
22
+ EXTRA = { 'GSSAPI' => [:gssapi_service_name, :canonicalize_host_name] }
23
+
24
+ # authentication module methods
25
+ class << self
26
+ # Helper to validate an authentication mechanism and optionally
27
+ # raise an error if invalid.
28
+ #
29
+ # @param mechanism [String] [description]
30
+ # @param raise_error [Boolean] [description]
31
+ #
32
+ # @raise [ArgumentError] if raise_error and not a valid auth mechanism.
33
+ # @return [Boolean] returns the validation result.
34
+ def validate_mechanism(mechanism, raise_error=false)
35
+ return true if MECHANISMS.include?(mechanism.upcase)
36
+ if raise_error
37
+ raise ArgumentError,
38
+ "Invalid authentication mechanism provided. Must be one of " +
39
+ "#{Mongo::Authentication::MECHANISMS.join(', ')}."
40
+ end
41
+ false
42
+ end
43
+
44
+
45
+ # Helper to validate and normalize credential sets.
46
+ #
47
+ # @param auth [Hash] A hash containing the credential set.
48
+ #
49
+ # @raise [MongoArgumentError] if the credential set is invalid.
50
+ # @return [Hash] The validated credential set.
51
+ def validate_credentials(auth)
52
+ # set the default auth mechanism if not defined
53
+ auth[:mechanism] ||= DEFAULT_MECHANISM
54
+
55
+ # set the default auth source if not defined
56
+ auth[:source] = auth[:source] || auth[:db_name] || 'admin'
57
+
58
+ if (auth[:mechanism] == 'MONGODB-CR' || auth[:mechanism] == 'PLAIN') && !auth[:password]
59
+ raise MongoArgumentError,
60
+ "When using the authentication mechanism #{auth[:mechanism]} " +
61
+ "both username and password are required."
62
+ end
63
+ # if extra opts exist, validate them
64
+ allowed_keys = EXTRA[auth[:mechanism]]
65
+ if auth[:extra] && !auth[:extra].empty?
66
+ invalid_opts = []
67
+ auth[:extra].keys.each { |k| invalid_opts << k unless allowed_keys.include?(k) }
68
+ raise MongoArgumentError,
69
+ "Invalid extra option(s): #{invalid_opts} found. Please check the extra options" +
70
+ " passed and try again." unless invalid_opts.empty?
71
+ end
72
+ auth
73
+ end
74
+
75
+ # Generate an MD5 for authentication.
76
+ #
77
+ # @param username [String] The username.
78
+ # @param password [String] The user's password.
79
+ # @param nonce [String] The nonce value.
80
+ #
81
+ # @return [String] MD5 key for db authentication.
82
+ def auth_key(username, password, nonce)
83
+ Digest::MD5.hexdigest("#{nonce}#{username}#{hash_password(username, password)}")
84
+ end
85
+
86
+ # Return a hashed password for auth.
87
+ #
88
+ # @param username [String] The username.
89
+ # @param password [String] The users's password.
90
+ #
91
+ # @return [String] The hashed password value.
92
+ def hash_password(username, password)
93
+ Digest::MD5.hexdigest("#{username}:mongo:#{password}")
94
+ end
95
+ end
96
+
97
+ # Saves a cache of authentication credentials to the current
98
+ # client instance. This method is called automatically by DB#authenticate.
99
+ #
100
+ # @param db_name [String] The current database name.
101
+ # @param username [String] The current username.
102
+ # @param password [String] (nil) The users's password (not required for
103
+ # all authentication mechanisms).
104
+ # @param source [String] (nil) The authentication source database
105
+ # (if different than the current database).
106
+ # @param mechanism [String] (nil) The authentication mechanism being used
107
+ # (default: 'MONGODB-CR').
108
+ # @param extra [Hash] (nil) A optional hash of extra options to be stored with
109
+ # the credential set.
110
+ #
111
+ # @raise [MongoArgumentError] Raised if the database has already been used
112
+ # for authentication. A log out is required before additional auths can
113
+ # be issued against a given database.
114
+ # @raise [AuthenticationError] Raised if authentication fails.
115
+ # @return [Hash] a hash representing the authentication just added.
116
+ def add_auth(db_name, username, password=nil, source=nil, mechanism=nil, extra=nil)
117
+ auth = Authentication.validate_credentials({
118
+ :db_name => db_name,
119
+ :username => username,
120
+ :password => password,
121
+ :source => source,
122
+ :mechanism => mechanism,
123
+ :extra => extra
124
+ })
125
+
126
+ if @auths.any? {|a| a[:source] == auth[:source]}
127
+ raise MongoArgumentError,
128
+ "Another user has already authenticated to the database " +
129
+ "'#{auth[:source]}' and multiple authentications are not " +
130
+ "permitted. Please logout first."
131
+ end
132
+
133
+ begin
134
+ socket = self.checkout_reader(:mode => :primary_preferred)
135
+ self.issue_authentication(auth, :socket => socket)
136
+ ensure
137
+ socket.checkin if socket
138
+ end
139
+
140
+ @auths << auth
141
+ auth
142
+ end
143
+
144
+ # Remove a saved authentication for this connection.
145
+ #
146
+ # @param db_name [String] The database name.
147
+ #
148
+ # @return [Boolean] The result of the operation.
149
+ def remove_auth(db_name)
150
+ return false unless @auths
151
+ @auths.reject! { |a| a[:source] == db_name } ? true : false
152
+ end
153
+
154
+ # Remove all authentication information stored in this connection.
155
+ #
156
+ # @return [Boolean] result of the operation.
157
+ def clear_auths
158
+ @auths = Set.new
159
+ true
160
+ end
161
+
162
+ # Method to handle and issue logout commands.
163
+ #
164
+ # @note This method should not be called directly. Use DB#logout.
165
+ #
166
+ # @param db_name [String] The database name.
167
+ # @param opts [Hash] Hash of optional settings and configuration values.
168
+ #
169
+ # @option opts [Socket] socket (nil) Optional socket instance to use.
170
+ #
171
+ # @raise [MongoDBError] Raised if the logout operation fails.
172
+ # @return [Boolean] The result of the logout operation.
173
+ def issue_logout(db_name, opts={})
174
+ doc = db(db_name).command({:logout => 1}, :socket => opts[:socket])
175
+ unless Support.ok?(doc)
176
+ raise MongoDBError, "Error logging out on DB #{db_name}."
177
+ end
178
+ true # somewhat pointless, but here to preserve the existing API
179
+ end
180
+
181
+ # Method to handle and issue authentication commands.
182
+ #
183
+ # @note This method should not be called directly. Use DB#authenticate.
184
+ #
185
+ # @param auth [Hash] The authentication credentials to be used.
186
+ # @param opts [Hash] Hash of optional settings and configuration values.
187
+ #
188
+ # @option opts [Socket] socket (nil) Optional socket instance to use.
189
+ #
190
+ # @raise [AuthenticationError] Raised if the authentication fails.
191
+ # @return [Boolean] Result of the authentication operation.
192
+ def issue_authentication(auth, opts={})
193
+ result = case auth[:mechanism]
194
+ when 'MONGODB-CR'
195
+ issue_cr(auth, opts)
196
+ when 'MONGODB-X509'
197
+ issue_x509(auth, opts)
198
+ when 'PLAIN'
199
+ issue_plain(auth, opts)
200
+ when 'GSSAPI'
201
+ issue_gssapi(auth, opts)
202
+ end
203
+
204
+ unless Support.ok?(result)
205
+ raise AuthenticationError,
206
+ "Failed to authenticate user '#{auth[:username]}' " +
207
+ "on db '#{auth[:source]}'."
208
+ end
209
+
210
+ true
211
+ end
212
+
213
+ private
214
+
215
+ # Handles issuing authentication commands for the MONGODB-CR auth mechanism.
216
+ #
217
+ # @param auth [Hash] The authentication credentials to be used.
218
+ # @param opts [Hash] Hash of optional settings and configuration values.
219
+ #
220
+ # @option opts [Socket] socket (nil) Optional socket instance to use.
221
+ #
222
+ # @return [Boolean] Result of the authentication operation.
223
+ #
224
+ # @private
225
+ def issue_cr(auth, opts={})
226
+ database = db(auth[:source])
227
+ nonce = get_nonce(database, opts)
228
+
229
+ # build auth command document
230
+ cmd = BSON::OrderedHash.new
231
+ cmd['authenticate'] = 1
232
+ cmd['user'] = auth[:username]
233
+ cmd['nonce'] = nonce
234
+ cmd['key'] = Authentication.auth_key(auth[:username],
235
+ auth[:password],
236
+ nonce)
237
+
238
+ database.command(cmd, :check_response => false,
239
+ :socket => opts[:socket])
240
+ end
241
+
242
+ # Handles issuing authentication commands for the MONGODB-X509 auth mechanism.
243
+ #
244
+ # @param auth [Hash] The authentication credentials to be used.
245
+ # @param opts [Hash] Hash of optional settings and configuration values.
246
+ #
247
+ # @private
248
+ def issue_x509(auth, opts={})
249
+ database = db('$external')
250
+
251
+ cmd = BSON::OrderedHash.new
252
+ cmd[:authenticate] = 1
253
+ cmd[:mechanism] = auth[:mechanism]
254
+ cmd[:user] = auth[:username]
255
+
256
+ database.command(cmd, :check_response => false,
257
+ :socket => opts[:socket])
258
+ end
259
+
260
+ # Handles issuing authentication commands for the PLAIN auth mechanism.
261
+ #
262
+ # @param auth [Hash] The authentication credentials to be used.
263
+ # @param opts [Hash] Hash of optional settings and configuration values.
264
+ #
265
+ # @option opts [Socket] socket (nil) Optional socket instance to use.
266
+ #
267
+ # @return [Boolean] Result of the authentication operation.
268
+ #
269
+ # @private
270
+ def issue_plain(auth, opts={})
271
+ database = db(auth[:source])
272
+ payload = "\x00#{auth[:username]}\x00#{auth[:password]}"
273
+
274
+ cmd = BSON::OrderedHash.new
275
+ cmd[:saslStart] = 1
276
+ cmd[:mechanism] = auth[:mechanism]
277
+ cmd[:payload] = BSON::Binary.new(payload)
278
+ cmd[:autoAuthorize] = 1
279
+
280
+ database.command(cmd, :check_response => false,
281
+ :socket => opts[:socket])
282
+ end
283
+
284
+ # Handles issuing authentication commands for the GSSAPI auth mechanism.
285
+ #
286
+ # @param auth [Hash] The authentication credentials to be used.
287
+ # @param opts [Hash] Hash of optional settings and configuration values.
288
+ #
289
+ # @private
290
+ def issue_gssapi(auth, opts={})
291
+ raise NotImplementedError,
292
+ "The #{auth[:mechanism]} authentication mechanism is only supported " +
293
+ "for JRuby." unless RUBY_PLATFORM =~ /java/
294
+ Mongo::Sasl::GSSAPI.authenticate(auth[:username], self, opts[:socket], auth[:extra] || {})
295
+ end
296
+
297
+ # Helper to fetch a nonce value from a given database instance.
298
+ #
299
+ # @param database [Mongo::DB] The DB instance to use for issue the nonce command.
300
+ # @param opts [Hash] Hash of optional settings and configuration values.
301
+ #
302
+ # @option opts [Socket] socket (nil) Optional socket instance to use.
303
+ #
304
+ # @raise [MongoDBError] Raised if there is an error executing the command.
305
+ # @return [String] Returns the nonce value.
306
+ #
307
+ # @private
308
+ def get_nonce(database, opts={})
309
+ doc = database.command({:getnonce => 1}, :check_response => false,
310
+ :socket => opts[:socket])
311
+ unless Support.ok?(doc)
312
+ raise MongoDBError, "Error retrieving nonce: #{doc}"
313
+ end
314
+ doc['nonce']
315
+ end
316
+
317
+ end
318
+ end
@@ -0,0 +1,85 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module Logging
17
+
18
+ module Instrumenter
19
+ def self.instrument(name, payload = {})
20
+ yield
21
+ end
22
+ end
23
+
24
+ @instrumenter = Instrumenter
25
+
26
+ def write_logging_startup_message
27
+ log(:debug, "Logging level is currently :debug which could negatively impact " +
28
+ "client-side performance. You should set your logging level no lower than " +
29
+ ":info in production.")
30
+ end
31
+
32
+ # Log a message with the given level.
33
+ def log(level, msg)
34
+ return unless @logger
35
+ case level
36
+ when :fatal then
37
+ @logger.fatal "MONGODB [FATAL] #{msg}"
38
+ when :error then
39
+ @logger.error "MONGODB [ERROR] #{msg}"
40
+ when :warn then
41
+ @logger.warn "MONGODB [WARNING] #{msg}"
42
+ when :info then
43
+ @logger.info "MONGODB [INFO] #{msg}"
44
+ when :debug then
45
+ @logger.debug "MONGODB [DEBUG] #{msg}"
46
+ else
47
+ @logger.debug "MONGODB [DEBUG] #{msg}"
48
+ end
49
+ end
50
+
51
+ # Execute the block and log the operation described by name and payload.
52
+ def instrument(name, payload = {})
53
+ start_time = Time.now
54
+ res = Logging.instrumenter.instrument(name, payload) do
55
+ yield
56
+ end
57
+ duration = Time.now - start_time
58
+ log_operation(name, payload, duration)
59
+ res
60
+ end
61
+
62
+ def self.instrumenter
63
+ @instrumenter
64
+ end
65
+
66
+ def self.instrumenter=(instrumenter)
67
+ @instrumenter = instrumenter
68
+ end
69
+
70
+ protected
71
+
72
+ def log_operation(name, payload, duration)
73
+ @logger && @logger.debug do
74
+ msg = "MONGODB "
75
+ msg << "(%.1fms) " % (duration * 1000)
76
+ msg << "#{payload[:database]}['#{payload[:collection]}'].#{name}("
77
+ msg << payload.values_at(:selector, :document, :documents, :fields ).compact.map(&:inspect).join(', ') + ")"
78
+ msg << ".skip(#{payload[:skip]})" if payload[:skip]
79
+ msg << ".limit(#{payload[:limit]})" if payload[:limit]
80
+ msg << ".sort(#{payload[:order]})" if payload[:order]
81
+ msg
82
+ end
83
+ end
84
+ end
85
+ end