Class: ScoutRails::Layaway

Inherits:
Object
  • Object
show all
Defined in:
lib/scout_rails/layaway.rb

Overview

Stores metrics in a file before sending them to the server. Two uses:

  1. A centralized store for multiple Agent processes. This way, only 1 checkin is sent to Scout rather than 1 per-process.

  2. Bundling up reports from multiple timeslices to make updates more efficent server-side.

Metrics are stored in a Hash, where the keys are Time.to_i on the minute. When depositing data, metrics are either merged with an existing time or placed in a new key.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeLayaway

Returns a new instance of Layaway.



9
10
11
# File 'lib/scout_rails/layaway.rb', line 9

def initialize
  @file = ScoutRails::LayawayFile.new
end

Instance Attribute Details

#fileObject

Returns the value of attribute file.



8
9
10
# File 'lib/scout_rails/layaway.rb', line 8

def file
  @file
end

Instance Method Details

#deposit_and_deliverObject



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/scout_rails/layaway.rb', line 13

def deposit_and_deliver
  new_data = ScoutRails::Agent.instance.store.metric_hash
  log_deposited_requests(new_data)
  to_deliver = {}
  file.read_and_write do |old_data|
    old_data ||= Hash.new
    # merge data
    # if (1) there's data in the file and (2) there isn't any data yet for the current minute, this means we've 
    # collected all metrics for the previous slots and we're ready to deliver.
    if old_data.any? and old_data[slot].nil?
      to_deliver = old_data
      old_data = Hash.new
    elsif old_data.any?
      ScoutRails::Agent.instance.logger.debug "Not yet time to deliver metrics for slot [#{Time.at(old_data.keys.sort.last).strftime("%m/%d/%y %H:%M:%S %z")}]"
    else
      ScoutRails::Agent.instance.logger.debug "There is no data in the layaway file to deliver."
    end
    old_data[slot]=ScoutRails::Agent.instance.store.merge_data_and_clear(old_data[slot] || Hash.new)
    log_saved_requests(old_data,new_data)
    old_data
  end
  to_deliver.any? ? validate_data(to_deliver) : {}
end

#log_deposited_requests(new_data) ⇒ Object



62
63
64
65
66
67
68
69
70
# File 'lib/scout_rails/layaway.rb', line 62

def log_deposited_requests(new_data)
  controller_count = 0
  new_data.each do |meta,stats|
    if meta.metric_name =~ /\AController/
      controller_count += stats.call_count
    end
  end
  ScoutRails::Agent.instance.logger.debug "Depositing #{controller_count} requests into #{Time.at(slot).strftime("%m/%d/%y %H:%M:%S %z")} slot."
end

#log_saved_requests(old_data, new_data) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/scout_rails/layaway.rb', line 72

def log_saved_requests(old_data,new_data)
  ScoutRails::Agent.instance.logger.debug "Saving the following #{old_data.size} time slots locally:"
  old_data.each do |k,v|
    controller_count = 0
    new_data.each do |meta,stats|
      if meta.metric_name =~ /\AController/
        controller_count += stats.call_count
      end
    end
    ScoutRails::Agent.instance.logger.debug "#{Time.at(k).strftime("%m/%d/%y %H:%M:%S %z")} => #{controller_count} requests"
  end
end

#slotObject



56
57
58
59
60
# File 'lib/scout_rails/layaway.rb', line 56

def slot
  t = Time.now
  t -= t.sec
  t.to_i
end

#validate_data(data) ⇒ Object

Ensures the data we’re sending to the server isn’t stale. This can occur if the agent is collecting data, and app server goes down w/data in the local storage. When it is restarted later data will remain in local storage but it won’t be for the current reporting interval.

If the data is stale, an empty Hash is returned. Otherwise, the data from the most recent slot is returned.



42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/scout_rails/layaway.rb', line 42

def validate_data(data)
  data = data.to_a.sort
  now = Time.now
  if (most_recent = data.first.first) < now.to_i - 2*60
    ScoutRails::Agent.instance.logger.debug "Local Storage is stale (#{Time.at(most_recent).strftime("%m/%d/%y %H:%M:%S %z")}). Not sending data."
    {}
  else
    data.first.last
  end
rescue
  ScoutRails::Agent.instance.logger.debug $!.message
  ScoutRails::Agent.instance.logger.debug $!.backtrace
end