appoptics_apm 4.1.2 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +8 -6
- data/Dockerfile_test +4 -2
- data/Rakefile +15 -4
- data/appoptics_apm.gemspec +3 -1
- data/examples/DNT.md +35 -0
- data/examples/carrying_context.rb +220 -0
- data/examples/instrumenting_metal_controller.rb +8 -0
- data/examples/puma_on_heroku_config.rb +17 -0
- data/examples/tracing_async_threads.rb +124 -0
- data/examples/tracing_background_jobs.rb +53 -0
- data/examples/tracing_forked_processes.rb +99 -0
- data/examples/unicorn_on_heroku_config.rb +28 -0
- data/ext/oboe_metal/src/VERSION +1 -1
- data/lib/appoptics_apm.rb +2 -0
- data/lib/appoptics_apm/api/logging.rb +13 -12
- data/lib/appoptics_apm/api/tracing.rb +28 -1
- data/lib/appoptics_apm/base.rb +7 -1
- data/lib/appoptics_apm/config.rb +15 -13
- data/lib/appoptics_apm/frameworks/grape.rb +7 -6
- data/lib/appoptics_apm/inst/rack.rb +102 -69
- data/lib/appoptics_apm/noop/README.md +9 -0
- data/lib/appoptics_apm/noop/context.rb +19 -0
- data/lib/appoptics_apm/support.rb +17 -18
- data/lib/appoptics_apm/version.rb +2 -2
- data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +8 -0
- data/run_tests_docker.rb +0 -6
- metadata +12 -2
@@ -26,6 +26,26 @@ if AppOpticsAPM.loaded
|
|
26
26
|
@app = app
|
27
27
|
end
|
28
28
|
|
29
|
+
def call(env)
|
30
|
+
# In the case of nested Ruby apps such as Grape inside of Rails
|
31
|
+
# or Grape inside of Grape, each app has it's own instance
|
32
|
+
# of rack middleware. We avoid tracing rack more than once and
|
33
|
+
# instead start instrumenting from the first rack pass.
|
34
|
+
return call_app(env) if AppOpticsAPM.tracing? && AppOpticsAPM.layer == :rack
|
35
|
+
|
36
|
+
# if we already have a context, we don't want to send metrics in the end
|
37
|
+
return sampling_call(env) if AppOpticsAPM::Context.isValid
|
38
|
+
|
39
|
+
# else we also send metrics
|
40
|
+
metrics_sampling_call(env)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.noop?
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
29
49
|
def collect(req, env)
|
30
50
|
report_kvs = {}
|
31
51
|
|
@@ -61,92 +81,105 @@ if AppOpticsAPM.loaded
|
|
61
81
|
report_kvs
|
62
82
|
end
|
63
83
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
req_url = req.url # saving it here because rails3.2 overrides it when there is a 500 error
|
69
|
-
|
70
|
-
# In the case of nested Ruby apps such as Grape inside of Rails
|
71
|
-
# or Grape inside of Grape, each app has it's own instance
|
72
|
-
# of rack middleware. We avoid tracing rack more than once and
|
73
|
-
# instead start instrumenting from the first rack pass.
|
74
|
-
if AppOpticsAPM.tracing? && AppOpticsAPM.layer == :rack
|
75
|
-
AppOpticsAPM.logger.debug "[appoptics_apm/rack] Rack skipped!"
|
76
|
-
return @app.call(env)
|
77
|
-
end
|
78
|
-
|
79
|
-
begin
|
80
|
-
report_kvs = {}
|
84
|
+
def call_app(env)
|
85
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/rack] Rack skipped!"
|
86
|
+
@app.call(env)
|
87
|
+
end
|
81
88
|
|
82
|
-
|
89
|
+
# in this case we have an existing context
|
90
|
+
def sampling_call(env)
|
91
|
+
req = ::Rack::Request.new(env)
|
92
|
+
report_kvs = {}
|
93
|
+
report_kvs[:URL] = AppOpticsAPM::Config[:rack][:log_args] ? ::CGI.unescape(req.fullpath) : ::CGI.unescape(req.path)
|
83
94
|
|
84
|
-
|
85
|
-
|
86
|
-
xtrace_header = AppOpticsAPM::XTrace.valid?(xtrace) ? xtrace : nil
|
95
|
+
AppOpticsAPM::API.trace(:rack, report_kvs) do
|
96
|
+
report_kvs = collect(req, env)
|
87
97
|
|
88
|
-
#
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
AppOpticsAPM.
|
98
|
+
# We log an info event with the HTTP KVs found in AppOpticsAPM::Rack.collect
|
99
|
+
# This is done here so in the case of stacks that try/catch/abort
|
100
|
+
# (looking at you Grape) we're sure the KVs get reported now as
|
101
|
+
# this code may not be returned to later.
|
102
|
+
AppOpticsAPM::API.log_info(:rack, report_kvs)
|
103
|
+
@app.call(env)
|
104
|
+
end
|
105
|
+
end
|
93
106
|
|
94
|
-
|
107
|
+
def metrics_sampling_call(env)
|
108
|
+
start = Time.now
|
109
|
+
AppOpticsAPM.transaction_name = nil
|
110
|
+
req = ::Rack::Request.new(env)
|
111
|
+
req_url = req.url # saving it here because rails3.2 overrides it when there is a 500 error
|
95
112
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
113
|
+
report_kvs = {}
|
114
|
+
report_kvs[:URL] = AppOpticsAPM::Config[:rack][:log_args] ? ::CGI.unescape(req.fullpath) : ::CGI.unescape(req.path)
|
115
|
+
|
116
|
+
# Check for and validate X-Trace request header to pick up tracing context
|
117
|
+
xtrace = env.is_a?(Hash) ? env['HTTP_X_TRACE'] : nil
|
118
|
+
xtrace = AppOpticsAPM::XTrace.valid?(xtrace) ? xtrace : nil
|
119
|
+
|
120
|
+
# TODO JRUBY
|
121
|
+
# Under JRuby, JAppOpticsAPM may have already started a trace. Make note of this
|
122
|
+
# if so and don't clear context on log_end (see appoptics_apm/api/logging.rb)
|
123
|
+
# AppOpticsAPM.has_incoming_context = AppOpticsAPM.tracing?
|
124
|
+
# AppOpticsAPM.has_xtrace_header = xtrace
|
125
|
+
# AppOpticsAPM.is_continued_trace = AppOpticsAPM.has_incoming_context || AppOpticsAPM.has_xtrace_header
|
126
|
+
|
127
|
+
AppOpticsAPM::API.log_start(:rack, xtrace, report_kvs) unless ::AppOpticsAPM::Util.static_asset?(env['PATH_INFO'])
|
128
|
+
|
129
|
+
# We log an info event with the HTTP KVs found in AppOpticsAPM::Rack.collect
|
130
|
+
# This is done here so in the case of stacks that try/catch/abort
|
131
|
+
# (looking at you Grape) we're sure the KVs get reported now as
|
132
|
+
# this code may not be returned to later.
|
133
|
+
AppOpticsAPM::API.log_info(:rack, collect(req, env))
|
134
|
+
|
135
|
+
status, headers, response = @app.call(env)
|
136
|
+
confirmed_transaction_name = send_metrics(env, req, req_url, start, status)
|
137
|
+
xtrace = AppOpticsAPM::API.log_end(:rack, :Status => status, :TransactionName => confirmed_transaction_name)
|
138
|
+
|
139
|
+
if headers && AppOpticsAPM::XTrace.valid?(xtrace)
|
140
|
+
# TODO revisit this JRUBY condition
|
141
|
+
# headers['X-Trace'] = xtrace if headers.is_a?(Hash) unless defined?(JRUBY_VERSION) && AppOpticsAPM.is_continued_trace?
|
142
|
+
headers['X-Trace'] = xtrace if headers.is_a?(Hash) unless defined?(JRUBY_VERSION) && AppOpticsAPM.is_continued_trace?
|
143
|
+
end
|
100
144
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
145
|
+
[status, headers, response]
|
146
|
+
rescue Exception => e
|
147
|
+
# it is ok to rescue Exception here because we are reraising it (we just need a chance to log_end)
|
148
|
+
AppOpticsAPM::API.log_exception(:rack, e)
|
149
|
+
confirmed_transaction_name ||= send_metrics(env, req, req_url, start, status)
|
150
|
+
xtrace = AppOpticsAPM::API.log_end(:rack, :Status => status, :TransactionName => confirmed_transaction_name)
|
151
|
+
|
152
|
+
if headers && AppOpticsAPM::XTrace.valid?(xtrace)
|
153
|
+
# TODO revisit this JRUBY condition
|
154
|
+
# headers['X-Trace'] = xtrace if headers.is_a?(Hash) unless defined?(JRUBY_VERSION) && AppOpticsAPM.is_continued_trace?
|
155
|
+
headers['X-Trace'] = xtrace if headers.is_a?(Hash) unless defined?(JRUBY_VERSION) && AppOpticsAPM.is_continued_trace?
|
156
|
+
end
|
106
157
|
|
107
|
-
|
158
|
+
raise
|
159
|
+
end
|
108
160
|
|
109
|
-
xtrace = AppOpticsAPM::API.log_end(:rack, :Status => status)
|
110
161
|
|
111
|
-
|
112
|
-
|
113
|
-
end
|
162
|
+
def send_metrics(env, req, req_url, start, status)
|
163
|
+
return if ::AppOpticsAPM::Util.static_asset?(env['PATH_INFO'])
|
114
164
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
if AppOpticsAPM.tracing?
|
119
|
-
AppOpticsAPM::API.log_exception(:rack, e)
|
120
|
-
xtrace = AppOpticsAPM::API.log_end(:rack, :Status => 500, 'TransactionName' => transaction_name(env))
|
121
|
-
end
|
122
|
-
raise
|
123
|
-
ensure
|
124
|
-
if headers && AppOpticsAPM::XTrace.valid?(xtrace)
|
125
|
-
unless defined?(JRUBY_VERSION) && AppOpticsAPM.is_continued_trace?
|
126
|
-
headers['X-Trace'] = xtrace if headers.is_a?(Hash)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
ensure
|
131
|
-
unless ::AppOpticsAPM::Util.static_asset?(env['PATH_INFO'])
|
132
|
-
status = status.to_i
|
133
|
-
error = status.between?(500,599) ? 1 : 0
|
134
|
-
duration =(1000 * 1000 * (Time.now - start)).round(0)
|
135
|
-
AppOpticsAPM::Span.createHttpSpan(transaction_name(env), req_url, duration, status, req.request_method, error)
|
165
|
+
domain = nil
|
166
|
+
if AppOpticsAPM::Config['transaction_name']['prepend_domain']
|
167
|
+
domain = [80, 443].include?(req.port) ? req.host : "#{req.host}:#{req.port}"
|
136
168
|
end
|
169
|
+
status = status.to_i
|
170
|
+
error = status.between?(500,599) ? 1 : 0
|
171
|
+
duration =(1000 * 1000 * (Time.now - start)).round(0)
|
172
|
+
AppOpticsAPM::Span.createHttpSpan(transaction_name(env), req_url, domain, duration, status, req.request_method, error) || ''
|
137
173
|
end
|
138
174
|
|
139
|
-
def self.noop?
|
140
|
-
false
|
141
|
-
end
|
142
|
-
|
143
|
-
private
|
144
|
-
|
145
175
|
def transaction_name(env)
|
146
|
-
if
|
176
|
+
if AppOpticsAPM.transaction_name
|
177
|
+
AppOpticsAPM.transaction_name
|
178
|
+
elsif env['appoptics_apm.controller'] || env['appoptics_apm.action']
|
147
179
|
[env['appoptics_apm.controller'], env['appoptics_apm.action']].join('.')
|
148
180
|
end
|
149
181
|
end
|
182
|
+
|
150
183
|
end
|
151
184
|
end
|
152
185
|
else
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Here we can define modules and classes for noop mode.
|
2
|
+
|
3
|
+
Instead of polluting code with AppOpticsAPM.loaded conditionals
|
4
|
+
|
5
|
+
we load these classes when in noop mode and they expose noop behavior.
|
6
|
+
|
7
|
+
so far only one class is needed:
|
8
|
+
|
9
|
+
- AppOpticsAPM::Context and its toString() method from oboe
|
@@ -0,0 +1,19 @@
|
|
1
|
+
####
|
2
|
+
# noop version of AppOpticsAPM::Context
|
3
|
+
#
|
4
|
+
#
|
5
|
+
|
6
|
+
module AppOpticsAPM
|
7
|
+
module Context
|
8
|
+
|
9
|
+
##
|
10
|
+
# noop version of toString
|
11
|
+
# toString would return the current context (xtrace) as string
|
12
|
+
#
|
13
|
+
# the noop version returns an empty string
|
14
|
+
#
|
15
|
+
def self.toString
|
16
|
+
''
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -81,28 +81,27 @@ module AppOpticsAPM
|
|
81
81
|
AppOpticsAPM.logger.warn 'No ActiveRecord'
|
82
82
|
end
|
83
83
|
|
84
|
-
|
85
|
-
AppOpticsAPM.logger.warn '
|
86
|
-
AppOpticsAPM.logger.warn '
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
84
|
+
# TODO we don't have libs in /usr/lib anymore, is this still needed???
|
85
|
+
# AppOpticsAPM.logger.warn '********************************************************'
|
86
|
+
# AppOpticsAPM.logger.warn '* AppOpticsAPM Libraries'
|
87
|
+
# AppOpticsAPM.logger.warn '********************************************************'
|
88
|
+
# files = []
|
89
|
+
# ['/usr/lib/liboboe*', '/usr/lib64/liboboe*'].each do |d|
|
90
|
+
# files = Dir.glob(d)
|
91
|
+
# break if !files.empty?
|
92
|
+
# end
|
93
|
+
# if files.empty?
|
94
|
+
# AppOpticsAPM.logger.warn 'Error: No liboboe libs!'
|
95
|
+
# else
|
96
|
+
# files.each { |f|
|
97
|
+
# AppOpticsAPM.logger.warn f
|
98
|
+
# }
|
99
|
+
# end
|
99
100
|
|
100
101
|
AppOpticsAPM.logger.warn '********************************************************'
|
101
102
|
AppOpticsAPM.logger.warn '* AppOpticsAPM::Config Values'
|
102
103
|
AppOpticsAPM.logger.warn '********************************************************'
|
103
|
-
AppOpticsAPM::Config.
|
104
|
-
AppOpticsAPM.logger.warn "#{k}: #{v}"
|
105
|
-
}
|
104
|
+
AppOpticsAPM::Config.print_config
|
106
105
|
|
107
106
|
AppOpticsAPM.logger.warn '********************************************************'
|
108
107
|
AppOpticsAPM.logger.warn '* OS, Platform + Env'
|
@@ -21,7 +21,15 @@ if defined?(AppOpticsAPM::Config)
|
|
21
21
|
# Verbose output of instrumentation initialization
|
22
22
|
#
|
23
23
|
AppOpticsAPM::Config[:verbose] = ENV.key?('APPOPTICS_GEM_VERBOSE') && ENV['APPOPTICS_GEM_VERBOSE'] == 'true' ? true : false
|
24
|
+
|
25
|
+
#
|
26
|
+
# Prepend domain to transaction name
|
27
|
+
#
|
28
|
+
# If this is set to `true` transaction names will be composed as `my.host.com/controller.action` instead of
|
29
|
+
# `controller.action`. This configuration applies to all transaction names, whether decducted by the instrumentation
|
30
|
+
# or implicitly set.
|
24
31
|
#
|
32
|
+
AppOpticsAPM::Config[:transaction_name][:prepend_domain] = false
|
25
33
|
|
26
34
|
#
|
27
35
|
# Sanitize SQL Statements
|
data/run_tests_docker.rb
CHANGED
@@ -7,10 +7,6 @@
|
|
7
7
|
|
8
8
|
# `docker build -f Dockerfile -t ruby_appoptics .`
|
9
9
|
# (docker-compose will build it too if missing)
|
10
|
-
#
|
11
|
-
# `docker-compose up -d`
|
12
|
-
# or to rebuild ruby_appoptics
|
13
|
-
# `docker-compose up --build -d`
|
14
10
|
|
15
11
|
require 'yaml'
|
16
12
|
travis = YAML.load_file('.travis.yml')
|
@@ -34,5 +30,3 @@ matrix.each do |args|
|
|
34
30
|
`docker-compose run --rm --service-ports ruby_appoptics_apm /code/ruby-appoptics_apm/ruby_setup.sh #{args['rvm']} #{args['gemfile']} #{args['env']}`
|
35
31
|
puts "docker-compose run --rm --service-ports ruby_appoptics_apm /code/ruby-appoptics_apm/ruby_setup.sh #{args['rvm']} #{args['gemfile']} #{args['env']}"
|
36
32
|
end
|
37
|
-
|
38
|
-
# `docker-compose down --rmi all`
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appoptics_apm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maia Engeli
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-05-
|
13
|
+
date: 2018-05-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -133,6 +133,14 @@ files:
|
|
133
133
|
- build_gems.sh
|
134
134
|
- config/initializers/.keep
|
135
135
|
- docker-compose.yml
|
136
|
+
- examples/DNT.md
|
137
|
+
- examples/carrying_context.rb
|
138
|
+
- examples/instrumenting_metal_controller.rb
|
139
|
+
- examples/puma_on_heroku_config.rb
|
140
|
+
- examples/tracing_async_threads.rb
|
141
|
+
- examples/tracing_background_jobs.rb
|
142
|
+
- examples/tracing_forked_processes.rb
|
143
|
+
- examples/unicorn_on_heroku_config.rb
|
136
144
|
- ext/oboe_metal/extconf.rb
|
137
145
|
- ext/oboe_metal/lib/.keep
|
138
146
|
- ext/oboe_metal/noop/noop.c
|
@@ -204,6 +212,8 @@ files:
|
|
204
212
|
- lib/appoptics_apm/loading.rb
|
205
213
|
- lib/appoptics_apm/logger.rb
|
206
214
|
- lib/appoptics_apm/method_profiling.rb
|
215
|
+
- lib/appoptics_apm/noop/README.md
|
216
|
+
- lib/appoptics_apm/noop/context.rb
|
207
217
|
- lib/appoptics_apm/ruby.rb
|
208
218
|
- lib/appoptics_apm/support.rb
|
209
219
|
- lib/appoptics_apm/test.rb
|