elastic-apm 0.2.0 → 0.3.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.
Potentially problematic release.
This version of elastic-apm might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/README.md +17 -49
- data/docs/api.asciidoc +15 -0
- data/docs/configuration.asciidoc +2 -0
- data/docs/context.asciidoc +16 -0
- data/docs/getting-started-rails.asciidoc +1 -0
- data/lib/elastic_apm.rb +33 -2
- data/lib/elastic_apm/agent.rb +15 -3
- data/lib/elastic_apm/config.rb +42 -22
- data/lib/elastic_apm/context_builder.rb +1 -22
- data/lib/elastic_apm/error_builder.rb +2 -4
- data/lib/elastic_apm/filters.rb +44 -0
- data/lib/elastic_apm/filters/request_body_filter.rb +33 -0
- data/lib/elastic_apm/filters/secrets_filter.rb +58 -0
- data/lib/elastic_apm/http.rb +7 -4
- data/lib/elastic_apm/instrumenter.rb +5 -1
- data/lib/elastic_apm/log.rb +7 -4
- data/lib/elastic_apm/middleware.rb +1 -10
- data/lib/elastic_apm/serializers/transactions.rb +18 -11
- data/lib/elastic_apm/service_info.rb +5 -7
- data/lib/elastic_apm/span.rb +2 -1
- data/lib/elastic_apm/sql_summarizer.rb +6 -2
- data/lib/elastic_apm/stacktrace.rb +11 -6
- data/lib/elastic_apm/stacktrace/frame.rb +13 -11
- data/lib/elastic_apm/stacktrace/line_cache.rb +25 -0
- data/lib/elastic_apm/subscriber.rb +3 -5
- data/lib/elastic_apm/system_info.rb +1 -5
- data/lib/elastic_apm/transaction.rb +8 -2
- data/lib/elastic_apm/util/dig.rb +31 -0
- data/lib/elastic_apm/util/lru_cache.rb +37 -0
- data/lib/elastic_apm/version.rb +1 -1
- data/lib/elastic_apm/worker.rb +2 -4
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6272279575b41ace4dc7581df1d6ea387f46c260d591c338fceb256f0b46ff2
|
4
|
+
data.tar.gz: f793a0c902a18abfe647e5a3a41c86d96926910dfef21094aa3b1c37deac45eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f16cbdffc10a05005c03ec0d122235c84b56a9bda9f2201fd913e1d3b96925d3f5ef0847cfd2cc369da0b1d1c39c21dccd187579f278d7439218c97b4548a97
|
7
|
+
data.tar.gz: 4daea6a3d579f4fba6435de9277bdd842889b6afeab63c97da9a9424809d6e4721bd873da4edecae1eeb66281ae43989385027099f0c828a38bff94c4ec3addd
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -1,57 +1,25 @@
|
|
1
|
-
# elastic-apm – Elastic APM agent for Ruby (
|
1
|
+
# elastic-apm – Elastic APM agent for Ruby (BETA)
|
2
2
|
|
3
3
|
[](https://apm-ci.elastic.co/job/elastic+apm-agent-ruby+master/) [](https://rubygems.org/gems/elastic-apm)
|
4
4
|
|
5
5
|
This is the official Rubygem for adding [Elastic][]'s [APM][] to your Ruby app.
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
The suggested way to configure is to create a file `config/elastic_apm.yml` with your config:
|
24
|
-
|
25
|
-
```yaml
|
26
|
-
# config/elastic_apm.yml
|
27
|
-
|
28
|
-
server_url: http://localhost:8200
|
29
|
-
secret_token: YOUR_SECRET
|
30
|
-
```
|
31
|
-
|
32
|
-
## Getting started with Sinatra
|
33
|
-
|
34
|
-
```ruby
|
35
|
-
# config.ru
|
36
|
-
|
37
|
-
require 'sinatra/base'
|
38
|
-
|
39
|
-
class MySinatraApp < Sinatra::Base
|
40
|
-
use ElasticAPM::Middleware
|
41
|
-
|
42
|
-
# ...
|
43
|
-
end
|
44
|
-
|
45
|
-
# Takes optional ElasticAPM::Config values
|
46
|
-
ElasticAPM.start(
|
47
|
-
app: MySinatraApp, # required
|
48
|
-
server_url: 'http://localhost:8200'
|
49
|
-
)
|
50
|
-
|
51
|
-
run MySinatraApp
|
52
|
-
|
53
|
-
at_exit { ElasticAPM.stop }
|
54
|
-
```
|
7
|
+
<div>
|
8
|
+
<ul>
|
9
|
+
<li><a href="https://www.elastic.co/guide/en/apm/agent/ruby/1.x/_introduction.html">Introduction</a></li>
|
10
|
+
<li><a href="https://www.elastic.co/guide/en/apm/agent/ruby/1.x/getting-started-rails.html">Getting started with Rails</a></li>
|
11
|
+
<li><a href="https://www.elastic.co/guide/en/apm/agent/ruby/1.x/getting-started-rack.html">Getting started with Rack</a></li>
|
12
|
+
<li><a href="https://www.elastic.co/guide/en/apm/agent/ruby/1.x/configuration.html">Configuration</a></li>
|
13
|
+
<li class="collapsible">
|
14
|
+
<a href="https://www.elastic.co/guide/en/apm/agent/ruby/1.x/advanced.html">Advanced Topics</a>
|
15
|
+
<ul>
|
16
|
+
<li><a href="https://www.elastic.co/guide/en/apm/agent/ruby/1.x/custom-instrumentation.html">Custom instrumentation</a></li>
|
17
|
+
<li><a href="https://www.elastic.co/guide/en/apm/agent/ruby/1.x/injectors.html">Injectors — automatic integrations with third-party libraries</a></li>
|
18
|
+
</ul>
|
19
|
+
</li>
|
20
|
+
<li><a href="https://www.elastic.co/guide/en/apm/agent/ruby/1.x/api.html">Public API</a></li>
|
21
|
+
</ul>
|
22
|
+
</div>
|
55
23
|
|
56
24
|
# License
|
57
25
|
|
data/docs/api.asciidoc
CHANGED
@@ -44,6 +44,7 @@ Returns whether the ElasticAPM Agent is currently running.
|
|
44
44
|
|
45
45
|
Returns the currently running agent or nil.
|
46
46
|
|
47
|
+
[float]
|
47
48
|
=== Instrumentation
|
48
49
|
|
49
50
|
[float]
|
@@ -119,6 +120,7 @@ Arguments:
|
|
119
120
|
|
120
121
|
Returns the built context.
|
121
122
|
|
123
|
+
[float]
|
122
124
|
=== Errors
|
123
125
|
|
124
126
|
[float]
|
@@ -165,6 +167,7 @@ Arguments:
|
|
165
167
|
|
166
168
|
Returns `[ElasticAPM::Error]`.
|
167
169
|
|
170
|
+
[float]
|
168
171
|
=== Context
|
169
172
|
|
170
173
|
[float]
|
@@ -208,3 +211,15 @@ Arguments:
|
|
208
211
|
|
209
212
|
Returns current custom context.
|
210
213
|
|
214
|
+
[float]
|
215
|
+
[[api-set-user]]
|
216
|
+
==== `ElasticAPM.set_user`
|
217
|
+
|
218
|
+
Add the current user to the current transaction's context.
|
219
|
+
|
220
|
+
Arguments:
|
221
|
+
|
222
|
+
* `user`: An object representing the user
|
223
|
+
|
224
|
+
Returns the given user
|
225
|
+
|
data/docs/configuration.asciidoc
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
There are several ways to shape how Elastic APM behaves.
|
5
5
|
|
6
|
+
[float]
|
6
7
|
=== Rails
|
7
8
|
|
8
9
|
The recommended way to configure Elastic APM for Rails is to create a file `config/elastic_apm.yml` and specify options in there:
|
@@ -14,6 +15,7 @@ server_url: 'http://localhost:8200'
|
|
14
15
|
secret_token: 'very_very_secret'
|
15
16
|
----
|
16
17
|
|
18
|
+
[float]
|
17
19
|
=== Sinatra and Rack
|
18
20
|
|
19
21
|
When using APM with Sinatra and Rack, you should configure it when starting the agent:
|
data/docs/context.asciidoc
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
[float]
|
1
2
|
[[context]]
|
2
3
|
=== Adding additional context
|
3
4
|
|
5
|
+
[float]
|
4
6
|
==== Adding custom context
|
5
7
|
|
6
8
|
You can add your own custom, nested JSON-compatible data to the current transaction using `ElasticAPM.add_custom_context(hash)` eg.:
|
@@ -16,6 +18,7 @@ class ThingsController < ApplicationController
|
|
16
18
|
end
|
17
19
|
----
|
18
20
|
|
21
|
+
[float]
|
19
22
|
==== Adding tags
|
20
23
|
|
21
24
|
Tags are special in that they are indexed in your Elasticsearch database and therefore searchable.
|
@@ -25,3 +28,16 @@ Tags are special in that they are indexed in your Elasticsearch database and the
|
|
25
28
|
ElasticAPM.set_tag(:company_name, 'Acme, Inc.')
|
26
29
|
----
|
27
30
|
|
31
|
+
[float]
|
32
|
+
==== Providing info about the user
|
33
|
+
|
34
|
+
You can provide ElasticAPM with info about the current user.
|
35
|
+
|
36
|
+
[source,ruby]
|
37
|
+
----
|
38
|
+
class ApplicationController < ActionController::Base
|
39
|
+
before_action do
|
40
|
+
current_user && ElasticAPM.set_user(current_user)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
----
|
data/lib/elastic_apm.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'elastic_apm/version'
|
4
4
|
require 'elastic_apm/log'
|
5
|
+
require 'elastic_apm/util/dig'
|
5
6
|
|
6
7
|
# Core
|
7
8
|
require 'elastic_apm/agent'
|
@@ -73,9 +74,17 @@ module ElasticAPM
|
|
73
74
|
# @param context [Span::Context] Context information about the span
|
74
75
|
# @yield [Span] Optional block encapsulating span
|
75
76
|
# @return [Span] Unless block given
|
76
|
-
def self.span(name, type = nil, context: nil,
|
77
|
+
def self.span(name, type = nil, context: nil, include_stacktrace: true,
|
78
|
+
&block)
|
77
79
|
return call_through(&block) unless agent
|
78
|
-
|
80
|
+
|
81
|
+
agent.span(
|
82
|
+
name,
|
83
|
+
type,
|
84
|
+
context: context,
|
85
|
+
backtrace: include_stacktrace ? caller : nil,
|
86
|
+
&block
|
87
|
+
)
|
79
88
|
end
|
80
89
|
|
81
90
|
# Build a [Context] from a Rack `env`. The context may include information
|
@@ -125,6 +134,28 @@ module ElasticAPM
|
|
125
134
|
agent && agent.set_custom_context(custom)
|
126
135
|
end
|
127
136
|
|
137
|
+
# Provide a user to the current transaction
|
138
|
+
#
|
139
|
+
# @param user [Object] An object representing a user
|
140
|
+
# @return [Object] Given user
|
141
|
+
def self.set_user(user)
|
142
|
+
agent && agent.set_user(user)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Provide a filter to transform payloads before sending them off
|
146
|
+
#
|
147
|
+
# @param key [Symbol] Unique filter key
|
148
|
+
# @param callback [Object, Proc] A filter that responds to #call(payload)
|
149
|
+
# @yield [Hash] A filter. Will be used if provided. Otherwise using `callback`
|
150
|
+
# @return [Bool] true
|
151
|
+
def self.add_filter(key, callback = nil, &block)
|
152
|
+
if callback.nil? && !block_given?
|
153
|
+
raise ArgumentError, '#add_filter needs either `callback\' or a block'
|
154
|
+
end
|
155
|
+
|
156
|
+
agent && agent.add_filter(key, block || callback)
|
157
|
+
end
|
158
|
+
|
128
159
|
class << self
|
129
160
|
private
|
130
161
|
|
data/lib/elastic_apm/agent.rb
CHANGED
@@ -28,7 +28,8 @@ module ElasticAPM
|
|
28
28
|
|
29
29
|
LOCK.synchronize do
|
30
30
|
return @instance if @instance
|
31
|
-
|
31
|
+
|
32
|
+
@instance = new(config.freeze).start
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
@@ -45,11 +46,13 @@ module ElasticAPM
|
|
45
46
|
!!@instance
|
46
47
|
end
|
47
48
|
|
49
|
+
# rubocop:disable Metrics/MethodLength
|
48
50
|
def initialize(config)
|
49
51
|
config = Config.new(config) if config.is_a?(Hash)
|
50
52
|
|
51
53
|
@config = config
|
52
54
|
|
55
|
+
@http = Http.new(config)
|
53
56
|
@queue = Queue.new
|
54
57
|
|
55
58
|
@instrumenter = Instrumenter.new(config, self)
|
@@ -61,8 +64,9 @@ module ElasticAPM
|
|
61
64
|
Serializers::Errors.new(config)
|
62
65
|
)
|
63
66
|
end
|
67
|
+
# rubocop:enable Metrics/MethodLength
|
64
68
|
|
65
|
-
attr_reader :config, :queue, :instrumenter, :context_builder
|
69
|
+
attr_reader :config, :queue, :instrumenter, :context_builder, :http
|
66
70
|
|
67
71
|
def start
|
68
72
|
debug 'Starting agent reporting to %s', config.server_url
|
@@ -150,6 +154,14 @@ module ElasticAPM
|
|
150
154
|
instrumenter.set_custom_context(*args)
|
151
155
|
end
|
152
156
|
|
157
|
+
def set_user(*args)
|
158
|
+
instrumenter.set_user(*args)
|
159
|
+
end
|
160
|
+
|
161
|
+
def add_filter(key, callback)
|
162
|
+
@http.filters.add(key, callback)
|
163
|
+
end
|
164
|
+
|
153
165
|
def inspect
|
154
166
|
'<ElasticAPM::Agent>'
|
155
167
|
end
|
@@ -160,7 +172,7 @@ module ElasticAPM
|
|
160
172
|
debug 'Booting worker in thread'
|
161
173
|
|
162
174
|
@worker_thread = Thread.new do
|
163
|
-
Worker.new(@config, @queue).run_forever
|
175
|
+
Worker.new(@config, @queue, @http).run_forever
|
164
176
|
end
|
165
177
|
end
|
166
178
|
|
data/lib/elastic_apm/config.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'logger'
|
4
4
|
|
5
5
|
module ElasticAPM
|
6
|
+
# rubocop:disable Metrics/ClassLength
|
6
7
|
# @api private
|
7
8
|
class Config
|
8
9
|
DEFAULTS = {
|
@@ -16,50 +17,67 @@ module ElasticAPM
|
|
16
17
|
|
17
18
|
log_path: '-',
|
18
19
|
log_level: Logger::INFO,
|
20
|
+
logger: nil,
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
+
http_timeout: 10,
|
23
|
+
http_open_timeout: 10,
|
22
24
|
transaction_send_interval: 10,
|
23
25
|
debug_transactions: false,
|
24
26
|
debug_http: false,
|
25
27
|
|
26
|
-
enabled_injectors: %w[net_http],
|
28
|
+
enabled_injectors: %w[net_http json],
|
27
29
|
|
28
|
-
current_user_method: :current_user,
|
29
30
|
current_user_id_method: :id,
|
30
31
|
current_user_email_method: :email,
|
31
32
|
current_user_username_method: :username,
|
32
33
|
|
33
|
-
view_paths: []
|
34
|
+
view_paths: [],
|
35
|
+
root_path: Dir.pwd
|
34
36
|
}.freeze
|
35
37
|
|
36
|
-
|
38
|
+
ENV_TO_KEY = {
|
39
|
+
'ELASTIC_APM_APP_NAME' => 'app_name',
|
40
|
+
'ELASTIC_APM_SERVER_URL' => 'server_url',
|
41
|
+
'ELASTIC_APM_SECRET_TOKEN' => 'secret_token'
|
42
|
+
}.freeze
|
37
43
|
|
44
|
+
# rubocop:disable Metrics/MethodLength
|
38
45
|
def initialize(options = nil)
|
39
46
|
options = {} if options.nil?
|
40
47
|
|
41
|
-
|
48
|
+
# Start with the defaults
|
49
|
+
DEFAULTS.each do |key, value|
|
42
50
|
send("#{key}=", value)
|
43
51
|
end
|
44
52
|
|
45
|
-
|
53
|
+
# Set options from ENV
|
54
|
+
ENV_TO_KEY.each do |env_key, key|
|
55
|
+
next unless (value = ENV[env_key])
|
56
|
+
send("#{key}=", value)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Set options from arguments
|
60
|
+
options.each do |key, value|
|
61
|
+
send("#{key}=", value)
|
62
|
+
end
|
46
63
|
|
47
|
-
yield self
|
64
|
+
yield self if block_given?
|
48
65
|
end
|
66
|
+
# rubocop:enable Metrics/MethodLength
|
49
67
|
|
50
68
|
attr_accessor :server_url
|
51
69
|
attr_accessor :secret_token
|
52
70
|
|
53
71
|
attr_accessor :app_name
|
54
|
-
|
72
|
+
attr_reader :environment
|
55
73
|
attr_accessor :framework_name
|
56
74
|
attr_accessor :framework_version
|
57
75
|
|
58
76
|
attr_accessor :log_path
|
59
77
|
attr_accessor :log_level
|
60
78
|
|
61
|
-
attr_accessor :
|
62
|
-
attr_accessor :
|
79
|
+
attr_accessor :http_timeout
|
80
|
+
attr_accessor :http_open_timeout
|
63
81
|
attr_accessor :transaction_send_interval
|
64
82
|
attr_accessor :debug_transactions
|
65
83
|
attr_accessor :debug_http
|
@@ -67,13 +85,14 @@ module ElasticAPM
|
|
67
85
|
attr_accessor :enabled_injectors
|
68
86
|
|
69
87
|
attr_accessor :view_paths
|
88
|
+
attr_accessor :root_path
|
70
89
|
|
71
90
|
attr_accessor :current_user_method
|
72
91
|
attr_accessor :current_user_id_method
|
73
92
|
attr_accessor :current_user_email_method
|
74
93
|
attr_accessor :current_user_username_method
|
75
94
|
|
76
|
-
|
95
|
+
attr_reader :logger
|
77
96
|
|
78
97
|
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
79
98
|
def app=(app)
|
@@ -82,11 +101,14 @@ module ElasticAPM
|
|
82
101
|
self.app_name = format_name(app_name || app.to_s)
|
83
102
|
self.framework_name = 'Sinatra'
|
84
103
|
self.framework_version = Sinatra::VERSION
|
104
|
+
self.enabled_injectors += %w[sinatra]
|
105
|
+
self.root_path = Dir.pwd
|
85
106
|
when :rails
|
86
107
|
self.app_name = format_name(app_name || app.class.parent_name)
|
87
108
|
self.framework_name = 'Ruby on Rails'
|
88
109
|
self.framework_version = Rails::VERSION::STRING
|
89
110
|
self.logger = Rails.logger
|
111
|
+
self.root_path = Rails.root.to_s
|
90
112
|
self.view_paths = app.config.paths['app/views'].existent
|
91
113
|
else
|
92
114
|
# TODO: define custom?
|
@@ -107,19 +129,16 @@ module ElasticAPM
|
|
107
129
|
nil
|
108
130
|
end
|
109
131
|
|
110
|
-
def
|
111
|
-
|
132
|
+
def use_ssl?
|
133
|
+
server_url.start_with?('https')
|
112
134
|
end
|
113
135
|
|
114
|
-
def
|
115
|
-
@
|
116
|
-
LOCK.synchronize do
|
117
|
-
build_logger(log_path, log_level)
|
118
|
-
end
|
136
|
+
def environment=(env)
|
137
|
+
@environment = env || ENV['RAILS_ENV'] || ENV['RACK_ENV']
|
119
138
|
end
|
120
139
|
|
121
|
-
def
|
122
|
-
|
140
|
+
def logger=(logger)
|
141
|
+
@logger = logger || build_logger(log_path, log_level)
|
123
142
|
end
|
124
143
|
|
125
144
|
private
|
@@ -134,4 +153,5 @@ module ElasticAPM
|
|
134
153
|
str.gsub('::', '_')
|
135
154
|
end
|
136
155
|
end
|
156
|
+
# rubocop:enable Metrics/ClassLength
|
137
157
|
end
|
@@ -3,20 +3,11 @@
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
5
|
class ContextBuilder
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(config)
|
9
|
-
@config = config
|
10
|
-
end
|
11
|
-
|
12
|
-
attr_reader :config
|
6
|
+
def initialize(_config); end
|
13
7
|
|
14
8
|
def build(rack_env)
|
15
9
|
context = Context.new
|
16
|
-
|
17
10
|
apply_to_request(context, rack_env)
|
18
|
-
apply_to_user(context, rack_env)
|
19
|
-
|
20
11
|
context
|
21
12
|
end
|
22
13
|
|
@@ -40,18 +31,6 @@ module ElasticAPM
|
|
40
31
|
end
|
41
32
|
# rubocop:enable Metrics/AbcSize
|
42
33
|
|
43
|
-
def apply_to_user(context, rack_env)
|
44
|
-
return unless (controller = rack_env[CONTROLLER_KEY])
|
45
|
-
|
46
|
-
method = config.current_user_method.to_sym
|
47
|
-
return unless controller.respond_to?(method)
|
48
|
-
|
49
|
-
return unless (record = controller.send method)
|
50
|
-
|
51
|
-
context.user = Context::User.new(config, record)
|
52
|
-
context
|
53
|
-
end
|
54
|
-
|
55
34
|
def get_body(req)
|
56
35
|
return req.POST if req.form_data?
|
57
36
|
|
@@ -7,8 +7,6 @@ module ElasticAPM
|
|
7
7
|
@config = config
|
8
8
|
end
|
9
9
|
|
10
|
-
attr_reader :config
|
11
|
-
|
12
10
|
def build_exception(exception, handled: true)
|
13
11
|
error = Error.new
|
14
12
|
error.exception = Error::Exception.new(exception, handled: handled)
|
@@ -36,7 +34,7 @@ module ElasticAPM
|
|
36
34
|
private
|
37
35
|
|
38
36
|
def add_stacktrace(error, kind, backtrace)
|
39
|
-
return unless (stacktrace = Stacktrace.build(config, backtrace))
|
37
|
+
return unless (stacktrace = Stacktrace.build(@config, backtrace))
|
40
38
|
|
41
39
|
case kind
|
42
40
|
when :exception
|
@@ -45,7 +43,7 @@ module ElasticAPM
|
|
45
43
|
error.log.stacktrace = stacktrace
|
46
44
|
end
|
47
45
|
|
48
|
-
error.culprit = stacktrace.frames.
|
46
|
+
error.culprit = stacktrace.frames.first.function
|
49
47
|
end
|
50
48
|
|
51
49
|
def add_transaction_id(error)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'elastic_apm/filters/request_body_filter'
|
4
|
+
require 'elastic_apm/filters/secrets_filter'
|
5
|
+
|
6
|
+
module ElasticAPM
|
7
|
+
# @api private
|
8
|
+
module Filters
|
9
|
+
def self.new(config)
|
10
|
+
Container.new(config)
|
11
|
+
end
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
class Container
|
15
|
+
def initialize(config)
|
16
|
+
@config = config
|
17
|
+
@filters = {
|
18
|
+
request_body: RequestBodyFilter.new(config),
|
19
|
+
secrets: SecretsFilter.new(config)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :config
|
24
|
+
|
25
|
+
def add(key, filter)
|
26
|
+
@filters[key] = filter
|
27
|
+
end
|
28
|
+
|
29
|
+
def remove(key)
|
30
|
+
@filters.delete(key)
|
31
|
+
end
|
32
|
+
|
33
|
+
def apply(payload)
|
34
|
+
@filters.reduce(payload) do |result, (_key, filter)|
|
35
|
+
filter.call(result)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def length
|
40
|
+
@filters.length
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ElasticAPM
|
4
|
+
module Filters
|
5
|
+
# @api private
|
6
|
+
class RequestBodyFilter
|
7
|
+
FILTERED = '[FILTERED]'.freeze
|
8
|
+
|
9
|
+
def initialize(config)
|
10
|
+
@config = config
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(payload)
|
14
|
+
strip_body_from payload[:transactions]
|
15
|
+
strip_body_from payload[:errors]
|
16
|
+
|
17
|
+
payload
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def strip_body_from(arr)
|
23
|
+
return unless arr
|
24
|
+
|
25
|
+
arr.each do |entity|
|
26
|
+
next unless (request = entity.dig(:context, :request))
|
27
|
+
|
28
|
+
request[:body] = FILTERED
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ElasticAPM
|
4
|
+
module Filters
|
5
|
+
# @api private
|
6
|
+
class SecretsFilter
|
7
|
+
FILTERED = '[FILTERED]'.freeze
|
8
|
+
|
9
|
+
KEY_FILTERS = [
|
10
|
+
/passw(or)?d/i,
|
11
|
+
/^pw$/,
|
12
|
+
/secret/i,
|
13
|
+
/token/i,
|
14
|
+
/api[-._]?key/i,
|
15
|
+
/session[-._]?id/i
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
VALUE_FILTERS = [
|
19
|
+
/^\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}$/ # (probably) credit card number
|
20
|
+
].freeze
|
21
|
+
|
22
|
+
def initialize(config)
|
23
|
+
@config = config
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(payload)
|
27
|
+
strip_from payload[:transactions], :context, :request, :headers
|
28
|
+
strip_from payload[:transactions], :context, :response, :headers
|
29
|
+
strip_from payload[:errors], :context, :request, :headers
|
30
|
+
strip_from payload[:errors], :context, :response, :headers
|
31
|
+
|
32
|
+
payload
|
33
|
+
end
|
34
|
+
|
35
|
+
def strip_from(events, *path)
|
36
|
+
return unless events
|
37
|
+
|
38
|
+
events.each do |event|
|
39
|
+
next unless (headers = event.dig(*path))
|
40
|
+
|
41
|
+
headers.each do |k, v|
|
42
|
+
if filter_key?(k) || filter_value?(v)
|
43
|
+
headers[k] = FILTERED
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def filter_key?(key)
|
50
|
+
KEY_FILTERS.any? { |regex| key =~ regex }
|
51
|
+
end
|
52
|
+
|
53
|
+
def filter_value?(value)
|
54
|
+
VALUE_FILTERS.any? { |regex| value =~ regex }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/elastic_apm/http.rb
CHANGED
@@ -5,6 +5,7 @@ require 'net/http'
|
|
5
5
|
require 'elastic_apm/service_info'
|
6
6
|
require 'elastic_apm/system_info'
|
7
7
|
require 'elastic_apm/process_info'
|
8
|
+
require 'elastic_apm/filters'
|
8
9
|
|
9
10
|
module ElasticAPM
|
10
11
|
# @api private
|
@@ -23,12 +24,14 @@ module ElasticAPM
|
|
23
24
|
process: ProcessInfo.build(config),
|
24
25
|
system: SystemInfo.build(config)
|
25
26
|
}
|
27
|
+
@filters = Filters.new(config)
|
26
28
|
end
|
27
29
|
|
28
|
-
attr_reader :
|
30
|
+
attr_reader :filters
|
29
31
|
|
30
32
|
def post(path, payload = {})
|
31
33
|
payload.merge! @base_payload
|
34
|
+
filters.apply(payload)
|
32
35
|
request = prepare_request path, payload.to_json
|
33
36
|
response = @adapter.perform request
|
34
37
|
|
@@ -50,7 +53,7 @@ module ElasticAPM
|
|
50
53
|
req['User-Agent'] = USER_AGENT
|
51
54
|
req['Content-Length'] = data.bytesize.to_s
|
52
55
|
|
53
|
-
if (token = config.secret_token)
|
56
|
+
if (token = @config.secret_token)
|
54
57
|
req['Authorization'] = "Bearer #{token}"
|
55
58
|
end
|
56
59
|
|
@@ -88,8 +91,8 @@ module ElasticAPM
|
|
88
91
|
|
89
92
|
http = Net::HTTP.new server_uri.host, server_uri.port
|
90
93
|
http.use_ssl = @config.use_ssl?
|
91
|
-
http.read_timeout = @config.
|
92
|
-
http.open_timeout = @config.
|
94
|
+
http.read_timeout = @config.http_timeout
|
95
|
+
http.open_timeout = @config.http_open_timeout
|
93
96
|
|
94
97
|
if @config.debug_http
|
95
98
|
http.set_debug_output(@config.logger)
|
@@ -32,7 +32,7 @@ module ElasticAPM
|
|
32
32
|
|
33
33
|
@transaction_info = TransactionInfo.new
|
34
34
|
|
35
|
-
@subscriber = subscriber_class.new(
|
35
|
+
@subscriber = subscriber_class.new(config)
|
36
36
|
|
37
37
|
@pending_transactions = []
|
38
38
|
@last_sent_transactions = Time.now.utc
|
@@ -92,6 +92,10 @@ module ElasticAPM
|
|
92
92
|
transaction.context.custom.merge!(context)
|
93
93
|
end
|
94
94
|
|
95
|
+
def set_user(user)
|
96
|
+
transaction.context.user = Context::User.new(config, user)
|
97
|
+
end
|
98
|
+
|
95
99
|
def submit_transaction(transaction)
|
96
100
|
@pending_transactions << transaction
|
97
101
|
|
data/lib/elastic_apm/log.rb
CHANGED
@@ -26,12 +26,14 @@ module ElasticAPM
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def log(lvl, msg, *args)
|
29
|
+
return unless logger
|
30
|
+
|
29
31
|
formatted_msg = prepend_prefix(format(msg.to_s, *args))
|
30
32
|
|
31
|
-
return
|
33
|
+
return logger.send(lvl, formatted_msg) unless block_given?
|
32
34
|
|
33
35
|
# TODO: dont evaluate block if level is higher
|
34
|
-
|
36
|
+
logger.send(lvl, "#{formatted_msg}\n#{yield}")
|
35
37
|
end
|
36
38
|
|
37
39
|
private
|
@@ -40,8 +42,9 @@ module ElasticAPM
|
|
40
42
|
"#{PREFIX}#{str}"
|
41
43
|
end
|
42
44
|
|
43
|
-
def
|
44
|
-
|
45
|
+
def logger
|
46
|
+
return false unless (config = instance_variable_get(:@config))
|
47
|
+
config.logger
|
45
48
|
end
|
46
49
|
end
|
47
50
|
end
|
@@ -10,7 +10,7 @@ module ElasticAPM
|
|
10
10
|
# rubocop:disable Metrics/MethodLength
|
11
11
|
def call(env)
|
12
12
|
begin
|
13
|
-
transaction = ElasticAPM.transaction 'Rack',
|
13
|
+
transaction = ElasticAPM.transaction 'Rack', 'app',
|
14
14
|
context: ElasticAPM.build_context(env)
|
15
15
|
|
16
16
|
resp = @app.call env
|
@@ -29,14 +29,5 @@ module ElasticAPM
|
|
29
29
|
resp
|
30
30
|
end
|
31
31
|
# rubocop:enable Metrics/MethodLength
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def type_for(env)
|
36
|
-
format(
|
37
|
-
'request.%s'.freeze,
|
38
|
-
env.fetch('REQUEST_METHOD'.freeze, 'unknown'.freeze)
|
39
|
-
)
|
40
|
-
end
|
41
32
|
end
|
42
33
|
end
|
@@ -13,17 +13,7 @@ module ElasticAPM
|
|
13
13
|
result: transaction.result.to_s,
|
14
14
|
duration: ms(transaction.duration),
|
15
15
|
timestamp: micros_to_time(transaction.timestamp).utc.iso8601,
|
16
|
-
spans: transaction.spans.map
|
17
|
-
{
|
18
|
-
id: span.id,
|
19
|
-
parent: span.parent && span.parent.id,
|
20
|
-
name: span.name,
|
21
|
-
type: span.type,
|
22
|
-
start: ms(span.relative_start),
|
23
|
-
duration: ms(span.duration),
|
24
|
-
context: span.context && { db: span.context.to_h }
|
25
|
-
}
|
26
|
-
end,
|
16
|
+
spans: transaction.spans.map(&method(:build_span)),
|
27
17
|
sampled: transaction.sampled,
|
28
18
|
context: transaction.context.to_h
|
29
19
|
}
|
@@ -33,6 +23,23 @@ module ElasticAPM
|
|
33
23
|
def build_all(transactions)
|
34
24
|
{ transactions: Array(transactions).map(&method(:build)) }
|
35
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# rubocop:disable Metrics/AbcSize
|
30
|
+
def build_span(span)
|
31
|
+
{
|
32
|
+
id: span.id,
|
33
|
+
parent: span.parent && span.parent.id,
|
34
|
+
name: span.name,
|
35
|
+
type: span.type,
|
36
|
+
start: ms(span.relative_start),
|
37
|
+
duration: ms(span.duration),
|
38
|
+
context: span.context && { db: span.context.to_h },
|
39
|
+
stacktrace: span.stacktrace.to_a
|
40
|
+
}
|
41
|
+
end
|
42
|
+
# rubocop:enable Metrics/AbcSize
|
36
43
|
end
|
37
44
|
end
|
38
45
|
end
|
@@ -7,13 +7,11 @@ module ElasticAPM
|
|
7
7
|
@config = config
|
8
8
|
end
|
9
9
|
|
10
|
-
attr_reader :config
|
11
|
-
|
12
10
|
# rubocop:disable Metrics/MethodLength
|
13
11
|
def build
|
14
12
|
base = {
|
15
|
-
name: config.app_name,
|
16
|
-
environment: config.environment,
|
13
|
+
name: @config.app_name,
|
14
|
+
environment: @config.environment,
|
17
15
|
agent: {
|
18
16
|
name: 'ruby',
|
19
17
|
version: VERSION
|
@@ -27,10 +25,10 @@ module ElasticAPM
|
|
27
25
|
version: git_sha
|
28
26
|
}
|
29
27
|
|
30
|
-
if config.framework_name
|
28
|
+
if @config.framework_name
|
31
29
|
base[:framework] = {
|
32
|
-
name: config.framework_name,
|
33
|
-
version: config.framework_version
|
30
|
+
name: @config.framework_name,
|
31
|
+
version: @config.framework_version
|
34
32
|
}
|
35
33
|
end
|
36
34
|
|
data/lib/elastic_apm/span.rb
CHANGED
@@ -22,10 +22,11 @@ module ElasticAPM
|
|
22
22
|
@type = type
|
23
23
|
@parent = parent
|
24
24
|
@context = context
|
25
|
+
@stacktrace = nil
|
25
26
|
end
|
26
27
|
# rubocop:enable Metrics/ParameterLists
|
27
28
|
|
28
|
-
attr_accessor :name, :context, :type
|
29
|
+
attr_accessor :name, :context, :type, :stacktrace
|
29
30
|
attr_reader :id, :duration, :parent, :relative_start
|
30
31
|
|
31
32
|
def start
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'elastic_apm/util/lru_cache'
|
4
|
+
|
3
5
|
module ElasticAPM
|
4
6
|
# @api private
|
5
7
|
class SqlSummarizer
|
@@ -10,15 +12,17 @@ module ElasticAPM
|
|
10
12
|
/^DELETE FROM ([^ ]+)/i => 'DELETE FROM '
|
11
13
|
}.freeze
|
12
14
|
|
15
|
+
FORMAT = '%s%s'.freeze
|
16
|
+
|
13
17
|
def self.cache
|
14
|
-
@cache ||=
|
18
|
+
@cache ||= Util::LruCache.new
|
15
19
|
end
|
16
20
|
|
17
21
|
def summarize(sql)
|
18
22
|
self.class.cache[sql] ||=
|
19
23
|
REGEXES.find do |regex, sig|
|
20
24
|
if (match = sql.match(regex))
|
21
|
-
break format(
|
25
|
+
break format(FORMAT, sig, match[1].gsub(/["']/, ''))
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
@@ -1,27 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'elastic_apm/stacktrace/frame'
|
4
|
+
require 'elastic_apm/stacktrace/line_cache'
|
4
5
|
|
5
6
|
module ElasticAPM
|
6
7
|
# @api private
|
7
8
|
class Stacktrace
|
9
|
+
GEMS_REGEX = %r{/gems/}
|
10
|
+
|
8
11
|
def initialize(backtrace)
|
9
12
|
@backtrace = backtrace
|
10
13
|
end
|
11
14
|
|
12
15
|
attr_reader :frames
|
13
16
|
|
14
|
-
def self.build(
|
17
|
+
def self.build(config, backtrace)
|
15
18
|
return nil unless backtrace
|
16
19
|
|
17
20
|
stack = new(backtrace)
|
18
|
-
stack.build_frames(
|
21
|
+
stack.build_frames(config)
|
19
22
|
stack
|
20
23
|
end
|
21
24
|
|
22
|
-
def build_frames(
|
23
|
-
@frames = @backtrace.
|
24
|
-
build_frame(
|
25
|
+
def build_frames(config)
|
26
|
+
@frames = @backtrace.map do |line|
|
27
|
+
build_frame(config, line)
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|
@@ -53,7 +56,7 @@ module ElasticAPM
|
|
53
56
|
[file, number, method, module_name]
|
54
57
|
end
|
55
58
|
|
56
|
-
def build_frame(
|
59
|
+
def build_frame(config, line)
|
57
60
|
abs_path, lineno, function, _module_name = parse_line(line)
|
58
61
|
|
59
62
|
frame = Frame.new
|
@@ -62,6 +65,8 @@ module ElasticAPM
|
|
62
65
|
frame.function = function
|
63
66
|
frame.lineno = lineno.to_i
|
64
67
|
frame.build_context 3
|
68
|
+
frame.library_frame =
|
69
|
+
!(abs_path && abs_path.start_with?(config.root_path))
|
65
70
|
|
66
71
|
frame
|
67
72
|
end
|
@@ -14,30 +14,32 @@ module ElasticAPM
|
|
14
14
|
:pre_context,
|
15
15
|
:context_line,
|
16
16
|
:post_context,
|
17
|
-
:
|
17
|
+
:library_frame,
|
18
18
|
:lineno,
|
19
19
|
:module,
|
20
20
|
:colno
|
21
21
|
)
|
22
22
|
|
23
|
-
# rubocop:disable Metrics/AbcSize
|
24
23
|
def build_context(context_line_count)
|
25
24
|
return unless abs_path
|
26
25
|
|
27
|
-
|
26
|
+
from = (lineno - context_line_count - 1)
|
27
|
+
to = (lineno + context_line_count)
|
28
|
+
file_lines = read_lines(abs_path, from..to)
|
28
29
|
|
29
|
-
self.context_line = file_lines[
|
30
|
-
self.pre_context
|
31
|
-
|
32
|
-
self.post_context =
|
33
|
-
file_lines[(lineno + 1)..(lineno + context_line_count)]
|
30
|
+
self.context_line = file_lines[context_line_count]
|
31
|
+
self.pre_context = file_lines.first(context_line_count)
|
32
|
+
self.post_context = file_lines.last(context_line_count)
|
34
33
|
end
|
35
|
-
# rubocop:enable Metrics/AbcSize
|
36
34
|
|
37
35
|
private
|
38
36
|
|
39
|
-
def read_lines(path)
|
40
|
-
|
37
|
+
def read_lines(path, range)
|
38
|
+
if (cached = LineCache.get(path, range))
|
39
|
+
return cached
|
40
|
+
end
|
41
|
+
|
42
|
+
LineCache.set(path, range, File.readlines(path)[range])
|
41
43
|
rescue Errno::ENOENT
|
42
44
|
[]
|
43
45
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'elastic_apm/util/lru_cache'
|
4
|
+
|
5
|
+
module ElasticAPM
|
6
|
+
class Stacktrace
|
7
|
+
# A basic LRU Cache
|
8
|
+
# @api private
|
9
|
+
class LineCache
|
10
|
+
class << self
|
11
|
+
def cache
|
12
|
+
@cache ||= Util::LruCache.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def get(*key)
|
16
|
+
cache[key]
|
17
|
+
end
|
18
|
+
|
19
|
+
def set(*key, value)
|
20
|
+
cache[key] = value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -8,14 +8,12 @@ module ElasticAPM
|
|
8
8
|
class Subscriber
|
9
9
|
include Log
|
10
10
|
|
11
|
-
def initialize(agent)
|
11
|
+
def initialize(config, agent: ElasticAPM)
|
12
|
+
@config = config
|
12
13
|
@agent = agent
|
13
|
-
@config = agent.config
|
14
14
|
@normalizers = Normalizers.build(config)
|
15
15
|
end
|
16
16
|
|
17
|
-
attr_reader :config
|
18
|
-
|
19
17
|
def register!
|
20
18
|
unregister! if @subscription
|
21
19
|
|
@@ -43,7 +41,7 @@ module ElasticAPM
|
|
43
41
|
nil
|
44
42
|
else
|
45
43
|
name, type, context = normalized
|
46
|
-
|
44
|
+
@agent.span(name, type, context: context)
|
47
45
|
end
|
48
46
|
|
49
47
|
transaction.notifications << Notification.new(id, span)
|
@@ -28,7 +28,7 @@ module ElasticAPM
|
|
28
28
|
|
29
29
|
attr_accessor :id, :name, :result, :type
|
30
30
|
attr_reader :context, :duration, :root_span, :timestamp, :spans,
|
31
|
-
:notifications, :sampled
|
31
|
+
:notifications, :sampled, :instrumenter
|
32
32
|
|
33
33
|
def release
|
34
34
|
@instrumenter.current_transaction = nil
|
@@ -61,9 +61,14 @@ module ElasticAPM
|
|
61
61
|
spans.select(&:running?)
|
62
62
|
end
|
63
63
|
|
64
|
-
|
64
|
+
# rubocop:disable Metrics/MethodLength
|
65
|
+
def span(name, type = nil, backtrace: nil, context: nil)
|
65
66
|
span = next_span(name, type, context)
|
66
67
|
spans << span
|
68
|
+
|
69
|
+
span.stacktrace =
|
70
|
+
backtrace && Stacktrace.build(@instrumenter.config, backtrace)
|
71
|
+
|
67
72
|
span.start
|
68
73
|
|
69
74
|
return span unless block_given?
|
@@ -76,6 +81,7 @@ module ElasticAPM
|
|
76
81
|
|
77
82
|
result
|
78
83
|
end
|
84
|
+
# rubocop:enable Metrics/MethodLength
|
79
85
|
|
80
86
|
def current_span
|
81
87
|
spans.reverse.lazy.find(&:running?)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Monkeypatch/backport/polyfill Enumerable#dig to Ruby < 2.3
|
2
|
+
#
|
3
|
+
# Implementation from
|
4
|
+
# https://github.com/Invoca/ruby_dig/blob/master/lib/ruby_dig.rb
|
5
|
+
|
6
|
+
# @api private
|
7
|
+
module RubyDig
|
8
|
+
def dig(key, *rest)
|
9
|
+
value = self[key]
|
10
|
+
|
11
|
+
if value.nil? || rest.empty?
|
12
|
+
value
|
13
|
+
elsif value.respond_to?(:dig)
|
14
|
+
value.dig(*rest)
|
15
|
+
else
|
16
|
+
raise TypeError, "#{value.class} does not respond to `#dig'"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
if RUBY_VERSION < '2.3'
|
22
|
+
# @api private
|
23
|
+
class Array
|
24
|
+
include RubyDig
|
25
|
+
end
|
26
|
+
|
27
|
+
# @api private
|
28
|
+
class Hash
|
29
|
+
include RubyDig
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ElasticAPM
|
4
|
+
module Util
|
5
|
+
# @api private
|
6
|
+
class LruCache
|
7
|
+
def initialize(max_size = 512)
|
8
|
+
@max_size = max_size
|
9
|
+
@data = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](key)
|
13
|
+
found = true
|
14
|
+
value = @data.delete(key) { found = false }
|
15
|
+
|
16
|
+
found ? @data[key] = value : nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(key, val)
|
20
|
+
@data.delete(key)
|
21
|
+
@data[key] = val
|
22
|
+
|
23
|
+
return unless @data.length > @max_size
|
24
|
+
|
25
|
+
@data.delete(@data.first[0])
|
26
|
+
end
|
27
|
+
|
28
|
+
def length
|
29
|
+
@data.length
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_a
|
33
|
+
@data.to_a
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/elastic_apm/version.rb
CHANGED
data/lib/elastic_apm/worker.rb
CHANGED
@@ -16,14 +16,12 @@ module ElasticAPM
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def initialize(config, queue,
|
19
|
+
def initialize(config, queue, adapter)
|
20
20
|
@config = config
|
21
|
-
@adapter =
|
21
|
+
@adapter = adapter
|
22
22
|
@queue = queue
|
23
23
|
end
|
24
24
|
|
25
|
-
attr_reader :config
|
26
|
-
|
27
25
|
def run_forever
|
28
26
|
loop do
|
29
27
|
while (item = @queue.pop)
|
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.
|
4
|
+
version: 0.3.0
|
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-01-
|
11
|
+
date: 2018-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -66,6 +66,9 @@ files:
|
|
66
66
|
- lib/elastic_apm/error/exception.rb
|
67
67
|
- lib/elastic_apm/error/log.rb
|
68
68
|
- lib/elastic_apm/error_builder.rb
|
69
|
+
- lib/elastic_apm/filters.rb
|
70
|
+
- lib/elastic_apm/filters/request_body_filter.rb
|
71
|
+
- lib/elastic_apm/filters/secrets_filter.rb
|
69
72
|
- lib/elastic_apm/http.rb
|
70
73
|
- lib/elastic_apm/injectors.rb
|
71
74
|
- lib/elastic_apm/injectors/action_dispatch.rb
|
@@ -96,11 +99,14 @@ files:
|
|
96
99
|
- lib/elastic_apm/sql_summarizer.rb
|
97
100
|
- lib/elastic_apm/stacktrace.rb
|
98
101
|
- lib/elastic_apm/stacktrace/frame.rb
|
102
|
+
- lib/elastic_apm/stacktrace/line_cache.rb
|
99
103
|
- lib/elastic_apm/subscriber.rb
|
100
104
|
- lib/elastic_apm/system_info.rb
|
101
105
|
- lib/elastic_apm/transaction.rb
|
102
106
|
- lib/elastic_apm/util.rb
|
107
|
+
- lib/elastic_apm/util/dig.rb
|
103
108
|
- lib/elastic_apm/util/inspector.rb
|
109
|
+
- lib/elastic_apm/util/lru_cache.rb
|
104
110
|
- lib/elastic_apm/version.rb
|
105
111
|
- lib/elastic_apm/worker.rb
|
106
112
|
- vendor/.gitkeep
|