diff --git a/.travis.yml b/.travis.yml index 61ad71e..7d9bc42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,9 @@ rvm: - 2.1.0 - jruby - jruby-head -env: CI="travis" +env: + - CI="travis" + - CI="travis" MOPED_LOG_FORMAT="shell" services: - mongodb matrix: diff --git a/lib/moped.rb b/lib/moped.rb index fb0e25c..b7dbfbc 100644 --- a/lib/moped.rb +++ b/lib/moped.rb @@ -8,6 +8,7 @@ require "optionable" require "moped/errors" require "moped/indexes" +require "moped/log_format" require "moped/loggable" require "moped/uri" require "moped/protocol" diff --git a/lib/moped/log_format.rb b/lib/moped/log_format.rb new file mode 100644 index 0000000..067034a --- /dev/null +++ b/lib/moped/log_format.rb @@ -0,0 +1,157 @@ +require "moped/log_format/utils/color_string" + +module Moped + module LogFormat + # Get colorize flag + # + # @example Get colorize flag. + # DefaultFormat.colorize + # + # @return [ true | false ] Status of colorization. + # + # @since 2.0.0 + def colorize + @@colorize + end + + # Set colorize flag + # + # @example Disable colorization. + # DefaultFormat.colorize = false + # + # @param [ true | false ] flag Flag to set + # + # @since 2.0.0 + def colorize=(flag) + @@colorize = !!flag + end + + # Format the provided operations log entry. + # + # @example Log the operations. + # Default.log("MOPED", {}, 30) + # + # @param [ String ] prefix The prefix for all operations in the log. + # @param [ Array ] ops The operations. + # @param [ String ] runtime The runtime in formatted ms. + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def log(prefix, payload, runtime = nil) + raise NotImplemented + end + + # Format the command event + # + # @example Format command. + # Default.command(event) + # + # @param [ Moped::Protocol::Command ] event Command event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def command(event) + raise NotImplemented + end + + # Format the insert event + # + # @example Format insert. + # Default.insert(event) + # + # @param [ Moped::Protocol::Insert ] event Insert event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def insert(event) + raise NotImplemented + end + + # Format the query event + # + # @example Format query. + # Default.query(event) + # + # @param [ Moped::Protocol::Query ] event Query event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def query(event) + raise NotImplemented + end + + # Format the query event + # + # @example Format query. + # Default.query(event) + # + # @param [ Moped::Protocol::Query ] event Query event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def update(event) + raise NotImplemented + end + + # Format the delete event + # + # @example Format delete. + # Default.delete(event) + # + # @param [ Moped::Protocol::Delete ] event Delete event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def delete(event) + raise NotImplemented + end + + # Format the cursor.next() event + # + # @example Format get_more. + # Default.get_more(event) + # + # @param [ Moped::Protocol::GetMore ] event GetMore event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def get_more(event) + raise NotImplemented + end + + # Format the cursor.close() event + # + # @example Format kill_cursors. + # Default.kill_cursors(event) + # + # @param [ Moped::Protocol::KillCursors ] event KillCursors event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def kill_cursors(event) + raise NotImplemented + end + + # Format the cursor.close() event + # + # @example Format kill_cursors. + # Default.kill_cursors(event) + # + # @param [ Moped::Protocol::KillCursors ] event KillCursors event to format + # + # @return [ ColorString ] ColorString + # + # @since 2.0.0 + def color(string) + ColorString.new(string, self.colorize) + end + end +end \ No newline at end of file diff --git a/lib/moped/log_format/default_format.rb b/lib/moped/log_format/default_format.rb new file mode 100644 index 0000000..5e7154e --- /dev/null +++ b/lib/moped/log_format/default_format.rb @@ -0,0 +1,159 @@ +require "moped/log_format" + +module Moped + module LogFormat + class DefaultFormat + extend LogFormat + + self.colorize = true + + # Format the provided operations log entry. + # + # @example Log the operations. + # Default.log("MOPED", {}, 30) + # + # @param [ String ] prefix The prefix for all operations in the log. + # @param [ Array ] ops The operations. + # @param [ String ] runtime The runtime in formatted ms. + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.log(prefix, payload, runtime = nil) + [ + color(prefix).magenta.bold, + payload, + color("runtime: #{runtime}").blue + ].join(' ') + end + + # Format the command event + # + # @example Format command. + # Default.command(event) + # + # @param [ Moped::Protocol::Command ] event Command event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.command(event) + type = color("COMMAND").bold + "%-12s database=%s command=%s" % [type, event.database, event.selector.inspect] + end + + # Format the insert event + # + # @example Format insert. + # Default.insert(event) + # + # @param [ Moped::Protocol::Insert ] event Insert event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.insert(event) + type = color("INSERT").bold + + "%-12s database=%s collection=%s documents=%s flags=%s" % [type, event.database, + event.collection, event.documents.inspect, + event.flags.inspect] + end + + # Format the query event + # + # @example Format query. + # Default.query(event) + # + # @param [ Moped::Protocol::Query ] event Query event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.query(event) + type = color("QUERY").bold + fields = [] + fields << ["%-12s", type] + fields << ["database=%s", event.database] + fields << ["collection=%s", event.collection] + fields << ["selector=%s", event.selector.inspect] + fields << ["flags=%s", event.flags.inspect] + fields << ["limit=%s", event.limit.inspect] + fields << ["skip=%s", event.skip.inspect] + fields << ["batch_size=%s", event.batch_size.inspect] + fields << ["fields=%s", event.fields.inspect] + f, v = fields.transpose + f.join(" ") % v + end + + # Format the query event + # + # @example Format query. + # Default.query(event) + # + # @param [ Moped::Protocol::Query ] event Query event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.update(event) + type = color("UPDATE").bold + + "%-12s database=%s collection=%s selector=%s update=%s flags=%s" % [type, event.database, + event.collection, + event.selector.inspect, + event.update.inspect, + event.flags.inspect] + end + + # Format the delete event + # + # @example Format delete. + # Default.delete(event) + # + # @param [ Moped::Protocol::Delete ] event Delete event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.delete(event) + type = color("DELETE").bold + + "%-12s database=%s collection=%s selector=%s flags=%s" % [type, event.database, event.collection, + event.selector.inspect, event.flags.inspect] + end + + # Format the cursor.next() event + # + # @example Format get_more. + # Default.get_more(event) + # + # @param [ Moped::Protocol::GetMore ] event GetMore event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.get_more(event) + type = color("GET_MORE").bold + "%-12s database=%s collection=%s limit=%s cursor_id=%s" % [type, event.database, + event.collection, event.limit, + event.cursor_id] + end + + # Format the cursor.close() event + # + # @example Format kill_cursors. + # Default.kill_cursors(event) + # + # @param [ Moped::Protocol::KillCursors ] event KillCursors event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.kill_cursors(event) + type = color("KILL_CURSORS").bold + "%-12s cursor_ids=%s" % [type, event.cursor_ids.inspect] + end + end + end +end \ No newline at end of file diff --git a/lib/moped/log_format/shell_format.rb b/lib/moped/log_format/shell_format.rb new file mode 100644 index 0000000..449e312 --- /dev/null +++ b/lib/moped/log_format/shell_format.rb @@ -0,0 +1,141 @@ +require "json" +require "moped/log_format/shell_format/core_ext/unsafe_json_string" +require "moped/log_format/shell_format/core_ext/active_support/json/encoding" +require "moped/log_format/shell_format/core_ext/bson/object_id" +require "moped/log_format/shell_format/core_ext/regexp" +require "moped/log_format/shell_format/core_ext/time" + +require "moped/log_format/shell_format/shellable" +require "moped/log_format/shell_format/command" +require "moped/log_format/shell_format/query" +require "moped/log_format/shell_format/insert" +require "moped/log_format/shell_format/update" +require "moped/log_format/shell_format/delete" + +module Moped + module LogFormat + class ShellFormat + extend LogFormat + + # Format the provided operations log entry. + # + # @example Log the operations. + # Default.log("MOPED", {}, 30) + # + # @param [ String ] prefix The prefix for all operations in the log. + # @param [ Array ] ops The operations. + # @param [ String ] runtime The runtime in formatted ms. + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.log(prefix, payload, runtime = nil) + line = [] + + line << color(prefix).magenta.bold + line << payload + line << color("runtime: #{runtime}").blue if runtime + + line.join(' ') + end + + # Format the command event + # + # @example Format command. + # Default.command(event) + # + # @param [ Moped::Protocol::Command ] event Command event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.command(event) + ShellFormat::Command.format event + end + + # Format the insert event + # + # @example Format insert. + # Default.insert(event) + # + # @param [ Moped::Protocol::Insert ] event Insert event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.insert(event) + ShellFormat::Insert.format event + end + + # Format the query event + # + # @example Format query. + # Default.query(event) + # + # @param [ Moped::Protocol::Query ] event Query event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.query(event) + ShellFormat::Query.format event + end + + # Format the query event + # + # @example Format query. + # Default.query(event) + # + # @param [ Moped::Protocol::Query ] event Query event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.update(event) + ShellFormat::Update.format event + end + + # Format the delete event + # + # @example Format delete. + # Default.delete(event) + # + # @param [ Moped::Protocol::Delete ] event Delete event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.delete(event) + ShellFormat::Delete.format event + end + + # Format the cursor.next() event + # + # @example Format get_more. + # Default.get_more(event) + # + # @param [ Moped::Protocol::GetMore ] event GetMore event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.get_more(event) + "#{event.database}: cursor.next() cursor_id: #{event.cursor_id}" + end + + # Format the db.killOp(opid) event + # + # @example Format kill_cursors. + # Default.kill_cursors(event) + # + # @param [ Moped::Protocol::KillCursors ] event KillCursors event to format + # + # @return [ String ] Formatted string + # + # @since 2.0.0 + def self.kill_cursors(event) + "db.killOp(#{event.cursor_ids})" + end + end + end +end \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/command.rb b/lib/moped/log_format/shell_format/command.rb new file mode 100644 index 0000000..d00bfb9 --- /dev/null +++ b/lib/moped/log_format/shell_format/command.rb @@ -0,0 +1,71 @@ +module Moped + module LogFormat + class ShellFormat + class Command + include Moped::LogFormat::ShellFormat::Shellable + + Commands = %w{addUser auth changeUserPassword cloneCollection cloneDatabase commandHelp copyDatabase + createCollection currentOp dropDatabase eval fsyncLock fsyncUnlock getCollection getCollectionNames + getLastError getLastErrorObj getMongo getName getPrevError getProfilingLevel getProfilingStatus + getReplicationInfo getSiblingDB help hostInfo isMaster killOp listCommands loadServerScripts + logout printCollectionStats printReplicationInfo printShardingStatus printSlaveReplicationInfo + removeUser repairDatabase resetError runCommand serverBuildInfo serverCmdLineOpts serverStatus + setProfilingLevel shutdownServer stats upgradeCheck upgradeCheckAllDBs version} + + Aliases = Commands.inject({}) do |acc, cmd| + if cmd.downcase != cmd + name = cmd.downcase.to_sym + acc[name] = cmd + end + + acc + end + + def sequence + [ + :db, :command + ] + end + + def to_shell_command + return shell(command_name, argument, rest) + end + + private + + def name + event.selector.keys.first + end + + def command_name + normalized_name = name.downcase.to_sym + + if Aliases.include? normalized_name + command_name = Aliases[normalized_name] + else + name + end + end + + def argument + if nil_if_blank(event.selector[name]).nil? + return nil + else + dump_json event.selector[name] + end + end + + def rest + selector = event.selector.dup + selector.delete name + + if selector.empty? + return nil + else + dump_json selector + end + end + end + end + end +end \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/core_ext.rb b/lib/moped/log_format/shell_format/core_ext.rb new file mode 100644 index 0000000..7fbd19b --- /dev/null +++ b/lib/moped/log_format/shell_format/core_ext.rb @@ -0,0 +1,7 @@ +require "moped/log_format/shell_format/core_ext/unsafe_json_string" +require "moped/log_format/shell_format/core_ext/active_support/json/encoding" +require "moped/log_format/shell_format/core_ext/bson/object_id" +require "moped/log_format/shell_format/core_ext/regexp" +require "moped/log_format/shell_format/core_ext/time" + + diff --git a/lib/moped/log_format/shell_format/core_ext/active_support/json/encoding.rb b/lib/moped/log_format/shell_format/core_ext/active_support/json/encoding.rb new file mode 100644 index 0000000..003f5b4 --- /dev/null +++ b/lib/moped/log_format/shell_format/core_ext/active_support/json/encoding.rb @@ -0,0 +1,25 @@ +module Moped + module ShellFormatPatch + module JSONGemEncoder + def jsonify_with_mongo_shell(value) + case value + when UnsafeJSONString + value + else + jsonify_without_mongo_shell(value) + end + end + + def self.included(base) + base.class_eval do + alias_method :jsonify_without_mongo_shell, :jsonify + alias_method :jsonify, :jsonify_with_mongo_shell + end + end + end + end +end + +if defined? ::ActiveSupport + ::ActiveSupport::JSON::Encoding::JSONGemEncoder.send(:include, Moped::ShellFormatPatch::JSONGemEncoder) +end \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/core_ext/bson/object_id.rb b/lib/moped/log_format/shell_format/core_ext/bson/object_id.rb new file mode 100644 index 0000000..f3ccb10 --- /dev/null +++ b/lib/moped/log_format/shell_format/core_ext/bson/object_id.rb @@ -0,0 +1,39 @@ +module Moped + module ShellFormatPatch + module ObjectId + def to_mongo_shell(*args) + UnsafeJSONString.new(%Q{ObjectId("#{to_s}")}) + end + + def as_json_with_mongo_shell(*args) + if args.first && args.first[:mongo_shell_format] + to_mongo_shell + else + as_json_without_mongo_shell(*args) + end + end + + def to_json_with_mongo_shell(*args) + if args.first && args.first[:mongo_shell_format] + to_mongo_shell + else + to_json_without_mongo_shell(*args) + end + end + + def self.included(base) + base.class_eval do + if defined? ActiveSupport + alias_method :as_json_without_mongo_shell, :as_json + alias_method :as_json, :as_json_with_mongo_shell + else + alias_method :to_json_without_mongo_shell, :to_json + alias_method :to_json, :to_json_with_mongo_shell + end + end + end + end + end +end + +::BSON::ObjectId.send(:include, Moped::ShellFormatPatch::ObjectId) \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/core_ext/regexp.rb b/lib/moped/log_format/shell_format/core_ext/regexp.rb new file mode 100644 index 0000000..b67b826 --- /dev/null +++ b/lib/moped/log_format/shell_format/core_ext/regexp.rb @@ -0,0 +1,39 @@ +module Moped + module ShellFormatPatch + module Regexp + def to_mongo_shell(*args) + UnsafeJSONString.new(inspect) + end + + def as_json_with_mongo_shell(*args) + if args.first && args.first[:mongo_shell_format] + to_mongo_shell + else + as_json_without_mongo_shell(*args) + end + end + + def to_json_with_mongo_shell(*args) + if args.first && args.first[:mongo_shell_format] + to_mongo_shell + else + to_json_without_mongo_shell(*args) + end + end + + def self.included(base) + base.class_eval do + if defined? ActiveSupport + alias_method :as_json_without_mongo_shell, :as_json + alias_method :as_json, :as_json_with_mongo_shell + else + alias_method :to_json_without_mongo_shell, :to_json + alias_method :to_json, :to_json_with_mongo_shell + end + end + end + end + end +end + +::Regexp.send(:include, Moped::ShellFormatPatch::Regexp) \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/core_ext/time.rb b/lib/moped/log_format/shell_format/core_ext/time.rb new file mode 100644 index 0000000..eb7a6ad --- /dev/null +++ b/lib/moped/log_format/shell_format/core_ext/time.rb @@ -0,0 +1,39 @@ +module Moped + module ShellFormatPatch + module Time + def to_mongo_shell(*args) + UnsafeJSONString.new(%Q{ISODate("#{xmlschema}")}) + end + + def as_json_with_mongo_shell(*args) + if args.first && args.first[:mongo_shell_format] + to_mongo_shell + else + as_json_without_mongo_shell(*args) + end + end + + def to_json_with_mongo_shell(*args) + if args.first && args.first[:mongo_shell_format] + to_mongo_shell + else + to_json_without_mongo_shell(*args) + end + end + + def self.included(base) + base.class_eval do + if defined? ActiveSupport + alias_method :as_json_without_mongo_shell, :as_json + alias_method :as_json, :as_json_with_mongo_shell + else + alias_method :to_json_without_mongo_shell, :to_json + alias_method :to_json, :to_json_with_mongo_shell + end + end + end + end + end +end + +::Time.send(:include, Moped::ShellFormatPatch::Time) \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/core_ext/unsafe_json_string.rb b/lib/moped/log_format/shell_format/core_ext/unsafe_json_string.rb new file mode 100644 index 0000000..8c1cb67 --- /dev/null +++ b/lib/moped/log_format/shell_format/core_ext/unsafe_json_string.rb @@ -0,0 +1,5 @@ +class UnsafeJSONString < String + def to_json(*args) + to_s + end +end \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/delete.rb b/lib/moped/log_format/shell_format/delete.rb new file mode 100644 index 0000000..cc2276a --- /dev/null +++ b/lib/moped/log_format/shell_format/delete.rb @@ -0,0 +1,19 @@ +module Moped + module LogFormat + class ShellFormat + class Delete + include Moped::LogFormat::ShellFormat::Shellable + + def sequence + [ + :db, :collection, :delete + ] + end + + def to_shell_delete + return shell :remove, selector, flags + end + end + end + end +end \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/insert.rb b/lib/moped/log_format/shell_format/insert.rb new file mode 100644 index 0000000..5dfeda1 --- /dev/null +++ b/lib/moped/log_format/shell_format/insert.rb @@ -0,0 +1,34 @@ +module Moped + module LogFormat + class ShellFormat + class Insert + include Moped::LogFormat::ShellFormat::Shellable + + def sequence + [ + :db, :collection, :insert + ] + end + + def to_shell_insert + return shell :insert, documents, flags + end + + private + + def documents + if event.documents.size == 1 + dump_json(event.documents.first) + else + dump_json(event.documents.first) + end + end + + def flags + return if nil_if_blank(event.flags).nil? + dump_json(event.flags) + end + end + end + end +end \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/query.rb b/lib/moped/log_format/shell_format/query.rb new file mode 100644 index 0000000..4fa2fa8 --- /dev/null +++ b/lib/moped/log_format/shell_format/query.rb @@ -0,0 +1,116 @@ +module Moped + module LogFormat + class ShellFormat + class Query + include Moped::LogFormat::ShellFormat::Shellable + + CommandToModifiers = { + min: '$min', + max: '$max', + sort: '$orderby', + hint: '$hint', + snapshot: '$snapshot', + maxTimeMS: '$maxTimeMS', + explain: '$explain' + } + + MethodsToCommand = { + batch_size: 'batchSize', + limit: 'limit', + skip: 'skip', + } + + FlagsToOptions = { + tailable: 'tailable', + slave_ok: 'slaveOk', + no_cursor_timeout: 'noTimeout', + await_data: 'awaitData', + exhaust: 'exhaust' + } + + def sequence + [ + :db, :collection, :find, :sort, :hint, + :min, :max, :limit, :skip, + :specials, + :batch_size, + :maxTimeMS, + :flags, + :snapshot, + :explain + ] + end + + def to_shell_find + selector = event.selector.dup + + query = selector.delete("$query") { Hash.new } + selector.keep_if {|k, v| not k.to_s.start_with? '$' } + selector.merge! query + + arguments = [] + arguments << dump_json(selector) + arguments << dump_json(event.fields) if not nil_if_blank(event.fields).nil? + + return shell :find, arguments + end + + def to_shell_limit + limit = event.limit + + return nil if limit.nil? or limit == 0 + + shell :limit, limit + end + + def to_shell_skip + skip = event.skip + return nil if skip.nil? or skip == 0 + + shell :skip, skip + end + + def to_shell_flags + # TODO: FlagsToOptions + return nil + end + + def to_shell_specials + unknown_modifiers = event.selector.dup.keep_if do |modifier, value| + modifier = modifier.to_s + modifier.start_with?("$") and ('$query' != modifier) and (not CommandToModifiers.has_value?(modifier)) + end + + unknown_modifiers.inject [] do |acc, (modifier, params)| + acc << shell(:_addSpecial, dump_json({modifier => params})) + acc + end + end + + def extact_command(command) + if command_name = MethodsToCommand[command] + result = event.send(command) + + if not nil_if_blank(result).nil? + return shell command_name, dump_json(result) + else + return nil + end + end + + if modifier_name = CommandToModifiers[command] + result = event.selector[modifier_name] + + if not nil_if_blank(result).nil? + return shell command, dump_json(result) + else + return nil + end + end + + raise ArgumentError, "can't convert '#{command}' to mongodb shell command for #{self.class}" + end + end + end + end +end \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/shellable.rb b/lib/moped/log_format/shell_format/shellable.rb new file mode 100644 index 0000000..d7315db --- /dev/null +++ b/lib/moped/log_format/shell_format/shellable.rb @@ -0,0 +1,89 @@ +module Moped + module LogFormat + class ShellFormat + module Shellable + module ClassMethods + def format(event) + new(event).to_s + end + end + + def self.included(receiver) + receiver.extend ClassMethods + end + + attr_reader :event + def initialize(event) + @event = event + end + + def to_s + commands = [] + + sequence.each do |item| + commands << comandify(item) + end + + "#{event.database}: #{commands.compact.join(".")}" + end + + def comandify(command) + if respond_to? :"to_shell_#{command}" + return nil_if_blank(send(:"to_shell_#{command}")) + end + + if respond_to? :extact_command + return nil_if_blank(extact_command(command)) + end + + raise ArgumentError, "can't convert '#{command}' to mongodb shell command for #{self.class}" + end + + def to_shell_db + :db + end + + def to_shell_collection + event.collection + end + + private + + def selector + dump_json(event.selector) + end + + def flags + return if nil_if_blank(event.flags).nil? + flags = Hash[event.flags.map {|f| [f, 1]}] + + dump_json(flags) + end + + def dump_json(object) + object.to_json(escape: false, mongo_shell_format: true) + end + + def shell(command, *args) + args.compact! + + "%s(%s)" % [command, args.join(", ")] + end + + def nil_if_blank(obj) + return if obj.nil? || obj == false + + if obj.respond_to? :blank? + return obj.blank? ? nil : obj + end + + if obj.respond_to? :empty? + return obj.empty? ? nil : obj + end + + return obj + end + end + end + end +end \ No newline at end of file diff --git a/lib/moped/log_format/shell_format/update.rb b/lib/moped/log_format/shell_format/update.rb new file mode 100644 index 0000000..856bc4d --- /dev/null +++ b/lib/moped/log_format/shell_format/update.rb @@ -0,0 +1,34 @@ +module Moped + module LogFormat + class ShellFormat + class Update + include Moped::LogFormat::ShellFormat::Shellable + + def sequence + [ + :db, :collection, :update + ] + end + + def to_shell_update + return shell :update, selector, update, flags + end + + private + + def selector + dump_json(event.selector) + end + + def update + dump_json(event.selector) + end + + def flags + return if nil_if_blank(event.flags).nil? + dump_json(event.flags) + end + end + end + end +end \ No newline at end of file diff --git a/lib/moped/log_format/utils/color_string.rb b/lib/moped/log_format/utils/color_string.rb new file mode 100644 index 0000000..91cf811 --- /dev/null +++ b/lib/moped/log_format/utils/color_string.rb @@ -0,0 +1,86 @@ +module Moped + module LogFormat + class ColorString + Colors = { + black: "\e[30m", + red: "\e[31m", + green: "\e[32m", + yellow: "\e[33m", + blue: "\e[34m", + magenta: "\e[35m", + cyan: "\e[36m", + white: "\e[37m", + default: "\e[38m" + }.freeze + + Backgrounds = { + black: "\e[40m", + red: "\e[41m", + green: "\e[42m", + yellow: "\e[43m", + blue: "\e[44m", + magenta: "\e[45m", + cyan: "\e[46m", + white: "\e[47m", + default: "\e[48m" + }.freeze + + Clear = "\e[0m".freeze + + Styles = { + bold: "\e[1m", + dim: "\e[1m", + underscore: "\e[4m", + blink: "\e[5m", + reverse: "\e[7m", + hidden: "\e[8m" + }.freeze + + attr_reader :string, :color, :background, :styles, :enable + + def initialize(string, enabled = false) + @enable = enabled + @string = string + + @color = Colors[:default] + @background = Backgrounds[:default] + @styles = [] + end + + def to_s + if self.enable == true + [styles.join, color, background, string, Clear].join + else + string + end + end + alias_method :inspect, :to_s + + Colors.each do |color_name, value| + define_method color_name do + @color = Colors[color_name] + self + end + end + + Backgrounds.each do |background_name, value| + define_method :"on_#{background_name}" do + @background = Backgrounds[background_name] + self + end + end + + Styles.each do |style_name, value| + define_method style_name do + @styles << Styles[style_name] + self + end + + define_method :"no_#{style_name}" do + @styles.delete Styles[style_name] + self + end + end + end + end +end \ No newline at end of file diff --git a/lib/moped/loggable.rb b/lib/moped/loggable.rb index dfebd72..1137279 100644 --- a/lib/moped/loggable.rb +++ b/lib/moped/loggable.rb @@ -1,3 +1,6 @@ +require "moped/log_format/default_format" +require "moped/log_format/shell_format" + # encoding: utf-8 module Moped @@ -19,12 +22,12 @@ module Loggable def self.log_operations(prefix, ops, runtime) indent = " "*prefix.length if ops.length == 1 - Moped.logger.debug([ prefix, ops.first.log_inspect, "runtime: #{runtime}" ].join(' ')) + Moped.logger.debug(Moped.log_format.log(prefix, ops.first.log_inspect, runtime)) else first, *middle, last = ops - Moped.logger.debug([ prefix, first.log_inspect ].join(' ')) - middle.each { |m| Moped.logger.debug([ indent, m.log_inspect ].join(' ')) } - Moped.logger.debug([ indent, last.log_inspect, "runtime: #{runtime}" ].join(' ')) + Moped.logger.debug(Moped.log_format.log(prefix, first.log_inspect)) + middle.each { |m| Moped.logger.debug(Moped.log_format.log(indent, m.log_inspect)) } + Moped.logger.debug(Moped.log_format.log(indent, last.log_inspect, runtime)) end end @@ -39,7 +42,7 @@ def self.log_operations(prefix, ops, runtime) # # @since 2.0.0 def self.debug(prefix, payload, runtime) - Moped.logger.debug([ prefix, payload, "runtime: #{runtime}" ].join(' ')) + Moped.logger.debug(Moped.log_format.log(prefix, payload, runtime)) end # Log the payload to warn. @@ -53,7 +56,7 @@ def self.debug(prefix, payload, runtime) # # @since 2.0.0 def self.warn(prefix, payload, runtime) - Moped.logger.warn([ prefix, payload, "runtime: #{runtime}" ].join(' ')) + Moped.logger.warn(Moped.log_format.log(prefix, payload, runtime)) end # Get the logger. @@ -106,5 +109,30 @@ def default_logger def logger=(logger) @logger = logger end + + # Get the log format. + # + # @example Get the log format. + # Loggable.logger + # + # @return [ Logger ] The log format. + # + # @since 2.0.0 + def log_format + return @log_format if defined?(@log_format) + @log_format = Moped::LogFormat::DefaultFormat + end + + # Set the log formatt. + # + # @example Set the log formatt. + # Loggable.log_format = format + # + # @return [ LogFormat ] The log format. + # + # @since 2.0.0 + def log_format=(format) + @log_format = format + end end -end +end \ No newline at end of file diff --git a/lib/moped/protocol/command.rb b/lib/moped/protocol/command.rb index 8c0461c..af86a25 100644 --- a/lib/moped/protocol/command.rb +++ b/lib/moped/protocol/command.rb @@ -63,8 +63,7 @@ def initialize(database, command, options = {}) # # @since 1.0.0 def log_inspect - type = "COMMAND" - "%-12s database=%s command=%s" % [type, database, selector.inspect] + Moped.log_format.command(self) end # Take the provided reply and return the expected results to api diff --git a/lib/moped/protocol/delete.rb b/lib/moped/protocol/delete.rb index 0695e66..f68e6a6 100644 --- a/lib/moped/protocol/delete.rb +++ b/lib/moped/protocol/delete.rb @@ -85,9 +85,7 @@ def op_code end def log_inspect - type = "DELETE" - - "%-12s database=%s collection=%s selector=%s flags=%s" % [type, database, collection, selector.inspect, flags.inspect] + Moped.log_format.delete(self) end private diff --git a/lib/moped/protocol/get_more.rb b/lib/moped/protocol/get_more.rb index 78710b4..882b09b 100644 --- a/lib/moped/protocol/get_more.rb +++ b/lib/moped/protocol/get_more.rb @@ -115,8 +115,7 @@ def initialize(database, collection, cursor_id, limit, options = {}) # # @since 1.0.0 def log_inspect - type = "GET_MORE" - "%-12s database=%s collection=%s limit=%s cursor_id=%s" % [type, database, collection, limit, cursor_id] + Moped.log_format.get_more(self) end undef op_code diff --git a/lib/moped/protocol/insert.rb b/lib/moped/protocol/insert.rb index 7d494e8..b512f1e 100644 --- a/lib/moped/protocol/insert.rb +++ b/lib/moped/protocol/insert.rb @@ -86,9 +86,7 @@ def initialize(database, collection, documents, options = {}) end def log_inspect - type = "INSERT" - - "%-12s database=%s collection=%s documents=%s flags=%s" % [type, database, collection, documents.inspect, flags.inspect] + Moped.log_format.insert(self) end private diff --git a/lib/moped/protocol/kill_cursors.rb b/lib/moped/protocol/kill_cursors.rb index 1058c52..5cdcf85 100644 --- a/lib/moped/protocol/kill_cursors.rb +++ b/lib/moped/protocol/kill_cursors.rb @@ -55,9 +55,7 @@ def initialize(cursor_ids, options = {}) end def log_inspect - type = "KILL_CURSORS" - - "%-12s cursor_ids=%s" % [type, cursor_ids.inspect] + Moped.log_format.kill_cursors(self) end end end diff --git a/lib/moped/protocol/query.rb b/lib/moped/protocol/query.rb index ac455fc..d3572e5 100644 --- a/lib/moped/protocol/query.rb +++ b/lib/moped/protocol/query.rb @@ -170,19 +170,7 @@ def initialize(database, collection, selector, options = {}) # # @since 1.0.0 def log_inspect - type = "QUERY" - fields = [] - fields << ["%-12s", type] - fields << ["database=%s", database] - fields << ["collection=%s", collection] - fields << ["selector=%s", selector.inspect] - fields << ["flags=%s", flags.inspect] - fields << ["limit=%s", limit.inspect] - fields << ["skip=%s", skip.inspect] - fields << ["batch_size=%s", batch_size.inspect] - fields << ["fields=%s", self.fields.inspect] - f, v = fields.transpose - f.join(" ") % v + Moped.log_format.query(self) end undef op_code diff --git a/lib/moped/protocol/update.rb b/lib/moped/protocol/update.rb index 58609fc..f2dc969 100644 --- a/lib/moped/protocol/update.rb +++ b/lib/moped/protocol/update.rb @@ -98,12 +98,7 @@ def initialize(database, collection, selector, update, options = {}) end def log_inspect - type = "UPDATE" - - "%-12s database=%s collection=%s selector=%s update=%s flags=%s" % [type, database, collection, - selector.inspect, - update.inspect, - flags.inspect] + Moped.log_format.update(self) end private diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 341a488..89530e6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -20,7 +20,16 @@ # Log to a StringIO instance to make sure no exceptions are rasied by our # logging code. -Moped.logger = Logger.new(StringIO.new, Logger::DEBUG) +if ENV.has_key? "MOPED_PRINT_LOG" + Moped.logger = Logger.new($stdout, Logger::DEBUG) +else + Moped.logger = Logger.new(StringIO.new, Logger::DEBUG) +end + +case ENV["MOPED_LOG_FORMAT"] +when 'shell' + Moped.log_format = Moped::LogFormat::ShellFormat +end RSpec.configure do |config| Support::Stats.install!