Class: ScoutApm::Layaway

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

Constant Summary collapse

REPORTING_AGE =

How old a file needs to be in Seconds before it gets reported.

120
STALE_AGE =

How long to let a stale file sit before deleting it. Letting it sit a bit may be useful for debugging

10 * 60
TIME_FORMAT =

A strftime format string for how we render timestamps in filenames. Must be sortable as an integer

"%Y%m%d%H%M"

Instance Method Summary collapse

Constructor Details

#initialize(directory = nil) ⇒ Layaway

Returns a new instance of Layaway.



21
22
23
# File 'lib/scout_apm/layaway.rb', line 21

def initialize(directory=nil)
  @directory = directory
end

Instance Method Details

#delete_files_for(timestamp) ⇒ Object



92
93
94
# File 'lib/scout_apm/layaway.rb', line 92

def delete_files_for(timestamp)
  all_files_for(timestamp).each { |layaway| File.unlink(layaway) }
end

#delete_stale_files(older_than) ⇒ Object



96
97
98
99
100
101
102
103
104
# File 'lib/scout_apm/layaway.rb', line 96

def delete_stale_files(older_than)
  all_files_for(:all).
    map { |filename| timestamp_from_filename(filename) }.
    compact.
    uniq.
    select { |timestamp| timestamp.to_i < older_than.strftime(TIME_FORMAT).to_i }.
      tap  { |timestamps| ScoutApm::Agent.instance.logger.debug("Deleting stale layaway files with timestamps: #{timestamps.inspect}") }.
    map    { |timestamp| delete_files_for(timestamp) }
end

#directoryObject

Returns a Pathname object with the fully qualified directory where the layaway files can be placed. That directory must be writable by this process.

Don’t set this in initializer, since it relies on agent instance existing to figure out the value.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/scout_apm/layaway.rb', line 30

def directory
  return @directory if @directory

  data_file = ScoutApm::Agent.instance.config.value("data_file")
  data_file = File.dirname(data_file) if data_file && !File.directory?

  candidates = [
    data_file,
    "#{ScoutApm::Agent.instance.environment.root}/tmp",
    "/tmp"
  ].compact

  found = candidates.detect { |dir| File.writable?(dir) }
  ScoutApm::Agent.instance.logger.debug("Storing Layaway Files in #{found}")
  @directory = Pathname.new(found)
end

#with_claim(timestamp) ⇒ Object

Claims a given timestamp (getting a lock on a particular filename), then yields ReportingPeriods collected up from all the files. If the yield returns truthy, delete the layaway files that made it up.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/scout_apm/layaway.rb', line 56

def with_claim(timestamp)
  coordinator_file = glob_pattern(timestamp, :coordinator)


  # This file gets deleted only by a process that successfully obtained a lock
  f = File.open(coordinator_file, File::RDWR | File::CREAT)
  begin
    # Nonblocking, Exclusive lock.
    if f.flock(File::LOCK_EX | File::LOCK_NB)

      ScoutApm::Agent.instance.logger.debug("Obtained Reporting Lock")

      files = all_files_for(timestamp).reject{|l| l.to_s == coordinator_file.to_s }
      rps = files.map{ |layaway| LayawayFile.new(layaway).load }.compact
      if rps.any?
        yield rps

        delete_files_for(timestamp) # also removes the coodinator_file
        delete_stale_files(timestamp.to_time - STALE_AGE)
      else
        File.unlink(coordinator_file)
        ScoutApm::Agent.instance.logger.debug("No layaway files to report")
      end

      # Unlock the file when done!
      f.flock(File::LOCK_UN | File::LOCK_NB)
      f.close
      true
    else
      # Didn't obtain lock, another process is reporting. Return false from this function, but otherwise no work
      f.close
      false
    end
  end
end

#write_reporting_period(reporting_period) ⇒ Object



47
48
49
50
51
# File 'lib/scout_apm/layaway.rb', line 47

def write_reporting_period(reporting_period)
  filename = file_for(reporting_period.timestamp)
  layaway_file = LayawayFile.new(filename)
  layaway_file.write(reporting_period)
end