Class: ErrorStalker::Store::Mongoid

Inherits:
Base
  • Object
show all
Defined in:
lib/error_stalker/store/mongoid.rb

Overview

Store exceptions using MongoDB. This store provides fast storage and querying of exceptions, and long-term persistence. It also allows querying based on arbitrary data stored in the data hash of the exception report, which allows for crazy things like searching reports by URL or IP address.

Defined Under Namespace

Classes: Application, ExceptionGroup, ExceptionReport, Machine, SchemaMigrations

Instance Method Summary collapse

Constructor Details

#initialize(config_file) ⇒ Mongoid

Configure mongoid from the mongoid config file found in config_file. This mongoid config file should be similar to the one on mongoid.org/docs/installation/, and must be indexed by environment name. config_file is relative to either wherever you start the server from or the config.ru file, unless you pass a full file path.



17
18
19
20
21
22
23
24
25
# File 'lib/error_stalker/store/mongoid.rb', line 17

def initialize(config_file)
  filename = File.expand_path(config_file)
  settings = YAML.load(ERB.new(File.new(filename).read).result)

  Mongoid.configure do |config|
    config.from_hash(settings[ENV['RACK_ENV']])
  end
  Thread.new { migrate_data }
end

Instance Method Details

#applicationsObject

All applications that have been seen by this store



58
59
60
# File 'lib/error_stalker/store/mongoid.rb', line 58

def applications
  Application.all.order_by(:name.asc).map(&:name)
end

#create_indexesObject

Creates the MongoDB indexes used by this driver. Should be called at some point after deciding to use the mongoid store. Can be called either manually, or by running bin/create_indexes



124
125
126
127
# File 'lib/error_stalker/store/mongoid.rb', line 124

def create_indexes
  ErrorStalker::Store::Mongoid::ExceptionReport.create_indexes
  ErrorStalker::Store::Mongoid::ExceptionGroup.create_indexes
end

#empty?Boolean

Have we logged any exceptions?

Returns:

  • (Boolean)


35
36
37
# File 'lib/error_stalker/store/mongoid.rb', line 35

def empty?
  ExceptionGroup.where(:most_recent_timestamp.gt => 7.days.ago).count == 0
end

#find(id) ⇒ Object

Find an exception report with the given id.



53
54
55
# File 'lib/error_stalker/store/mongoid.rb', line 53

def find(id)
  ExceptionReport.find(id).to_exception_report
end

#group(digest) ⇒ Object

returns the ExceptionGroup object corresponding to a particular digest



75
76
77
# File 'lib/error_stalker/store/mongoid.rb', line 75

def group(digest)
  ExceptionGroup.where(:digest => digest).first
end

#machinesObject

All machines that have been seen by this store



63
64
65
# File 'lib/error_stalker/store/mongoid.rb', line 63

def machines
  Machine.all.order_by(:name.asc).map(&:name)
end

#migrate_dataObject

Migrate the data in the mongoid database to a newer format. This should eventually be more robust, like the Rails version, but for now this should be fine.



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/error_stalker/store/mongoid.rb', line 132

def migrate_data
  if SchemaMigrations.where(:version => 1).empty?
    ExceptionGroup.all.order_by(:timestamp).desc.each do |group|
      exceptions = ExceptionReport.where(:digest => group.digest).order_by(:timestamp)
      unless exceptions.empty?
        exceptions = exceptions.to_a
        group.attributes[:timestamp] = nil
        group.first_timestamp = exceptions[0].timestamp
        group.most_recent_timestamp = exceptions[-1].timestamp
        group.machines = exceptions.map(&:machine).uniq
        group.save
      end
    end
    SchemaMigrations.create(:version => 1)
  end
end

#recentObject

Return the last 7 days worth of unique exception reports grouped by exception group.



41
42
43
44
45
46
47
48
49
50
# File 'lib/error_stalker/store/mongoid.rb', line 41

def recent
  # Needs to be wrapped in a PaginationHelper because we'll call
  # paginate on the collection returned from this method. We don't
  # want to use mongoid pagination here because we don't know what
  # parameters we want to paginate on, and we don't want to return
  # an array here because we don't want to load all the mongid
  # models in memory. This is also made trickier because of my
  # hacked-up :include stuff I built into ExceptionGroup.
  ExceptionGroup::PaginationHelper.new(ExceptionGroup.where(:most_recent_timestamp.gt => 7.days.ago).order_by(:most_recent_timestamp.desc))
end

#reports_in_group(digest) ⇒ Object

Returns all the exceptions in a group, ordered by most_recent_timestamp



69
70
71
# File 'lib/error_stalker/store/mongoid.rb', line 69

def reports_in_group(digest)
  ExceptionReport.where(:digest => digest).order_by(:timestamp.desc)
end

#search(params) ⇒ Object

Searches for exception reports maching params. Supports querying by arbitrary data in the data hash associated with the exception, with the format:

REMOTE_ADDR:127.0.0.1 PATH:/test



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/error_stalker/store/mongoid.rb', line 96

def search(params)
  scope = ExceptionReport.all

  [:application, :machine].each do |param|
    if params[param] && !params[param].empty?
      scope.where(param => params[param])
    end
  end

  [:exception, :type].each do |param|
    if params[param] && !params[param].empty?
      scope.where(param => /#{params[param]}/)
    end
  end

  if params[:data] && !params[:data].empty?
    params[:data].split.each do |keyvalue|
      key, value = keyvalue.split(':')
      scope.where("data" => {"#{key}" => "#{value}"})
    end
  end
  
  scope.order_by(:timestamp.desc)
end

#store(exception_report) ⇒ Object

Store exception_report in the database.



28
29
30
31
32
# File 'lib/error_stalker/store/mongoid.rb', line 28

def store(exception_report)
  report = ExceptionReport.create_from_exception_report(exception_report)
  update_caches(report)
  report.id
end

#supports_extended_searches?Boolean

Does this store support searching through the data blob?

Returns:

  • (Boolean)


80
81
82
# File 'lib/error_stalker/store/mongoid.rb', line 80

def supports_extended_searches?
  true
end

#totalObject



84
85
86
# File 'lib/error_stalker/store/mongoid.rb', line 84

def total
  ExceptionReport.count()
end

#total_since(timestamp) ⇒ Object



88
89
90
# File 'lib/error_stalker/store/mongoid.rb', line 88

def total_since(timestamp)
  ExceptionReport.where(:timestamp.gte => timestamp).count()
end