loga 2.6.1 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +2 -9
- data/Appraisals +30 -12
- data/CHANGELOG.md +8 -0
- data/README.md +1 -1
- data/gemfiles/{rails32.gemfile → sidekiq60.gemfile} +2 -2
- data/gemfiles/{rails40.gemfile → sidekiq62.gemfile} +2 -2
- data/gemfiles/sidekiq63.gemfile +11 -0
- data/gemfiles/sidekiq64.gemfile +11 -0
- data/gemfiles/sidekiq65.gemfile +11 -0
- data/gemfiles/{sidekiq6.gemfile → sidekiq7.gemfile} +1 -1
- data/gemfiles/sidekiq70.gemfile +11 -0
- data/gemfiles/sidekiq71.gemfile +11 -0
- data/lib/loga/formatters/gelf_formatter.rb +13 -6
- data/lib/loga/sidekiq.rb +32 -9
- data/lib/loga/sidekiq7/job_logger.rb +51 -0
- data/lib/loga/version.rb +1 -1
- data/spec/integration/sidekiq60_spec.rb +180 -0
- data/spec/integration/sidekiq65_spec.rb +166 -0
- data/spec/integration/sidekiq7_spec.rb +193 -0
- data/spec/loga/sidekiq7/job_logger_spec.rb +125 -0
- data/spec/spec_helper.rb +23 -4
- data/spec/unit/loga/formatters/gelf_formatter_spec.rb +23 -0
- metadata +21 -11
- data/spec/fixtures/rails32.rb +0 -80
- data/spec/fixtures/rails40.rb +0 -80
- /data/spec/integration/{sidekiq6_spec.rb → sidekiq61_spec.rb} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc1346e981871beb7504038280a989df0b08f8758de0aafbc2ad6353bf15b37b
|
4
|
+
data.tar.gz: 7cca9a16fd0d79616445d8b497d28064b4e62c5b9ec075594787e069020d031c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b644025cbf6f8ff20b5980d8c261146a3832b2ea0e18eec3efabd1c8d7fbb75b540591fe5eb480a3475c8e646a85fd274a2352c9ed95baebf84ec01c29c8a8b
|
7
|
+
data.tar.gz: 5b5b9ae15e5383bb6b8b48e2a990b340134c2e77391fef261a275ae47e41b95538a9ba95553820d335634bdd8cbd1530f839bae8dade08b8bfd57af18dfd15aa
|
data/.circleci/config.yml
CHANGED
@@ -30,10 +30,6 @@ test_build: &test_build
|
|
30
30
|
|
31
31
|
version: 2
|
32
32
|
jobs:
|
33
|
-
ruby-2.4:
|
34
|
-
docker:
|
35
|
-
- image: circleci/ruby:2.4
|
36
|
-
<<: *test_build
|
37
33
|
ruby-2.5:
|
38
34
|
docker:
|
39
35
|
- image: circleci/ruby:2.5
|
@@ -45,10 +41,12 @@ jobs:
|
|
45
41
|
ruby-2.7:
|
46
42
|
docker:
|
47
43
|
- image: cimg/ruby:2.7
|
44
|
+
- image: redis:7
|
48
45
|
<<: *test_build
|
49
46
|
ruby-3.0:
|
50
47
|
docker:
|
51
48
|
- image: cimg/ruby:3.0
|
49
|
+
- image: redis:7
|
52
50
|
<<: *test_build
|
53
51
|
rubocop:
|
54
52
|
<<: *basic_build
|
@@ -83,10 +81,6 @@ workflows:
|
|
83
81
|
filters:
|
84
82
|
tags:
|
85
83
|
only: /.*/
|
86
|
-
- ruby-2.4:
|
87
|
-
filters:
|
88
|
-
tags:
|
89
|
-
only: /.*/
|
90
84
|
- ruby-2.5:
|
91
85
|
filters:
|
92
86
|
tags:
|
@@ -112,7 +106,6 @@ workflows:
|
|
112
106
|
ignore: /.*/
|
113
107
|
requires:
|
114
108
|
- rubocop
|
115
|
-
- ruby-2.4
|
116
109
|
- ruby-2.5
|
117
110
|
- ruby-2.6
|
118
111
|
- ruby-2.7
|
data/Appraisals
CHANGED
@@ -1,13 +1,3 @@
|
|
1
|
-
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4.0')
|
2
|
-
appraise 'rails32' do
|
3
|
-
gem 'rails', '~> 3.2.0'
|
4
|
-
end
|
5
|
-
|
6
|
-
appraise 'rails40' do
|
7
|
-
gem 'rails', '~> 4.0.0'
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
1
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
|
12
2
|
appraise 'rails42' do
|
13
3
|
gem 'rails', '~> 4.2.0'
|
@@ -31,13 +21,29 @@ if Gem::Version.new(RUBY_VERSION) > Gem::Version.new('2.5.0')
|
|
31
21
|
gem 'rails', '~> 6.0.0'
|
32
22
|
end
|
33
23
|
|
34
|
-
appraise '
|
35
|
-
gem 'sidekiq', '~> 6.0'
|
24
|
+
appraise 'sidekiq60' do
|
25
|
+
gem 'sidekiq', '~> 6.0.0'
|
36
26
|
end
|
37
27
|
|
38
28
|
appraise 'sidekiq61' do
|
39
29
|
gem 'sidekiq', '~> 6.1.0'
|
40
30
|
end
|
31
|
+
|
32
|
+
appraise 'sidekiq62' do
|
33
|
+
gem 'sidekiq', '~> 6.2.0'
|
34
|
+
end
|
35
|
+
|
36
|
+
appraise 'sidekiq63' do
|
37
|
+
gem 'sidekiq', '~> 6.3.0'
|
38
|
+
end
|
39
|
+
|
40
|
+
appraise 'sidekiq64' do
|
41
|
+
gem 'sidekiq', '~> 6.4.0'
|
42
|
+
end
|
43
|
+
|
44
|
+
appraise 'sidekiq65' do
|
45
|
+
gem 'sidekiq', '~> 6.5.0'
|
46
|
+
end
|
41
47
|
end
|
42
48
|
|
43
49
|
if Gem::Version.new(RUBY_VERSION) > Gem::Version.new('2.7.0')
|
@@ -48,6 +54,18 @@ if Gem::Version.new(RUBY_VERSION) > Gem::Version.new('2.7.0')
|
|
48
54
|
appraise 'rails70' do
|
49
55
|
gem 'rails', '~> 7.0.0'
|
50
56
|
end
|
57
|
+
|
58
|
+
appraise 'sidekiq7' do
|
59
|
+
gem 'sidekiq', '~> 7.0'
|
60
|
+
end
|
61
|
+
|
62
|
+
appraise 'sidekiq70' do
|
63
|
+
gem 'sidekiq', '~> 7.0.0'
|
64
|
+
end
|
65
|
+
|
66
|
+
appraise 'sidekiq71' do
|
67
|
+
gem 'sidekiq', '~> 7.1.0'
|
68
|
+
end
|
51
69
|
end
|
52
70
|
|
53
71
|
appraise 'sidekiq51' do
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6
6
|
|
7
|
+
## [2.8.0] - 2023-11-14
|
8
|
+
### Added
|
9
|
+
- Support open-telemetry and add trace_id and span_id to logs events
|
10
|
+
|
11
|
+
## [2.7.0] - 2023-03-28
|
12
|
+
### Added
|
13
|
+
- Support for sidekiq 7
|
14
|
+
|
7
15
|
## [2.6.1] - 2022-02-22
|
8
16
|
### Fixed
|
9
17
|
- Fix compatibility with sidekiq 6.4.1
|
data/README.md
CHANGED
@@ -39,12 +39,7 @@ module Loga
|
|
39
39
|
private
|
40
40
|
|
41
41
|
def build_event(time, message)
|
42
|
-
event =
|
43
|
-
when Loga::Event
|
44
|
-
message
|
45
|
-
else
|
46
|
-
Loga::Event.new(message: message)
|
47
|
-
end
|
42
|
+
event = message.is_a?(Loga::Event) ? message : Loga::Event.new(message: message)
|
48
43
|
|
49
44
|
event.timestamp ||= time
|
50
45
|
# Overwrite sidekiq_context data anything manually specified
|
@@ -54,6 +49,7 @@ module Loga
|
|
54
49
|
hash.merge! compute_type(event.type)
|
55
50
|
# Overwrite hash with Loga's additional fields
|
56
51
|
hash.merge! loga_additional_fields
|
52
|
+
hash.merge! open_telemetry_fields
|
57
53
|
end
|
58
54
|
event
|
59
55
|
end
|
@@ -103,6 +99,17 @@ module Loga
|
|
103
99
|
}
|
104
100
|
end
|
105
101
|
|
102
|
+
def open_telemetry_fields
|
103
|
+
return {} unless defined?(::OpenTelemetry::Trace)
|
104
|
+
|
105
|
+
span = ::OpenTelemetry::Trace.current_span
|
106
|
+
|
107
|
+
{
|
108
|
+
trace_id: span.context.hex_trace_id,
|
109
|
+
span_id: span.context.hex_span_id,
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
106
113
|
def sidekiq_context
|
107
114
|
return {} unless defined?(::Sidekiq::Context)
|
108
115
|
|
data/lib/loga/sidekiq.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Loga
|
2
4
|
module Sidekiq
|
3
5
|
def self.configure_logging
|
@@ -5,20 +7,41 @@ module Loga
|
|
5
7
|
return if Gem::Version.new(::Sidekiq::VERSION) < Gem::Version.new('5.0')
|
6
8
|
|
7
9
|
if Gem::Version.new(::Sidekiq::VERSION) < Gem::Version.new('6.0')
|
8
|
-
|
9
|
-
|
10
|
-
::Sidekiq.configure_server do |config|
|
11
|
-
config.options[:job_logger] = Loga::Sidekiq5::JobLogger
|
12
|
-
end
|
10
|
+
configure_for_sidekiq5
|
13
11
|
elsif Gem::Version.new(::Sidekiq::VERSION) < Gem::Version.new('7.0')
|
14
|
-
|
12
|
+
configure_for_sidekiq6
|
13
|
+
elsif Gem::Version.new(::Sidekiq::VERSION) < Gem::Version.new('8.0')
|
14
|
+
configure_for_sidekiq7
|
15
|
+
end
|
16
|
+
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
18
|
+
def self.configure_for_sidekiq5
|
19
|
+
require 'loga/sidekiq5/job_logger'
|
20
|
+
|
21
|
+
::Sidekiq.configure_server do |config|
|
22
|
+
config.options[:job_logger] = Loga::Sidekiq5::JobLogger
|
19
23
|
end
|
20
24
|
|
21
25
|
::Sidekiq.logger = Loga.configuration.logger
|
22
26
|
end
|
27
|
+
|
28
|
+
def self.configure_for_sidekiq6
|
29
|
+
require 'loga/sidekiq6/job_logger'
|
30
|
+
|
31
|
+
::Sidekiq.configure_server do |config|
|
32
|
+
config.options[:job_logger] = Loga::Sidekiq6::JobLogger
|
33
|
+
end
|
34
|
+
|
35
|
+
::Sidekiq.logger = Loga.configuration.logger
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.configure_for_sidekiq7
|
39
|
+
require 'loga/sidekiq7/job_logger'
|
40
|
+
|
41
|
+
::Sidekiq.configure_server do |config|
|
42
|
+
config[:job_logger] = Loga::Sidekiq7::JobLogger
|
43
|
+
config.logger = Loga.configuration.logger
|
44
|
+
end
|
45
|
+
end
|
23
46
|
end
|
24
47
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sidekiq/job_logger'
|
4
|
+
|
5
|
+
module Loga
|
6
|
+
module Sidekiq7
|
7
|
+
class JobLogger < ::Sidekiq::JobLogger
|
8
|
+
EVENT_TYPE = 'sidekiq'.freeze
|
9
|
+
|
10
|
+
def call(item, _queue)
|
11
|
+
start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
12
|
+
|
13
|
+
yield
|
14
|
+
|
15
|
+
::Sidekiq::Context.add(:elapsed, elapsed(start))
|
16
|
+
|
17
|
+
loga_log(message: "#{item['class']} with jid: '#{item['jid']}' done", item: item)
|
18
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
19
|
+
::Sidekiq::Context.add(:elapsed, elapsed(start))
|
20
|
+
|
21
|
+
loga_log(
|
22
|
+
message: "#{item['class']} with jid: '#{item['jid']}' fail", item: item,
|
23
|
+
exception: e
|
24
|
+
)
|
25
|
+
|
26
|
+
raise
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def loga_log(message:, item:, exception: nil)
|
32
|
+
data = item.select do |k, _v|
|
33
|
+
%w[created_at enqueued_at jid queue retry
|
34
|
+
class].include? k
|
35
|
+
end
|
36
|
+
|
37
|
+
data['params'] = item['args']
|
38
|
+
|
39
|
+
data['exception'] = exception if exception
|
40
|
+
|
41
|
+
event = Event.new(type: EVENT_TYPE, message: message, data: data)
|
42
|
+
|
43
|
+
if exception
|
44
|
+
@logger.warn(event)
|
45
|
+
else
|
46
|
+
@logger.info(event)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/loga/version.rb
CHANGED
@@ -0,0 +1,180 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'timecop'
|
5
|
+
require 'fakeredis'
|
6
|
+
|
7
|
+
dummy_redis_config = ConnectionPool.new(size: 5) { Redis.new }
|
8
|
+
|
9
|
+
Sidekiq.configure_client do |config|
|
10
|
+
config.redis = dummy_redis_config
|
11
|
+
end
|
12
|
+
|
13
|
+
Sidekiq.configure_server do |config|
|
14
|
+
config.redis = dummy_redis_config
|
15
|
+
end
|
16
|
+
|
17
|
+
class MySidekiqWorker
|
18
|
+
include Sidekiq::Worker
|
19
|
+
|
20
|
+
def perform(_name)
|
21
|
+
logger.info('Hello from MySidekiqWorker')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'Sidekiq client logger' do
|
26
|
+
let(:mgr) do
|
27
|
+
# https://github.com/mperham/sidekiq/blob/v6.0.0/test/test_actors.rb#L57:79
|
28
|
+
Class.new do
|
29
|
+
attr_reader :latest_error
|
30
|
+
attr_reader :mutex
|
31
|
+
attr_reader :cond
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@mutex = ::Mutex.new
|
35
|
+
@cond = ::ConditionVariable.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def processor_died(_inst, err)
|
39
|
+
@latest_error = err
|
40
|
+
@mutex.synchronize do
|
41
|
+
@cond.signal
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def processor_stopped(_inst)
|
46
|
+
@mutex.synchronize do
|
47
|
+
@cond.signal
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def options
|
52
|
+
{
|
53
|
+
concurrency: 3,
|
54
|
+
job_logger: Loga::Sidekiq6::JobLogger,
|
55
|
+
queues: ['default'],
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
let(:target) { StringIO.new }
|
62
|
+
|
63
|
+
def read_json_log(line:)
|
64
|
+
target.rewind
|
65
|
+
JSON.parse(target.each_line.drop(line - 1).first)
|
66
|
+
end
|
67
|
+
|
68
|
+
def dump_log
|
69
|
+
offset = target.pos
|
70
|
+
|
71
|
+
target.rewind
|
72
|
+
target.each_line { puts _1 }
|
73
|
+
|
74
|
+
target.pos = offset
|
75
|
+
end
|
76
|
+
|
77
|
+
before do
|
78
|
+
Redis.current.flushall
|
79
|
+
|
80
|
+
Loga.reset
|
81
|
+
|
82
|
+
Loga.configure(
|
83
|
+
service_name: 'hello_world_app',
|
84
|
+
service_version: '1.0',
|
85
|
+
device: target,
|
86
|
+
format: :gelf,
|
87
|
+
)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'has the proper job logger' do
|
91
|
+
expect(Sidekiq.options[:job_logger]).to eq Loga::Sidekiq6::JobLogger
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'has the proper logger for Sidekiq.logger' do
|
95
|
+
expect(Sidekiq.logger).to eq Loga.logger
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'pushes a new element in the default queue' do
|
99
|
+
MySidekiqWorker.perform_async('Bob')
|
100
|
+
|
101
|
+
last_element = JSON.parse(Redis.current.lpop('queue:default'))
|
102
|
+
|
103
|
+
aggregate_failures do
|
104
|
+
expect(last_element['class']).to eq 'MySidekiqWorker'
|
105
|
+
expect(last_element['args']).to eq ['Bob']
|
106
|
+
expect(last_element['retry']).to eq true
|
107
|
+
expect(last_element['queue']).to eq 'default'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_log_from_worker(json_line)
|
112
|
+
aggregate_failures do
|
113
|
+
expect(json_line).to include(
|
114
|
+
'_class' => 'MySidekiqWorker',
|
115
|
+
'_service.name' => 'hello_world_app',
|
116
|
+
'_service.version' => '1.0',
|
117
|
+
'_tags' => '',
|
118
|
+
'level' => 6,
|
119
|
+
'version' => '1.1',
|
120
|
+
'short_message' => 'Hello from MySidekiqWorker',
|
121
|
+
)
|
122
|
+
|
123
|
+
%w[_jid timestamp host].each do |key|
|
124
|
+
expect(json_line).to have_key(key)
|
125
|
+
end
|
126
|
+
|
127
|
+
expect(json_line).not_to include('_duration')
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_job_end_log(json_line) # rubocop:disable Metrics/MethodLength
|
132
|
+
aggregate_failures do
|
133
|
+
expect(json_line).to include(
|
134
|
+
'_queue' => 'default',
|
135
|
+
'_retry' => true,
|
136
|
+
'_params' => ['Bob'],
|
137
|
+
'_class' => 'MySidekiqWorker',
|
138
|
+
'_type' => 'sidekiq',
|
139
|
+
'_service.name' => 'hello_world_app',
|
140
|
+
'_service.version' => '1.0',
|
141
|
+
'_tags' => '',
|
142
|
+
'level' => 6,
|
143
|
+
'version' => '1.1',
|
144
|
+
)
|
145
|
+
|
146
|
+
%w[_created_at _enqueued_at _jid _duration timestamp host].each do |key|
|
147
|
+
expect(json_line).to have_key(key)
|
148
|
+
end
|
149
|
+
|
150
|
+
expect(json_line['_duration']).to be < 500
|
151
|
+
expect(json_line['short_message']).to match(/MySidekiqWorker with jid:*/)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'logs the job processing event' do
|
156
|
+
MySidekiqWorker.perform_async('Bob')
|
157
|
+
|
158
|
+
require 'sidekiq/processor'
|
159
|
+
|
160
|
+
Sidekiq::Processor.new(mgr.new).start
|
161
|
+
|
162
|
+
sleep 0.5
|
163
|
+
|
164
|
+
test_log_from_worker(read_json_log(line: 1))
|
165
|
+
test_job_end_log(read_json_log(line: 2))
|
166
|
+
|
167
|
+
# This was a bug - the duration was constantly incresing based on when
|
168
|
+
# the logger was created. https://github.com/FundingCircle/loga/pull/117
|
169
|
+
#
|
170
|
+
# Test that after sleeping for few seconds the duration is still under 500ms
|
171
|
+
sleep 1
|
172
|
+
|
173
|
+
MySidekiqWorker.perform_async('Bob')
|
174
|
+
|
175
|
+
sleep 1
|
176
|
+
|
177
|
+
test_log_from_worker(read_json_log(line: 3))
|
178
|
+
test_job_end_log(read_json_log(line: 4))
|
179
|
+
end
|
180
|
+
end
|