Log queue duration for Grape API calls

This mimics the same thing the RailsQueueDuration does for Rails controller
requests and will help diagnose issues with API delays.

Closes #46601
This commit is contained in:
Stan Hu 2018-05-25 21:00:26 -07:00
parent 6e354cb642
commit 16e04e006c
4 changed files with 68 additions and 1 deletions

View file

@ -0,0 +1,5 @@
---
title: Log Workhorse queue duration for Grape API calls
merge_request:
author:
type: other

View file

@ -15,7 +15,8 @@ module API
include: [
GrapeLogging::Loggers::FilterParameters.new,
GrapeLogging::Loggers::ClientEnv.new,
Gitlab::GrapeLogging::Loggers::UserLogger.new
Gitlab::GrapeLogging::Loggers::UserLogger.new,
Gitlab::GrapeLogging::Loggers::QueueDurationLogger.new
]
allow_access_with_scope :api

View file

@ -0,0 +1,26 @@
# This grape_logging module (https://github.com/aserafin/grape_logging) makes it
# possible to log how much time an API request was queued by Workhorse.
module Gitlab
module GrapeLogging
module Loggers
class QueueDurationLogger < ::GrapeLogging::Loggers::Base
attr_accessor :start_time
def before
@start_time = Time.now
end
def parameters(request, _)
proxy_start = request.env['HTTP_GITLAB_WORKHORSE_PROXY_START'].presence
return {} unless proxy_start && start_time
# Time in milliseconds since gitlab-workhorse started the request
duration = (start_time.to_f * 1_000 - proxy_start.to_f / 1_000_000).round(2)
{ 'queue_duration': duration }
end
end
end
end
end

View file

@ -0,0 +1,35 @@
require 'spec_helper'
describe Gitlab::GrapeLogging::Loggers::QueueDurationLogger do
subject { described_class.new }
describe ".parameters" do
let(:start_time) { Time.new(2018, 01, 01) }
describe 'when no proxy time is available' do
let(:mock_request) { OpenStruct.new(env: {}) }
it 'returns an empty hash' do
expect(subject.parameters(mock_request, nil)).to eq({})
end
end
describe 'when a proxy time is available' do
let(:mock_request) do
OpenStruct.new(
env: {
'HTTP_GITLAB_WORKHORSE_PROXY_START' => (start_time - 1.hour).to_i * (10**9)
}
)
end
it 'returns the correct duration in ms' do
Timecop.freeze(start_time) do
subject.before
expect(subject.parameters(mock_request, nil)).to eq( { 'queue_duration': 1.hour.to_f * 1000 })
end
end
end
end
end