gitlab-labkit 0.7.0 → 0.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/.ruby-version +1 -1
- data/gitlab-labkit.gemspec +3 -1
- data/lib/gitlab-labkit.rb +2 -0
- data/lib/labkit/context.rb +133 -0
- data/lib/labkit/correlation/correlation_id.rb +6 -23
- data/lib/labkit/correlation/grpc.rb +1 -0
- data/lib/labkit/correlation/grpc/client_interceptor.rb +52 -0
- data/lib/labkit/middleware.rb +9 -0
- data/lib/labkit/middleware/rack.rb +34 -0
- data/lib/labkit/middleware/sidekiq.rb +11 -0
- data/lib/labkit/middleware/sidekiq/client.rb +20 -0
- data/lib/labkit/middleware/sidekiq/server.rb +17 -0
- metadata +39 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c306478521702991b9c5ba1d80e6ab1c3bcb42b70562890a48204ab9e320c6b8
|
4
|
+
data.tar.gz: 5b4fdf319fa79405c89c0de7d91617602a6aec6bf784223a6d8e86830c6900ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f88db3bf552afa6f20e95e8760d91b97149d41e4b1cfe995c0e64bdc852ca0490713ba52a5bdcadebea1c827b83b344df61695386741c37d2dd8458243bd0144
|
7
|
+
data.tar.gz: a1ab50bd164cd46da510b03ac53aa3e148a6b8720611ef380b288d282072446b06772c43777c019da4fd93d5d9b1e1f197704fc36bf0b6e47985fc35535e2a9b
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.6.3
|
data/gitlab-labkit.gemspec
CHANGED
@@ -28,11 +28,13 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
# Please maintain alphabetical order for dev dependencies
|
30
30
|
spec.add_development_dependency "grpc-tools", "~> 1.19"
|
31
|
+
spec.add_development_dependency "pry", "~> 0.12"
|
31
32
|
spec.add_development_dependency "rack", "~> 2.0"
|
32
33
|
spec.add_development_dependency "rake", "~> 12.3"
|
33
|
-
spec.add_development_dependency "rspec", "~> 3.
|
34
|
+
spec.add_development_dependency "rspec", "~> 3.8.0"
|
34
35
|
spec.add_development_dependency "rspec-parameterized", "~> 0.4"
|
35
36
|
spec.add_development_dependency "rubocop", "~> 0.65.0"
|
36
37
|
spec.add_development_dependency "rubocop-rspec", "~> 1.22.1"
|
37
38
|
spec.add_development_dependency "rufo", "~> 0.6"
|
39
|
+
spec.add_development_dependency "sidekiq", "~> 5.2.7"
|
38
40
|
end
|
data/lib/gitlab-labkit.rb
CHANGED
@@ -8,8 +8,10 @@ require "active_support/all"
|
|
8
8
|
# observability.
|
9
9
|
module Labkit
|
10
10
|
autoload :Correlation, "labkit/correlation"
|
11
|
+
autoload :Context, "labkit/context"
|
11
12
|
autoload :Tracing, "labkit/tracing"
|
12
13
|
autoload :Logging, "labkit/logging"
|
14
|
+
autoload :Middleware, "labkit/middleware"
|
13
15
|
end
|
14
16
|
|
15
17
|
# rubocop:enable Naming/FileName
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labkit
|
4
|
+
# A context can be used to provide structured information on what resources
|
5
|
+
# GitLab is working on within a service.
|
6
|
+
# The currently supported keys are defined in the `KNOWN_KEYS` constant.
|
7
|
+
#
|
8
|
+
# Values can be provided by passing a hash. If one of the values is a Proc
|
9
|
+
# the proc will only be called when the value is actually needed.
|
10
|
+
#
|
11
|
+
# Multiple contexts can be nested, the nested context will inherit the values
|
12
|
+
# from the closest outer one.
|
13
|
+
# All contexts will have the same correlation id.
|
14
|
+
#
|
15
|
+
# Usage:
|
16
|
+
# Labkit::Context.with_context(user: 'username', root_namespace: -> { get_root_namespace } do |context|
|
17
|
+
# logger.info(context.to_h)
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
class Context
|
21
|
+
LOG_KEY = "meta"
|
22
|
+
CORRELATION_ID_KEY = "correlation_id"
|
23
|
+
RAW_KEYS = [CORRELATION_ID_KEY].freeze
|
24
|
+
KNOWN_KEYS = %w[user project root_namespace].freeze
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def with_context(attributes = {})
|
28
|
+
context = push(attributes)
|
29
|
+
|
30
|
+
begin
|
31
|
+
yield(context)
|
32
|
+
ensure
|
33
|
+
pop(context)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def push(new_attributes = {})
|
38
|
+
new_context = current&.merge(new_attributes) || new(new_attributes)
|
39
|
+
|
40
|
+
contexts.push(new_context)
|
41
|
+
|
42
|
+
new_context
|
43
|
+
end
|
44
|
+
|
45
|
+
def pop(context)
|
46
|
+
contexts.pop while contexts.include?(context)
|
47
|
+
end
|
48
|
+
|
49
|
+
def correlation_id
|
50
|
+
contexts.last&.correlation_id
|
51
|
+
end
|
52
|
+
|
53
|
+
def current
|
54
|
+
contexts.last
|
55
|
+
end
|
56
|
+
|
57
|
+
def log_key(key)
|
58
|
+
key = key.to_s
|
59
|
+
return key if RAW_KEYS.include?(key)
|
60
|
+
return key if key.starts_with?("#{LOG_KEY}.")
|
61
|
+
|
62
|
+
"#{LOG_KEY}.#{key}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def known_log_keys
|
66
|
+
@known_log_keys ||= (KNOWN_KEYS.map(&method(:log_key)) + RAW_KEYS).freeze
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def contexts
|
72
|
+
Thread.current[:labkit_contexts] ||= []
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def initialize(values = {})
|
77
|
+
@data = {}
|
78
|
+
|
79
|
+
assign_attributes(values)
|
80
|
+
end
|
81
|
+
|
82
|
+
def merge(new_attributes)
|
83
|
+
new_context = self.class.new(data.dup)
|
84
|
+
new_context.assign_attributes(new_attributes)
|
85
|
+
|
86
|
+
new_context
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_h
|
90
|
+
expand_data
|
91
|
+
end
|
92
|
+
|
93
|
+
def correlation_id
|
94
|
+
data[CORRELATION_ID_KEY]
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
|
99
|
+
def assign_attributes(attributes)
|
100
|
+
attributes = attributes.transform_keys(&method(:log_key))
|
101
|
+
attributes = attributes.slice(*known_log_keys)
|
102
|
+
|
103
|
+
data.merge!(attributes)
|
104
|
+
|
105
|
+
# Remove keys that had their values set to `nil` in the new attributes
|
106
|
+
data.keep_if { |_, value| value.present? }
|
107
|
+
|
108
|
+
# Assign a correlation if it was missing in the first context or when
|
109
|
+
# explicitly removed
|
110
|
+
data[CORRELATION_ID_KEY] ||= new_id
|
111
|
+
|
112
|
+
data
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
delegate :log_key, :known_log_keys, to: :class
|
118
|
+
|
119
|
+
attr_reader :data
|
120
|
+
|
121
|
+
def expand_data
|
122
|
+
data.transform_values do |value|
|
123
|
+
value = value.respond_to?(:call) ? value.call : value
|
124
|
+
|
125
|
+
value.presence
|
126
|
+
end.compact
|
127
|
+
end
|
128
|
+
|
129
|
+
def new_id
|
130
|
+
SecureRandom.hex
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -5,38 +5,21 @@ module Labkit
|
|
5
5
|
# CorrelationId module provides access the Correlation-ID
|
6
6
|
# of the current request
|
7
7
|
module CorrelationId
|
8
|
-
LOG_KEY =
|
8
|
+
LOG_KEY = Labkit::Context::CORRELATION_ID_KEY
|
9
9
|
|
10
10
|
class << self
|
11
|
-
def use_id(correlation_id
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
ids.push(correlation_id || new_id)
|
16
|
-
|
17
|
-
begin
|
18
|
-
yield(current_id)
|
19
|
-
ensure
|
20
|
-
ids.pop
|
11
|
+
def use_id(correlation_id)
|
12
|
+
Labkit::Context.with_context(LOG_KEY => correlation_id) do |context|
|
13
|
+
yield(context.correlation_id)
|
21
14
|
end
|
22
15
|
end
|
23
16
|
|
24
17
|
def current_id
|
25
|
-
|
18
|
+
Labkit::Context.correlation_id
|
26
19
|
end
|
27
20
|
|
28
21
|
def current_or_new_id
|
29
|
-
current_id ||
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def ids
|
35
|
-
Thread.current[:correlation_id] ||= []
|
36
|
-
end
|
37
|
-
|
38
|
-
def new_id
|
39
|
-
SecureRandom.uuid
|
22
|
+
current_id || Labkit::Context.push.correlation_id
|
40
23
|
end
|
41
24
|
end
|
42
25
|
end
|
@@ -4,6 +4,7 @@ module Labkit
|
|
4
4
|
module Correlation
|
5
5
|
# The GRPC module contains functionality for instrumenting GRPC calls
|
6
6
|
module GRPC
|
7
|
+
autoload :ClientInterceptor, "labkit/correlation/grpc/client_interceptor"
|
7
8
|
autoload :GRPCCommon, "labkit/correlation/grpc/grpc_common"
|
8
9
|
autoload :ServerInterceptor, "labkit/correlation/grpc/server_interceptor"
|
9
10
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Disable the UnusedMethodArgument linter, since we need to declare the kwargs
|
4
|
+
# in the methods, but we don't actually use them.
|
5
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
6
|
+
|
7
|
+
require "grpc"
|
8
|
+
|
9
|
+
module Labkit
|
10
|
+
module Correlation
|
11
|
+
module GRPC
|
12
|
+
# ClientInterceptor is used to inject the correlation_id into the metadata
|
13
|
+
# or a GRPC call for onward propagation to the server
|
14
|
+
class ClientInterceptor < ::GRPC::ClientInterceptor
|
15
|
+
include Labkit::Correlation::GRPC::GRPCCommon
|
16
|
+
include Singleton
|
17
|
+
|
18
|
+
def request_response(request:, call:, method:, metadata:)
|
19
|
+
inject_correlation_id_into_metadata(metadata)
|
20
|
+
|
21
|
+
yield
|
22
|
+
end
|
23
|
+
|
24
|
+
def client_streamer(requests:, call:, method:, metadata:)
|
25
|
+
inject_correlation_id_into_metadata(metadata)
|
26
|
+
|
27
|
+
yield
|
28
|
+
end
|
29
|
+
|
30
|
+
def server_streamer(request:, call:, method:, metadata:)
|
31
|
+
inject_correlation_id_into_metadata(metadata)
|
32
|
+
|
33
|
+
yield
|
34
|
+
end
|
35
|
+
|
36
|
+
def bidi_streamer(requests:, call:, method:, metadata:)
|
37
|
+
inject_correlation_id_into_metadata(metadata)
|
38
|
+
|
39
|
+
yield
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def inject_correlation_id_into_metadata(metadata, &block)
|
45
|
+
metadata[CORRELATION_METADATA_KEY] = Labkit::Correlation::CorrelationId.current_id if Labkit::Correlation::CorrelationId.current_id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_dispatch"
|
4
|
+
|
5
|
+
module Labkit
|
6
|
+
module Middleware
|
7
|
+
# This is a rack middleware to be inserted in GitLab-rails
|
8
|
+
# It makes sure that there's always a root context containing the correlation
|
9
|
+
# id.
|
10
|
+
# Since this context always get's cleaned up by this middleware, we can be
|
11
|
+
# sure that any nested contexts will also be cleaned up.
|
12
|
+
class Rack
|
13
|
+
def initialize(app)
|
14
|
+
@app = app
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
Labkit::Context.with_context(Labkit::Context::CORRELATION_ID_KEY => correlation_id(env)) do
|
19
|
+
@app.call(env)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def correlation_id(env)
|
26
|
+
request(env).request_id
|
27
|
+
end
|
28
|
+
|
29
|
+
def request(env)
|
30
|
+
ActionDispatch::Request.new(env)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labkit
|
4
|
+
module Middleware
|
5
|
+
module Sidekiq
|
6
|
+
# This middleware for Sidekiq-client wraps scheduling jobs in a context
|
7
|
+
# The context will also be added to the sidekiq job in redis so it can
|
8
|
+
# be reinstantiated by Sidekiq-server when running the job.
|
9
|
+
class Client
|
10
|
+
def call(_worker_class, job, _queue, _redis_pool)
|
11
|
+
Labkit::Context.with_context do |context|
|
12
|
+
job.merge!(context.to_h)
|
13
|
+
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labkit
|
4
|
+
module Middleware
|
5
|
+
module Sidekiq
|
6
|
+
# This middleware for Sidekiq-client uses the values stored on a job to
|
7
|
+
# reinstantiate a context in which the job will run.
|
8
|
+
class Server
|
9
|
+
def call(_worker_class, job, _queue)
|
10
|
+
Labkit::Context.with_context(job) do |_context|
|
11
|
+
yield
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitlab-labkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Newdigate
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-12-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -126,6 +126,20 @@ dependencies:
|
|
126
126
|
- - "~>"
|
127
127
|
- !ruby/object:Gem::Version
|
128
128
|
version: '1.19'
|
129
|
+
- !ruby/object:Gem::Dependency
|
130
|
+
name: pry
|
131
|
+
requirement: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - "~>"
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0.12'
|
136
|
+
type: :development
|
137
|
+
prerelease: false
|
138
|
+
version_requirements: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - "~>"
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0.12'
|
129
143
|
- !ruby/object:Gem::Dependency
|
130
144
|
name: rack
|
131
145
|
requirement: !ruby/object:Gem::Requirement
|
@@ -160,14 +174,14 @@ dependencies:
|
|
160
174
|
requirements:
|
161
175
|
- - "~>"
|
162
176
|
- !ruby/object:Gem::Version
|
163
|
-
version: 3.
|
177
|
+
version: 3.8.0
|
164
178
|
type: :development
|
165
179
|
prerelease: false
|
166
180
|
version_requirements: !ruby/object:Gem::Requirement
|
167
181
|
requirements:
|
168
182
|
- - "~>"
|
169
183
|
- !ruby/object:Gem::Version
|
170
|
-
version: 3.
|
184
|
+
version: 3.8.0
|
171
185
|
- !ruby/object:Gem::Dependency
|
172
186
|
name: rspec-parameterized
|
173
187
|
requirement: !ruby/object:Gem::Requirement
|
@@ -224,6 +238,20 @@ dependencies:
|
|
224
238
|
- - "~>"
|
225
239
|
- !ruby/object:Gem::Version
|
226
240
|
version: '0.6'
|
241
|
+
- !ruby/object:Gem::Dependency
|
242
|
+
name: sidekiq
|
243
|
+
requirement: !ruby/object:Gem::Requirement
|
244
|
+
requirements:
|
245
|
+
- - "~>"
|
246
|
+
- !ruby/object:Gem::Version
|
247
|
+
version: 5.2.7
|
248
|
+
type: :development
|
249
|
+
prerelease: false
|
250
|
+
version_requirements: !ruby/object:Gem::Requirement
|
251
|
+
requirements:
|
252
|
+
- - "~>"
|
253
|
+
- !ruby/object:Gem::Version
|
254
|
+
version: 5.2.7
|
227
255
|
description:
|
228
256
|
email:
|
229
257
|
- andrew@gitlab.com
|
@@ -243,13 +271,20 @@ files:
|
|
243
271
|
- Rakefile
|
244
272
|
- gitlab-labkit.gemspec
|
245
273
|
- lib/gitlab-labkit.rb
|
274
|
+
- lib/labkit/context.rb
|
246
275
|
- lib/labkit/correlation.rb
|
247
276
|
- lib/labkit/correlation/correlation_id.rb
|
248
277
|
- lib/labkit/correlation/grpc.rb
|
278
|
+
- lib/labkit/correlation/grpc/client_interceptor.rb
|
249
279
|
- lib/labkit/correlation/grpc/grpc_common.rb
|
250
280
|
- lib/labkit/correlation/grpc/server_interceptor.rb
|
251
281
|
- lib/labkit/logging.rb
|
252
282
|
- lib/labkit/logging/sanitizer.rb
|
283
|
+
- lib/labkit/middleware.rb
|
284
|
+
- lib/labkit/middleware/rack.rb
|
285
|
+
- lib/labkit/middleware/sidekiq.rb
|
286
|
+
- lib/labkit/middleware/sidekiq/client.rb
|
287
|
+
- lib/labkit/middleware/sidekiq/server.rb
|
253
288
|
- lib/labkit/tracing.rb
|
254
289
|
- lib/labkit/tracing/factory.rb
|
255
290
|
- lib/labkit/tracing/grpc.rb
|