gitlab-labkit 0.13.1 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.gitlab-ci.yml +4 -4
- data/.gitlab/CODEOWNERS +1 -0
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -1
- data/gitlab-labkit.gemspec +8 -2
- data/lib/gitlab-labkit.rb +29 -0
- data/lib/labkit/context.rb +12 -1
- data/lib/labkit/excon_publisher.rb +130 -0
- data/lib/labkit/httpclient_publisher.rb +66 -0
- data/lib/labkit/logging/grpc/server_interceptor.rb +2 -1
- data/lib/labkit/logging/sanitizer.rb +8 -0
- data/lib/labkit/middleware/sidekiq/tracing/client.rb +1 -1
- data/lib/labkit/middleware/sidekiq/tracing/server.rb +1 -1
- data/lib/labkit/middleware/sidekiq/tracing/sidekiq_common.rb +14 -1
- data/lib/labkit/net_http_publisher.rb +88 -0
- data/lib/labkit/system.rb +13 -0
- data/lib/labkit/tracing.rb +9 -0
- data/lib/labkit/tracing/abstract_instrumenter.rb +47 -0
- data/lib/labkit/tracing/external_http.rb +26 -0
- data/lib/labkit/tracing/external_http/request_instrumenter.rb +33 -0
- data/lib/labkit/tracing/jaeger_factory.rb +1 -1
- data/lib/labkit/tracing/rails.rb +0 -2
- data/lib/labkit/tracing/rails/action_view.rb +14 -0
- data/lib/labkit/tracing/rails/action_view/render_collection_instrumenter.rb +7 -2
- data/lib/labkit/tracing/rails/action_view/render_partial_instrumenter.rb +7 -2
- data/lib/labkit/tracing/rails/action_view/render_template_instrumenter.rb +7 -2
- data/lib/labkit/tracing/rails/action_view/subscriber.rb +1 -1
- data/lib/labkit/tracing/rails/active_record/sql_instrumenter.rb +3 -2
- data/lib/labkit/tracing/rails/active_record/subscriber.rb +1 -1
- data/lib/labkit/tracing/rails/active_support/cache_delete_instrumenter.rb +1 -1
- data/lib/labkit/tracing/rails/active_support/cache_fetch_hit_instrumenter.rb +1 -1
- data/lib/labkit/tracing/rails/active_support/cache_generate_instrumenter.rb +1 -1
- data/lib/labkit/tracing/rails/active_support/cache_read_instrumenter.rb +1 -1
- data/lib/labkit/tracing/rails/active_support/cache_write_instrumenter.rb +1 -1
- data/lib/labkit/tracing/rails/active_support/subscriber.rb +1 -1
- data/lib/labkit/tracing/tracing_common.rb +20 -0
- data/lib/labkit/tracing/tracing_utils.rb +3 -1
- metadata +99 -8
- data/lib/labkit/tracing/rails/abstract_instrumenter.rb +0 -46
- data/lib/labkit/tracing/rails/rails_common.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b2b166e9a540a6314a2c5e863e7f109f6c3763f2649aa459dfec41a5018e57f
|
4
|
+
data.tar.gz: 7dc9c77305e855d930420dca4e59cba0e18bd990fae24a7a44e871a7e03e84ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81819b7e4fd168c805e286f9315dd5a757423367938619021dcb7e81d5ad41a6f057224bfc046d96a132354688b33b0b4ed2c3e2196dfa09725176bb32b6ca3e
|
7
|
+
data.tar.gz: 35d67adc6f7561609f617df26af9a3942e77cd1b66000523584308bd160c88062dc0fcd1ed6e0d9662f1af6a5c6436c80fe80b53d5b6b4c86ba1e880b24f5a61
|
data/.gitignore
CHANGED
data/.gitlab-ci.yml
CHANGED
@@ -14,6 +14,10 @@ workflow:
|
|
14
14
|
- bundle install
|
15
15
|
- bundle exec rake verify build install
|
16
16
|
|
17
|
+
test:2.7:
|
18
|
+
image: ruby:2.7
|
19
|
+
<<: *test_definition
|
20
|
+
|
17
21
|
test:2.6:
|
18
22
|
image: ruby:2.6
|
19
23
|
<<: *test_definition
|
@@ -22,10 +26,6 @@ test:2.5:
|
|
22
26
|
image: ruby:2.5
|
23
27
|
<<: *test_definition
|
24
28
|
|
25
|
-
test:2.4:
|
26
|
-
image: ruby:2.4
|
27
|
-
<<: *test_definition
|
28
|
-
|
29
29
|
deploy:
|
30
30
|
stage: deploy
|
31
31
|
script:
|
data/.gitlab/CODEOWNERS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* @andrewn @ayufan @reprazent
|
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.7.2
|
data/gitlab-labkit.gemspec
CHANGED
@@ -19,18 +19,24 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.required_ruby_version = ">= 2.4.0"
|
20
20
|
|
21
21
|
# Please maintain alphabetical order for dependencies
|
22
|
-
spec.add_runtime_dependency "actionpack", ">= 5.0.0", "<
|
23
|
-
spec.add_runtime_dependency "activesupport", ">= 5.0.0", "<
|
22
|
+
spec.add_runtime_dependency "actionpack", ">= 5.0.0", "< 7.0.0"
|
23
|
+
spec.add_runtime_dependency "activesupport", ">= 5.0.0", "< 7.0.0"
|
24
|
+
spec.add_runtime_dependency "gitlab-pg_query", "~> 1.3"
|
24
25
|
spec.add_runtime_dependency "grpc", "~> 1.19" # Be sure to update the "grpc-tools" dev_depenency too
|
25
26
|
spec.add_runtime_dependency "jaeger-client", "~> 1.1"
|
26
27
|
spec.add_runtime_dependency "opentracing", "~> 0.4"
|
27
28
|
spec.add_runtime_dependency "redis", ">3.0.0", "<5.0.0"
|
28
29
|
|
29
30
|
# Please maintain alphabetical order for dev dependencies
|
31
|
+
spec.add_development_dependency "excon", "~> 0.78.1"
|
32
|
+
spec.add_development_dependency "faraday", "~> 1.2.0"
|
30
33
|
spec.add_development_dependency "grpc-tools", "~> 1.19"
|
34
|
+
spec.add_development_dependency "httparty", "~> 0.17.3"
|
35
|
+
spec.add_development_dependency "httpclient", "~> 2.8.3"
|
31
36
|
spec.add_development_dependency "pry", "~> 0.12"
|
32
37
|
spec.add_development_dependency "rack", "~> 2.0"
|
33
38
|
spec.add_development_dependency "rake", "~> 12.3"
|
39
|
+
spec.add_development_dependency "rest-client", "~> 2.1.0"
|
34
40
|
spec.add_development_dependency "rspec", "~> 3.8.0"
|
35
41
|
spec.add_development_dependency "rspec-parameterized", "~> 0.4"
|
36
42
|
spec.add_development_dependency "rubocop", "~> 0.65.0"
|
data/lib/gitlab-labkit.rb
CHANGED
@@ -7,11 +7,40 @@ require "active_support/all"
|
|
7
7
|
# infrastructural concerns, partcularly related to
|
8
8
|
# observability.
|
9
9
|
module Labkit
|
10
|
+
autoload :System, "labkit/system"
|
11
|
+
|
10
12
|
autoload :Correlation, "labkit/correlation"
|
11
13
|
autoload :Context, "labkit/context"
|
12
14
|
autoload :Tracing, "labkit/tracing"
|
13
15
|
autoload :Logging, "labkit/logging"
|
14
16
|
autoload :Middleware, "labkit/middleware"
|
17
|
+
|
18
|
+
# Publishers to publish notifications whenever a HTTP reqeust is made.
|
19
|
+
# A broadcasted notification's payload in topic "request.external_http" includes:
|
20
|
+
# + method (String): "GET"
|
21
|
+
# + code (String): "200" # This is the status code read directly from HTTP response
|
22
|
+
# + duration (Float - seconds): 0.234
|
23
|
+
# + host (String): "gitlab.com"
|
24
|
+
# + port (Integer): 80,
|
25
|
+
# + path (String): "/gitlab-org/gitlab"
|
26
|
+
# + scheme (String): "https"
|
27
|
+
# + query (String): "field_a=1&field_b=2"
|
28
|
+
# + fragment (String): "issue-number-1"
|
29
|
+
# + proxy_host (String - Optional): "proxy.gitlab.com"
|
30
|
+
# + proxy_port (Integer - Optional): 80
|
31
|
+
# + exception (Array<String> - Optional): ["Net::ReadTimeout", "Net::ReadTimeout with #<TCPSocket:(closed)>"]
|
32
|
+
# + exception_object (Error Object - Optional): #<Net::ReadTimeout: Net::ReadTimeout>
|
33
|
+
#
|
34
|
+
# Usage:
|
35
|
+
#
|
36
|
+
# ActiveSupport::Notifications.subscribe "request.external_http" do |name, started, finished, unique_id, data|
|
37
|
+
# puts "#{name} | #{started} | #{finished} | #{unique_id} | #{data.inspect}"
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
EXTERNAL_HTTP_NOTIFICATION_TOPIC = "request.external_http"
|
41
|
+
autoload :NetHttpPublisher, "labkit/net_http_publisher"
|
42
|
+
autoload :ExconPublisher, "labkit/excon_publisher"
|
43
|
+
autoload :HTTPClientPublisher, "labkit/httpclient_publisher"
|
15
44
|
end
|
16
45
|
|
17
46
|
# rubocop:enable Naming/FileName
|
data/lib/labkit/context.rb
CHANGED
@@ -21,8 +21,9 @@ module Labkit
|
|
21
21
|
LOG_KEY = "meta"
|
22
22
|
CORRELATION_ID_KEY = "correlation_id"
|
23
23
|
RAW_KEYS = [CORRELATION_ID_KEY].freeze
|
24
|
+
HEADER_PREFIX = "X-Gitlab-"
|
24
25
|
KNOWN_KEYS = %w[user project root_namespace subscription_plan caller_id
|
25
|
-
related_class feature_category].freeze
|
26
|
+
remote_ip related_class feature_category].freeze
|
26
27
|
|
27
28
|
class << self
|
28
29
|
def with_context(attributes = {})
|
@@ -67,6 +68,10 @@ module Labkit
|
|
67
68
|
@known_log_keys ||= (KNOWN_KEYS.map(&method(:log_key)) + RAW_KEYS).freeze
|
68
69
|
end
|
69
70
|
|
71
|
+
def header_name(name)
|
72
|
+
HEADER_PREFIX + log_key(name).titlecase(keep_id_suffix: true).gsub(/\W/, "-")
|
73
|
+
end
|
74
|
+
|
70
75
|
private
|
71
76
|
|
72
77
|
def contexts
|
@@ -95,6 +100,12 @@ module Labkit
|
|
95
100
|
data[CORRELATION_ID_KEY]
|
96
101
|
end
|
97
102
|
|
103
|
+
def to_headers
|
104
|
+
to_h.except(CORRELATION_ID_KEY).transform_keys do |key|
|
105
|
+
self.class.header_name(key)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
98
109
|
protected
|
99
110
|
|
100
111
|
def assign_attributes(attributes)
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labkit
|
4
|
+
##
|
5
|
+
# A middleware for Excon HTTP library to publish a notification
|
6
|
+
# whenever a HTTP request is triggered.
|
7
|
+
#
|
8
|
+
# Excon supports a middleware system that allows request/response
|
9
|
+
# interception freely. Whenever a new Excon connection is created, a list of
|
10
|
+
# default middlewares is injected. This list of middlewares can be altered
|
11
|
+
# thanks to Excon.defaults accessor. ExconPublisher is inserted into this
|
12
|
+
# list. It affects all connections created in future. There is a limitation
|
13
|
+
# that this approach doesn't work if a user decides to override the default
|
14
|
+
# middleware list. It is unlikely though, at least in the dependency tree of
|
15
|
+
# GitLab.
|
16
|
+
#
|
17
|
+
# ExconPublisher instance is created once and shared between all Excon
|
18
|
+
# connections later. Each connection may be triggered by different threads in
|
19
|
+
# parallel. In such cases, a connection objects creates multiple sockets for
|
20
|
+
# each thread. Therfore in the implementation of this middleware, the
|
21
|
+
# instrumation payload for each connection is stored inside a thread-isolated
|
22
|
+
# storage.
|
23
|
+
#
|
24
|
+
# For more information:
|
25
|
+
# https://github.com/excon/excon/blob/81a0130537f2f8cd00d6daafb05d02d9a90dc9f7/lib/excon/middlewares/base.rb
|
26
|
+
# https://github.com/excon/excon/blob/fa3ec51e9bb062a12846a1cfff09534e76c99f4b/lib/excon/constants.rb#L146
|
27
|
+
# https://github.com/excon/excon/blob/fa3ec51e9bb062a12846a1cfff09534e76c99f4b/lib/excon/connection.rb#L474
|
28
|
+
class ExconPublisher
|
29
|
+
@prepend_mutex = Mutex.new
|
30
|
+
|
31
|
+
def self.labkit_prepend!
|
32
|
+
@prepend_mutex.synchronize do
|
33
|
+
return if !defined?(Excon) || @prepended
|
34
|
+
|
35
|
+
defaults = Excon.defaults
|
36
|
+
defaults[:middlewares] << ExconPublisher
|
37
|
+
|
38
|
+
@prepended = true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize(stack)
|
43
|
+
@stack = stack
|
44
|
+
@instrumenter = ActiveSupport::Notifications.instrumenter
|
45
|
+
end
|
46
|
+
|
47
|
+
def request_call(datum)
|
48
|
+
payload = start_payload(datum)
|
49
|
+
store_connection_payload(datum, payload)
|
50
|
+
@instrumenter.start(::Labkit::EXTERNAL_HTTP_NOTIFICATION_TOPIC, payload)
|
51
|
+
@stack.request_call(datum)
|
52
|
+
end
|
53
|
+
|
54
|
+
def response_call(datum)
|
55
|
+
payload = fetch_connection_payload(datum)
|
56
|
+
|
57
|
+
return @stack.response_call(datum) if payload.nil?
|
58
|
+
|
59
|
+
calculate_duration(payload)
|
60
|
+
payload[:code] = datum[:response][:status].to_s
|
61
|
+
|
62
|
+
@instrumenter.finish(::Labkit::EXTERNAL_HTTP_NOTIFICATION_TOPIC, payload)
|
63
|
+
@stack.response_call(datum)
|
64
|
+
ensure
|
65
|
+
remove_connection_payload(datum)
|
66
|
+
end
|
67
|
+
|
68
|
+
def error_call(datum)
|
69
|
+
payload = fetch_connection_payload(datum)
|
70
|
+
|
71
|
+
return @stack.error_call(datum) if payload.nil?
|
72
|
+
|
73
|
+
calculate_duration(payload)
|
74
|
+
|
75
|
+
if datum[:error].is_a?(Exception)
|
76
|
+
payload[:exception] = [datum[:error].class.name, datum[:error].message]
|
77
|
+
payload[:exception_object] = datum[:error]
|
78
|
+
elsif datum[:error].is_a?(String)
|
79
|
+
exception = StandardError.new(datum[:error])
|
80
|
+
payload[:exception] = [exception.class.name, exception.message]
|
81
|
+
payload[:exception_object] = exception
|
82
|
+
end
|
83
|
+
|
84
|
+
@instrumenter.finish(::Labkit::EXTERNAL_HTTP_NOTIFICATION_TOPIC, payload)
|
85
|
+
@stack.error_call(datum)
|
86
|
+
ensure
|
87
|
+
remove_connection_payload(datum)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def start_payload(datum)
|
93
|
+
payload = {
|
94
|
+
method: datum[:method].to_s.upcase,
|
95
|
+
host: datum[:host],
|
96
|
+
path: datum[:path],
|
97
|
+
port: datum[:port],
|
98
|
+
scheme: datum[:scheme],
|
99
|
+
query: datum[:query],
|
100
|
+
start_time: ::Labkit::System.monotonic_time,
|
101
|
+
}
|
102
|
+
unless datum[:proxy].nil?
|
103
|
+
payload[:proxy_host] = datum[:proxy][:host]
|
104
|
+
payload[:proxy_port] = datum[:proxy][:port]
|
105
|
+
end
|
106
|
+
payload
|
107
|
+
end
|
108
|
+
|
109
|
+
def calculate_duration(payload)
|
110
|
+
start_time = payload.delete(:start_time) || ::Labkit::System.monotonic_time
|
111
|
+
payload[:duration] = (::Labkit::System.monotonic_time - start_time).to_f
|
112
|
+
end
|
113
|
+
|
114
|
+
def connection_payload
|
115
|
+
Thread.current[:__labkit_http_excon_payload] ||= {}
|
116
|
+
end
|
117
|
+
|
118
|
+
def store_connection_payload(datum, payload)
|
119
|
+
connection_payload[datum[:connection]] = payload
|
120
|
+
end
|
121
|
+
|
122
|
+
def fetch_connection_payload(datum)
|
123
|
+
connection_payload.fetch(datum[:connection], nil)
|
124
|
+
end
|
125
|
+
|
126
|
+
def remove_connection_payload(datum)
|
127
|
+
connection_payload.delete(datum[:connection])
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labkit
|
4
|
+
##
|
5
|
+
# Prepend to HTTPClient class to publish an ActiveSupport::Notifcation
|
6
|
+
# whenever a HTTP request is triggered.
|
7
|
+
#
|
8
|
+
# Similar to Net::HTTP, this HTTP client redirects all calls to
|
9
|
+
# HTTPClient#do_get_block. HTTPClient is prepended with HTTPClientPublisher.
|
10
|
+
# Although HTTPClient supports request filter (a kind of middleware), its
|
11
|
+
# support is strictly limited. The request and response passed into the
|
12
|
+
# filter don't contain connection information. The response doesn't even
|
13
|
+
# contain any link to the request object. It's impossible to fit this filter
|
14
|
+
# mechanism into our subscribing model.
|
15
|
+
#
|
16
|
+
# For more information;
|
17
|
+
# https://github.com/nahi/httpclient/blob/d3091b095a1b29f65f4531a70a8e581e75be035e/lib/httpclient.rb#L1233
|
18
|
+
module HTTPClientPublisher
|
19
|
+
@prepend_mutex = Mutex.new
|
20
|
+
|
21
|
+
def self.labkit_prepend!
|
22
|
+
@prepend_mutex.synchronize do
|
23
|
+
return if !defined?(HTTPClient) || @prepended
|
24
|
+
|
25
|
+
HTTPClient.prepend(self)
|
26
|
+
@prepended = true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def do_get_block(req, proxy, conn, &block)
|
31
|
+
start_time = ::Labkit::System.monotonic_time
|
32
|
+
ActiveSupport::Notifications.instrument ::Labkit::EXTERNAL_HTTP_NOTIFICATION_TOPIC, create_request_payload(req, proxy) do |payload|
|
33
|
+
response =
|
34
|
+
begin
|
35
|
+
super
|
36
|
+
ensure
|
37
|
+
payload[:duration] = (::Labkit::System.monotonic_time - start_time).to_f
|
38
|
+
end
|
39
|
+
payload[:code] = response.status_code.to_s
|
40
|
+
response
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def create_request_payload(request, proxy)
|
47
|
+
http_header = request.http_header
|
48
|
+
payload = {
|
49
|
+
method: http_header.request_method,
|
50
|
+
host: http_header.request_uri.host,
|
51
|
+
path: http_header.request_uri.path,
|
52
|
+
port: http_header.request_uri.port,
|
53
|
+
scheme: http_header.request_uri.scheme,
|
54
|
+
query: http_header.request_uri.query,
|
55
|
+
fragment: http_header.request_uri.fragment,
|
56
|
+
}
|
57
|
+
|
58
|
+
unless proxy.nil?
|
59
|
+
payload[:proxy_host] = proxy.host
|
60
|
+
payload[:proxy_port] = proxy.port
|
61
|
+
end
|
62
|
+
|
63
|
+
payload
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -55,7 +55,7 @@ module Labkit
|
|
55
55
|
|
56
56
|
private
|
57
57
|
|
58
|
-
def log_request(method,
|
58
|
+
def log_request(method, _call)
|
59
59
|
start = Time.now
|
60
60
|
code = ::GRPC::Core::StatusCodes::OK
|
61
61
|
|
@@ -67,6 +67,7 @@ module Labkit
|
|
67
67
|
ensure
|
68
68
|
service_name, method_name = rpc_split(method)
|
69
69
|
message = @default_tags.merge(
|
70
|
+
'grpc.start_time': start.utc.rfc3339,
|
70
71
|
'grpc.time_ms': ((Time.now - start) * 1000.0).truncate(3),
|
71
72
|
'grpc.code': CODE_STRINGS.fetch(code, code.to_s),
|
72
73
|
'grpc.method': method_name,
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "pg_query"
|
4
|
+
|
3
5
|
module Labkit
|
4
6
|
module Logging
|
5
7
|
# Sanitizer provides log message sanitization, removing
|
@@ -22,6 +24,12 @@ module Labkit
|
|
22
24
|
content
|
23
25
|
end
|
24
26
|
|
27
|
+
def self.sanitize_sql(sql)
|
28
|
+
PgQuery.normalize(sql)
|
29
|
+
rescue PgQuery::ParseError
|
30
|
+
""
|
31
|
+
end
|
32
|
+
|
25
33
|
# Ensures that URLS are sanitized to hide credentials
|
26
34
|
def self.mask_url(url)
|
27
35
|
url = url.to_s.strip
|
@@ -15,7 +15,7 @@ module Labkit
|
|
15
15
|
SPAN_KIND = "client"
|
16
16
|
|
17
17
|
def call(_worker_class, job, _queue, _redis_pool)
|
18
|
-
Labkit::Tracing::TracingUtils.with_tracing(operation_name: "sidekiq:#{job
|
18
|
+
Labkit::Tracing::TracingUtils.with_tracing(operation_name: "sidekiq:#{job_class(job)}", tags: tags_from_job(job, SPAN_KIND)) do |span|
|
19
19
|
# Inject the details directly into the job
|
20
20
|
Labkit::Tracing::TracingUtils.tracer.inject(span.context, OpenTracing::FORMAT_TEXT_MAP, job)
|
21
21
|
|
@@ -17,7 +17,7 @@ module Labkit
|
|
17
17
|
def call(_worker, job, _queue)
|
18
18
|
context = Labkit::Tracing::TracingUtils.tracer.extract(OpenTracing::FORMAT_TEXT_MAP, job)
|
19
19
|
|
20
|
-
Labkit::Tracing::TracingUtils.with_tracing(operation_name: "sidekiq:#{job
|
20
|
+
Labkit::Tracing::TracingUtils.with_tracing(operation_name: "sidekiq:#{job_class(job)}", child_of: context, tags: tags_from_job(job, SPAN_KIND)) { |_span| yield }
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -6,15 +6,28 @@ module Labkit
|
|
6
6
|
module Tracing
|
7
7
|
# SidekiqCommon is a mixin for the sidekiq middleware components
|
8
8
|
module SidekiqCommon
|
9
|
+
def job_class(job)
|
10
|
+
# Active Job wrapping can be found at
|
11
|
+
# https://github.com/rails/rails/blob/v6.0.3.1/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb
|
12
|
+
job["wrapped"].presence || job["class"].presence || "undefined"
|
13
|
+
end
|
14
|
+
|
15
|
+
def wrapped?(job)
|
16
|
+
job["wrapped"].present?
|
17
|
+
end
|
18
|
+
|
9
19
|
def tags_from_job(job, kind)
|
10
|
-
{
|
20
|
+
tags = {
|
11
21
|
"component" => "sidekiq",
|
12
22
|
"span.kind" => kind,
|
23
|
+
"sidekiq.wrapped" => wrapped?(job),
|
13
24
|
"sidekiq.queue" => job["queue"],
|
14
25
|
"sidekiq.jid" => job["jid"],
|
15
26
|
"sidekiq.retry" => job["retry"].to_s,
|
16
27
|
"sidekiq.args" => job["args"]&.join(", "),
|
17
28
|
}
|
29
|
+
tags["sidekiq.at"] = job["at"] if job["at"]
|
30
|
+
tags
|
18
31
|
end
|
19
32
|
end
|
20
33
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labkit
|
4
|
+
##
|
5
|
+
# Prepend to Ruby's Net/HTTP standard HTTP library to publish a notification
|
6
|
+
# whenever a HTTP request is triggered. Net::HTTP has different class methods
|
7
|
+
# for each http method. Those methods are delegated to corresponding instance
|
8
|
+
# methods. Eventually, `request` method is call to dispatch the HTTP request.
|
9
|
+
# Therefore, a prepender that override `request` method covers all HTTP
|
10
|
+
# calls.
|
11
|
+
#
|
12
|
+
# For more information:
|
13
|
+
# https://github.com/ruby/ruby/blob/9b9cbbbc17bb5840581c7da37fd0feb0a7d4c1f3/lib/net/http.rb#L1510
|
14
|
+
#
|
15
|
+
# Note: some use cases to take care of
|
16
|
+
# - Create a request from input URI
|
17
|
+
# - Create a request from input host, port, and path string
|
18
|
+
# - Create a singular request and closes the connection immediately
|
19
|
+
# - Create a persistent connection and perform multiple HTTP requests
|
20
|
+
# - Notification payload must separate URI components
|
21
|
+
# - Create a post request with a body
|
22
|
+
# - Create a post request with form data
|
23
|
+
# - Create a request with basic authentication
|
24
|
+
# - Make a request via a proxy server
|
25
|
+
# - Streaming
|
26
|
+
module NetHttpPublisher
|
27
|
+
@prepend_mutex = Mutex.new
|
28
|
+
|
29
|
+
def self.labkit_prepend!
|
30
|
+
@prepend_mutex.synchronize do
|
31
|
+
return if @prepended
|
32
|
+
|
33
|
+
require "net/http"
|
34
|
+
Net::HTTP.prepend(self)
|
35
|
+
@prepended = true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def request(request, *args, &block)
|
40
|
+
return super unless started?
|
41
|
+
|
42
|
+
start_time = ::Labkit::System.monotonic_time
|
43
|
+
|
44
|
+
ActiveSupport::Notifications.instrument ::Labkit::EXTERNAL_HTTP_NOTIFICATION_TOPIC, create_request_payload(request) do |payload|
|
45
|
+
response =
|
46
|
+
begin
|
47
|
+
super
|
48
|
+
ensure
|
49
|
+
payload[:duration] = (::Labkit::System.monotonic_time - start_time).to_f
|
50
|
+
end
|
51
|
+
payload[:code] = response.code
|
52
|
+
response
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def create_request_payload(request)
|
59
|
+
payload = {
|
60
|
+
method: request.method,
|
61
|
+
}
|
62
|
+
|
63
|
+
if request.uri.nil?
|
64
|
+
path_uri = URI(request.path)
|
65
|
+
payload[:host] = address
|
66
|
+
payload[:path] = path_uri.path
|
67
|
+
payload[:port] = port
|
68
|
+
payload[:scheme] = use_ssl? ? "https" : "http"
|
69
|
+
payload[:query] = path_uri.query
|
70
|
+
payload[:fragment] = path_uri.fragment
|
71
|
+
else
|
72
|
+
payload[:host] = request.uri.host
|
73
|
+
payload[:path] = request.uri.path
|
74
|
+
payload[:port] = request.uri.port
|
75
|
+
payload[:scheme] = request.uri.scheme
|
76
|
+
payload[:query] = request.uri.query
|
77
|
+
payload[:fragment] = request.uri.fragment
|
78
|
+
end
|
79
|
+
|
80
|
+
if proxy?
|
81
|
+
payload[:proxy_host] = proxy_address
|
82
|
+
payload[:proxy_port] = proxy_port
|
83
|
+
end
|
84
|
+
|
85
|
+
payload
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labkit
|
4
|
+
# A helper class to store system-related methods used in metrics, tracing, and logging
|
5
|
+
module System
|
6
|
+
# Returns the current monotonic clock time as seconds with microseconds precision.
|
7
|
+
#
|
8
|
+
# Returns the time as a Float.
|
9
|
+
def self.monotonic_time
|
10
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/labkit/tracing.rb
CHANGED
@@ -5,6 +5,8 @@ require "active_support/all"
|
|
5
5
|
module Labkit
|
6
6
|
# Tracing provides distributed tracing functionality
|
7
7
|
module Tracing
|
8
|
+
autoload :AbstractInstrumenter, "labkit/tracing/abstract_instrumenter"
|
9
|
+
autoload :TracingCommon, "labkit/tracing/tracing_common"
|
8
10
|
autoload :Factory, "labkit/tracing/factory"
|
9
11
|
autoload :GRPC, "labkit/tracing/grpc"
|
10
12
|
autoload :GRPCInterceptor, "labkit/tracing/grpc_interceptor" # Deprecated
|
@@ -12,6 +14,7 @@ module Labkit
|
|
12
14
|
autoload :RackMiddleware, "labkit/tracing/rack_middleware"
|
13
15
|
autoload :Rails, "labkit/tracing/rails"
|
14
16
|
autoload :Redis, "labkit/tracing/redis"
|
17
|
+
autoload :ExternalHttp, "labkit/tracing/external_http"
|
15
18
|
autoload :Sidekiq, "labkit/tracing/sidekiq"
|
16
19
|
autoload :TracingUtils, "labkit/tracing/tracing_utils"
|
17
20
|
|
@@ -28,6 +31,12 @@ module Labkit
|
|
28
31
|
ENV["GITLAB_TRACING_URL"]
|
29
32
|
end
|
30
33
|
|
34
|
+
# Check if the current request is being traced.
|
35
|
+
def self.sampled?
|
36
|
+
context = OpenTracing.active_span&.context
|
37
|
+
context&.respond_to?(:sampled?) && context&.sampled?
|
38
|
+
end
|
39
|
+
|
31
40
|
def self.stacktrace_operations
|
32
41
|
@stacktrace_operations ||= Set.new(ENV["GITLAB_TRACING_INCLUDE_STACKTRACE"].to_s.split(",").map(&:strip))
|
33
42
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "opentracing"
|
4
|
+
require "active_support/all"
|
5
|
+
|
6
|
+
module Labkit
|
7
|
+
module Tracing
|
8
|
+
# https://edgeapi.rubyonrails.org/classes/ActiveSupport/Notifications/Instrumenter.html#method-c-new
|
9
|
+
class AbstractInstrumenter
|
10
|
+
def start(_name, _id, payload)
|
11
|
+
scope = OpenTracing.start_active_span(span_name(payload))
|
12
|
+
|
13
|
+
scope_stack.push scope
|
14
|
+
end
|
15
|
+
|
16
|
+
def finish(_name, _id, payload)
|
17
|
+
scope = scope_stack.pop
|
18
|
+
span = scope.span
|
19
|
+
|
20
|
+
Labkit::Tracing::TracingUtils.log_common_fields_on_span(span, span_name(payload))
|
21
|
+
|
22
|
+
# exception_object is the standard exception payload from ActiveSupport::Notifications
|
23
|
+
# https://github.com/rails/rails/blob/v6.0.3.1/activesupport/lib/active_support/notifications/instrumenter.rb#L26
|
24
|
+
exception = payload[:exception_object].presence || payload[:exception].presence
|
25
|
+
Labkit::Tracing::TracingUtils.log_exception_on_span(span, exception)
|
26
|
+
|
27
|
+
tags(payload).each do |k, v|
|
28
|
+
span.set_tag(k, v)
|
29
|
+
end
|
30
|
+
|
31
|
+
scope.close
|
32
|
+
end
|
33
|
+
|
34
|
+
def scope_stack
|
35
|
+
Thread.current[:_labkit_trace_scope_stack] ||= []
|
36
|
+
end
|
37
|
+
|
38
|
+
def span_name(_payload)
|
39
|
+
raise "span_name not implemented"
|
40
|
+
end
|
41
|
+
|
42
|
+
def tags(_payload)
|
43
|
+
{}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labkit
|
4
|
+
module Tracing
|
5
|
+
# Instrument external HTTP calls made by the HTTP client libraries. This
|
6
|
+
# tracing instrumenter listens to the events broadcasted from the
|
7
|
+
# publishers injected into the libraries whenever there is a request.
|
8
|
+
module ExternalHttp
|
9
|
+
include Labkit::Tracing::TracingCommon
|
10
|
+
|
11
|
+
autoload :RequestInstrumenter, "labkit/tracing/external_http/request_instrumenter"
|
12
|
+
|
13
|
+
def self.instrument
|
14
|
+
Labkit::NetHttpPublisher.labkit_prepend!
|
15
|
+
Labkit::ExconPublisher.labkit_prepend!
|
16
|
+
Labkit::HTTPClientPublisher.labkit_prepend!
|
17
|
+
|
18
|
+
subscriptions = [
|
19
|
+
::ActiveSupport::Notifications.subscribe(::Labkit::EXTERNAL_HTTP_NOTIFICATION_TOPIC, RequestInstrumenter.new),
|
20
|
+
]
|
21
|
+
|
22
|
+
create_unsubscriber subscriptions
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Labkit
|
4
|
+
module Tracing
|
5
|
+
module ExternalHttp
|
6
|
+
# For more information on the payloads: lib/labkit/net_http_publisher.rb
|
7
|
+
class RequestInstrumenter < Labkit::Tracing::AbstractInstrumenter
|
8
|
+
def span_name(_payload)
|
9
|
+
"external_http:request"
|
10
|
+
end
|
11
|
+
|
12
|
+
def tags(payload)
|
13
|
+
# Duration is calculated by start and end time
|
14
|
+
# Exception is already captured in lib/labkit/tracing/tracing_utils.rb
|
15
|
+
tags = {
|
16
|
+
"component" => "external_http",
|
17
|
+
"method" => payload[:method],
|
18
|
+
"code" => payload[:code],
|
19
|
+
"host" => payload[:host],
|
20
|
+
"port" => payload[:port],
|
21
|
+
"path" => payload[:path],
|
22
|
+
"scheme" => payload[:scheme],
|
23
|
+
}
|
24
|
+
unless payload[:proxy_host].nil?
|
25
|
+
tags["proxy_host"] = payload[:proxy_host]
|
26
|
+
tags["proxy_port"] = payload[:proxy_port]
|
27
|
+
end
|
28
|
+
tags
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/labkit/tracing/rails.rb
CHANGED
@@ -4,11 +4,9 @@ module Labkit
|
|
4
4
|
module Tracing
|
5
5
|
# Rails provides classes for instrumenting Rails events
|
6
6
|
module Rails
|
7
|
-
autoload :AbstractInstrumenter, "labkit/tracing/rails/abstract_instrumenter"
|
8
7
|
autoload :ActionView, "labkit/tracing/rails/action_view"
|
9
8
|
autoload :ActiveRecord, "labkit/tracing/rails/active_record"
|
10
9
|
autoload :ActiveSupport, "labkit/tracing/rails/active_support"
|
11
|
-
autoload :RailsCommon, "labkit/tracing/rails/rails_common"
|
12
10
|
|
13
11
|
ActionViewSubscriber = ActionView::Subscriber
|
14
12
|
ActiveRecordSubscriber = ActiveRecord::Subscriber
|
@@ -10,6 +10,20 @@ module Labkit
|
|
10
10
|
autoload :Subscriber, "labkit/tracing/rails/action_view/subscriber"
|
11
11
|
|
12
12
|
COMPONENT_TAG = "ActionView"
|
13
|
+
|
14
|
+
# Returns identifier relative to Rails.root. Rails supports different template types and returns corresponding identifiers:
|
15
|
+
# - Text template: the identifier is "text template"
|
16
|
+
# - Html template: the identifier is "html template"
|
17
|
+
# - Inline template: the identifier is "inline template"
|
18
|
+
# - Raw template: the identifier is the file path of the template
|
19
|
+
# Therefore, the amount of returned identifiers is static.
|
20
|
+
def self.template_identifier(payload)
|
21
|
+
return if !defined?(::Rails.root) || payload[:identifier].nil?
|
22
|
+
|
23
|
+
# Rails.root returns a Pathname object, whose `to_s` methods returns an absolute path without ending "/"
|
24
|
+
# Source: https://github.com/rails/rails/blob/v6.0.3.1/railties/lib/rails.rb#L64
|
25
|
+
payload[:identifier].sub("#{::Rails.root}/", "")
|
26
|
+
end
|
13
27
|
end
|
14
28
|
end
|
15
29
|
end
|
@@ -5,9 +5,14 @@ module Labkit
|
|
5
5
|
module Rails
|
6
6
|
module ActionView
|
7
7
|
# For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
|
8
|
-
class RenderCollectionInstrumenter < AbstractInstrumenter
|
8
|
+
class RenderCollectionInstrumenter < Labkit::Tracing::AbstractInstrumenter
|
9
9
|
def span_name(payload)
|
10
|
-
|
10
|
+
identifier = ActionView.template_identifier(payload)
|
11
|
+
if identifier.nil?
|
12
|
+
"render_collection"
|
13
|
+
else
|
14
|
+
"render_collection:#{identifier}"
|
15
|
+
end
|
11
16
|
end
|
12
17
|
|
13
18
|
def tags(payload)
|
@@ -5,9 +5,14 @@ module Labkit
|
|
5
5
|
module Rails
|
6
6
|
module ActionView
|
7
7
|
# For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
|
8
|
-
class RenderPartialInstrumenter < AbstractInstrumenter
|
8
|
+
class RenderPartialInstrumenter < Labkit::Tracing::AbstractInstrumenter
|
9
9
|
def span_name(payload)
|
10
|
-
|
10
|
+
identifier = ActionView.template_identifier(payload)
|
11
|
+
if identifier.nil?
|
12
|
+
"render_partial"
|
13
|
+
else
|
14
|
+
"render_partial:#{identifier}"
|
15
|
+
end
|
11
16
|
end
|
12
17
|
|
13
18
|
def tags(payload)
|
@@ -5,9 +5,14 @@ module Labkit
|
|
5
5
|
module Rails
|
6
6
|
module ActionView
|
7
7
|
# For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
|
8
|
-
class RenderTemplateInstrumenter < AbstractInstrumenter
|
8
|
+
class RenderTemplateInstrumenter < Labkit::Tracing::AbstractInstrumenter
|
9
9
|
def span_name(payload)
|
10
|
-
|
10
|
+
identifier = ActionView.template_identifier(payload)
|
11
|
+
if identifier.nil?
|
12
|
+
"render_template"
|
13
|
+
else
|
14
|
+
"render_template:#{identifier}"
|
15
|
+
end
|
11
16
|
end
|
12
17
|
|
13
18
|
def tags(payload)
|
@@ -7,7 +7,7 @@ module Labkit
|
|
7
7
|
# ActionView bridges action view notifications to
|
8
8
|
# the distributed tracing subsystem
|
9
9
|
class Subscriber
|
10
|
-
include
|
10
|
+
include Labkit::Tracing::TracingCommon
|
11
11
|
|
12
12
|
RENDER_TEMPLATE_NOTIFICATION_TOPIC = "render_template.action_view"
|
13
13
|
RENDER_COLLECTION_NOTIFICATION_TOPIC = "render_collection.action_view"
|
@@ -5,7 +5,7 @@ module Labkit
|
|
5
5
|
module Rails
|
6
6
|
module ActiveRecord
|
7
7
|
# For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
|
8
|
-
class SqlInstrumenter < AbstractInstrumenter
|
8
|
+
class SqlInstrumenter < Labkit::Tracing::AbstractInstrumenter
|
9
9
|
OPERATION_NAME_PREFIX = "active_record:"
|
10
10
|
DEFAULT_OPERATION_NAME = "sqlquery"
|
11
11
|
|
@@ -14,13 +14,14 @@ module Labkit
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def tags(payload)
|
17
|
+
sql = Labkit::Logging::Sanitizer.sanitize_sql(payload[:sql]) if Labkit::Tracing.sampled? && payload[:sql]
|
17
18
|
{
|
18
19
|
"component" => COMPONENT_TAG,
|
19
20
|
"span.kind" => "client",
|
20
21
|
"db.type" => "sql",
|
21
22
|
"db.connection_id" => payload[:connection_id],
|
22
23
|
"db.cached" => payload[:cached] || false,
|
23
|
-
"db.statement" =>
|
24
|
+
"db.statement" => sql,
|
24
25
|
}
|
25
26
|
end
|
26
27
|
end
|
@@ -5,7 +5,7 @@ module Labkit
|
|
5
5
|
module Rails
|
6
6
|
module ActiveSupport
|
7
7
|
# For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
|
8
|
-
class CacheDeleteInstrumenter < AbstractInstrumenter
|
8
|
+
class CacheDeleteInstrumenter < Labkit::Tracing::AbstractInstrumenter
|
9
9
|
def span_name(payload)
|
10
10
|
"cache_delete"
|
11
11
|
end
|
@@ -5,7 +5,7 @@ module Labkit
|
|
5
5
|
module Rails
|
6
6
|
module ActiveSupport
|
7
7
|
# For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
|
8
|
-
class CacheFetchHitInstrumenter < AbstractInstrumenter
|
8
|
+
class CacheFetchHitInstrumenter < Labkit::Tracing::AbstractInstrumenter
|
9
9
|
def span_name(payload)
|
10
10
|
"cache_fetch_hit"
|
11
11
|
end
|
@@ -5,7 +5,7 @@ module Labkit
|
|
5
5
|
module Rails
|
6
6
|
module ActiveSupport
|
7
7
|
# For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
|
8
|
-
class CacheGenerateInstrumenter < AbstractInstrumenter
|
8
|
+
class CacheGenerateInstrumenter < Labkit::Tracing::AbstractInstrumenter
|
9
9
|
def span_name(payload)
|
10
10
|
"cache_generate"
|
11
11
|
end
|
@@ -5,7 +5,7 @@ module Labkit
|
|
5
5
|
module Rails
|
6
6
|
module ActiveSupport
|
7
7
|
# For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
|
8
|
-
class CacheReadInstrumenter < AbstractInstrumenter
|
8
|
+
class CacheReadInstrumenter < Labkit::Tracing::AbstractInstrumenter
|
9
9
|
def span_name(payload)
|
10
10
|
"cache_read"
|
11
11
|
end
|
@@ -5,7 +5,7 @@ module Labkit
|
|
5
5
|
module Rails
|
6
6
|
module ActiveSupport
|
7
7
|
# For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
|
8
|
-
class CacheWriteInstrumenter < AbstractInstrumenter
|
8
|
+
class CacheWriteInstrumenter < Labkit::Tracing::AbstractInstrumenter
|
9
9
|
def span_name(payload)
|
10
10
|
"cache_write"
|
11
11
|
end
|
@@ -7,7 +7,7 @@ module Labkit
|
|
7
7
|
# ActiveSupport bridges action active support notifications to
|
8
8
|
# the distributed tracing subsystem
|
9
9
|
class Subscriber
|
10
|
-
include
|
10
|
+
include Labkit::Tracing::TracingCommon
|
11
11
|
|
12
12
|
CACHE_READ_TOPIC = "cache_read.active_support"
|
13
13
|
CACHE_GENERATE_TOPIC = "cache_generate.active_support"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/all"
|
4
|
+
|
5
|
+
module Labkit
|
6
|
+
module Tracing
|
7
|
+
# TracingCommon is a mixin for providing instrumentation
|
8
|
+
# functionality for the instrumentation classes based on
|
9
|
+
# ActiveSupport::Notifications
|
10
|
+
module TracingCommon
|
11
|
+
extend ::ActiveSupport::Concern
|
12
|
+
|
13
|
+
class_methods do
|
14
|
+
def create_unsubscriber(subscriptions)
|
15
|
+
-> { subscriptions.each { |subscriber| ::ActiveSupport::Notifications.unsubscribe(subscriber) } }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -48,8 +48,10 @@ module Labkit
|
|
48
48
|
|
49
49
|
# Add exception logging to a span
|
50
50
|
def self.log_exception_on_span(span, exception)
|
51
|
+
return if exception.blank?
|
52
|
+
|
51
53
|
span.set_tag("error", true)
|
52
|
-
span.log_kv(kv_tags_for_exception(exception))
|
54
|
+
span.log_kv(**kv_tags_for_exception(exception))
|
53
55
|
end
|
54
56
|
|
55
57
|
# Generate key-value tags for an exception
|
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.14.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:
|
11
|
+
date: 2021-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: 5.0.0
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: 7.0.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: 5.0.0
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
32
|
+
version: 7.0.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: activesupport
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
version: 5.0.0
|
40
40
|
- - "<"
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version:
|
42
|
+
version: 7.0.0
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -49,7 +49,21 @@ dependencies:
|
|
49
49
|
version: 5.0.0
|
50
50
|
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version:
|
52
|
+
version: 7.0.0
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: gitlab-pg_query
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '1.3'
|
60
|
+
type: :runtime
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '1.3'
|
53
67
|
- !ruby/object:Gem::Dependency
|
54
68
|
name: grpc
|
55
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,6 +126,34 @@ dependencies:
|
|
112
126
|
- - "<"
|
113
127
|
- !ruby/object:Gem::Version
|
114
128
|
version: 5.0.0
|
129
|
+
- !ruby/object:Gem::Dependency
|
130
|
+
name: excon
|
131
|
+
requirement: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - "~>"
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: 0.78.1
|
136
|
+
type: :development
|
137
|
+
prerelease: false
|
138
|
+
version_requirements: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - "~>"
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 0.78.1
|
143
|
+
- !ruby/object:Gem::Dependency
|
144
|
+
name: faraday
|
145
|
+
requirement: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - "~>"
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 1.2.0
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - "~>"
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: 1.2.0
|
115
157
|
- !ruby/object:Gem::Dependency
|
116
158
|
name: grpc-tools
|
117
159
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,6 +168,34 @@ dependencies:
|
|
126
168
|
- - "~>"
|
127
169
|
- !ruby/object:Gem::Version
|
128
170
|
version: '1.19'
|
171
|
+
- !ruby/object:Gem::Dependency
|
172
|
+
name: httparty
|
173
|
+
requirement: !ruby/object:Gem::Requirement
|
174
|
+
requirements:
|
175
|
+
- - "~>"
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
version: 0.17.3
|
178
|
+
type: :development
|
179
|
+
prerelease: false
|
180
|
+
version_requirements: !ruby/object:Gem::Requirement
|
181
|
+
requirements:
|
182
|
+
- - "~>"
|
183
|
+
- !ruby/object:Gem::Version
|
184
|
+
version: 0.17.3
|
185
|
+
- !ruby/object:Gem::Dependency
|
186
|
+
name: httpclient
|
187
|
+
requirement: !ruby/object:Gem::Requirement
|
188
|
+
requirements:
|
189
|
+
- - "~>"
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: 2.8.3
|
192
|
+
type: :development
|
193
|
+
prerelease: false
|
194
|
+
version_requirements: !ruby/object:Gem::Requirement
|
195
|
+
requirements:
|
196
|
+
- - "~>"
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: 2.8.3
|
129
199
|
- !ruby/object:Gem::Dependency
|
130
200
|
name: pry
|
131
201
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,6 +238,20 @@ dependencies:
|
|
168
238
|
- - "~>"
|
169
239
|
- !ruby/object:Gem::Version
|
170
240
|
version: '12.3'
|
241
|
+
- !ruby/object:Gem::Dependency
|
242
|
+
name: rest-client
|
243
|
+
requirement: !ruby/object:Gem::Requirement
|
244
|
+
requirements:
|
245
|
+
- - "~>"
|
246
|
+
- !ruby/object:Gem::Version
|
247
|
+
version: 2.1.0
|
248
|
+
type: :development
|
249
|
+
prerelease: false
|
250
|
+
version_requirements: !ruby/object:Gem::Requirement
|
251
|
+
requirements:
|
252
|
+
- - "~>"
|
253
|
+
- !ruby/object:Gem::Version
|
254
|
+
version: 2.1.0
|
171
255
|
- !ruby/object:Gem::Dependency
|
172
256
|
name: rspec
|
173
257
|
requirement: !ruby/object:Gem::Requirement
|
@@ -261,6 +345,7 @@ extra_rdoc_files: []
|
|
261
345
|
files:
|
262
346
|
- ".gitignore"
|
263
347
|
- ".gitlab-ci.yml"
|
348
|
+
- ".gitlab/CODEOWNERS"
|
264
349
|
- ".rspec"
|
265
350
|
- ".rubocop.yml"
|
266
351
|
- ".ruby-version"
|
@@ -278,6 +363,8 @@ files:
|
|
278
363
|
- lib/labkit/correlation/grpc/client_interceptor.rb
|
279
364
|
- lib/labkit/correlation/grpc/grpc_common.rb
|
280
365
|
- lib/labkit/correlation/grpc/server_interceptor.rb
|
366
|
+
- lib/labkit/excon_publisher.rb
|
367
|
+
- lib/labkit/httpclient_publisher.rb
|
281
368
|
- lib/labkit/logging.rb
|
282
369
|
- lib/labkit/logging/grpc.rb
|
283
370
|
- lib/labkit/logging/grpc/server_interceptor.rb
|
@@ -294,7 +381,12 @@ files:
|
|
294
381
|
- lib/labkit/middleware/sidekiq/tracing/client.rb
|
295
382
|
- lib/labkit/middleware/sidekiq/tracing/server.rb
|
296
383
|
- lib/labkit/middleware/sidekiq/tracing/sidekiq_common.rb
|
384
|
+
- lib/labkit/net_http_publisher.rb
|
385
|
+
- lib/labkit/system.rb
|
297
386
|
- lib/labkit/tracing.rb
|
387
|
+
- lib/labkit/tracing/abstract_instrumenter.rb
|
388
|
+
- lib/labkit/tracing/external_http.rb
|
389
|
+
- lib/labkit/tracing/external_http/request_instrumenter.rb
|
298
390
|
- lib/labkit/tracing/factory.rb
|
299
391
|
- lib/labkit/tracing/grpc.rb
|
300
392
|
- lib/labkit/tracing/grpc/client_interceptor.rb
|
@@ -303,7 +395,6 @@ files:
|
|
303
395
|
- lib/labkit/tracing/jaeger_factory.rb
|
304
396
|
- lib/labkit/tracing/rack_middleware.rb
|
305
397
|
- lib/labkit/tracing/rails.rb
|
306
|
-
- lib/labkit/tracing/rails/abstract_instrumenter.rb
|
307
398
|
- lib/labkit/tracing/rails/action_view.rb
|
308
399
|
- lib/labkit/tracing/rails/action_view/render_collection_instrumenter.rb
|
309
400
|
- lib/labkit/tracing/rails/action_view/render_partial_instrumenter.rb
|
@@ -319,10 +410,10 @@ files:
|
|
319
410
|
- lib/labkit/tracing/rails/active_support/cache_read_instrumenter.rb
|
320
411
|
- lib/labkit/tracing/rails/active_support/cache_write_instrumenter.rb
|
321
412
|
- lib/labkit/tracing/rails/active_support/subscriber.rb
|
322
|
-
- lib/labkit/tracing/rails/rails_common.rb
|
323
413
|
- lib/labkit/tracing/redis.rb
|
324
414
|
- lib/labkit/tracing/redis/redis_interceptor.rb
|
325
415
|
- lib/labkit/tracing/redis/redis_interceptor_helper.rb
|
416
|
+
- lib/labkit/tracing/tracing_common.rb
|
326
417
|
- lib/labkit/tracing/tracing_utils.rb
|
327
418
|
homepage: https://gitlab.com/gitlab-org/labkit-ruby
|
328
419
|
licenses:
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_support/all"
|
4
|
-
|
5
|
-
module Labkit
|
6
|
-
module Tracing
|
7
|
-
module Rails
|
8
|
-
# https://edgeapi.rubyonrails.org/classes/ActiveSupport/Notifications/Instrumenter.html#method-c-new
|
9
|
-
class AbstractInstrumenter
|
10
|
-
def start(name, id, payload)
|
11
|
-
scope = OpenTracing.start_active_span(span_name(payload))
|
12
|
-
|
13
|
-
scope_stack.push scope
|
14
|
-
end
|
15
|
-
|
16
|
-
def finish(name, id, payload)
|
17
|
-
scope = scope_stack.pop
|
18
|
-
span = scope.span
|
19
|
-
|
20
|
-
Labkit::Tracing::TracingUtils.log_common_fields_on_span(span, span_name(payload))
|
21
|
-
|
22
|
-
exception = payload[:exception]
|
23
|
-
Labkit::Tracing::TracingUtils.log_exception_on_span(span, exception) if exception
|
24
|
-
|
25
|
-
tags(payload).each do |k, v|
|
26
|
-
span.set_tag(k, v)
|
27
|
-
end
|
28
|
-
|
29
|
-
scope.close
|
30
|
-
end
|
31
|
-
|
32
|
-
def scope_stack
|
33
|
-
Thread.current[:_labkit_trace_scope_stack] ||= []
|
34
|
-
end
|
35
|
-
|
36
|
-
def span_name(payload)
|
37
|
-
raise "span_name not implemented"
|
38
|
-
end
|
39
|
-
|
40
|
-
def tags(payload)
|
41
|
-
{}
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_support/all"
|
4
|
-
|
5
|
-
module Labkit
|
6
|
-
module Tracing
|
7
|
-
module Rails
|
8
|
-
# RailsCommon is a mixin for providing instrumentation
|
9
|
-
# functionality for the rails instrumentation classes
|
10
|
-
module RailsCommon
|
11
|
-
extend ::ActiveSupport::Concern
|
12
|
-
|
13
|
-
class_methods do
|
14
|
-
def create_unsubscriber(subscriptions)
|
15
|
-
-> { subscriptions.each { |subscriber| ::ActiveSupport::Notifications.unsubscribe(subscriber) } }
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|