2016-01-14 18:37:52 +05:30
|
|
|
module Gitlab
|
|
|
|
module Metrics
|
|
|
|
# Class that sends certain metrics to InfluxDB at a specific interval.
|
|
|
|
#
|
|
|
|
# This class is used to gather statistics that can't be directly associated
|
|
|
|
# with a transaction such as system memory usage, garbage collection
|
|
|
|
# statistics, etc.
|
2017-09-10 17:25:29 +05:30
|
|
|
class InfluxSampler < BaseSampler
|
2016-01-14 18:37:52 +05:30
|
|
|
# interval - The sampling interval in seconds.
|
2016-01-19 16:12:03 +05:30
|
|
|
def initialize(interval = Metrics.settings[:sample_interval])
|
2017-09-10 17:25:29 +05:30
|
|
|
super(interval)
|
|
|
|
@last_step = nil
|
2016-01-19 16:12:03 +05:30
|
|
|
|
|
|
|
@metrics = []
|
2016-01-14 18:37:52 +05:30
|
|
|
|
|
|
|
@last_minor_gc = Delta.new(GC.stat[:minor_gc_count])
|
|
|
|
@last_major_gc = Delta.new(GC.stat[:major_gc_count])
|
|
|
|
|
|
|
|
if Gitlab::Metrics.mri?
|
|
|
|
require 'allocations'
|
|
|
|
|
|
|
|
Allocations.start
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def sample
|
|
|
|
sample_memory_usage
|
|
|
|
sample_file_descriptors
|
|
|
|
sample_objects
|
|
|
|
sample_gc
|
|
|
|
|
|
|
|
flush
|
|
|
|
ensure
|
|
|
|
GC::Profiler.clear
|
|
|
|
@metrics.clear
|
|
|
|
end
|
|
|
|
|
|
|
|
def flush
|
|
|
|
Metrics.submit_metrics(@metrics.map(&:to_hash))
|
|
|
|
end
|
|
|
|
|
|
|
|
def sample_memory_usage
|
|
|
|
add_metric('memory_usage', value: System.memory_usage)
|
|
|
|
end
|
|
|
|
|
|
|
|
def sample_file_descriptors
|
|
|
|
add_metric('file_descriptors', value: System.file_descriptor_count)
|
|
|
|
end
|
|
|
|
|
|
|
|
if Metrics.mri?
|
|
|
|
def sample_objects
|
|
|
|
sample = Allocations.to_hash
|
|
|
|
counts = sample.each_with_object({}) do |(klass, count), hash|
|
2016-06-16 23:09:34 +05:30
|
|
|
name = klass.name
|
|
|
|
|
|
|
|
next unless name
|
|
|
|
|
|
|
|
hash[name] = count
|
2016-01-14 18:37:52 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
# Symbols aren't allocated so we'll need to add those manually.
|
|
|
|
counts['Symbol'] = Symbol.all_symbols.length
|
|
|
|
|
|
|
|
counts.each do |name, count|
|
|
|
|
add_metric('object_counts', { count: count }, type: name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
def sample_objects
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def sample_gc
|
2017-09-10 17:25:29 +05:30
|
|
|
time = GC::Profiler.total_time * 1000.0
|
2016-01-14 18:37:52 +05:30
|
|
|
stats = GC.stat.merge(total_time: time)
|
|
|
|
|
|
|
|
# We want the difference of GC runs compared to the last sample, not the
|
|
|
|
# total amount since the process started.
|
|
|
|
stats[:minor_gc_count] =
|
|
|
|
@last_minor_gc.compared_with(stats[:minor_gc_count])
|
|
|
|
|
|
|
|
stats[:major_gc_count] =
|
|
|
|
@last_major_gc.compared_with(stats[:major_gc_count])
|
|
|
|
|
|
|
|
stats[:count] = stats[:minor_gc_count] + stats[:major_gc_count]
|
|
|
|
|
|
|
|
add_metric('gc_statistics', stats)
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_metric(series, values, tags = {})
|
|
|
|
prefix = sidekiq? ? 'sidekiq_' : 'rails_'
|
|
|
|
|
|
|
|
@metrics << Metric.new("#{prefix}#{series}", values, tags)
|
|
|
|
end
|
|
|
|
|
|
|
|
def sidekiq?
|
|
|
|
Sidekiq.server?
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|