gitlab-labkit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b0e98b5b882ecd840a8fd9cc638c6c6c8802249ac7a8c501b6fba56deb1170dc
4
+ data.tar.gz: 46c8894fc4cd432bc07a08c64f3090976fa74476d21b1bf482ead09c93cb27f8
5
+ SHA512:
6
+ metadata.gz: d8c5fd9a8309b00b3c62652b62fbac2112dc023a5061d85731127c519ba6cb77c475ff405142cac74fb9d5eb30239b17c0d23978998ca8dca79f4f352b950897
7
+ data.tar.gz: b7fb1d3b8c683295a58054192f1326ce985714698991c7e9f304631cb3ba4b0fd92e49b282f587ad9396b7f1846e0550cd9278fa992e254dc447bb898b81d208
data/lib/labkit.rb ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labkit
4
+ autoload :Correlation, 'labkit/correlation'
5
+ autoload :Tracing, 'labkit/tracing'
6
+ autoload :Logging, 'labkit/logging'
7
+
8
+ def self.process_name
9
+ return 'sidekiq' if Sidekiq.server?
10
+ return 'console' if defined?(Rails::Console)
11
+ return 'test' if Rails.env.test?
12
+
13
+ 'web'
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labkit
4
+ module Correlation
5
+ autoload :CorrelationId, 'labkit/correlation/correlation_id'
6
+ end
7
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labkit
4
+ module Correlation
5
+ module CorrelationId
6
+ LOG_KEY = 'correlation_id'
7
+
8
+ class << self
9
+ def use_id(correlation_id, &blk)
10
+ # always generate a id if null is passed
11
+ correlation_id ||= new_id
12
+
13
+ ids.push(correlation_id || new_id)
14
+
15
+ begin
16
+ yield(current_id)
17
+ ensure
18
+ ids.pop
19
+ end
20
+ end
21
+
22
+ def current_id
23
+ ids.last
24
+ end
25
+
26
+ def current_or_new_id
27
+ current_id || new_id
28
+ end
29
+
30
+ private
31
+
32
+ def ids
33
+ Thread.current[:correlation_id] ||= []
34
+ end
35
+
36
+ def new_id
37
+ SecureRandom.uuid
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labkit
4
+ module Logging
5
+ autoload :Sanitizer, 'labkit/logging/sanitizer'
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labkit
4
+ module Logging
5
+ class Sanitizer
6
+ ALLOWED_SCHEMES = %w[http https ssh git].freeze
7
+
8
+ def self.sanitize_field(content)
9
+ regexp = URI::DEFAULT_PARSER.make_regexp(ALLOWED_SCHEMES)
10
+
11
+ content.gsub(regexp) { |url| masked_url(url) }
12
+ end
13
+
14
+ def self.masked_url(url)
15
+ url = url.to_s.strip
16
+ url = Addressable::URI.parse(url)
17
+
18
+ url.password = '*****' if url.password.present?
19
+ url.user = '*****' if url.user.present?
20
+ url.to_s
21
+ rescue Addressable::URI::InvalidURIError
22
+ ''
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/all'
4
+
5
+ module Labkit
6
+ module Tracing
7
+ autoload :Common, 'labkit/tracing/common'
8
+ autoload :Factory, 'labkit/tracing/factory'
9
+ autoload :GRPCInterceptor, 'labkit/tracing/grpc_interceptor'
10
+ autoload :JaegerFactory, 'labkit/tracing/jaeger_factory'
11
+ autoload :RackMiddleware, 'labkit/tracing/rack_middleware'
12
+
13
+ module Rails
14
+ autoload :ActionViewSubscriber, 'labkit/tracing/rails/action_view_subscriber.rb'
15
+ autoload :ActiveRecordSubscriber, 'labkit/tracing/rails/active_record_subscriber.rb'
16
+ autoload :RailsCommon, 'labkit/tracing/rails/rails_common'
17
+ end
18
+
19
+ module Sidekiq
20
+ autoload :ClientMiddleware, 'labkit/tracing/sidekiq/client_middleware'
21
+ autoload :ServerMiddleware, 'labkit/tracing/sidekiq/server_middleware'
22
+ autoload :SidekiqCommon, 'labkit/tracing/sidekiq/sidekiq_common'
23
+ end
24
+
25
+ # Only enable tracing when the `GITLAB_TRACING` env var is configured. Note that we avoid using ApplicationSettings since
26
+ # the same environment variable needs to be configured for Workhorse, Gitaly and any other components which
27
+ # emit tracing. Since other components may start before Rails, and may not have access to ApplicationSettings,
28
+ # an env var makes more sense.
29
+ def self.enabled?
30
+ connection_string.present?
31
+ end
32
+
33
+ def self.connection_string
34
+ ENV['GITLAB_TRACING']
35
+ end
36
+
37
+ def self.tracing_url_template
38
+ ENV['GITLAB_TRACING_URL']
39
+ end
40
+
41
+ def self.tracing_url_enabled?
42
+ enabled? && tracing_url_template.present?
43
+ end
44
+
45
+ # This will provide a link into the distributed tracing for the current trace,
46
+ # if it has been captured.
47
+ def self.tracing_url
48
+ return unless tracing_url_enabled?
49
+
50
+ tracing_url_template.to_s % { correlation_id: Labkit::Correlation::CorrelationId.current_id.to_s, service: Labkit.process_name }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'opentracing'
4
+
5
+ module Labkit
6
+ module Tracing
7
+ module Common
8
+ def tracer
9
+ OpenTracing.global_tracer
10
+ end
11
+
12
+ # Convience method for running a block with a span
13
+ def in_tracing_span(operation_name:, tags:, child_of: nil)
14
+ scope = tracer.start_active_span(operation_name, child_of: child_of, tags: tags)
15
+ span = scope.span
16
+
17
+ # Add correlation details to the span if we have them
18
+ correlation_id = Labkit::Correlation::CorrelationId.current_id
19
+ span.set_tag('correlation_id', correlation_id) if correlation_id
20
+
21
+ begin
22
+ yield span
23
+ rescue StandardError => e
24
+ log_exception_on_span(span, e)
25
+ raise e
26
+ ensure
27
+ scope.close
28
+ end
29
+ end
30
+
31
+ def postnotify_span(operation_name, start_time, end_time, tags: nil, child_of: nil, exception: nil)
32
+ span = OpenTracing.start_span(operation_name, start_time: start_time, tags: tags, child_of: child_of)
33
+
34
+ log_exception_on_span(span, exception) if exception
35
+
36
+ span.finish(end_time: end_time)
37
+ end
38
+
39
+ def log_exception_on_span(span, exception)
40
+ span.set_tag('error', true)
41
+ span.log_kv(kv_tags_for_exception(exception))
42
+ end
43
+
44
+ def kv_tags_for_exception(exception)
45
+ case exception
46
+ when Exception
47
+ {
48
+ :"event" => 'error',
49
+ :"error.kind" => exception.class.to_s,
50
+ :"message" => Labkit::Logging::Sanitizer.sanitize_field(exception.message),
51
+ :"stack" => exception.backtrace&.join('\n')
52
+ }
53
+ else
54
+ { :"event" => 'error', :"error.kind" => exception.class.to_s, :"error.object" => Labkit::Logging::Sanitizer.sanitize_field(exception.to_s) }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+
5
+ module Labkit
6
+ module Tracing
7
+ class Factory
8
+ OPENTRACING_SCHEME = 'opentracing'
9
+
10
+ def self.create_tracer(service_name, connection_string)
11
+ return unless connection_string.present?
12
+
13
+ begin
14
+ opentracing_details = parse_connection_string(connection_string)
15
+ driver_name = opentracing_details[:driver_name]
16
+
17
+ case driver_name
18
+ when 'jaeger'
19
+ JaegerFactory.create_tracer(service_name, opentracing_details[:options])
20
+ else
21
+ raise "Unknown driver: #{driver_name}"
22
+ end
23
+
24
+ # Can't create the tracer? Warn and continue sans tracer
25
+ rescue StandardError => e
26
+ warn "Unable to instantiate tracer: #{e}"
27
+ nil
28
+ end
29
+ end
30
+
31
+ def self.parse_connection_string(connection_string)
32
+ parsed = URI.parse(connection_string)
33
+
34
+ raise 'Invalid tracing connection string' unless valid_uri?(parsed)
35
+
36
+ { driver_name: parsed.host, options: parse_query(parsed.query) }
37
+ end
38
+ private_class_method :parse_connection_string
39
+
40
+ def self.parse_query(query)
41
+ return {} unless query
42
+
43
+ CGI.parse(query).symbolize_keys.transform_values(&:first)
44
+ end
45
+ private_class_method :parse_query
46
+
47
+ def self.valid_uri?(uri)
48
+ return false unless uri
49
+
50
+ uri.scheme == OPENTRACING_SCHEME && uri.host.to_s =~ /^[a-z0-9_]+$/ && uri.path.empty?
51
+ end
52
+ private_class_method :valid_uri?
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'opentracing'
4
+ require 'grpc'
5
+
6
+ module Labkit
7
+ module Tracing
8
+ class GRPCInterceptor < GRPC::ClientInterceptor
9
+ include Common
10
+ include Singleton
11
+
12
+ def request_response(request:, call:, method:, metadata:)
13
+ wrap_with_tracing(method, 'unary', metadata) { yield }
14
+ end
15
+
16
+ def client_streamer(requests:, call:, method:, metadata:)
17
+ wrap_with_tracing(method, 'client_stream', metadata) { yield }
18
+ end
19
+
20
+ def server_streamer(request:, call:, method:, metadata:)
21
+ wrap_with_tracing(method, 'server_stream', metadata) { yield }
22
+ end
23
+
24
+ def bidi_streamer(requests:, call:, method:, metadata:)
25
+ wrap_with_tracing(method, 'bidi_stream', metadata) { yield }
26
+ end
27
+
28
+ private
29
+
30
+ def wrap_with_tracing(method, grpc_type, metadata)
31
+ tags = { 'component' => 'grpc', 'span.kind' => 'client', 'grpc.method' => method, 'grpc.type' => grpc_type }
32
+
33
+ in_tracing_span(operation_name: "grpc:#{method}", tags: tags) do |span|
34
+ OpenTracing.inject(span.context, OpenTracing::FORMAT_TEXT_MAP, metadata)
35
+
36
+ yield
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jaeger/client'
4
+
5
+ module Labkit
6
+ module Tracing
7
+ class JaegerFactory
8
+ # When the probabilistic sampler is used, by default 0.1% of requests will be traced
9
+ DEFAULT_PROBABILISTIC_RATE = 0.001
10
+
11
+ # The default port for the Jaeger agent UDP listener
12
+ DEFAULT_UDP_PORT = 6831
13
+
14
+ # Reduce this from default of 10 seconds as the Ruby jaeger
15
+ # client doesn't have overflow control, leading to very large
16
+ # messages which fail to send over UDP (max packet = 64k)
17
+ # Flush more often, with smaller packets
18
+ FLUSH_INTERVAL = 5
19
+
20
+ def self.create_tracer(service_name, options)
21
+ kwargs = {
22
+ service_name: service_name,
23
+ sampler: get_sampler(options[:sampler], options[:sampler_param]),
24
+ reporter: get_reporter(service_name, options[:http_endpoint], options[:udp_endpoint])
25
+ }
26
+ .compact
27
+
28
+ extra_params = options.except(:sampler, :sampler_param, :http_endpoint, :udp_endpoint, :strict_parsing, :debug)
29
+ if extra_params.present?
30
+ message = "jaeger tracer: invalid option: #{extra_params.keys.join(', ')}"
31
+
32
+ raise message if options[:strict_parsing]
33
+
34
+ warn message
35
+ end
36
+
37
+ Jaeger::Client.build(kwargs)
38
+ end
39
+
40
+ def self.get_sampler(sampler_type, sampler_param)
41
+ case sampler_type
42
+ when 'probabilistic'
43
+ sampler_rate = sampler_param ? sampler_param.to_f : DEFAULT_PROBABILISTIC_RATE
44
+ Jaeger::Samplers::Probabilistic.new(rate: sampler_rate)
45
+ when 'const'
46
+ const_value = sampler_param == '1'
47
+ Jaeger::Samplers::Const.new(const_value)
48
+ end
49
+ end
50
+ private_class_method :get_sampler
51
+
52
+ def self.get_reporter(service_name, http_endpoint, udp_endpoint)
53
+ encoder = Jaeger::Encoders::ThriftEncoder.new(service_name: service_name)
54
+
55
+ if http_endpoint.present?
56
+ sender = get_http_sender(encoder, http_endpoint)
57
+ elsif udp_endpoint.present?
58
+ sender = get_udp_sender(encoder, udp_endpoint)
59
+ else
60
+ return nil
61
+ end
62
+
63
+ Jaeger::Reporters::RemoteReporter.new(sender: sender, flush_interval: FLUSH_INTERVAL)
64
+ end
65
+ private_class_method :get_reporter
66
+
67
+ def self.get_http_sender(encoder, address)
68
+ Jaeger::HttpSender.new(url: address, encoder: encoder, logger: Logger.new(STDOUT))
69
+ end
70
+ private_class_method :get_http_sender
71
+
72
+ def self.get_udp_sender(encoder, address)
73
+ pair = address.split(':', 2)
74
+ host = pair[0]
75
+ port = pair[1] ? pair[1].to_i : DEFAULT_UDP_PORT
76
+
77
+ Jaeger::UdpSender.new(host: host, port: port, encoder: encoder, logger: Logger.new(STDOUT))
78
+ end
79
+ private_class_method :get_udp_sender
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'opentracing'
4
+ require 'rails'
5
+
6
+ module Labkit
7
+ module Tracing
8
+ class RackMiddleware
9
+ include Common
10
+
11
+ REQUEST_METHOD = 'REQUEST_METHOD'
12
+
13
+ def initialize(app)
14
+ @app = app
15
+ end
16
+
17
+ def call(env)
18
+ method = env[REQUEST_METHOD]
19
+
20
+ context = tracer.extract(OpenTracing::FORMAT_RACK, env)
21
+ tags = { 'component' => 'rack', 'span.kind' => 'server', 'http.method' => method, 'http.url' => self.class.build_sanitized_url_from_env(env) }
22
+
23
+ in_tracing_span(operation_name: "http:#{method}", child_of: context, tags: tags) do |span|
24
+ @app.call(env).tap { |status_code, _headers, _body| span.set_tag('http.status_code', status_code) }
25
+ end
26
+ end
27
+
28
+ # Generate a sanitized (safe) request URL from the rack environment
29
+ def self.build_sanitized_url_from_env(env)
30
+ request = ::ActionDispatch::Request.new(env)
31
+
32
+ original_url = request.original_url
33
+ uri = URI.parse(original_url)
34
+ uri.query = request.filtered_parameters.to_query if uri.query.present?
35
+
36
+ uri.to_s
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labkit
4
+ module Tracing
5
+ module Rails
6
+ class ActionViewSubscriber
7
+ include RailsCommon
8
+
9
+ COMPONENT_TAG = 'ActionView'
10
+ RENDER_TEMPLATE_NOTIFICATION_TOPIC = 'render_template.action_view'
11
+ RENDER_COLLECTION_NOTIFICATION_TOPIC = 'render_collection.action_view'
12
+ RENDER_PARTIAL_NOTIFICATION_TOPIC = 'render_partial.action_view'
13
+
14
+ # Instruments Rails ActionView events for opentracing.
15
+ # Returns a lambda, which, when called will unsubscribe from the notifications
16
+ def self.instrument
17
+ subscriber = new
18
+
19
+ subscriptions = [
20
+ ActiveSupport::Notifications.subscribe(RENDER_TEMPLATE_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
21
+ subscriber.notify_render_template(start, finish, payload)
22
+ end,
23
+ ActiveSupport::Notifications.subscribe(RENDER_COLLECTION_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
24
+ subscriber.notify_render_collection(start, finish, payload)
25
+ end,
26
+ ActiveSupport::Notifications.subscribe(RENDER_PARTIAL_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
27
+ subscriber.notify_render_partial(start, finish, payload)
28
+ end
29
+ ]
30
+
31
+ create_unsubscriber subscriptions
32
+ end
33
+
34
+ # For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
35
+ def notify_render_template(start, finish, payload)
36
+ generate_span_for_notification('render_template', start, finish, payload, tags_for_render_template(payload))
37
+ end
38
+
39
+ def notify_render_collection(start, finish, payload)
40
+ generate_span_for_notification('render_collection', start, finish, payload, tags_for_render_collection(payload))
41
+ end
42
+
43
+ def notify_render_partial(start, finish, payload)
44
+ generate_span_for_notification('render_partial', start, finish, payload, tags_for_render_partial(payload))
45
+ end
46
+
47
+ private
48
+
49
+ def tags_for_render_template(payload)
50
+ { 'component' => COMPONENT_TAG, 'template.id' => payload[:identifier], 'template.layout' => payload[:layout] }
51
+ end
52
+
53
+ def tags_for_render_collection(payload)
54
+ {
55
+ 'component' => COMPONENT_TAG,
56
+ 'template.id' => payload[:identifier],
57
+ 'template.count' => payload[:count] || 0,
58
+ 'template.cache.hits' => payload[:cache_hits] || 0
59
+ }
60
+ end
61
+
62
+ def tags_for_render_partial(payload)
63
+ { 'component' => COMPONENT_TAG, 'template.id' => payload[:identifier] }
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labkit
4
+ module Tracing
5
+ module Rails
6
+ class ActiveRecordSubscriber
7
+ include RailsCommon
8
+
9
+ ACTIVE_RECORD_NOTIFICATION_TOPIC = 'sql.active_record'
10
+ OPERATION_NAME_PREFIX = 'active_record:'
11
+ DEFAULT_OPERATION_NAME = 'sqlquery'
12
+
13
+ # Instruments Rails ActiveRecord events for opentracing.
14
+ # Returns a lambda, which, when called will unsubscribe from the notifications
15
+ def self.instrument
16
+ subscriber = new
17
+
18
+ subscription =
19
+ ActiveSupport::Notifications.subscribe(ACTIVE_RECORD_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
20
+ subscriber.notify(start, finish, payload)
21
+ end
22
+
23
+ create_unsubscriber [subscription]
24
+ end
25
+
26
+ # For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
27
+ def notify(start, finish, payload)
28
+ generate_span_for_notification(notification_name(payload), start, finish, payload, tags_for_notification(payload))
29
+ end
30
+
31
+ private
32
+
33
+ def notification_name(payload)
34
+ OPERATION_NAME_PREFIX + (payload[:name].presence || DEFAULT_OPERATION_NAME)
35
+ end
36
+
37
+ def tags_for_notification(payload)
38
+ {
39
+ 'component' => 'ActiveRecord',
40
+ 'span.kind' => 'client',
41
+ 'db.type' => 'sql',
42
+ 'db.connection_id' => payload[:connection_id],
43
+ 'db.cached' => payload[:cached] || false,
44
+ 'db.statement' => payload[:sql]
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/all'
4
+
5
+ module Labkit
6
+ module Tracing
7
+ module Rails
8
+ module RailsCommon
9
+ extend ActiveSupport::Concern
10
+ include Labkit::Tracing::Common
11
+
12
+ class_methods do
13
+ def create_unsubscriber(subscriptions)
14
+ -> { subscriptions.each { |subscriber| ActiveSupport::Notifications.unsubscribe(subscriber) } }
15
+ end
16
+ end
17
+
18
+ def generate_span_for_notification(operation_name, start, finish, payload, tags)
19
+ exception = payload[:exception]
20
+
21
+ postnotify_span(operation_name, start, finish, tags: tags, exception: exception)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'opentracing'
4
+
5
+ module Labkit
6
+ module Tracing
7
+ module Sidekiq
8
+ class ClientMiddleware
9
+ include SidekiqCommon
10
+
11
+ SPAN_KIND = 'client'
12
+
13
+ def call(worker_class, job, queue, redis_pool)
14
+ in_tracing_span(operation_name: "sidekiq:#{job['class']}", tags: tags_from_job(job, SPAN_KIND)) do |span|
15
+ # Inject the details directly into the job
16
+ tracer
17
+ .inject(span.context, OpenTracing::FORMAT_TEXT_MAP, job)
18
+
19
+ yield
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'opentracing'
4
+
5
+ module Labkit
6
+ module Tracing
7
+ module Sidekiq
8
+ class ServerMiddleware
9
+ include SidekiqCommon
10
+
11
+ SPAN_KIND = 'server'
12
+
13
+ def call(worker, job, queue)
14
+ context = tracer.extract(OpenTracing::FORMAT_TEXT_MAP, job)
15
+
16
+ in_tracing_span(operation_name: "sidekiq:#{job['class']}", child_of: context, tags: tags_from_job(job, SPAN_KIND)) { |span| yield }
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labkit
4
+ module Tracing
5
+ module Sidekiq
6
+ module SidekiqCommon
7
+ include Labkit::Tracing::Common
8
+
9
+ def tags_from_job(job, kind)
10
+ {
11
+ 'component' => 'sidekiq',
12
+ 'span.kind' => kind,
13
+ 'sidekiq.queue' => job['queue'],
14
+ 'sidekiq.jid' => job['jid'],
15
+ 'sidekiq.retry' => job['retry'].to_s,
16
+ 'sidekiq.args' => job['args']&.join(', ')
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,229 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gitlab-labkit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Newdigate
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: grpc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.16'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: jaeger-client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.10'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: opentracing
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.4'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rack
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '5.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: gitlab-styles
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.4'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.4'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '12.3'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '12.3'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 3.6.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 3.6.0
139
+ - !ruby/object:Gem::Dependency
140
+ name: rspec-parameterized
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.4'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.4'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: 0.54.0
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: 0.54.0
167
+ - !ruby/object:Gem::Dependency
168
+ name: rubocop-rspec
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: 1.22.1
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 1.22.1
181
+ description:
182
+ email:
183
+ - andrew@gitlab.com
184
+ executables: []
185
+ extensions: []
186
+ extra_rdoc_files: []
187
+ files:
188
+ - lib/labkit.rb
189
+ - lib/labkit/correlation.rb
190
+ - lib/labkit/correlation/correlation_id.rb
191
+ - lib/labkit/logging.rb
192
+ - lib/labkit/logging/sanitizer.rb
193
+ - lib/labkit/tracing.rb
194
+ - lib/labkit/tracing/common.rb
195
+ - lib/labkit/tracing/factory.rb
196
+ - lib/labkit/tracing/grpc_interceptor.rb
197
+ - lib/labkit/tracing/jaeger_factory.rb
198
+ - lib/labkit/tracing/rack_middleware.rb
199
+ - lib/labkit/tracing/rails/action_view_subscriber.rb
200
+ - lib/labkit/tracing/rails/active_record_subscriber.rb
201
+ - lib/labkit/tracing/rails/rails_common.rb
202
+ - lib/labkit/tracing/sidekiq/client_middleware.rb
203
+ - lib/labkit/tracing/sidekiq/server_middleware.rb
204
+ - lib/labkit/tracing/sidekiq/sidekiq_common.rb
205
+ homepage: http://about.gitlab.com
206
+ licenses:
207
+ - MIT
208
+ metadata: {}
209
+ post_install_message:
210
+ rdoc_options: []
211
+ require_paths:
212
+ - lib
213
+ required_ruby_version: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: '0'
218
+ required_rubygems_version: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ requirements: []
224
+ rubyforge_project:
225
+ rubygems_version: 2.7.8
226
+ signing_key:
227
+ specification_version: 4
228
+ summary: Instrumentation for GitLab
229
+ test_files: []