Class: SemanticLogger::Appender::MongoDB

Inherits:
Base
  • Object
show all
Defined in:
lib/semantic_logger/appender/mongodb.rb

Overview

The Mongo Appender for the SemanticLogger

Mongo Document Schema:

_id        : ObjectId("4d9cbcbf7abb3abdaf9679cd"),
time       : ISODate("2011-04-06T19:19:27.006Z"),
host_name  : "Name of the host on which this log entry originated",
application: 'Name of application or service logging the data - clarity_base, nginx, tomcat',
pid        : process id
thread_name: "name or id of thread",
name       : "com.clarity.MyClass",
level      : 'trace|debug|info|warn|error|fatal'
level_index: 0|1|2|3|4|5
message    : "Message supplied to the logging call",
duration   : ms,  # Set by Logger#benchmark
tags       : "Some tracking id" | ["id1", "id2"]
payload : {
  Optional. Any user supplied data, including any thread specific context variables
  values supplied on a per log entry will override any thread context values
}
# When an exception is supplied as the first or second parameter
# If supplied as the first parameter, message='exception name'
exception: {
  name:        'MyException',
  message:     'Invalid value',
  stack_trace: []
}

Instance Attribute Summary collapse

Attributes inherited from Base

#formatter

Attributes inherited from Base

#filter, #name

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

colorized_formatter

Methods inherited from Base

#benchmark, default_level, default_level=, #level, #level=, #payload, #pop_tags, #push_tags, #tagged, #tags, #with_payload

Constructor Details

#initialize(params = {}, &block) ⇒ MongoDB

Create a MongoDB Appender instance

SemanticLogger::Appender::MongoDB.new(:db => Mongo::Connection.new['database'])

Parameters: :db [Mongo::Database]

The MongoDB database connection to use, not the database name

:collection_name [String]

Name of the collection to store log data in
Default: semantic_logger

:host_name [String]

host_name to include in the document logged to Mongo
Default: first part of host name extracted from Socket

:write_concern [Integer]

Write concern to use
see: http://docs.mongodb.org/manual/reference/write-concern/
Default: 0

:application [String]

Name of the application to include in the document written to mongo
Default: nil (None)

:collection_size [Integer]

 The size of the MongoDB capped collection to create in bytes
 Default: 1 GB

 Some examples
   Prod: 25GB (.5GB per day across 4 servers over 10 days)
   Dev: .5GB
   Test: File
   Release: 4GB

:collection_max [Integer]
  Maximum number of log entries that the capped collection will hold

:level [Symbol]
  Only allow log entries of this level or higher to be written to MongoDB

:filter [Regexp|Proc]
  RegExp: Only include log messages where the class name matches the supplied
  regular expression. All other messages will be ignored
  Proc: Only include log messages where the supplied Proc returns true
        The Proc must return true or false


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/semantic_logger/appender/mongodb.rb', line 82

def initialize(params={}, &block)
  @db              = params[:db] || raise('Missing mandatory parameter :db')
  @collection_name = params[:collection_name] || 'semantic_logger'
  @host_name       = params[:host_name] || Socket.gethostname.split('.').first
  @write_concern   = params[:write_concern] || 0
  @application     = params[:application]
  filter           = params[:filter]

  # Create a collection that will hold the lesser of 1GB space or 10K documents
  @collection_size = params[:collection_size] || 1024**3
  @collection_max  = params[:collection_max]

  # Create the collection and necessary indexes
  create_indexes

  # Set the log level and formatter
  super(params[:level], filter, &block)
end

Instance Attribute Details

#applicationObject

Returns the value of attribute application.



34
35
36
# File 'lib/semantic_logger/appender/mongodb.rb', line 34

def application
  @application
end

#collection_nameObject (readonly)

Returns the value of attribute collection_name.



33
34
35
# File 'lib/semantic_logger/appender/mongodb.rb', line 33

def collection_name
  @collection_name
end

#dbObject (readonly)

Returns the value of attribute db.



33
34
35
# File 'lib/semantic_logger/appender/mongodb.rb', line 33

def db
  @db
end

#host_nameObject

Returns the value of attribute host_name.



34
35
36
# File 'lib/semantic_logger/appender/mongodb.rb', line 34

def host_name
  @host_name
end

#write_concernObject

Returns the value of attribute write_concern.



34
35
36
# File 'lib/semantic_logger/appender/mongodb.rb', line 34

def write_concern
  @write_concern
end

Class Method Details

.host_nameObject

Default host_name to use if none is supplied to the appenders initializer



170
171
172
# File 'lib/semantic_logger/appender/mongodb.rb', line 170

def self.host_name
  @@host_name ||= Socket.gethostname.split('.').first
end

.host_name=(host_name) ⇒ Object

Override the default host_name



175
176
177
# File 'lib/semantic_logger/appender/mongodb.rb', line 175

def self.host_name=(host_name)
  @@host_name = host_name
end

.strip_colorizing(message) ⇒ Object

Strip the standard Rails colorizing from the logged message



165
166
167
# File 'lib/semantic_logger/appender/mongodb.rb', line 165

def self.strip_colorizing(message)
  message.to_s.gsub(/(\e(\[([\d;]*[mz]?))?)?/, '').strip
end

Instance Method Details

#collectionObject

Return the collection being used to write the log document to



127
128
129
# File 'lib/semantic_logger/appender/mongodb.rb', line 127

def collection
  @collection ||= db[collection_name]
end

#create_indexesObject

Create the required capped collection Features of capped collection:

  • No indexes by default (not even on _id)

  • Documents cannot be deleted,

  • Document updates cannot make them any larger

  • Documents are always stored in insertion order

    • A find will always return the documents in their insertion order

Creates an index based on tags to support faster lookups



110
111
112
113
114
115
# File 'lib/semantic_logger/appender/mongodb.rb', line 110

def create_indexes
  options = {:capped => true, :size => @collection_size}
  options[:max] = @collection_max if @collection_max
  db.create_collection(collection_name, options)
  collection.ensure_index('tags')
end

#default_formatterObject

Default log formatter

Replace this formatter by supplying a Block to the initializer


139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/semantic_logger/appender/mongodb.rb', line 139

def default_formatter
  Proc.new do |log|
    document = {
      :time        => log.time,
      :host_name   => host_name,
      :pid         => $$,
      :thread_name => log.thread_name,
      :name        => log.name,
      :level       => log.level,
      :level_index => log.level_index,
    }
    document[:application] = application if application
    document[:message]     = self.class.strip_colorizing(log.message) if log.message
    document[:duration]    = log.duration if log.duration
    document[:tags]        = log.tags if log.tags && (log.tags.size > 0)
    document[:payload]     = log.payload if log.payload
    document[:exception]   = {
      :name        => log.exception.class.name,
      :message     => log.exception.message,
      :stack_trace => log.exception.backtrace
    } if log.exception
    document
  end
end

#flushObject

Flush all pending logs to disk.

Waits for all sent documents to be written to disk


133
134
135
# File 'lib/semantic_logger/appender/mongodb.rb', line 133

def flush
  db.get_last_error
end

#log(log) ⇒ Object

Log the message to MongoDB



180
181
182
183
184
185
186
187
# File 'lib/semantic_logger/appender/mongodb.rb', line 180

def log(log)
  # Ensure minimum log level is met, and check filter
  return false if (level_index > (log.level_index || 0)) || !include_message?(log)

  # Insert log entry into Mongo
  collection.insert(formatter.call(log), :w=>@write_concern)
  true
end

#purge_allObject

Purge all data from the capped collection by dropping the collection and recreating it. Also useful when the size of the capped collection needs to be changed



120
121
122
123
124
# File 'lib/semantic_logger/appender/mongodb.rb', line 120

def purge_all
  collection.drop
  @collection = nil
  create_indexes
end