summaryrefslogtreecommitdiff
path: root/lib/gitlab/memory/watchdog/monitor/heap_fragmentation.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/memory/watchdog/monitor/heap_fragmentation.rb')
-rw-r--r--lib/gitlab/memory/watchdog/monitor/heap_fragmentation.rb51
1 files changed, 51 insertions, 0 deletions
diff --git a/lib/gitlab/memory/watchdog/monitor/heap_fragmentation.rb b/lib/gitlab/memory/watchdog/monitor/heap_fragmentation.rb
new file mode 100644
index 00000000000..7748c19c6d8
--- /dev/null
+++ b/lib/gitlab/memory/watchdog/monitor/heap_fragmentation.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Memory
+ class Watchdog
+ module Monitor
+ # A monitor that observes Ruby heap fragmentation and calls
+ # memory_violation_callback when the Ruby heap has been fragmented for an extended
+ # period of time.
+ #
+ # See Gitlab::Metrics::Memory for how heap fragmentation is defined.
+ class HeapFragmentation
+ attr_reader :max_heap_fragmentation
+
+ # max_heap_fragmentation:
+ # The degree to which the Ruby heap is allowed to be fragmented. Range [0,1].
+ def initialize(max_heap_fragmentation:)
+ @max_heap_fragmentation = max_heap_fragmentation
+ init_frag_limit_metrics
+ end
+
+ def call
+ heap_fragmentation = Gitlab::Metrics::Memory.gc_heap_fragmentation
+
+ return { threshold_violated: false, payload: {} } unless heap_fragmentation > max_heap_fragmentation
+
+ { threshold_violated: true, payload: payload(heap_fragmentation) }
+ end
+
+ private
+
+ def payload(heap_fragmentation)
+ {
+ message: 'heap fragmentation limit exceeded',
+ memwd_cur_heap_frag: heap_fragmentation,
+ memwd_max_heap_frag: max_heap_fragmentation
+ }
+ end
+
+ def init_frag_limit_metrics
+ heap_frag_limit = Gitlab::Metrics.gauge(
+ :gitlab_memwd_heap_frag_limit,
+ 'The configured limit for how fragmented the Ruby heap is allowed to be'
+ )
+ heap_frag_limit.set({}, max_heap_fragmentation)
+ end
+ end
+ end
+ end
+ end
+end