Module: RailsMetrics

Defined in:
lib/rails_metrics.rb,
lib/rails_metrics/store.rb,
lib/rails_metrics/engine.rb,
lib/rails_metrics/version.rb,
lib/rails_metrics/middleware.rb,
lib/rails_metrics/async_consumer.rb,
lib/rails_metrics/payload_parser.rb,
lib/rails_metrics/orm/active_record.rb

Defined Under Namespace

Modules: ORM, PayloadParser, Store Classes: AsyncConsumer, Engine, Middleware, VoidInstrumenter

Constant Summary collapse

VERSION =
"0.1".freeze

Class Method Summary collapse

Class Method Details

.async_consumerObject

Holds the queue which store stuff in the database.


82
83
84
85
86
87
88
# File 'lib/rails_metrics.rb', line 82

def self.async_consumer
  @@async_consumer ||= AsyncConsumer.new do |events|
    next if events.empty?
    root = RailsMetrics.store.events_to_metrics_tree(events)
    root.save_metrics!
  end
end

.eventsObject

Holds the events for a specific thread.


28
29
30
# File 'lib/rails_metrics.rb', line 28

def self.events
  Thread.current[:rails_metrics_events] ||= []
end

.ignore(name, &block) ⇒ Object

Allow you to specify a condition to ignore a notification based on its name and/or payload. For example, if you want to ignore all notifications with empty payload, one can do:

RailsMetrics.ignore :with_empty_payload do |name, payload|
  payload.empty?
end

However, if you want to ignore something based solely on its name, you can use ignore_patterns instead:

RailsMetrics.ignore_patterns << /^some_noise_plugin/

Raises:

  • (ArgumentError)

66
67
68
69
# File 'lib/rails_metrics.rb', line 66

def self.ignore(name, &block)
  raise ArgumentError, "ignore expects a block" unless block_given?
  ignore_lambdas[name] = block
end

.ignore_lambdasObject

Stores the blocks given to ignore with their respective identifier in a hash.


72
73
74
# File 'lib/rails_metrics.rb', line 72

def self.ignore_lambdas
  @@ignore_lambdas ||= {}
end

.ignore_patternsObject

Stores ignore patterns that can be given as strings or regexps.


77
78
79
# File 'lib/rails_metrics.rb', line 77

def self.ignore_patterns
  @@ignore_patterns ||= []
end

.listen_requestObject

Turn RailsMetrics on, i.e. make it listen to notifications during the block. At the end, it pushes notifications to the async consumer.


34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/rails_metrics.rb', line 34

def self.listen_request
  events = RailsMetrics.events
  events.clear

  Thread.current[:rails_metrics_listening] = true
  result = yield

  RailsMetrics.async_consumer.push(events.dup)
  result
ensure
  Thread.current[:rails_metrics_listening] = false
  RailsMetrics.events.clear
end

.listening?Boolean

Returns if events are being registered or not.

Returns:

  • (Boolean)

49
50
51
# File 'lib/rails_metrics.rb', line 49

def self.listening?
  Thread.current[:rails_metrics_listening] || false
end

.set_store(&block) ⇒ Object

Set which store to use in RailsMetrics.

RailsMetrics.set_store { Metric }

20
21
22
# File 'lib/rails_metrics.rb', line 20

def self.set_store(&block)
  metaclass.send :define_method, :store, &block
end

.storeObject

Place holder for the store.


25
# File 'lib/rails_metrics.rb', line 25

def self.store; end

.valid_for_storing?(args) ⇒ Boolean

A notification is valid for storing if two conditions are met:

1) The instrumenter id which created the notification is not the same
   instrumenter id of this thread. This means that notifications generated
   inside this thread are stored in the database;

2) If the notification name does not match any ignored pattern;

Returns:

  • (Boolean)

103
104
105
106
107
108
109
# File 'lib/rails_metrics.rb', line 103

def self.valid_for_storing?(args) #:nodoc:
  name, payload = args[0].to_s, args[4]

  RailsMetrics.listening? && RailsMetrics.store &&
  !self.ignore_patterns.find { |p| String === p ? name == p : name =~ p } &&
  !self.ignore_lambdas.values.any? { |b| b.call(name, payload) }
end

.waitObject

Wait until the async queue is consumed.


91
92
93
# File 'lib/rails_metrics.rb', line 91

def self.wait
  sleep(0.01) until async_consumer.finished?
end