atatus 1.3.0 → 1.4.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/CHANGELOG.md +6 -0
- data/Gemfile +72 -22
- data/LICENSE +1 -1
- data/atatus.gemspec +2 -2
- data/lib/atatus.rb +76 -16
- data/lib/atatus/agent.rb +78 -29
- data/lib/atatus/central_config.rb +72 -27
- data/lib/atatus/central_config/cache_control.rb +18 -1
- data/lib/atatus/child_durations.rb +64 -0
- data/lib/atatus/collector/base.rb +61 -29
- data/lib/atatus/collector/builder.rb +46 -2
- data/lib/atatus/collector/hist.rb +54 -0
- data/lib/atatus/collector/transport.rb +41 -11
- data/lib/atatus/config.rb +129 -28
- data/lib/atatus/config/bytes.rb +17 -0
- data/lib/atatus/config/duration.rb +17 -0
- data/lib/atatus/config/options.rb +29 -9
- data/lib/atatus/config/regexp_list.rb +17 -0
- data/lib/atatus/config/wildcard_pattern_list.rb +64 -0
- data/lib/atatus/context.rb +32 -1
- data/lib/atatus/context/request.rb +17 -0
- data/lib/atatus/context/request/socket.rb +18 -1
- data/lib/atatus/context/request/url.rb +17 -0
- data/lib/atatus/context/response.rb +27 -2
- data/lib/atatus/context/user.rb +17 -0
- data/lib/atatus/context_builder.rb +19 -4
- data/lib/atatus/deprecations.rb +17 -0
- data/lib/atatus/error.rb +27 -0
- data/lib/atatus/error/exception.rb +24 -0
- data/lib/atatus/error/log.rb +17 -0
- data/lib/atatus/error_builder.rb +17 -2
- data/lib/atatus/grape.rb +62 -0
- data/lib/atatus/graphql.rb +91 -0
- data/lib/atatus/grpc.rb +99 -0
- data/lib/atatus/instrumenter.rb +135 -30
- data/lib/atatus/internal_error.rb +17 -0
- data/lib/atatus/logging.rb +17 -2
- data/lib/atatus/metadata.rb +17 -0
- data/lib/atatus/metadata/process_info.rb +17 -0
- data/lib/atatus/metadata/service_info.rb +21 -6
- data/lib/atatus/metadata/system_info.rb +22 -3
- data/lib/atatus/metadata/system_info/container_info.rb +49 -10
- data/lib/atatus/metadata/system_info/hw_info.rb +1 -1
- data/lib/atatus/metrics.rb +69 -27
- data/lib/atatus/metrics/breakdown_set.rb +31 -0
- data/lib/atatus/metrics/{cpu_mem.rb → cpu_mem_set.rb} +110 -63
- data/lib/atatus/metrics/metric.rb +140 -0
- data/lib/atatus/metrics/set.rb +123 -0
- data/lib/atatus/metrics/span_scoped_set.rb +56 -0
- data/lib/atatus/metrics/transaction_set.rb +26 -0
- data/lib/atatus/metrics/vm_set.rb +58 -0
- data/lib/atatus/metricset.rb +48 -4
- data/lib/atatus/middleware.rb +28 -8
- data/lib/atatus/naively_hashable.rb +17 -0
- data/lib/atatus/normalizers.rb +23 -9
- data/lib/atatus/normalizers/grape.rb +22 -0
- data/lib/atatus/normalizers/grape/endpoint_run.rb +65 -0
- data/lib/atatus/normalizers/rails.rb +27 -0
- data/lib/atatus/normalizers/rails/action_controller.rb +44 -0
- data/lib/atatus/normalizers/rails/action_mailer.rb +43 -0
- data/lib/atatus/normalizers/{action_view.rb → rails/action_view.rb} +17 -0
- data/lib/atatus/normalizers/rails/active_record.rb +80 -0
- data/lib/atatus/opentracing.rb +75 -42
- data/lib/atatus/rails.rb +29 -13
- data/lib/atatus/railtie.rb +19 -6
- data/lib/atatus/resque.rb +29 -0
- data/lib/atatus/sinatra.rb +53 -0
- data/lib/atatus/span.rb +44 -15
- data/lib/atatus/span/context.rb +43 -28
- data/lib/atatus/span/context/db.rb +43 -0
- data/lib/atatus/span/context/destination.rb +77 -0
- data/lib/atatus/span/context/http.rb +43 -0
- data/lib/atatus/span_helpers.rb +18 -1
- data/lib/atatus/spies.rb +33 -15
- data/lib/atatus/spies/action_dispatch.rb +27 -6
- data/lib/atatus/spies/delayed_job.rb +26 -5
- data/lib/atatus/spies/dynamo_db.rb +62 -0
- data/lib/atatus/spies/elasticsearch.rb +53 -7
- data/lib/atatus/spies/faraday.rb +54 -20
- data/lib/atatus/spies/http.rb +36 -6
- data/lib/atatus/spies/json.rb +18 -0
- data/lib/atatus/spies/mongo.rb +41 -10
- data/lib/atatus/spies/net_http.rb +52 -11
- data/lib/atatus/spies/rake.rb +42 -23
- data/lib/atatus/spies/redis.rb +17 -0
- data/lib/atatus/spies/resque.rb +57 -0
- data/lib/atatus/spies/sequel.rb +54 -17
- data/lib/atatus/spies/shoryuken.rb +69 -0
- data/lib/atatus/spies/sidekiq.rb +46 -25
- data/lib/atatus/spies/sinatra.rb +20 -4
- data/lib/atatus/spies/sneakers.rb +74 -0
- data/lib/atatus/spies/sucker_punch.rb +58 -0
- data/lib/atatus/spies/tilt.rb +20 -1
- data/lib/atatus/sql.rb +36 -0
- data/lib/atatus/sql/signature.rb +169 -0
- data/lib/atatus/sql/tokenizer.rb +264 -0
- data/lib/atatus/sql/tokens.rb +63 -0
- data/lib/atatus/sql_summarizer.rb +24 -6
- data/lib/atatus/stacktrace.rb +17 -0
- data/lib/atatus/stacktrace/frame.rb +17 -3
- data/lib/atatus/stacktrace_builder.rb +23 -3
- data/lib/atatus/subscriber.rb +23 -4
- data/lib/atatus/trace_context.rb +84 -51
- data/lib/atatus/trace_context/traceparent.rb +111 -0
- data/lib/atatus/trace_context/tracestate.rb +148 -0
- data/lib/atatus/transaction.rb +74 -18
- data/lib/atatus/transport/base.rb +44 -27
- data/lib/atatus/transport/connection.rb +28 -72
- data/lib/atatus/transport/connection/http.rb +58 -35
- data/lib/atatus/transport/connection/proxy_pipe.rb +24 -5
- data/lib/atatus/transport/filters.rb +18 -1
- data/lib/atatus/transport/filters/hash_sanitizer.rb +77 -0
- data/lib/atatus/transport/filters/secrets_filter.rb +30 -55
- data/lib/atatus/transport/headers.rb +83 -0
- data/lib/atatus/transport/serializers.rb +17 -5
- data/lib/atatus/transport/serializers/context_serializer.rb +30 -3
- data/lib/atatus/transport/serializers/error_serializer.rb +17 -2
- data/lib/atatus/transport/serializers/metadata_serializer.rb +44 -22
- data/lib/atatus/transport/serializers/metricset_serializer.rb +34 -6
- data/lib/atatus/transport/serializers/span_serializer.rb +47 -12
- data/lib/atatus/transport/serializers/transaction_serializer.rb +18 -2
- data/lib/atatus/transport/user_agent.rb +48 -0
- data/lib/atatus/transport/worker.rb +31 -7
- data/lib/atatus/util.rb +18 -1
- data/lib/atatus/util/inflector.rb +17 -0
- data/lib/atatus/util/lru_cache.rb +17 -0
- data/lib/atatus/util/throttle.rb +17 -0
- data/lib/atatus/version.rb +19 -1
- metadata +46 -26
- data/Rakefile +0 -19
- data/bench/.gitignore +0 -2
- data/bench/app.rb +0 -53
- data/bench/benchmark.rb +0 -36
- data/bench/report.rb +0 -55
- data/bench/rubyprof.rb +0 -39
- data/bench/stackprof.rb +0 -23
- data/bin/build_docs +0 -5
- data/bin/console +0 -15
- data/bin/setup +0 -8
- data/bin/with_framework +0 -7
- data/lib/atatus/metrics/vm.rb +0 -60
- data/lib/atatus/normalizers/action_controller.rb +0 -27
- data/lib/atatus/normalizers/action_mailer.rb +0 -26
- data/lib/atatus/normalizers/active_record.rb +0 -45
- data/lib/atatus/util/prefixed_logger.rb +0 -18
- data/vendor/.gitkeep +0 -0
data/lib/atatus/deprecations.rb
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright
|
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
|
6
|
+
# not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
|
|
1
18
|
# frozen_string_literal: true
|
|
2
19
|
|
|
3
20
|
module Atatus
|
data/lib/atatus/error.rb
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright
|
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
|
6
|
+
# not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
|
|
1
18
|
# frozen_string_literal: true
|
|
2
19
|
|
|
3
20
|
require 'atatus/stacktrace'
|
|
@@ -18,5 +35,15 @@ module Atatus
|
|
|
18
35
|
attr_accessor :id, :culprit, :exception, :log, :transaction_id,
|
|
19
36
|
:transaction, :context, :parent_id, :trace_id
|
|
20
37
|
attr_reader :timestamp
|
|
38
|
+
|
|
39
|
+
def inspect
|
|
40
|
+
"<Atatus::Error id:#{id}" \
|
|
41
|
+
" culprit:#{culprit}" \
|
|
42
|
+
" timestamp:#{timestamp}" \
|
|
43
|
+
" transaction_id:#{transaction_id}" \
|
|
44
|
+
" trace_id:#{trace_id}" \
|
|
45
|
+
" exception:#{exception.inspect}" \
|
|
46
|
+
'>'
|
|
47
|
+
end
|
|
21
48
|
end
|
|
22
49
|
end
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright
|
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
|
6
|
+
# not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
|
|
1
18
|
# frozen_string_literal: true
|
|
2
19
|
|
|
3
20
|
module Atatus
|
|
@@ -34,6 +51,13 @@ module Atatus
|
|
|
34
51
|
:cause
|
|
35
52
|
)
|
|
36
53
|
|
|
54
|
+
def inspect
|
|
55
|
+
'<Atatus::Error::Exception' \
|
|
56
|
+
" type:#{type}" \
|
|
57
|
+
" message:#{message}" \
|
|
58
|
+
'>'
|
|
59
|
+
end
|
|
60
|
+
|
|
37
61
|
class << self
|
|
38
62
|
private
|
|
39
63
|
|
data/lib/atatus/error/log.rb
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright
|
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
|
6
|
+
# not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
|
|
1
18
|
# frozen_string_literal: true
|
|
2
19
|
|
|
3
20
|
module Atatus
|
data/lib/atatus/error_builder.rb
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright
|
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
|
6
|
+
# not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
|
|
1
18
|
# frozen_string_literal: true
|
|
2
19
|
|
|
3
20
|
module Atatus
|
|
@@ -53,7 +70,6 @@ module Atatus
|
|
|
53
70
|
error.culprit = stacktrace.frames.first&.function
|
|
54
71
|
end
|
|
55
72
|
|
|
56
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
57
73
|
def add_current_transaction_fields(error, transaction)
|
|
58
74
|
return unless transaction
|
|
59
75
|
|
|
@@ -71,6 +87,5 @@ module Atatus
|
|
|
71
87
|
Util.reverse_merge!(error.context.labels, transaction.context.labels)
|
|
72
88
|
Util.reverse_merge!(error.context.custom, transaction.context.custom)
|
|
73
89
|
end
|
|
74
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
|
75
90
|
end
|
|
76
91
|
end
|
data/lib/atatus/grape.rb
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright
|
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
|
6
|
+
# not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
|
|
18
|
+
# frozen_string_literal: true
|
|
19
|
+
|
|
20
|
+
require 'atatus/subscriber'
|
|
21
|
+
require 'atatus/normalizers/grape'
|
|
22
|
+
|
|
23
|
+
module Atatus
|
|
24
|
+
# Module for starting the Atatus agent and hooking into Grape.
|
|
25
|
+
module Grape
|
|
26
|
+
extend self
|
|
27
|
+
# Start the Atatus agent and hook into Grape.
|
|
28
|
+
#
|
|
29
|
+
# @param app [Grape::API] A Grape app.
|
|
30
|
+
# @param config [Config, Hash] An instance of Config or a Hash config.
|
|
31
|
+
# @return [true, nil] true if the agent was started, nil otherwise.
|
|
32
|
+
def start(app, config = {})
|
|
33
|
+
config = Config.new(config) unless config.is_a?(Config)
|
|
34
|
+
configure_app(app, config)
|
|
35
|
+
|
|
36
|
+
Atatus.start(config).tap do |agent|
|
|
37
|
+
attach_subscriber(agent)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
Atatus.running?
|
|
41
|
+
rescue StandardError => e
|
|
42
|
+
config.logger.error format('Failed to start: %s', e.message)
|
|
43
|
+
config.logger.debug "Backtrace:\n" + e.backtrace.join("\n")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def configure_app(app, config)
|
|
49
|
+
config.service_name ||= app.name
|
|
50
|
+
config.framework_name ||= 'Grape'
|
|
51
|
+
config.framework_version ||= ::Grape::VERSION
|
|
52
|
+
config.logger ||= app.logger
|
|
53
|
+
config.__root_path ||= Dir.pwd
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def attach_subscriber(agent)
|
|
57
|
+
return unless agent
|
|
58
|
+
|
|
59
|
+
agent.instrumenter.subscriber = Atatus::Subscriber.new(agent)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright
|
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
|
6
|
+
# not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
|
|
18
|
+
# frozen_string_literal: true
|
|
19
|
+
|
|
20
|
+
module Atatus
|
|
21
|
+
# @api private
|
|
22
|
+
module GraphQL
|
|
23
|
+
TYPE = 'app'
|
|
24
|
+
SUBTYPE = 'graphql'
|
|
25
|
+
|
|
26
|
+
PREFIX = 'GraphQL: '
|
|
27
|
+
UNNAMED = '[unnamed]'
|
|
28
|
+
MULTIPLE_QUERIES = '[multiple-queries]'
|
|
29
|
+
CONCATENATOR = '+'
|
|
30
|
+
MAX_NUMBER_OF_QUERIES_FOR_NAME = 5
|
|
31
|
+
|
|
32
|
+
KEYS_TO_NAME = {
|
|
33
|
+
'lex' => 'graphql.lex',
|
|
34
|
+
'parse' => 'graphql.parse',
|
|
35
|
+
'validate' => 'graphql.validate',
|
|
36
|
+
'analyze_multiplex' => 'graphql.analyze_multiplex',
|
|
37
|
+
'analyze_query' => 'graphql.analyze_query',
|
|
38
|
+
'execute_multiplex' => 'graphql.execute_multiplex',
|
|
39
|
+
'execute_query' => 'graphql.execute_query',
|
|
40
|
+
'execute_query_lazy' => 'graphql.execute_query_lazy',
|
|
41
|
+
'authorized_lazy' => 'graphql.authorized_lazy',
|
|
42
|
+
'resolve_type' => 'graphql.resolve_type',
|
|
43
|
+
'resolve_type_lazy' => 'graphql.resolve_type_lazy'
|
|
44
|
+
|
|
45
|
+
# These are available but deliberately left out as they are mostly noise.
|
|
46
|
+
# "execute_field" => "graphql.execute_field",
|
|
47
|
+
# "execute_field_lazy" => "graphql.execute_field_lazy",
|
|
48
|
+
# "authorized" => "graphql.authorized",
|
|
49
|
+
}.freeze
|
|
50
|
+
|
|
51
|
+
def self.trace(key, data)
|
|
52
|
+
return yield unless KEYS_TO_NAME.key?(key)
|
|
53
|
+
return yield unless (transaction = Atatus.current_transaction)
|
|
54
|
+
|
|
55
|
+
if key == 'execute_query'
|
|
56
|
+
transaction.name =
|
|
57
|
+
"#{PREFIX}#{query_name(data[:query])}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
results =
|
|
61
|
+
Atatus.with_span(
|
|
62
|
+
KEYS_TO_NAME.fetch(key, key),
|
|
63
|
+
TYPE, subtype: SUBTYPE, action: key
|
|
64
|
+
) { yield }
|
|
65
|
+
|
|
66
|
+
if key == 'execute_multiplex'
|
|
67
|
+
transaction.name = "#{PREFIX}#{concat_names(results)}"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
results
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class << self
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def query_name(query)
|
|
77
|
+
query.operation_name || UNNAMED
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def concat_names(results)
|
|
81
|
+
if results.length > MAX_NUMBER_OF_QUERIES_FOR_NAME
|
|
82
|
+
return MULTIPLE_QUERIES
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
results.map do |result|
|
|
86
|
+
query_name(result.query)
|
|
87
|
+
end.join(CONCATENATOR)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
data/lib/atatus/grpc.rb
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright
|
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
|
6
|
+
# not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
|
|
18
|
+
# frozen_string_literal: true
|
|
19
|
+
|
|
20
|
+
module Atatus
|
|
21
|
+
# @api private
|
|
22
|
+
class GRPC
|
|
23
|
+
# @api private
|
|
24
|
+
class ClientInterceptor < ::GRPC::ClientInterceptor
|
|
25
|
+
TYPE = 'external'
|
|
26
|
+
SUBTYPE = 'grpc'
|
|
27
|
+
|
|
28
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
|
29
|
+
def request_response(request:, call:, method:, metadata:)
|
|
30
|
+
return yield unless (transaction = Atatus.current_transaction)
|
|
31
|
+
if (trace_context = transaction.trace_context)
|
|
32
|
+
trace_context.apply_headers { |k, v| metadata[k.downcase] = v }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Atatus.with_span(
|
|
36
|
+
method, TYPE,
|
|
37
|
+
subtype: SUBTYPE,
|
|
38
|
+
context: span_context(call)
|
|
39
|
+
) do
|
|
40
|
+
yield
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def span_context(call)
|
|
48
|
+
peer = call.instance_variable_get(:@wrapped)&.peer
|
|
49
|
+
return unless peer
|
|
50
|
+
|
|
51
|
+
split_peer = URI.split(peer)
|
|
52
|
+
destination = Atatus::Span::Context::Destination.new(
|
|
53
|
+
type: TYPE,
|
|
54
|
+
name: SUBTYPE,
|
|
55
|
+
resource: peer,
|
|
56
|
+
address: split_peer[0],
|
|
57
|
+
port: split_peer[6]
|
|
58
|
+
)
|
|
59
|
+
Atatus::Span::Context.new(destination: destination)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @api private
|
|
64
|
+
class ServerInterceptor < ::GRPC::ClientInterceptor
|
|
65
|
+
TYPE = 'request'
|
|
66
|
+
|
|
67
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
|
68
|
+
def request_response(request:, call:, method:)
|
|
69
|
+
transaction = start_transaction(call)
|
|
70
|
+
yield
|
|
71
|
+
transaction.done 'success'
|
|
72
|
+
rescue ::Exception => e
|
|
73
|
+
Atatus.report(e, handled: false)
|
|
74
|
+
transaction.done 'error' if transaction
|
|
75
|
+
raise
|
|
76
|
+
ensure
|
|
77
|
+
Atatus.end_transaction
|
|
78
|
+
end
|
|
79
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def start_transaction(call)
|
|
84
|
+
Atatus.start_transaction(
|
|
85
|
+
'grpc',
|
|
86
|
+
'request',
|
|
87
|
+
trace_context: trace_context(call)
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def trace_context(call)
|
|
92
|
+
TraceContext.parse(metadata: call.metadata)
|
|
93
|
+
rescue TraceContext::InvalidTraceparentHeader
|
|
94
|
+
warn "Couldn't parse invalid trace context header: #{call.metadata}"
|
|
95
|
+
nil
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
data/lib/atatus/instrumenter.rb
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright
|
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
|
6
|
+
# not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
|
|
1
18
|
# frozen_string_literal: true
|
|
2
19
|
|
|
3
20
|
require 'atatus/trace_context'
|
|
21
|
+
require 'atatus/child_durations'
|
|
4
22
|
require 'atatus/span'
|
|
5
23
|
require 'atatus/transaction'
|
|
6
24
|
require 'atatus/span_helpers'
|
|
7
25
|
|
|
8
26
|
module Atatus
|
|
9
|
-
# rubocop:disable Metrics/ClassLength
|
|
10
27
|
# @api private
|
|
11
28
|
class Instrumenter
|
|
12
29
|
TRANSACTION_KEY = :__atatus_instrumenter_transaction_key
|
|
@@ -39,18 +56,22 @@ module Atatus
|
|
|
39
56
|
end
|
|
40
57
|
end
|
|
41
58
|
|
|
42
|
-
def initialize(config, stacktrace_builder:, &enqueue)
|
|
59
|
+
def initialize(config, metrics:, stacktrace_builder:, &enqueue)
|
|
43
60
|
@config = config
|
|
44
61
|
@stacktrace_builder = stacktrace_builder
|
|
45
62
|
@enqueue = enqueue
|
|
63
|
+
@metrics = metrics
|
|
46
64
|
|
|
47
65
|
@current = Current.new
|
|
48
66
|
end
|
|
49
67
|
|
|
50
|
-
attr_reader :
|
|
68
|
+
attr_reader :stacktrace_builder, :enqueue
|
|
51
69
|
|
|
52
70
|
def start
|
|
53
71
|
debug 'Starting instrumenter'
|
|
72
|
+
# We call register! on @subscriber in case the
|
|
73
|
+
# instrumenter was stopped and started again
|
|
74
|
+
@subscriber&.register!
|
|
54
75
|
end
|
|
55
76
|
|
|
56
77
|
def stop
|
|
@@ -59,7 +80,12 @@ module Atatus
|
|
|
59
80
|
self.current_transaction = nil
|
|
60
81
|
current_spans.pop until current_spans.empty?
|
|
61
82
|
|
|
62
|
-
@subscriber
|
|
83
|
+
@subscriber&.unregister!
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def handle_forking!
|
|
87
|
+
stop
|
|
88
|
+
start
|
|
63
89
|
end
|
|
64
90
|
|
|
65
91
|
def subscriber=(subscriber)
|
|
@@ -78,10 +104,10 @@ module Atatus
|
|
|
78
104
|
@current.transaction = transaction
|
|
79
105
|
end
|
|
80
106
|
|
|
81
|
-
# rubocop:disable Metrics/MethodLength
|
|
82
107
|
def start_transaction(
|
|
83
108
|
name = nil,
|
|
84
109
|
type = nil,
|
|
110
|
+
config:,
|
|
85
111
|
context: nil,
|
|
86
112
|
trace_context: nil
|
|
87
113
|
)
|
|
@@ -89,10 +115,17 @@ module Atatus
|
|
|
89
115
|
|
|
90
116
|
if (transaction = current_transaction)
|
|
91
117
|
raise ExistingTransactionError,
|
|
92
|
-
"Transactions may not be nested.\
|
|
118
|
+
"Transactions may not be nested.\n" \
|
|
119
|
+
"Already inside #{transaction.inspect}"
|
|
93
120
|
end
|
|
94
121
|
|
|
95
|
-
|
|
122
|
+
if trace_context
|
|
123
|
+
samled = trace_context.recorded?
|
|
124
|
+
sample_rate = trace_context.tracestate.sample_rate
|
|
125
|
+
else
|
|
126
|
+
sampled = random_sample?(config)
|
|
127
|
+
sample_rate = config.transaction_sample_rate
|
|
128
|
+
end
|
|
96
129
|
|
|
97
130
|
transaction =
|
|
98
131
|
Transaction.new(
|
|
@@ -101,14 +134,14 @@ module Atatus
|
|
|
101
134
|
context: context,
|
|
102
135
|
trace_context: trace_context,
|
|
103
136
|
sampled: sampled,
|
|
104
|
-
|
|
137
|
+
sample_rate: sample_rate,
|
|
138
|
+
config: config
|
|
105
139
|
)
|
|
106
140
|
|
|
107
141
|
transaction.start
|
|
108
142
|
|
|
109
143
|
self.current_transaction = transaction
|
|
110
144
|
end
|
|
111
|
-
# rubocop:enable Metrics/MethodLength
|
|
112
145
|
|
|
113
146
|
def end_transaction(result = nil)
|
|
114
147
|
return nil unless (transaction = current_transaction)
|
|
@@ -119,6 +152,8 @@ module Atatus
|
|
|
119
152
|
|
|
120
153
|
enqueue.call transaction
|
|
121
154
|
|
|
155
|
+
update_transaction_metrics(transaction)
|
|
156
|
+
|
|
122
157
|
transaction
|
|
123
158
|
end
|
|
124
159
|
|
|
@@ -132,8 +167,8 @@ module Atatus
|
|
|
132
167
|
current_spans.last
|
|
133
168
|
end
|
|
134
169
|
|
|
135
|
-
# rubocop:disable Metrics/
|
|
136
|
-
# rubocop:disable Metrics/
|
|
170
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
171
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
137
172
|
# rubocop:disable Metrics/ParameterLists
|
|
138
173
|
def start_span(
|
|
139
174
|
name,
|
|
@@ -142,32 +177,40 @@ module Atatus
|
|
|
142
177
|
action: nil,
|
|
143
178
|
backtrace: nil,
|
|
144
179
|
context: nil,
|
|
145
|
-
trace_context: nil
|
|
180
|
+
trace_context: nil,
|
|
181
|
+
parent: nil,
|
|
182
|
+
sync: nil
|
|
146
183
|
)
|
|
147
|
-
return unless (transaction = current_transaction)
|
|
148
|
-
return unless transaction.sampled?
|
|
149
|
-
|
|
150
|
-
transaction.inc_started_spans!
|
|
151
184
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
185
|
+
transaction =
|
|
186
|
+
case parent
|
|
187
|
+
when Span
|
|
188
|
+
parent.transaction
|
|
189
|
+
when Transaction
|
|
190
|
+
parent
|
|
191
|
+
else
|
|
192
|
+
current_transaction
|
|
193
|
+
end
|
|
194
|
+
return unless transaction
|
|
195
|
+
return unless transaction.sampled?
|
|
196
|
+
return unless transaction.inc_started_spans!
|
|
156
197
|
|
|
157
|
-
parent
|
|
198
|
+
parent ||= (current_span || current_transaction)
|
|
158
199
|
|
|
159
200
|
span = Span.new(
|
|
160
201
|
name: name,
|
|
161
202
|
subtype: subtype,
|
|
162
203
|
action: action,
|
|
163
|
-
|
|
164
|
-
|
|
204
|
+
transaction: transaction,
|
|
205
|
+
parent: parent,
|
|
206
|
+
trace_context: trace_context,
|
|
165
207
|
type: type,
|
|
166
208
|
context: context,
|
|
167
|
-
stacktrace_builder: stacktrace_builder
|
|
209
|
+
stacktrace_builder: stacktrace_builder,
|
|
210
|
+
sync: sync
|
|
168
211
|
)
|
|
169
212
|
|
|
170
|
-
if backtrace &&
|
|
213
|
+
if backtrace && transaction.span_frames_min_duration
|
|
171
214
|
span.original_backtrace = backtrace
|
|
172
215
|
end
|
|
173
216
|
|
|
@@ -176,8 +219,8 @@ module Atatus
|
|
|
176
219
|
span.start
|
|
177
220
|
end
|
|
178
221
|
# rubocop:enable Metrics/ParameterLists
|
|
179
|
-
# rubocop:enable Metrics/
|
|
180
|
-
# rubocop:enable Metrics/
|
|
222
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
223
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
181
224
|
|
|
182
225
|
def end_span
|
|
183
226
|
return unless (span = current_spans.pop)
|
|
@@ -186,6 +229,8 @@ module Atatus
|
|
|
186
229
|
|
|
187
230
|
enqueue.call span
|
|
188
231
|
|
|
232
|
+
update_span_metrics(span)
|
|
233
|
+
|
|
189
234
|
span
|
|
190
235
|
end
|
|
191
236
|
|
|
@@ -205,7 +250,7 @@ module Atatus
|
|
|
205
250
|
|
|
206
251
|
def set_user(user)
|
|
207
252
|
return unless current_transaction
|
|
208
|
-
current_transaction.
|
|
253
|
+
current_transaction.set_user(user)
|
|
209
254
|
end
|
|
210
255
|
|
|
211
256
|
def inspect
|
|
@@ -216,9 +261,69 @@ module Atatus
|
|
|
216
261
|
|
|
217
262
|
private
|
|
218
263
|
|
|
219
|
-
def random_sample?
|
|
264
|
+
def random_sample?(config)
|
|
220
265
|
rand <= config.transaction_sample_rate
|
|
221
266
|
end
|
|
267
|
+
|
|
268
|
+
def update_transaction_metrics(transaction)
|
|
269
|
+
return unless transaction.collect_metrics?
|
|
270
|
+
|
|
271
|
+
tags = {
|
|
272
|
+
'transaction.name': transaction.name,
|
|
273
|
+
'transaction.type': transaction.type
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
@metrics.get(:transaction).timer(
|
|
277
|
+
:'transaction.duration.sum.us',
|
|
278
|
+
tags: tags, reset_on_collect: true
|
|
279
|
+
).update(transaction.duration)
|
|
280
|
+
|
|
281
|
+
@metrics.get(:transaction).counter(
|
|
282
|
+
:'transaction.duration.count',
|
|
283
|
+
tags: tags, reset_on_collect: true
|
|
284
|
+
).inc!
|
|
285
|
+
|
|
286
|
+
return unless transaction.sampled?
|
|
287
|
+
return unless transaction.breakdown_metrics
|
|
288
|
+
|
|
289
|
+
@metrics.get(:breakdown).counter(
|
|
290
|
+
:'transaction.breakdown.count',
|
|
291
|
+
tags: tags, reset_on_collect: true
|
|
292
|
+
).inc!
|
|
293
|
+
|
|
294
|
+
span_tags = tags.merge('span.type': 'app')
|
|
295
|
+
|
|
296
|
+
@metrics.get(:breakdown).timer(
|
|
297
|
+
:'span.self_time.sum.us',
|
|
298
|
+
tags: span_tags, reset_on_collect: true
|
|
299
|
+
).update(transaction.self_time)
|
|
300
|
+
|
|
301
|
+
@metrics.get(:breakdown).counter(
|
|
302
|
+
:'span.self_time.count',
|
|
303
|
+
tags: span_tags, reset_on_collect: true
|
|
304
|
+
).inc!
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def update_span_metrics(span)
|
|
308
|
+
return unless span.transaction.collect_metrics?
|
|
309
|
+
|
|
310
|
+
tags = {
|
|
311
|
+
'span.type': span.type,
|
|
312
|
+
'transaction.name': span.transaction.name,
|
|
313
|
+
'transaction.type': span.transaction.type
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
tags[:'span.subtype'] = span.subtype if span.subtype
|
|
317
|
+
|
|
318
|
+
@metrics.get(:breakdown).timer(
|
|
319
|
+
:'span.self_time.sum.us',
|
|
320
|
+
tags: tags, reset_on_collect: true
|
|
321
|
+
).update(span.self_time)
|
|
322
|
+
|
|
323
|
+
@metrics.get(:breakdown).counter(
|
|
324
|
+
:'span.self_time.count',
|
|
325
|
+
tags: tags, reset_on_collect: true
|
|
326
|
+
).inc!
|
|
327
|
+
end
|
|
222
328
|
end
|
|
223
|
-
# rubocop:enable Metrics/ClassLength
|
|
224
329
|
end
|