elastic-apm 0.6.1 → 0.6.2
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.
Potentially problematic release.
This version of elastic-apm might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +2 -5
- data/lib/elastic_apm.rb +1 -1
- data/lib/elastic_apm/config.rb +1 -8
- data/lib/elastic_apm/http.rb +1 -2
- data/lib/elastic_apm/injectors.rb +2 -0
- data/lib/elastic_apm/injectors/mongo.rb +57 -0
- data/lib/elastic_apm/injectors/net_http.rb +3 -14
- data/lib/elastic_apm/normalizers.rb +6 -1
- data/lib/elastic_apm/normalizers/action_mailer.rb +24 -0
- data/lib/elastic_apm/serializers/errors.rb +16 -2
- data/lib/elastic_apm/stacktrace.rb +28 -21
- data/lib/elastic_apm/transaction.rb +7 -1
- data/lib/elastic_apm/util/lru_cache.rb +8 -3
- data/lib/elastic_apm/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e3f8d9490f60e28d99b6e15e7efa2823fb773bacbdc9762f91fc92a4214b05b
|
4
|
+
data.tar.gz: 655814ff9046d8e9dd2d586688b9bc45acdb95f0102626af5ad0886330b58c16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4b9cace9b89eddb0ec281061fd098daa1e9297feb7fbc1c5de8ba44746ad2ab225df877480b5a213847d65502e39c321a79d4f35bee257d60d4a63a254c76e5
|
7
|
+
data.tar.gz: ae713fe3ad97666862ed91ecaeb8a199cfdaacb69edeb011840bb34e7da7692e97dffe15b729e3ec1275663bf2e381f241cb7579ca366a1ac7224c7465cbe9db
|
data/Gemfile
CHANGED
@@ -7,9 +7,9 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
7
7
|
gemspec
|
8
8
|
|
9
9
|
gem 'elasticsearch'
|
10
|
-
gem 'fakeredis', require: nil
|
11
|
-
github: 'guilleiguaran/fakeredis' # needs master right now
|
10
|
+
gem 'fakeredis', require: nil
|
12
11
|
gem 'json-schema'
|
12
|
+
gem 'mongo'
|
13
13
|
gem 'pry'
|
14
14
|
gem 'rack-test'
|
15
15
|
gem 'redis', require: nil
|
@@ -39,8 +39,5 @@ else
|
|
39
39
|
gem framework
|
40
40
|
end
|
41
41
|
|
42
|
-
# doesn't work with Rails master, so skip testing
|
43
|
-
gem 'delayed_job', '~> 4' unless [framework, version] == %w[rails 5.2]
|
44
|
-
|
45
42
|
gem 'rails' if framework == 'sinatra'
|
46
43
|
gem 'sinatra' if framework == 'rails'
|
data/lib/elastic_apm.rb
CHANGED
@@ -61,7 +61,7 @@ module ElasticAPM
|
|
61
61
|
# @param context [Context] An optional [Context]
|
62
62
|
# @yield [Transaction] Optional block encapsulating transaction
|
63
63
|
# @return [Transaction] Unless block given
|
64
|
-
def self.transaction(name, type = nil, context: nil, &block)
|
64
|
+
def self.transaction(name = nil, type = nil, context: nil, &block)
|
65
65
|
return (block_given? ? yield : nil) unless agent
|
66
66
|
|
67
67
|
agent.transaction(name, type, context: context, &block)
|
data/lib/elastic_apm/config.rb
CHANGED
@@ -8,21 +8,13 @@ module ElasticAPM
|
|
8
8
|
class Config
|
9
9
|
DEFAULTS = {
|
10
10
|
config_file: 'config/elastic_apm.yml',
|
11
|
-
|
12
11
|
server_url: 'http://localhost:8200',
|
13
|
-
secret_token: nil,
|
14
12
|
|
15
|
-
service_name: nil,
|
16
|
-
service_version: nil,
|
17
13
|
environment: ENV['RAILS_ENV'] || ENV['RACK_ENV'],
|
18
14
|
enabled_environments: %w[production],
|
19
|
-
framework_name: nil,
|
20
|
-
framework_version: nil,
|
21
|
-
hostname: nil,
|
22
15
|
|
23
16
|
log_path: '-',
|
24
17
|
log_level: Logger::INFO,
|
25
|
-
logger: nil,
|
26
18
|
|
27
19
|
max_queue_size: 500,
|
28
20
|
flush_interval: 10,
|
@@ -184,6 +176,7 @@ module ElasticAPM
|
|
184
176
|
delayed_job
|
185
177
|
elasticsearch
|
186
178
|
json
|
179
|
+
mongo
|
187
180
|
net_http
|
188
181
|
redis
|
189
182
|
sequel
|
data/lib/elastic_apm/http.rb
CHANGED
@@ -37,8 +37,7 @@ module ElasticAPM
|
|
37
37
|
request = prepare_request path, payload.to_json
|
38
38
|
response = @adapter.perform request
|
39
39
|
|
40
|
-
|
41
|
-
return response if status >= 200 && status <= 299
|
40
|
+
return response if response.is_a?(Net::HTTPSuccess)
|
42
41
|
|
43
42
|
error 'POST returned an unsuccessful status code (%d)', response.code
|
44
43
|
error "apm-server's response: %s", response.body
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ElasticAPM
|
4
|
+
# @api private
|
5
|
+
module Injectors
|
6
|
+
# @api private
|
7
|
+
class MongoInjector
|
8
|
+
def install
|
9
|
+
::Mongo::Monitoring::Global.subscribe(
|
10
|
+
::Mongo::Monitoring::COMMAND,
|
11
|
+
Subscriber.new
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
class Subscriber
|
17
|
+
TYPE = 'db.mongodb.query'.freeze
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@events = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def started(event)
|
24
|
+
push_event(event)
|
25
|
+
end
|
26
|
+
|
27
|
+
def failed(event)
|
28
|
+
pop_event(event)
|
29
|
+
end
|
30
|
+
|
31
|
+
def succeeded(event)
|
32
|
+
pop_event(event)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def push_event(event)
|
38
|
+
ctx = Span::Context.new(
|
39
|
+
instance: event.database_name,
|
40
|
+
statement: nil,
|
41
|
+
type: 'mongodb'.freeze,
|
42
|
+
user: nil
|
43
|
+
)
|
44
|
+
span = ElasticAPM.span(event.command_name, TYPE, context: ctx)
|
45
|
+
@events[event.operation_id] = span
|
46
|
+
end
|
47
|
+
|
48
|
+
def pop_event(event)
|
49
|
+
span = @events[event.operation_id]
|
50
|
+
span.done
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
register 'Mongo', 'mongo', MongoInjector.new
|
56
|
+
end
|
57
|
+
end
|
@@ -5,7 +5,7 @@ module ElasticAPM
|
|
5
5
|
module Injectors
|
6
6
|
# @api private
|
7
7
|
class NetHTTPInjector
|
8
|
-
# rubocop:disable Metrics/
|
8
|
+
# rubocop:disable Metrics/MethodLength
|
9
9
|
def install
|
10
10
|
Net::HTTP.class_eval do
|
11
11
|
alias request_without_apm request
|
@@ -15,21 +15,10 @@ module ElasticAPM
|
|
15
15
|
return request_without_apm(req, body, &block)
|
16
16
|
end
|
17
17
|
|
18
|
-
host,
|
18
|
+
host, = req['host'] && req['host'].split(':')
|
19
19
|
method = req.method
|
20
|
-
path = req.path
|
21
|
-
scheme = use_ssl? ? 'https' : 'http'
|
22
20
|
|
23
|
-
# inside a session
|
24
21
|
host ||= address
|
25
|
-
port ||= 80
|
26
|
-
|
27
|
-
# TODO: investigate
|
28
|
-
_extra = {
|
29
|
-
scheme: scheme,
|
30
|
-
port: port,
|
31
|
-
path: path
|
32
|
-
}
|
33
22
|
|
34
23
|
name = "#{method} #{host}"
|
35
24
|
type = "ext.net_http.#{method}"
|
@@ -40,7 +29,7 @@ module ElasticAPM
|
|
40
29
|
end
|
41
30
|
end
|
42
31
|
end
|
43
|
-
# rubocop:enable Metrics/
|
32
|
+
# rubocop:enable Metrics/MethodLength
|
44
33
|
end
|
45
34
|
|
46
35
|
register 'Net::HTTP', 'net/http', NetHTTPInjector.new
|
@@ -57,7 +57,12 @@ module ElasticAPM # :nodoc:
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
%w[
|
60
|
+
%w[
|
61
|
+
action_controller
|
62
|
+
action_mailer
|
63
|
+
action_view
|
64
|
+
active_record
|
65
|
+
].each do |lib|
|
61
66
|
require "elastic_apm/normalizers/#{lib}"
|
62
67
|
end
|
63
68
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ElasticAPM
|
4
|
+
module Normalizers
|
5
|
+
module ActionMailer
|
6
|
+
# @api private
|
7
|
+
class ProcessActionNormalizer < Normalizer
|
8
|
+
register 'process.action_mailer'
|
9
|
+
TYPE = 'app.mailer.action'.freeze
|
10
|
+
|
11
|
+
def normalize(transaction, _name, payload)
|
12
|
+
transaction.name = endpoint(payload)
|
13
|
+
[transaction.name, TYPE, nil]
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def endpoint(payload)
|
19
|
+
"#{payload[:mailer]}##{payload[:action]}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -4,7 +4,7 @@ module ElasticAPM
|
|
4
4
|
module Serializers
|
5
5
|
# @api private
|
6
6
|
class Errors < Serializer
|
7
|
-
# rubocop:disable Metrics/MethodLength
|
7
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
8
8
|
def build(error)
|
9
9
|
base = {
|
10
10
|
id: error.id,
|
@@ -17,13 +17,17 @@ module ElasticAPM
|
|
17
17
|
base[:exception] = build_exception exception
|
18
18
|
end
|
19
19
|
|
20
|
+
if (log = error.log)
|
21
|
+
base[:log] = build_log log
|
22
|
+
end
|
23
|
+
|
20
24
|
if (transaction_id = error.transaction_id)
|
21
25
|
base[:transaction] = { id: transaction_id }
|
22
26
|
end
|
23
27
|
|
24
28
|
base
|
25
29
|
end
|
26
|
-
# rubocop:enable Metrics/MethodLength
|
30
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
27
31
|
|
28
32
|
def build_all(errors)
|
29
33
|
{ errors: Array(errors).map(&method(:build)) }
|
@@ -42,6 +46,16 @@ module ElasticAPM
|
|
42
46
|
handled: exception.handled
|
43
47
|
}
|
44
48
|
end
|
49
|
+
|
50
|
+
def build_log(log)
|
51
|
+
{
|
52
|
+
message: log.message,
|
53
|
+
level: log.level,
|
54
|
+
logger_name: log.logger_name,
|
55
|
+
param_message: log.param_message,
|
56
|
+
stacktrace: log.stacktrace.to_a
|
57
|
+
}
|
58
|
+
end
|
45
59
|
end
|
46
60
|
end
|
47
61
|
end
|
@@ -71,38 +71,45 @@ module ElasticAPM
|
|
71
71
|
false
|
72
72
|
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
frame = Frame.new
|
79
|
-
frame.abs_path = abs_path
|
80
|
-
frame.filename = strip_load_path(abs_path)
|
81
|
-
frame.function = function
|
82
|
-
frame.lineno = lineno.to_i
|
83
|
-
frame.library_frame = library_frame?(config, abs_path)
|
74
|
+
class << self
|
75
|
+
attr_accessor :frame_cache
|
76
|
+
end
|
84
77
|
|
85
|
-
|
86
|
-
|
87
|
-
|
78
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
79
|
+
def build_frame(config, line, type)
|
80
|
+
# TODO: Eventually move this to agent 'context'
|
81
|
+
self.class.frame_cache ||= Util::LruCache.new(2048) do |cache, keys|
|
82
|
+
line, type = keys
|
83
|
+
abs_path, lineno, function, _module_name = parse_line(line)
|
84
|
+
|
85
|
+
frame = Frame.new
|
86
|
+
frame.abs_path = abs_path
|
87
|
+
frame.filename = strip_load_path(abs_path)
|
88
|
+
frame.function = function
|
89
|
+
frame.lineno = lineno.to_i
|
90
|
+
frame.library_frame = library_frame?(config, abs_path)
|
91
|
+
|
92
|
+
line_count =
|
93
|
+
context_lines_for(config, type, library_frame: frame.library_frame)
|
94
|
+
frame.build_context line_count
|
95
|
+
|
96
|
+
cache[[line, type]] = frame
|
97
|
+
end
|
88
98
|
|
89
|
-
|
99
|
+
self.class.frame_cache[[line, type]]
|
90
100
|
end
|
91
|
-
# rubocop:enable Metrics/MethodLength
|
101
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
92
102
|
|
93
103
|
def strip_load_path(path)
|
94
|
-
return nil
|
104
|
+
return nil if path.nil?
|
95
105
|
|
96
106
|
prefix =
|
97
107
|
$LOAD_PATH
|
98
108
|
.map(&:to_s)
|
99
109
|
.select { |s| path.start_with?(s) }
|
100
|
-
.
|
101
|
-
.last
|
102
|
-
|
103
|
-
return path unless prefix
|
110
|
+
.max_by(&:length)
|
104
111
|
|
105
|
-
path[prefix.chomp(File::SEPARATOR).length + 1..-1]
|
112
|
+
prefix ? path[prefix.chomp(File::SEPARATOR).length + 1..-1] : path
|
106
113
|
end
|
107
114
|
|
108
115
|
def context_lines_for(config, type, library_frame:)
|
@@ -6,7 +6,13 @@ module ElasticAPM
|
|
6
6
|
DEFAULT_TYPE = 'custom'.freeze
|
7
7
|
|
8
8
|
# rubocop:disable Metrics/MethodLength
|
9
|
-
def initialize(
|
9
|
+
def initialize(
|
10
|
+
instrumenter,
|
11
|
+
name = nil,
|
12
|
+
type = nil,
|
13
|
+
context: nil,
|
14
|
+
sampled: true
|
15
|
+
)
|
10
16
|
@id = SecureRandom.uuid
|
11
17
|
@instrumenter = instrumenter
|
12
18
|
@name = name
|
@@ -4,16 +4,21 @@ module ElasticAPM
|
|
4
4
|
module Util
|
5
5
|
# @api private
|
6
6
|
class LruCache
|
7
|
-
def initialize(max_size = 512)
|
7
|
+
def initialize(max_size = 512, &block)
|
8
8
|
@max_size = max_size
|
9
|
-
@data =
|
9
|
+
@data = Hash.new(&block)
|
10
|
+
@missing_key_block = block
|
10
11
|
end
|
11
12
|
|
12
13
|
def [](key)
|
13
14
|
found = true
|
14
15
|
value = @data.delete(key) { found = false }
|
15
16
|
|
16
|
-
found
|
17
|
+
if found
|
18
|
+
@data[key] = value
|
19
|
+
else
|
20
|
+
@missing_key_block && @missing_key_block.call(self, key)
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
def []=(key, val)
|
data/lib/elastic_apm/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elastic-apm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mikkel Malmberg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- lib/elastic_apm/injectors/delayed_job.rb
|
77
77
|
- lib/elastic_apm/injectors/elasticsearch.rb
|
78
78
|
- lib/elastic_apm/injectors/json.rb
|
79
|
+
- lib/elastic_apm/injectors/mongo.rb
|
79
80
|
- lib/elastic_apm/injectors/net_http.rb
|
80
81
|
- lib/elastic_apm/injectors/redis.rb
|
81
82
|
- lib/elastic_apm/injectors/sequel.rb
|
@@ -89,6 +90,7 @@ files:
|
|
89
90
|
- lib/elastic_apm/naively_hashable.rb
|
90
91
|
- lib/elastic_apm/normalizers.rb
|
91
92
|
- lib/elastic_apm/normalizers/action_controller.rb
|
93
|
+
- lib/elastic_apm/normalizers/action_mailer.rb
|
92
94
|
- lib/elastic_apm/normalizers/action_view.rb
|
93
95
|
- lib/elastic_apm/normalizers/active_record.rb
|
94
96
|
- lib/elastic_apm/process_info.rb
|