Add the following: * Container name, machine name, worker id. * Container uptime, puma uptime, worker uptime. * Number of requests processed by current worker. * ExifTool version. Also change /status page to show information in tables instead of lists.
194 lines
4.7 KiB
Ruby
194 lines
4.7 KiB
Ruby
# Returns status information about the running server, including software
|
|
# versions, basic load info, and Redis and Postgres info.
|
|
#
|
|
# @see StatusController
|
|
# @see https://danbooru.donmai.us/status
|
|
class ServerStatus
|
|
extend Memoist
|
|
include ActiveModel::Serializers::JSON
|
|
include ActiveModel::Serializers::Xml
|
|
|
|
attr_reader :request
|
|
|
|
def initialize(request)
|
|
@request = request
|
|
end
|
|
|
|
def serializable_hash(options = {})
|
|
{
|
|
ip: request.remote_ip,
|
|
headers: http_headers,
|
|
instance: {
|
|
container_name: container_name,
|
|
instance_name: instance_name,
|
|
worker_name: worker_name,
|
|
container_uptime: container_uptime,
|
|
instance_uptime: instance_uptime,
|
|
worker_uptime: worker_uptime,
|
|
requests_processed: requests_processed,
|
|
danbooru_version: danbooru_version,
|
|
ruby_version: RUBY_VERSION,
|
|
distro_version: distro_version,
|
|
libvips_version: libvips_version,
|
|
ffmpeg_version: ffmpeg_version,
|
|
mkvmerge_version: mkvmerge_version,
|
|
exiftool_version: exiftool_version,
|
|
redis_version: redis_version,
|
|
postgres_version: postgres_version,
|
|
},
|
|
server: {
|
|
node_name: node_name,
|
|
node_uptime: node_uptime,
|
|
loadavg: loadavg,
|
|
kernel_version: kernel_version,
|
|
},
|
|
postgres: {
|
|
connection_stats: postgres_connection_stats,
|
|
},
|
|
redis: {
|
|
info: redis_info,
|
|
}
|
|
}
|
|
end
|
|
|
|
concerning :InfoMethods do
|
|
def http_headers
|
|
headers = request.headers.env.select { |key| key.starts_with?("HTTP_") }
|
|
headers = headers.transform_keys { |key| key.delete_prefix("HTTP_").titleize.tr(" ", "-") }
|
|
headers = headers.except("Cookie")
|
|
headers = headers.reject { |k, v| v.blank? }
|
|
headers
|
|
end
|
|
|
|
def hostname
|
|
Socket.gethostname
|
|
end
|
|
|
|
def instance_name
|
|
if container_name.present?
|
|
"#{container_name}/#{node_name}"
|
|
else
|
|
node_name
|
|
end
|
|
end
|
|
|
|
def container_name
|
|
ENV["K8S_POD_NAME"]
|
|
end
|
|
|
|
def node_name
|
|
ENV["K8S_NODE_NAME"] || hostname
|
|
end
|
|
|
|
def worker_name
|
|
Thread.current.object_id
|
|
end
|
|
|
|
def node_uptime
|
|
uptime = File.read("/proc/uptime").split[0].to_f.seconds
|
|
Danbooru::Helpers.distance_of_time_in_words(uptime)
|
|
end
|
|
|
|
def container_uptime
|
|
started_at = File.stat("/proc/1").mtime
|
|
uptime = Time.zone.now - started_at
|
|
Danbooru::Helpers.distance_of_time_in_words(uptime)
|
|
end
|
|
|
|
def instance_uptime
|
|
started_at = File.stat("/proc/#{Process.ppid}").mtime
|
|
uptime = Time.zone.now - started_at
|
|
Danbooru::Helpers.distance_of_time_in_words(uptime)
|
|
end
|
|
|
|
def worker_uptime
|
|
started_at = File.stat("/proc/#{Process.pid}").mtime
|
|
uptime = Time.zone.now - started_at
|
|
Danbooru::Helpers.distance_of_time_in_words(uptime)
|
|
end
|
|
|
|
def requests_processed
|
|
if Puma::Server.current.present?
|
|
Puma::Server.current.requests_count
|
|
end
|
|
end
|
|
|
|
def loadavg
|
|
File.read("/proc/loadavg").chomp
|
|
end
|
|
|
|
def danbooru_version
|
|
Rails.application.config.x.git_hash
|
|
end
|
|
|
|
def kernel_version
|
|
File.read("/proc/version").chomp
|
|
end
|
|
|
|
def distro_version
|
|
`. /etc/os-release; echo "$NAME $VERSION"`.chomp
|
|
end
|
|
|
|
def libvips_version
|
|
Vips::LIBRARY_VERSION
|
|
end
|
|
|
|
def ffmpeg_version
|
|
version = `ffmpeg -version`
|
|
version[/ffmpeg version ([0-9.]+)/, 1]
|
|
end
|
|
|
|
def mkvmerge_version
|
|
`mkvmerge --version`.chomp
|
|
end
|
|
|
|
def exiftool_version
|
|
`exiftool -ver`.chomp
|
|
end
|
|
end
|
|
|
|
concerning :RedisMethods do
|
|
def redis_info
|
|
return {} if Rails.cache.try(:redis).nil?
|
|
Rails.cache.redis.info
|
|
end
|
|
|
|
def redis_used_memory
|
|
redis_info["used_memory_rss_human"]
|
|
end
|
|
|
|
def redis_version
|
|
redis_info["redis_version"]
|
|
end
|
|
end
|
|
|
|
concerning :PostgresMethods do
|
|
def postgres_version
|
|
ApplicationRecord.connection.select_value("SELECT version()")
|
|
end
|
|
|
|
def postgres_active_connections
|
|
ApplicationRecord.connection.select_value("SELECT COUNT(*) FROM pg_stat_activity WHERE state = 'active'")
|
|
end
|
|
|
|
def postgres_connection_stats
|
|
run_query("SELECT pid, state, query_start, state_change, xact_start, backend_start, backend_type FROM pg_stat_activity ORDER BY state, query_start DESC, backend_type")
|
|
end
|
|
|
|
def run_query(query)
|
|
result = ApplicationRecord.connection.select_all(query)
|
|
serialize_result(result)
|
|
end
|
|
|
|
def serialize_result(result)
|
|
result.rows.map do |row|
|
|
row.each_with_index.map do |col, i|
|
|
[result.columns[i], col]
|
|
end.to_h
|
|
end
|
|
end
|
|
end
|
|
|
|
memoize :redis_info
|
|
end
|