# frozen_string_literal: true require 'traxor/rack/middleware/queue_time' module Traxor module Rack module Middleware class Pre MIDDLEWARE_METRIC = 'rack.request.middleware.duration' DURATION_METRIC = 'rack.request.duration' QUEUE_METRIC = 'rack.request.queue.duration' REQUEST_COUNT_METRIC = 'rack.request.count' GC_DURATION_METRIC = 'ruby.gc.duration' GC_COUNT_METRIC = 'ruby.gc.count' MAJOR_METRIC = 'ruby.gc.major.count' MINOR_METRIC = 'ruby.gc.minor.count' ALLOCATED_METRIC = 'ruby.gc.allocated_objects.count' def initialize(app) @app = app end def call(env) Middleware.request_start_at = QueueTime.parse(env) Middleware.pre_start_at = Time.now.utc GC::Profiler.enable Middleware.gc_stat_before = GC.stat status, headers, body = @app.call(env) Middleware.gc_stat_after = GC.stat Middleware.post_finish_at = Time.now.utc record_request_metrics record_gc_metrics [status, headers, body] end def record_request_metrics if Middleware.middleware_total.positive? Metric.measure MIDDLEWARE_METRIC, "#{Middleware.middleware_total.round(2)}ms" end if Middleware.request_total.positive? Metric.measure DURATION_METRIC, "#{Middleware.request_total.round(2)}ms" end if Middleware.request_queue_total.positive? Metric.measure QUEUE_METRIC, "#{Middleware.request_queue_total.round(2)}ms" end Metric.count REQUEST_COUNT_METRIC, 1 end def record_gc_metrics total_gc_time = (GC::Profiler.total_time * 1_000).to_f if total_gc_time.positive? Metric.measure GC_DURATION_METRIC, "#{total_gc_time.round(2)}ms" end Metric.count GC_COUNT_METRIC, Middleware.gc_count Metric.count MAJOR_METRIC, Middleware.gc_major_count Metric.count MINOR_METRIC, Middleware.gc_minor_count Metric.count ALLOCATED_METRIC, Middleware.gc_allocated_objects_count GC::Profiler.clear end end end end end