Commit b5cf18b0 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'sh-flatten-sidekiq-exception-logs' into 'master'

Stringify Sidekiq job args in exception logs

Closes #213639

See merge request gitlab-org/gitlab!28996
parents 004ecae8 6096875c
---
title: Stringify Sidekiq job args in exception logs
merge_request: 28996
author:
type: fixed
...@@ -19,6 +19,7 @@ module Gitlab ...@@ -19,6 +19,7 @@ module Gitlab
output[:message] = data output[:message] = data
when Hash when Hash
convert_to_iso8601!(data) convert_to_iso8601!(data)
stringify_args!(data)
output.merge!(data) output.merge!(data)
end end
...@@ -39,6 +40,10 @@ module Gitlab ...@@ -39,6 +40,10 @@ module Gitlab
Time.at(timestamp).utc.iso8601(3) Time.at(timestamp).utc.iso8601(3)
end end
def stringify_args!(payload)
payload['args'] = Gitlab::Utils::LogLimitedArray.log_limited_array(payload['args'].map(&:to_s)) if payload['args']
end
end end
end end
end end
...@@ -7,6 +7,7 @@ module Gitlab ...@@ -7,6 +7,7 @@ module Gitlab
"#{payload['class']} JID-#{payload['jid']}" "#{payload['class']} JID-#{payload['jid']}"
end end
# NOTE: Arguments are truncated/stringified in sidekiq_logging/json_formatter.rb
def parse_job(job) def parse_job(job)
# Error information from the previous try is in the payload for # Error information from the previous try is in the payload for
# displaying in the Sidekiq UI, but is very confusing in logs! # displaying in the Sidekiq UI, but is very confusing in logs!
...@@ -16,7 +17,6 @@ module Gitlab ...@@ -16,7 +17,6 @@ module Gitlab
job['pid'] = ::Process.pid job['pid'] = ::Process.pid
job.delete('args') unless ENV['SIDEKIQ_LOG_ARGUMENTS'] job.delete('args') unless ENV['SIDEKIQ_LOG_ARGUMENTS']
job['args'] = Gitlab::Utils::LogLimitedArray.log_limited_array(job['args'].map(&:to_s)) if job['args']
job job
end end
......
...@@ -9,6 +9,8 @@ describe Gitlab::SidekiqLogging::JSONFormatter do ...@@ -9,6 +9,8 @@ describe Gitlab::SidekiqLogging::JSONFormatter do
let(:timestamp_iso8601) { now.iso8601(3) } let(:timestamp_iso8601) { now.iso8601(3) }
describe 'with a Hash' do describe 'with a Hash' do
subject { JSON.parse(described_class.new.call('INFO', now, 'my program', hash_input)) }
let(:hash_input) do let(:hash_input) do
{ {
foo: 1, foo: 1,
...@@ -23,9 +25,6 @@ describe Gitlab::SidekiqLogging::JSONFormatter do ...@@ -23,9 +25,6 @@ describe Gitlab::SidekiqLogging::JSONFormatter do
end end
it 'properly formats timestamps into ISO 8601 form' do it 'properly formats timestamps into ISO 8601 form' do
result = subject.call('INFO', now, 'my program', hash_input)
data = JSON.parse(result)
expected_output = hash_input.stringify_keys.merge!( expected_output = hash_input.stringify_keys.merge!(
{ {
'severity' => 'INFO', 'severity' => 'INFO',
...@@ -39,20 +38,39 @@ describe Gitlab::SidekiqLogging::JSONFormatter do ...@@ -39,20 +38,39 @@ describe Gitlab::SidekiqLogging::JSONFormatter do
} }
) )
expect(data).to eq(expected_output) expect(subject).to eq(expected_output)
end
context 'when the job args are bigger than the maximum allowed' do
it 'keeps args from the front until they exceed the limit' do
half_limit = Gitlab::Utils::LogLimitedArray::MAXIMUM_ARRAY_LENGTH / 2
hash_input['args'] = [1, 2, 'a' * half_limit, 'b' * half_limit, 3]
expected_args = hash_input['args'].take(3).map(&:to_s) + ['...']
expect(subject['args']).to eq(expected_args)
end
end
it 'properly flattens arguments to a String' do
hash_input['args'] = [1, "test", 2, { 'test' => 1 }]
expect(subject['args']).to eq(["1", "test", "2", %({"test"=>1})])
end end
end end
it 'wraps a String' do describe 'with a String' do
result = subject.call('DEBUG', now, 'my string', message) it 'accepts strings with no changes' do
result = subject.call('DEBUG', now, 'my string', message)
data = JSON.parse(result) data = JSON.parse(result)
expected_output = { expected_output = {
severity: 'DEBUG', severity: 'DEBUG',
time: timestamp_iso8601, time: timestamp_iso8601,
message: message message: message
} }
expect(data).to eq(expected_output.stringify_keys) expect(data).to eq(expected_output.stringify_keys)
end
end end
end end
...@@ -30,7 +30,6 @@ describe Gitlab::SidekiqLogging::StructuredLogger do ...@@ -30,7 +30,6 @@ describe Gitlab::SidekiqLogging::StructuredLogger do
let(:clock_thread_cputime_end) { 1.333333799 } let(:clock_thread_cputime_end) { 1.333333799 }
let(:start_payload) do let(:start_payload) do
job.except('error_backtrace', 'error_class', 'error_message').merge( job.except('error_backtrace', 'error_class', 'error_message').merge(
'args' => %w(1234 hello {"key"=>"value"}),
'message' => 'TestWorker JID-da883554ee4fe414012f5f42: start', 'message' => 'TestWorker JID-da883554ee4fe414012f5f42: start',
'job_status' => 'start', 'job_status' => 'start',
'pid' => Process.pid, 'pid' => Process.pid,
...@@ -113,24 +112,6 @@ describe Gitlab::SidekiqLogging::StructuredLogger do ...@@ -113,24 +112,6 @@ describe Gitlab::SidekiqLogging::StructuredLogger do
end end
end end
end end
context 'when the job args are bigger than the maximum allowed' do
it 'keeps args from the front until they exceed the limit' do
Timecop.freeze(timestamp) do
half_limit = Gitlab::Utils::LogLimitedArray::MAXIMUM_ARRAY_LENGTH / 2
job['args'] = [1, 2, 'a' * half_limit, 'b' * half_limit, 3]
expected_args = job['args'].take(3).map(&:to_s) + ['...']
expect(logger).to receive(:info).with(start_payload.merge('args' => expected_args)).ordered
expect(logger).to receive(:info).with(end_payload.merge('args' => expected_args)).ordered
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
subject.call(job, 'test_queue') { }
end
end
end
end end
context 'with SIDEKIQ_LOG_ARGUMENTS disabled' do context 'with SIDEKIQ_LOG_ARGUMENTS disabled' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment