opentracing-instrumentation 0.1.15 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.BUNDLER_VERSION +1 -1
- data/.drone.jsonnet +3 -3
- data/.gitlab-ci.yml +12 -11
- data/.rubocop.yml +7 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +7 -0
- data/GEM_VERSION +1 -1
- data/Gemfile +7 -7
- data/Gemfile.lock +80 -60
- data/bin/check_gemfile_lock +18 -0
- data/lib/opentracing/instrumentation/bunny.rb +11 -11
- data/lib/opentracing/instrumentation/bunny/regexp_routing_key_sanitazer.rb +1 -1
- data/lib/opentracing/instrumentation/common.rb +2 -0
- data/lib/opentracing/instrumentation/common/error_writer.rb +2 -2
- data/lib/opentracing/instrumentation/common/operation_name_builder.rb +23 -0
- data/lib/opentracing/instrumentation/faraday/response_logger.rb +4 -4
- data/lib/opentracing/instrumentation/faraday/trace_middleware.rb +1 -1
- data/lib/opentracing/instrumentation/hutch.rb +6 -6
- data/lib/opentracing/instrumentation/mongo.rb +2 -0
- data/lib/opentracing/instrumentation/mongo/query_sanitazer.rb +48 -5
- data/lib/opentracing/instrumentation/mongo/sample_safety_argument_checker.rb +30 -0
- data/lib/opentracing/instrumentation/mongo/trace_subscriber.rb +5 -5
- data/lib/opentracing/instrumentation/rack/http_tagger.rb +3 -3
- data/lib/opentracing/instrumentation/rack/trace_middleware.rb +5 -5
- data/lib/opentracing/instrumentation/redis/config.rb +5 -5
- data/lib/opentracing/instrumentation/redis/tracing_driver_wrapper.rb +4 -4
- data/lib/opentracing/instrumentation/sidekiq/client_middleware.rb +41 -18
- data/lib/opentracing/instrumentation/sidekiq/job_tagger.rb +7 -7
- data/lib/opentracing/instrumentation/sidekiq/server_middleware.rb +41 -15
- data/lib/opentracing/instrumentation/thrift.rb +9 -9
- data/lib/opentracing/instrumentation/thrift/traced_processor.rb +2 -2
- data/lib/opentracing/instrumentation/thrift/traced_processor_config.rb +1 -1
- data/lib/opentracing/instrumentation/thrift/traced_processor_tags_builder.rb +1 -0
- data/lib/opentracing/instrumentation/thrift/traced_protocol.rb +3 -3
- data/lib/opentracing/instrumentation/thrift/traced_protocol_factory.rb +1 -0
- data/lib/opentracing/instrumentation/thrift/traced_protocol_tags_builder.rb +1 -1
- data/opentracing-instrumentation.gemspec +11 -7
- metadata +42 -23
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OpenTracing
|
4
|
+
module Instrumentation
|
5
|
+
module Common
|
6
|
+
# Build operation name by template and tags
|
7
|
+
class OperationNameBuilder
|
8
|
+
def initialize(operation_name_template:)
|
9
|
+
@operation_name_template = operation_name_template
|
10
|
+
end
|
11
|
+
|
12
|
+
# build operation name with tags
|
13
|
+
def build(tags)
|
14
|
+
format(operation_name_template, **tags)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :operation_name_template
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -20,10 +20,10 @@ module OpenTracing
|
|
20
20
|
content_type: 'Content-Type',
|
21
21
|
}.freeze
|
22
22
|
|
23
|
-
attr_reader :request_tag_headers
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
attr_reader :request_tag_headers,
|
24
|
+
:request_log_headers,
|
25
|
+
:response_tag_headers,
|
26
|
+
:response_log_headers
|
27
27
|
|
28
28
|
def initialize(
|
29
29
|
request_log_headers: DEFAULT_REQUEST_LOG_HEADERS,
|
@@ -12,17 +12,17 @@ module OpenTracing
|
|
12
12
|
module_path = 'opentracing/instrumentation/hutch'
|
13
13
|
|
14
14
|
autoload :ConsumeOperationNameBuilder,
|
15
|
-
module_path
|
15
|
+
"#{module_path}/consume_operation_name_builder"
|
16
16
|
autoload :ConsumeTagsBuilder,
|
17
|
-
module_path
|
17
|
+
"#{module_path}/consume_tags_builder"
|
18
18
|
autoload :ConsumeTracer,
|
19
|
-
module_path
|
19
|
+
"#{module_path}/consume_tracer"
|
20
20
|
autoload :ConsumeTracerBuilder,
|
21
|
-
module_path
|
21
|
+
"#{module_path}/consume_tracer_builder"
|
22
22
|
autoload :ConsumeTracerConfig,
|
23
|
-
module_path
|
23
|
+
"#{module_path}/consume_tracer_config"
|
24
24
|
autoload :GlobalPropertiesBuilder,
|
25
|
-
module_path
|
25
|
+
"#{module_path}/global_properties_builder"
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -9,6 +9,8 @@ module OpenTracing
|
|
9
9
|
'opentracing/instrumentation/mongo/operation_name_builder'
|
10
10
|
autoload :TraceSubscriber, 'opentracing/instrumentation/mongo/trace_subscriber'
|
11
11
|
autoload :QuerySanitazer, 'opentracing/instrumentation/mongo/query_sanitazer'
|
12
|
+
autoload :SampleSafetyArgumentChecker,
|
13
|
+
'opentracing/instrumentation/mongo/sample_safety_argument_checker'
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
@@ -19,10 +19,15 @@ module OpenTracing
|
|
19
19
|
DEFAULT_EXCLUDE_KEYS = %w[lsid].freeze
|
20
20
|
|
21
21
|
def initialize(
|
22
|
+
safety_argument_checker: SampleSafetyArgumentChecker.new,
|
22
23
|
safe_classes: DEFAULT_SAFE_CLASSES,
|
24
|
+
max_array_size: 4,
|
23
25
|
exclude_keys: DEFAULT_EXCLUDE_KEYS
|
24
26
|
)
|
27
|
+
super()
|
28
|
+
@safety_argument_checker = safety_argument_checker
|
25
29
|
@safe_classes = safe_classes
|
30
|
+
@max_array_size = max_array_size
|
26
31
|
@exclude_keys = exclude_keys
|
27
32
|
end
|
28
33
|
|
@@ -36,8 +41,10 @@ module OpenTracing
|
|
36
41
|
|
37
42
|
private
|
38
43
|
|
39
|
-
attr_reader :safe_classes
|
40
|
-
|
44
|
+
attr_reader :safe_classes,
|
45
|
+
:exclude_keys,
|
46
|
+
:max_array_size,
|
47
|
+
:safety_argument_checker
|
41
48
|
|
42
49
|
OBJECT_ID_PLACEHOLDER = '$oid'
|
43
50
|
STRING_PLACEHOLDER = '$string'
|
@@ -54,30 +61,66 @@ module OpenTracing
|
|
54
61
|
end
|
55
62
|
end
|
56
63
|
|
64
|
+
# rubocop:disable Metrics/MethodLength
|
57
65
|
def sanitaze_simple(value)
|
58
66
|
case value
|
59
67
|
when BSON::ObjectId
|
60
68
|
OBJECT_ID_PLACEHOLDER
|
61
69
|
when String
|
62
70
|
STRING_PLACEHOLDER
|
71
|
+
when ArrayItemPlaceholder
|
72
|
+
value.to_s
|
63
73
|
when *safe_classes
|
64
74
|
value
|
65
75
|
else
|
66
76
|
PLACEHOLDER
|
67
77
|
end
|
68
78
|
end
|
79
|
+
# rubocop:enable Metrics/MethodLength
|
69
80
|
|
70
81
|
def sanitaze_hash(hash)
|
71
|
-
hash.
|
72
|
-
|
82
|
+
hash.map do |(key, value)|
|
83
|
+
# TODO: pass command name.
|
84
|
+
# TODO: recursive build path to key
|
85
|
+
safe_value =
|
86
|
+
if safety_argument_checker.argument_safe?(nil, key, value)
|
87
|
+
value
|
88
|
+
else
|
89
|
+
sanitaze_value(value)
|
90
|
+
end
|
91
|
+
|
92
|
+
[key, safe_value]
|
93
|
+
end.to_h
|
94
|
+
end
|
95
|
+
|
96
|
+
# Placehoder for skipped array items
|
97
|
+
class ArrayItemPlaceholder
|
98
|
+
def initialize(skipped_items)
|
99
|
+
@skipped_items = skipped_items
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_s
|
103
|
+
"SKIPPED #{@skipped_items} ITEMS"
|
73
104
|
end
|
74
105
|
end
|
75
106
|
|
76
107
|
def sanitaze_array(array)
|
77
|
-
array.
|
108
|
+
if max_array_size&.positive? && array.size > max_array_size
|
109
|
+
array_with_placeholder(array)
|
110
|
+
else
|
111
|
+
array
|
112
|
+
end.map do |value|
|
78
113
|
sanitaze_value(value)
|
79
114
|
end
|
80
115
|
end
|
116
|
+
|
117
|
+
def array_with_placeholder(array)
|
118
|
+
prefix_size = (max_array_size / 2).ceil
|
119
|
+
suffix_size = max_array_size - prefix_size
|
120
|
+
array[0...prefix_size] \
|
121
|
+
+ [ArrayItemPlaceholder.new(array.size - max_array_size)] \
|
122
|
+
+ array[-suffix_size..-1]
|
123
|
+
end
|
81
124
|
end
|
82
125
|
end
|
83
126
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OpenTracing
|
4
|
+
module Instrumentation
|
5
|
+
module Mongo
|
6
|
+
# SampleSafetyArgumentChecker check argument to safety
|
7
|
+
# Draft implementation
|
8
|
+
class SampleSafetyArgumentChecker
|
9
|
+
DEFAULT_SAFE_ARGUMENTS = [
|
10
|
+
'$readPreference',
|
11
|
+
'$clusterTime',
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
attr_reader :safe_arguments
|
15
|
+
|
16
|
+
def initialize(safe_arguments: DEFAULT_SAFE_ARGUMENTS)
|
17
|
+
@safe_arguments = safe_arguments
|
18
|
+
end
|
19
|
+
|
20
|
+
# check
|
21
|
+
#
|
22
|
+
# @return (TrueClass, FalseClass) `true`, if argument safe and not
|
23
|
+
# not should be cleaned. Otherwise return `false``.
|
24
|
+
def argument_safe?(_command_name, argument_path, _argument_value)
|
25
|
+
safe_arguments.include?(argument_path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -43,11 +43,11 @@ module OpenTracing
|
|
43
43
|
|
44
44
|
private
|
45
45
|
|
46
|
-
attr_reader :tracer
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
attr_reader :tracer,
|
47
|
+
:scope_store,
|
48
|
+
:monitor,
|
49
|
+
:operation_name_builder,
|
50
|
+
:sanitazer
|
51
51
|
|
52
52
|
def build_operation_name(event)
|
53
53
|
operation_name_builder.build_operation_name(event)
|
@@ -50,15 +50,15 @@ module OpenTracing
|
|
50
50
|
|
51
51
|
def prepare_request_mapping(source_mapping)
|
52
52
|
source_mapping.map do |key, header|
|
53
|
-
rack_header =
|
54
|
-
tag_name =
|
53
|
+
rack_header = "HTTP_#{header.tr('-', '_').upcase}"
|
54
|
+
tag_name = "http.request.#{key}"
|
55
55
|
[tag_name, rack_header]
|
56
56
|
end.to_h
|
57
57
|
end
|
58
58
|
|
59
59
|
def prepare_response_mapping(source_mapping)
|
60
60
|
source_mapping.map do |key, header|
|
61
|
-
tag_name =
|
61
|
+
tag_name = "http.response.#{key}"
|
62
62
|
header_regexp = /^#{header}$/i
|
63
63
|
[tag_name, header_regexp]
|
64
64
|
end.to_h
|
@@ -36,10 +36,10 @@ module OpenTracing
|
|
36
36
|
|
37
37
|
private
|
38
38
|
|
39
|
-
attr_reader :app
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
attr_reader :app,
|
40
|
+
:http_tagger,
|
41
|
+
:tracer,
|
42
|
+
:logger
|
43
43
|
|
44
44
|
def trace_request(env)
|
45
45
|
extracted_ctx = tracer.extract(OpenTracing::FORMAT_RACK, env)
|
@@ -84,7 +84,7 @@ module OpenTracing
|
|
84
84
|
def set_header_tags(span, headers)
|
85
85
|
http_tagger
|
86
86
|
.response_tags(headers)
|
87
|
-
.each(
|
87
|
+
.each { |(key, value)| span.set_tag(key, value) }
|
88
88
|
end
|
89
89
|
|
90
90
|
def error_tag(span, error)
|
@@ -14,11 +14,11 @@ module OpenTracing
|
|
14
14
|
DEFAULT_LOG_REPLY = false
|
15
15
|
DEFAULT_COMPONENT = 'kv'
|
16
16
|
|
17
|
-
attr_accessor :tracer
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
attr_accessor :tracer,
|
18
|
+
:operation_name_pattern,
|
19
|
+
:log_args,
|
20
|
+
:log_reply,
|
21
|
+
:component
|
22
22
|
|
23
23
|
def initialize(
|
24
24
|
tracer: OpenTracing.global_tracer,
|
@@ -35,8 +35,8 @@ module OpenTracing
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
attr_reader :connection
|
39
|
-
|
38
|
+
attr_reader :connection,
|
39
|
+
:span_builder
|
40
40
|
|
41
41
|
def initialize(
|
42
42
|
connection:,
|
@@ -80,8 +80,8 @@ module OpenTracing
|
|
80
80
|
|
81
81
|
private
|
82
82
|
|
83
|
-
attr_reader :pipeline_scope
|
84
|
-
|
83
|
+
attr_reader :pipeline_scope,
|
84
|
+
:error_writer
|
85
85
|
|
86
86
|
def peer_addr
|
87
87
|
"#{@host}:#{@port}"
|
@@ -7,41 +7,66 @@ module OpenTracing
|
|
7
7
|
class ClientMiddleware
|
8
8
|
extend Forwardable
|
9
9
|
|
10
|
-
DEFAULT_SPAN_NAME = 'sidekiq_enqueue'
|
11
10
|
DEFAULT_SPAN_KIND = 'producer'
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
DEFAULT_OPERATION_NAME_TEMPLATE = \
|
13
|
+
'sidekiq_enqueue(%<sidekiq.class>s)'
|
14
|
+
DEFAULT_OPERATION_NAME_BUILDER = \
|
15
|
+
Common::OperationNameBuilder.new(
|
16
|
+
operation_name_template: DEFAULT_OPERATION_NAME_TEMPLATE,
|
17
|
+
)
|
18
18
|
|
19
|
+
attr_reader :tracer,
|
20
|
+
:tagger,
|
21
|
+
:error_writter,
|
22
|
+
:logger,
|
23
|
+
:span_kind,
|
24
|
+
:operation_name_builder
|
25
|
+
|
26
|
+
# rubocop:disable Metrics/ParameterLists
|
19
27
|
def initialize(
|
20
28
|
tracer: OpenTracing.global_tracer,
|
21
29
|
tagger: JobTagger.new,
|
22
30
|
error_writter: Common::ErrorWriter.new,
|
31
|
+
logger: nil,
|
23
32
|
span_kind: DEFAULT_SPAN_KIND,
|
24
|
-
|
33
|
+
operation_name_builder: DEFAULT_OPERATION_NAME_BUILDER
|
25
34
|
)
|
26
35
|
@tracer = tracer
|
27
36
|
@tagger = tagger
|
28
37
|
@error_writter = error_writter
|
38
|
+
@logger = logger
|
29
39
|
@span_kind = span_kind
|
30
|
-
@
|
40
|
+
@operation_name_builder = operation_name_builder
|
31
41
|
end
|
42
|
+
# rubocop:enable Metrics/ParameterLists
|
32
43
|
|
33
|
-
def call(_worker_class, job, _queue, _redis_pool)
|
34
|
-
scope =
|
44
|
+
def call(_worker_class, job, _queue, _redis_pool, &block)
|
45
|
+
scope = safe_start_scope(job)
|
35
46
|
inject(scope.span.context, job)
|
36
|
-
log(scope.span, job)
|
37
|
-
yield
|
38
|
-
end
|
47
|
+
log(scope.span, job, &block)
|
39
48
|
ensure
|
40
|
-
scope
|
49
|
+
safe_close_scope(scope)
|
41
50
|
end
|
42
51
|
|
43
52
|
private
|
44
53
|
|
54
|
+
def safe_start_scope(job)
|
55
|
+
tags = build_tags(job)
|
56
|
+
operation_name = operation_name_builder.build(tags)
|
57
|
+
tracer.start_active_span(operation_name, tags: tags)
|
58
|
+
rescue StandardError => e
|
59
|
+
logger&.error(e)
|
60
|
+
end
|
61
|
+
|
62
|
+
def safe_close_scope(scope)
|
63
|
+
return unless scope
|
64
|
+
|
65
|
+
scope.close
|
66
|
+
rescue StandardError => e
|
67
|
+
logger&.error(e)
|
68
|
+
end
|
69
|
+
|
45
70
|
def log(span, job)
|
46
71
|
tagger.write_args_log(span, job['jid'], job['args'])
|
47
72
|
|
@@ -51,10 +76,8 @@ module OpenTracing
|
|
51
76
|
raise
|
52
77
|
end
|
53
78
|
|
54
|
-
def
|
55
|
-
|
56
|
-
tags: tagger.build_tags(job, span_kind),
|
57
|
-
}
|
79
|
+
def build_tags(job)
|
80
|
+
tagger.build_tags(job, span_kind)
|
58
81
|
end
|
59
82
|
|
60
83
|
def inject(span_context, carrier)
|
@@ -12,8 +12,8 @@ module OpenTracing
|
|
12
12
|
|
13
13
|
DEFAULT_COMPONENT = 'sidekiq'
|
14
14
|
|
15
|
-
attr_accessor :component
|
16
|
-
|
15
|
+
attr_accessor :component,
|
16
|
+
:log_args
|
17
17
|
|
18
18
|
# @param component [String] component name
|
19
19
|
# @param log_args [TrueClass, FalseClass] enable attribute logging
|
@@ -30,11 +30,11 @@ module OpenTracing
|
|
30
30
|
# build tags from job data and static attributes
|
31
31
|
def build_tags(job, span_kind)
|
32
32
|
{
|
33
|
-
|
34
|
-
'span.kind'
|
35
|
-
'sidekiq.queue'
|
36
|
-
'sidekiq.class'
|
37
|
-
'sidekiq.retry'
|
33
|
+
component: component,
|
34
|
+
'span.kind': span_kind,
|
35
|
+
'sidekiq.queue': job['queue'],
|
36
|
+
'sidekiq.class': job['class'],
|
37
|
+
'sidekiq.retry': job['retry'],
|
38
38
|
}
|
39
39
|
end
|
40
40
|
|
@@ -9,41 +9,66 @@ module OpenTracing
|
|
9
9
|
class ServerMiddleware
|
10
10
|
extend Forwardable
|
11
11
|
|
12
|
-
DEFAULT_SPAN_NAME = 'sidekiq_perform'
|
13
12
|
DEFAULT_SPAN_KIND = 'consumer'
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
DEFAULT_OPERATION_NAME_TEMPLATE = \
|
15
|
+
'sidekiq_perform(%<sidekiq.class>s)'
|
16
|
+
DEFAULT_OPERATION_NAME_BUILDER = \
|
17
|
+
Common::OperationNameBuilder.new(
|
18
|
+
operation_name_template: DEFAULT_OPERATION_NAME_TEMPLATE,
|
19
|
+
)
|
20
20
|
|
21
|
+
attr_reader :tracer,
|
22
|
+
:tagger,
|
23
|
+
:error_writter,
|
24
|
+
:logger,
|
25
|
+
:span_kind,
|
26
|
+
:operation_name_builder
|
27
|
+
|
28
|
+
# rubocop:disable Metrics/ParameterLists
|
21
29
|
def initialize(
|
22
30
|
tracer: OpenTracing.global_tracer,
|
23
31
|
tagger: JobTagger.new,
|
24
32
|
error_writter: Common::ErrorWriter.new,
|
33
|
+
logger: nil,
|
25
34
|
span_kind: DEFAULT_SPAN_KIND,
|
26
|
-
|
35
|
+
operation_name_builder: DEFAULT_OPERATION_NAME_BUILDER
|
27
36
|
)
|
28
37
|
@tracer = tracer
|
29
38
|
@tagger = tagger
|
30
39
|
@error_writter = error_writter
|
40
|
+
@logger = logger
|
31
41
|
@span_kind = span_kind
|
32
|
-
@
|
42
|
+
@operation_name_builder = operation_name_builder
|
33
43
|
end
|
44
|
+
# rubocop:enable Metrics/ParameterLists
|
34
45
|
|
35
|
-
def call(_worker, job, _queue)
|
36
|
-
scope =
|
46
|
+
def call(_worker, job, _queue, &block)
|
47
|
+
scope = safe_start_scope(job)
|
37
48
|
|
38
|
-
log(scope.span, job)
|
39
|
-
yield
|
40
|
-
end
|
49
|
+
log(scope.span, job, &block)
|
41
50
|
ensure
|
42
|
-
scope
|
51
|
+
scope&.close
|
43
52
|
end
|
44
53
|
|
45
54
|
private
|
46
55
|
|
56
|
+
def safe_start_scope(job)
|
57
|
+
tags = tagger.build_tags(job, span_kind)
|
58
|
+
operation_name = operation_name_builder.build(tags)
|
59
|
+
tracer.start_active_span(operation_name, tags: tags, **build_span_args(job))
|
60
|
+
rescue StandardError => e
|
61
|
+
logger&.error(e)
|
62
|
+
end
|
63
|
+
|
64
|
+
def safe_close_scope(scope)
|
65
|
+
return unless socpe
|
66
|
+
|
67
|
+
scope.close
|
68
|
+
rescue StandardError => e
|
69
|
+
logger&.error(e)
|
70
|
+
end
|
71
|
+
|
47
72
|
def log(span, job)
|
48
73
|
tagger.write_args_log(span, job['jid'], job['args'])
|
49
74
|
|
@@ -56,12 +81,13 @@ module OpenTracing
|
|
56
81
|
def build_span_args(job)
|
57
82
|
{
|
58
83
|
references: extract_references(job),
|
59
|
-
tags: tagger.build_tags(job, span_kind),
|
60
84
|
}
|
61
85
|
end
|
62
86
|
|
63
87
|
def extract_references(job)
|
64
88
|
span_context = tracer.extract(OpenTracing::FORMAT_TEXT_MAP, job)
|
89
|
+
return unless span_context
|
90
|
+
|
65
91
|
[OpenTracing::Reference.follows_from(span_context)]
|
66
92
|
end
|
67
93
|
end
|