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.
@@ -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 call(env)
65
- start = Time.now
66
- status = 500
67
- req = ::Rack::Request.new(env)
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
- report_kvs[:URL] = AppOpticsAPM::Config[:rack][:log_args] ? ::CGI.unescape(req.fullpath) : ::CGI.unescape(req.path)
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
- # Check for and validate X-Trace request header to pick up tracing context
85
- xtrace = env.is_a?(Hash) ? env['HTTP_X_TRACE'] : nil
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
- # Under JRuby, JAppOpticsAPM may have already started a trace. Make note of this
89
- # if so and don't clear context on log_end (see appoptics_apm/api/logging.rb)
90
- AppOpticsAPM.has_incoming_context = AppOpticsAPM.tracing?
91
- AppOpticsAPM.has_xtrace_header = xtrace_header
92
- AppOpticsAPM.is_continued_trace = AppOpticsAPM.has_incoming_context || AppOpticsAPM.has_xtrace_header
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
- xtrace = AppOpticsAPM::API.log_start(:rack, xtrace_header, report_kvs)
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
- # We only trace a subset of requests based off of sample rate so if
97
- # AppOpticsAPM::API.log_start really did start a trace, we act accordingly here.
98
- if AppOpticsAPM.tracing?
99
- report_kvs = collect(req, env)
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
- # We log an info event with the HTTP KVs found in AppOpticsAPM::Rack.collect
102
- # This is done here so in the case of stacks that try/catch/abort
103
- # (looking at you Grape) we're sure the KVs get reported now as
104
- # this code may not be returned to later.
105
- AppOpticsAPM::API.log_info(:rack, report_kvs)
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
- status, headers, response = @app.call(env)
158
+ raise
159
+ end
108
160
 
109
- xtrace = AppOpticsAPM::API.log_end(:rack, :Status => status)
110
161
 
111
- else
112
- status, headers, response = @app.call(env)
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
- [status, headers, response]
116
- rescue Exception => e
117
- # it is ok to rescue Exception here because we are reraising it (we just need a chance to log_end)
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 env['appoptics_apm.controller'] || env['appoptics_apm.action']
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
- AppOpticsAPM.logger.warn '********************************************************'
85
- AppOpticsAPM.logger.warn '* AppOpticsAPM Libraries'
86
- AppOpticsAPM.logger.warn '********************************************************'
87
- files = []
88
- ['/usr/lib/liboboe*', '/usr/lib64/liboboe*'].each do |d|
89
- files = Dir.glob(d)
90
- break if !files.empty?
91
- end
92
- if files.empty?
93
- AppOpticsAPM.logger.warn 'Error: No liboboe libs!'
94
- else
95
- files.each { |f|
96
- AppOpticsAPM.logger.warn f
97
- }
98
- end
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.config.each { |k,v|
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'
@@ -7,8 +7,8 @@ module AppOpticsAPM
7
7
  # appoptics_apm.gemspec during gem build process
8
8
  module Version
9
9
  MAJOR = 4
10
- MINOR = 1
11
- PATCH = 2
10
+ MINOR = 2
11
+ PATCH = 0
12
12
 
13
13
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
14
14
  end
@@ -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.1.2
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-09 00:00:00.000000000 Z
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