Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
ebc74f8f61
commit
e8e149fc94
|
|
@ -21,6 +21,10 @@ module Gitlab
|
||||||
payload['exception.cause_class'] = exception.cause.class.name
|
payload['exception.cause_class'] = exception.cause.class.name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if gitaly_metadata = find_gitaly_metadata(exception)
|
||||||
|
payload['exception.gitaly'] = gitaly_metadata.to_s
|
||||||
|
end
|
||||||
|
|
||||||
if sql = find_sql(exception)
|
if sql = find_sql(exception)
|
||||||
payload['exception.sql'] = sql
|
payload['exception.sql'] = sql
|
||||||
end
|
end
|
||||||
|
|
@ -35,6 +39,16 @@ module Gitlab
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_gitaly_metadata(exception)
|
||||||
|
if exception.is_a?(::Gitlab::Git::BaseError)
|
||||||
|
exception.metadata
|
||||||
|
elsif exception.is_a?(::GRPC::BadStatus)
|
||||||
|
exception.metadata[::Gitlab::Git::BaseError::METADATA_KEY]
|
||||||
|
elsif exception.cause.present?
|
||||||
|
find_gitaly_metadata(exception.cause)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def normalize_query(sql)
|
def normalize_query(sql)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ require 'grpc'
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Git
|
module Git
|
||||||
class BaseError < StandardError
|
class BaseError < StandardError
|
||||||
|
METADATA_KEY = :gitaly_error_metadata
|
||||||
DEBUG_ERROR_STRING_REGEX = /(.*?) debug_error_string:.*$/m.freeze
|
DEBUG_ERROR_STRING_REGEX = /(.*?) debug_error_string:.*$/m.freeze
|
||||||
GRPC_CODES = {
|
GRPC_CODES = {
|
||||||
'0' => 'ok',
|
'0' => 'ok',
|
||||||
|
|
@ -25,12 +26,15 @@ module Gitlab
|
||||||
'16' => 'unauthenticated'
|
'16' => 'unauthenticated'
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
attr_reader :status, :code, :service
|
attr_reader :status, :code, :service, :metadata
|
||||||
|
|
||||||
def initialize(msg = nil)
|
def initialize(msg = nil)
|
||||||
super && return if msg.nil?
|
super && return if msg.nil?
|
||||||
|
|
||||||
set_grpc_error_code(msg) if msg.is_a?(::GRPC::BadStatus)
|
if msg.is_a?(::GRPC::BadStatus)
|
||||||
|
set_grpc_error_code(msg)
|
||||||
|
set_grpc_error_metadata(msg)
|
||||||
|
end
|
||||||
|
|
||||||
super(build_raw_message(msg))
|
super(build_raw_message(msg))
|
||||||
end
|
end
|
||||||
|
|
@ -46,6 +50,10 @@ module Gitlab
|
||||||
@code = GRPC_CODES[@status.to_s]
|
@code = GRPC_CODES[@status.to_s]
|
||||||
@service = 'git'
|
@service = 'git'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_grpc_error_metadata(grpc_error)
|
||||||
|
@metadata = grpc_error.metadata.fetch(METADATA_KEY, {}).clone
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ module Gitlab
|
||||||
end
|
end
|
||||||
rescue StandardError => err
|
rescue StandardError => err
|
||||||
store_timings
|
store_timings
|
||||||
|
set_gitaly_error_metadata(err) if err.is_a?(::GRPC::BadStatus)
|
||||||
|
|
||||||
raise err
|
raise err
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -44,6 +46,9 @@ module Gitlab
|
||||||
|
|
||||||
yielder.yield(value)
|
yielder.yield(value)
|
||||||
end
|
end
|
||||||
|
rescue ::GRPC::BadStatus => err
|
||||||
|
set_gitaly_error_metadata(err)
|
||||||
|
raise err
|
||||||
ensure
|
ensure
|
||||||
store_timings
|
store_timings
|
||||||
end
|
end
|
||||||
|
|
@ -73,6 +78,15 @@ module Gitlab
|
||||||
backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller)
|
backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_gitaly_error_metadata(err)
|
||||||
|
err.metadata[::Gitlab::Git::BaseError::METADATA_KEY] = {
|
||||||
|
storage: @storage,
|
||||||
|
address: ::Gitlab::GitalyClient.address(@storage),
|
||||||
|
service: @service,
|
||||||
|
rpc: @rpc
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -67,5 +67,53 @@ RSpec.describe Gitlab::ExceptionLogFormatter do
|
||||||
expect(payload['exception.sql']).to eq('SELECT SELECT FROM SELECT')
|
expect(payload['exception.sql']).to eq('SELECT SELECT FROM SELECT')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when exception is a gRPC bad status' do
|
||||||
|
let(:unavailable_error) do
|
||||||
|
::GRPC::Unavailable.new(
|
||||||
|
"unavailable",
|
||||||
|
gitaly_error_metadata: {
|
||||||
|
storage: 'default',
|
||||||
|
address: 'unix://gitaly.socket',
|
||||||
|
service: :ref_service,
|
||||||
|
rpc: :find_local_branches
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the gRPC error is wrapped by ::Gitlab::Git::BaseError' do
|
||||||
|
let(:exception) { ::Gitlab::Git::CommandError.new(unavailable_error) }
|
||||||
|
|
||||||
|
it 'adds gitaly metadata to payload' do
|
||||||
|
described_class.format!(exception, payload)
|
||||||
|
|
||||||
|
expect(payload['exception.gitaly']).to eq('{:storage=>"default", :address=>"unix://gitaly.socket", :service=>:ref_service, :rpc=>:find_local_branches}')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the gRPC error is wrapped by another error' do
|
||||||
|
before do
|
||||||
|
allow(exception).to receive(:cause).and_return(unavailable_error)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'adds gitaly metadata to payload' do
|
||||||
|
described_class.format!(exception, payload)
|
||||||
|
|
||||||
|
expect(payload['exception.cause_class']).to eq('GRPC::Unavailable')
|
||||||
|
expect(payload['exception.gitaly']).to eq('{:storage=>"default", :address=>"unix://gitaly.socket", :service=>:ref_service, :rpc=>:find_local_branches}')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the gRPC error is not wrapped' do
|
||||||
|
let(:exception) { unavailable_error }
|
||||||
|
|
||||||
|
it 'adds gitaly metadata to payload' do
|
||||||
|
described_class.format!(exception, payload)
|
||||||
|
|
||||||
|
expect(payload['exception.cause_class']).to be_nil
|
||||||
|
expect(payload['exception.gitaly']).to eq('{:storage=>"default", :address=>"unix://gitaly.socket", :service=>:ref_service, :rpc=>:find_local_branches}')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ RSpec.describe Gitlab::Git::BaseError do
|
||||||
it { is_expected.to eq(result) }
|
it { is_expected.to eq(result) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "When initialized with GRPC errors" do
|
describe "when initialized with GRPC errors without metadata" do
|
||||||
let(:grpc_error) { GRPC::DeadlineExceeded.new }
|
let(:grpc_error) { GRPC::DeadlineExceeded.new }
|
||||||
let(:git_error) { described_class.new grpc_error }
|
let(:git_error) { described_class.new grpc_error }
|
||||||
|
|
||||||
|
|
@ -29,6 +29,33 @@ RSpec.describe Gitlab::Git::BaseError do
|
||||||
expect(git_error.service).to eq('git')
|
expect(git_error.service).to eq('git')
|
||||||
expect(git_error.status).to eq(4)
|
expect(git_error.status).to eq(4)
|
||||||
expect(git_error.code).to eq('deadline_exceeded')
|
expect(git_error.code).to eq('deadline_exceeded')
|
||||||
|
expect(git_error.metadata).to eq({})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when initialized with GRPC errors with metadata" do
|
||||||
|
let(:grpc_error) do
|
||||||
|
GRPC::DeadlineExceeded.new(
|
||||||
|
"deadline exceeded",
|
||||||
|
gitaly_error_metadata: {
|
||||||
|
storage: "default",
|
||||||
|
address: "unix://gitaly.socket",
|
||||||
|
service: :ref_service, rpc: :find_local_branches
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:git_error) { described_class.new grpc_error }
|
||||||
|
|
||||||
|
it "has status, code, and metadata fields" do
|
||||||
|
expect(git_error.service).to eq('git')
|
||||||
|
expect(git_error.status).to eq(4)
|
||||||
|
expect(git_error.code).to eq('deadline_exceeded')
|
||||||
|
expect(git_error.metadata).to eq(
|
||||||
|
storage: "default",
|
||||||
|
address: "unix://gitaly.socket",
|
||||||
|
service: :ref_service, rpc: :find_local_branches
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
RSpec.describe Gitlab::GitalyClient::Call do
|
RSpec.describe Gitlab::GitalyClient::Call, feature_category: :gitaly do
|
||||||
describe '#call', :request_store do
|
describe '#call', :request_store do
|
||||||
let(:client) { Gitlab::GitalyClient }
|
let(:client) { Gitlab::GitalyClient }
|
||||||
let(:storage) { 'default' }
|
let(:storage) { 'default' }
|
||||||
|
|
@ -50,7 +50,7 @@ RSpec.describe Gitlab::GitalyClient::Call do
|
||||||
expect_call_details_to_match
|
expect_call_details_to_match
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when err' do
|
context 'when the call raises an standard error' do
|
||||||
before do
|
before do
|
||||||
allow(client).to receive(:execute).and_raise(StandardError)
|
allow(client).to receive(:execute).and_raise(StandardError)
|
||||||
end
|
end
|
||||||
|
|
@ -62,6 +62,25 @@ RSpec.describe Gitlab::GitalyClient::Call do
|
||||||
expect_call_details_to_match
|
expect_call_details_to_match
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the call raises a BadStatus error' do
|
||||||
|
before do
|
||||||
|
allow(client).to receive(:execute).and_raise(GRPC::Unavailable)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'attaches gitaly metadata' do
|
||||||
|
expect { subject }.to raise_error do |err|
|
||||||
|
expect(err.metadata).to eql(
|
||||||
|
gitaly_error_metadata: {
|
||||||
|
storage: storage,
|
||||||
|
address: client.address(storage),
|
||||||
|
service: service,
|
||||||
|
rpc: rpc
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the response is an enumerator' do
|
context 'when the response is an enumerator' do
|
||||||
|
|
@ -103,7 +122,7 @@ RSpec.describe Gitlab::GitalyClient::Call do
|
||||||
expect_call_details_to_match(duration_higher_than: 0.1)
|
expect_call_details_to_match(duration_higher_than: 0.1)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when err' do
|
context 'when the call raises an standard error' do
|
||||||
let(:response) do
|
let(:response) do
|
||||||
Enumerator.new do |yielder|
|
Enumerator.new do |yielder|
|
||||||
sleep 0.2
|
sleep 0.2
|
||||||
|
|
@ -119,6 +138,28 @@ RSpec.describe Gitlab::GitalyClient::Call do
|
||||||
expect_call_details_to_match(duration_higher_than: 0.2)
|
expect_call_details_to_match(duration_higher_than: 0.2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the call raises a BadStatus error' do
|
||||||
|
let(:response) do
|
||||||
|
Enumerator.new do |yielder|
|
||||||
|
yielder << 1
|
||||||
|
raise GRPC::Unavailable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'attaches gitaly metadata' do
|
||||||
|
expect { subject.to_a }.to raise_error do |err|
|
||||||
|
expect(err.metadata).to eql(
|
||||||
|
gitaly_error_metadata: {
|
||||||
|
storage: storage,
|
||||||
|
address: client.address(storage),
|
||||||
|
service: service,
|
||||||
|
rpc: rpc
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue