2019-08-22 06:57:44 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2018-04-01 03:46:52 -04:00
|
|
|
require 'spec_helper'
|
|
|
|
|
|
|
|
describe Gitlab::SidekiqLogging::StructuredLogger do
|
|
|
|
describe '#call' do
|
2019-07-31 08:07:47 -04:00
|
|
|
let(:timestamp) { Time.iso8601('2018-01-01T12:00:00Z') }
|
2019-08-08 23:51:40 -04:00
|
|
|
let(:created_at) { timestamp - 1.second }
|
|
|
|
let(:scheduling_latency_s) { 1.0 }
|
2019-07-31 08:07:47 -04:00
|
|
|
|
2018-04-01 03:46:52 -04:00
|
|
|
let(:job) do
|
|
|
|
{
|
|
|
|
"class" => "TestWorker",
|
|
|
|
"args" => [1234, 'hello'],
|
|
|
|
"retry" => false,
|
|
|
|
"queue" => "cronjob:test_queue",
|
|
|
|
"queue_namespace" => "cronjob",
|
|
|
|
"jid" => "da883554ee4fe414012f5f42",
|
2019-07-31 08:07:47 -04:00
|
|
|
"created_at" => created_at.to_f,
|
|
|
|
"enqueued_at" => created_at.to_f,
|
2018-12-06 15:46:31 -05:00
|
|
|
"correlation_id" => 'cid'
|
2018-04-01 03:46:52 -04:00
|
|
|
}
|
|
|
|
end
|
2019-07-31 08:07:47 -04:00
|
|
|
|
2019-01-24 08:43:02 -05:00
|
|
|
let(:logger) { double }
|
2018-04-01 03:46:52 -04:00
|
|
|
let(:start_payload) do
|
|
|
|
job.merge(
|
|
|
|
'message' => 'TestWorker JID-da883554ee4fe414012f5f42: start',
|
|
|
|
'job_status' => 'start',
|
|
|
|
'pid' => Process.pid,
|
2019-07-31 08:07:47 -04:00
|
|
|
'created_at' => created_at.iso8601(3),
|
|
|
|
'enqueued_at' => created_at.iso8601(3),
|
|
|
|
'scheduling_latency_s' => scheduling_latency_s
|
2018-04-01 03:46:52 -04:00
|
|
|
)
|
|
|
|
end
|
|
|
|
let(:end_payload) do
|
|
|
|
start_payload.merge(
|
|
|
|
'message' => 'TestWorker JID-da883554ee4fe414012f5f42: done: 0.0 sec',
|
|
|
|
'job_status' => 'done',
|
|
|
|
'duration' => 0.0,
|
2019-08-22 10:31:57 -04:00
|
|
|
"completed_at" => timestamp.iso8601(3),
|
|
|
|
"system_s" => 0.0,
|
|
|
|
"user_s" => 0.0
|
2018-04-01 03:46:52 -04:00
|
|
|
)
|
|
|
|
end
|
|
|
|
let(:exception_payload) do
|
|
|
|
end_payload.merge(
|
|
|
|
'message' => 'TestWorker JID-da883554ee4fe414012f5f42: fail: 0.0 sec',
|
|
|
|
'job_status' => 'fail',
|
|
|
|
'error' => ArgumentError,
|
|
|
|
'error_message' => 'some exception'
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
allow(Sidekiq).to receive(:logger).and_return(logger)
|
|
|
|
|
|
|
|
allow(subject).to receive(:current_time).and_return(timestamp.to_f)
|
2019-08-22 10:31:57 -04:00
|
|
|
|
|
|
|
allow(Process).to receive(:times).and_return(
|
|
|
|
stime: 0.0,
|
|
|
|
utime: 0.0,
|
|
|
|
cutime: 0.0,
|
|
|
|
cstime: 0.0
|
|
|
|
)
|
2018-04-01 03:46:52 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
subject { described_class.new }
|
|
|
|
|
|
|
|
context 'with SIDEKIQ_LOG_ARGUMENTS enabled' do
|
|
|
|
before do
|
|
|
|
stub_env('SIDEKIQ_LOG_ARGUMENTS', '1')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'logs start and end of job' do
|
|
|
|
Timecop.freeze(timestamp) do
|
|
|
|
expect(logger).to receive(:info).with(start_payload).ordered
|
|
|
|
expect(logger).to receive(:info).with(end_payload).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
|
|
|
|
|
|
|
|
it 'logs an exception in job' do
|
|
|
|
Timecop.freeze(timestamp) do
|
|
|
|
expect(logger).to receive(:info).with(start_payload)
|
|
|
|
# This excludes the exception_backtrace
|
|
|
|
expect(logger).to receive(:warn).with(hash_including(exception_payload))
|
|
|
|
expect(subject).to receive(:log_job_start).and_call_original
|
|
|
|
expect(subject).to receive(:log_job_done).and_call_original
|
|
|
|
|
|
|
|
expect do
|
|
|
|
subject.call(job, 'test_queue') do
|
|
|
|
raise ArgumentError, 'some exception'
|
|
|
|
end
|
|
|
|
end.to raise_error(ArgumentError)
|
|
|
|
end
|
|
|
|
end
|
2019-01-18 11:21:38 -05:00
|
|
|
|
|
|
|
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
|
|
|
|
job['args'] = [
|
|
|
|
1,
|
|
|
|
2,
|
|
|
|
'a' * (described_class::MAXIMUM_JOB_ARGUMENTS_LENGTH / 2),
|
|
|
|
'b' * (described_class::MAXIMUM_JOB_ARGUMENTS_LENGTH / 2),
|
|
|
|
3
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_args = job['args'].take(3) + ['...']
|
|
|
|
|
|
|
|
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
|
2018-04-01 03:46:52 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'with SIDEKIQ_LOG_ARGUMENTS disabled' do
|
2019-01-18 11:21:38 -05:00
|
|
|
it 'logs start and end of job without args' do
|
2018-04-01 03:46:52 -04:00
|
|
|
Timecop.freeze(timestamp) do
|
2019-01-18 11:21:38 -05:00
|
|
|
expect(logger).to receive(:info).with(start_payload.except('args')).ordered
|
|
|
|
expect(logger).to receive(:info).with(end_payload.except('args')).ordered
|
2018-04-01 03:46:52 -04:00
|
|
|
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
|
2019-07-31 08:07:47 -04:00
|
|
|
|
|
|
|
it 'logs without created_at and enqueued_at fields' do
|
|
|
|
Timecop.freeze(timestamp) do
|
|
|
|
excluded_fields = %w(created_at enqueued_at args scheduling_latency_s)
|
|
|
|
|
|
|
|
expect(logger).to receive(:info).with(start_payload.except(*excluded_fields)).ordered
|
|
|
|
expect(logger).to receive(:info).with(end_payload.except(*excluded_fields)).ordered
|
|
|
|
expect(subject).to receive(:log_job_start).and_call_original
|
|
|
|
expect(subject).to receive(:log_job_done).and_call_original
|
|
|
|
|
|
|
|
subject.call(job.except("created_at", "enqueued_at"), 'test_queue') { }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with latency' do
|
|
|
|
let(:created_at) { Time.iso8601('2018-01-01T10:00:00Z') }
|
|
|
|
let(:scheduling_latency_s) { 7200.0 }
|
|
|
|
|
|
|
|
it 'logs with scheduling latency' do
|
|
|
|
Timecop.freeze(timestamp) do
|
|
|
|
expect(logger).to receive(:info).with(start_payload.except('args')).ordered
|
|
|
|
expect(logger).to receive(:info).with(end_payload.except('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
|
2018-04-01 03:46:52 -04:00
|
|
|
end
|
2019-08-09 00:33:20 -04:00
|
|
|
|
|
|
|
context 'with Gitaly and Rugged calls' do
|
|
|
|
let(:timing_data) do
|
|
|
|
{
|
|
|
|
gitaly_calls: 10,
|
|
|
|
gitaly_duration: 10000,
|
|
|
|
rugged_calls: 1,
|
|
|
|
rugged_duration_ms: 5000
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
job.merge!(timing_data)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'logs with Gitaly and Rugged timing data' do
|
|
|
|
Timecop.freeze(timestamp) do
|
|
|
|
expect(logger).to receive(:info).with(start_payload.except('args')).ordered
|
|
|
|
expect(logger).to receive(:info).with(end_payload.except('args')).ordered
|
|
|
|
|
|
|
|
subject.call(job, 'test_queue') { }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-08-22 10:31:57 -04:00
|
|
|
|
|
|
|
def ctime(times)
|
|
|
|
times[:cstime] + times[:cutime]
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with ctime value greater than 0' do
|
|
|
|
let(:times_start) { { stime: 0.04999, utime: 0.0483, cstime: 0.0188, cutime: 0.0188 } }
|
|
|
|
let(:times_end) { { stime: 0.0699, utime: 0.0699, cstime: 0.0399, cutime: 0.0399 } }
|
|
|
|
|
|
|
|
before do
|
|
|
|
end_payload['system_s'] = 0.02
|
|
|
|
end_payload['user_s'] = 0.022
|
|
|
|
end_payload['child_s'] = 0.042
|
|
|
|
|
|
|
|
allow(Process).to receive(:times).and_return(times_start, times_end)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'logs with ctime data and other cpu data' do
|
|
|
|
Timecop.freeze(timestamp) do
|
|
|
|
expect(logger).to receive(:info).with(start_payload.except('args')).ordered
|
|
|
|
expect(logger).to receive(:info).with(end_payload.except('args')).ordered
|
|
|
|
|
|
|
|
subject.call(job, 'test_queue') { }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2018-04-01 03:46:52 -04:00
|
|
|
end
|
|
|
|
end
|