90 lines
3.3 KiB
Ruby
90 lines
3.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
module Metrics
|
|
module Samplers
|
|
class PumaSampler < BaseSampler
|
|
DEFAULT_SAMPLING_INTERVAL_SECONDS = 5
|
|
|
|
def metrics
|
|
@metrics ||= init_metrics
|
|
end
|
|
|
|
def init_metrics
|
|
{
|
|
puma_workers: ::Gitlab::Metrics.gauge(:puma_workers, 'Total number of workers'),
|
|
puma_running_workers: ::Gitlab::Metrics.gauge(:puma_running_workers, 'Number of active workers'),
|
|
puma_stale_workers: ::Gitlab::Metrics.gauge(:puma_stale_workers, 'Number of stale workers'),
|
|
puma_running: ::Gitlab::Metrics.gauge(:puma_running, 'Number of running threads'),
|
|
puma_queued_connections: ::Gitlab::Metrics.gauge(:puma_queued_connections, 'Number of connections in that worker\'s "todo" set waiting for a worker thread'),
|
|
puma_active_connections: ::Gitlab::Metrics.gauge(:puma_active_connections, 'Number of threads processing a request'),
|
|
puma_pool_capacity: ::Gitlab::Metrics.gauge(:puma_pool_capacity, 'Number of requests the worker is capable of taking right now'),
|
|
puma_max_threads: ::Gitlab::Metrics.gauge(:puma_max_threads, 'Maximum number of worker threads'),
|
|
puma_idle_threads: ::Gitlab::Metrics.gauge(:puma_idle_threads, 'Number of spawned threads which are not processing a request')
|
|
}
|
|
end
|
|
|
|
def sample
|
|
json_stats = puma_stats
|
|
return unless json_stats
|
|
|
|
stats = Gitlab::Json.parse(json_stats)
|
|
|
|
if cluster?(stats)
|
|
sample_cluster(stats)
|
|
else
|
|
sample_single_worker(stats)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def puma_stats
|
|
Puma.stats
|
|
rescue NoMethodError
|
|
Gitlab::AppLogger.info "PumaSampler: stats are not available yet, waiting for Puma to boot"
|
|
nil
|
|
end
|
|
|
|
def sample_cluster(stats)
|
|
set_master_metrics(stats)
|
|
|
|
stats['worker_status'].each do |worker|
|
|
last_status = worker['last_status']
|
|
labels = { worker: "worker_#{worker['index']}" }
|
|
|
|
set_worker_metrics(last_status, labels) if last_status.present?
|
|
end
|
|
end
|
|
|
|
def sample_single_worker(stats)
|
|
metrics[:puma_workers].set({}, 1)
|
|
metrics[:puma_running_workers].set({}, 1)
|
|
|
|
set_worker_metrics(stats)
|
|
end
|
|
|
|
def cluster?(stats)
|
|
stats['worker_status'].present?
|
|
end
|
|
|
|
def set_master_metrics(stats)
|
|
labels = { worker: "master" }
|
|
|
|
metrics[:puma_workers].set(labels, stats['workers'])
|
|
metrics[:puma_running_workers].set(labels, stats['booted_workers'])
|
|
metrics[:puma_stale_workers].set(labels, stats['old_workers'])
|
|
end
|
|
|
|
def set_worker_metrics(stats, labels = {})
|
|
metrics[:puma_running].set(labels, stats['running'])
|
|
metrics[:puma_queued_connections].set(labels, stats['backlog'])
|
|
metrics[:puma_active_connections].set(labels, stats['max_threads'] - stats['pool_capacity'])
|
|
metrics[:puma_pool_capacity].set(labels, stats['pool_capacity'])
|
|
metrics[:puma_max_threads].set(labels, stats['max_threads'])
|
|
metrics[:puma_idle_threads].set(labels, stats['running'] + stats['pool_capacity'] - stats['max_threads'])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|