Class: Contrast::Utils::HeapDumpUtil

Inherits:
Object
  • Object
show all
Includes:
Components::Interface
Defined in:
lib/contrast/utils/heap_dump_util.rb

Overview

Implementation of a heap dump util to automate generation

Constant Summary collapse

LOG_ERROR_DUMPS =
'Unable to generate heap dumps'
FILE_WRITE_FLAGS =
'w'

Class Method Summary collapse

Methods included from Components::Interface

included

Class Method Details

.capture_heap_dumpObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/contrast/utils/heap_dump_util.rb', line 78

def capture_heap_dump
  dir    = heap_dump_control[:path]
  window = heap_dump_control[:window]
  count  = heap_dump_control[:count]
  clean  = heap_dump_control[:clean]
  logger.info('HEAP DUMP MAIN LOOP')
  ObjectSpace.trace_object_allocations_start
  count.times do |i|
    logger.info('STARTING HEAP DUMP PASS', current_pass: i + 1, max: count)
    output = "#{ Time.now.to_f }-heap.dump"
    output = File.join(dir, output)
    begin
      logger.info('OPENING HEADUMP FILE', dir: dir, file: output)
      file = File.new(output, FILE_WRITE_FLAGS)
      if clean
        logger.info('PERFORMING GARBAGE COLLECTION BEFORE HEAP DUMP')
        GC.start
      end
      ObjectSpace.dump_all(output: file)
      logger.info('FINISHING HEAP DUMP PASS', current_pass: i + 1, max: count)
    ensure
      file.close
    end
    sleep(window)
  end
ensure
  ObjectSpace.trace_object_allocations_stop
  logger.info('*****************************************************')
  logger.info('********        HEAP DUMP HAS CONCLUDED      ********')
  logger.info('***     APPLICATION PROCESS WILL EXIT SHORTLY     ***')
  logger.info('*****************************************************')
  exit # We weren't kidding!
end

.log_enabled_warningObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/contrast/utils/heap_dump_util.rb', line 37

def log_enabled_warning
  dir    = heap_dump_control[:path]
  window = heap_dump_control[:window]
  count  = heap_dump_control[:count]
  delay  = heap_dump_control[:delay]
  clean  = heap_dump_control[:clean]

  logger.info "    *****************************************************\n    ********      HEAP DUMP HAS BEEN ENABLED     ********\n    *** APPLICATION PROCESS WILL EXIT UPON COMPLETION ***\n    *****************************************************\n\n    Heap dump is a debugging tool that snapshots the entire\n    state of the Ruby VM. It is an exceptionally expensive\n    process, and should only be used to debug especially\n    pernicious errors.\n\n    It will write multiple memory snaphots, which are liable\n    to be multiple gigabytes in size.\n    They will be named \"[unix timestamp]-heap.dump\",\n    e.g.: 1020304050-heap.dump\n\n    It will then call Ruby `exit()`.\n\n    If this is not your specific intent, you can (and should)\n    disable this option in your Contrast config file.\n\n    HEAP DUMP PARAMETERS:\n    \\t[write files to this directory]             dir:     \#{ dir    }\n    \\t[wait this many seconds in between dumps]   window:  \#{ window }\n    \\t[heap dump this many times]                 count:   \#{ count  }\n    \\t[wait this many seconds into app lifetime]  delay:   \#{ delay  }\n    \\t[perform gc pass before dump]               clean:   \#{ clean  }\n\n    *****************************************************\n    ********        YOU HAVE BEEN WARNED         ********\n    *****************************************************\n  WARNING\nend\n"

.runObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/contrast/utils/heap_dump_util.rb', line 18

def run
  return unless heap_dump_enabled?

  log_enabled_warning
  dir = heap_dump_control[:path]
  Dir.mkdir(dir) unless Dir.exist?(dir)
  return unless File.writable?(dir)

  delay = heap_dump_control[:delay]
  Contrast::Agent::Thread.new do
    logger.info("HEAP DUMP THREAD INITIALIZED. WAITING #{ delay } SECONDS TO BEGIN.")
    sleep(delay)
    capture_heap_dump
  end
rescue StandardError => e
  logger.info(LOG_ERROR_DUMPS, e)
  nil
end