oneapm_rpm 1.3.6 → 1.3.7.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +8 -8
  2. data/lib/one_apm/agent/agent/start_worker_thread.rb +8 -8
  3. data/lib/one_apm/agent/cross_app/cross_app_monitor.rb +2 -2
  4. data/lib/one_apm/agent/cross_app/cross_app_tracing.rb +2 -2
  5. data/lib/one_apm/agent/database.rb +17 -17
  6. data/lib/one_apm/agent/database/obfuscation_helpers.rb +13 -13
  7. data/lib/one_apm/agent/database/obfuscator.rb +5 -5
  8. data/lib/one_apm/agent/database/postgres_explain_obfuscator.rb +4 -4
  9. data/lib/one_apm/agent/datastore/metric_helper.rb +12 -12
  10. data/lib/one_apm/agent/datastore/mongo/command_formatter.rb +6 -6
  11. data/lib/one_apm/agent/datastore/mongo/metric_translator.rb +6 -6
  12. data/lib/one_apm/agent/datastore/mongo/obfuscator.rb +2 -2
  13. data/lib/one_apm/agent/datastore/mongo/statement_formatter.rb +4 -4
  14. data/lib/one_apm/agent/javascript_instrumentor.rb +22 -22
  15. data/lib/one_apm/agent/synthetics_monitor.rb +7 -7
  16. data/lib/one_apm/agent/threading/thread_profile.rb +2 -2
  17. data/lib/one_apm/collector/collector/http_connection.rb +4 -4
  18. data/lib/one_apm/collector/collector_service.rb +1 -1
  19. data/lib/one_apm/collector/commands/thread_profiler_session.rb +4 -4
  20. data/lib/one_apm/collector/containers/agent_command_router.rb +4 -4
  21. data/lib/one_apm/collector/containers/custom_event_aggregator.rb +10 -10
  22. data/lib/one_apm/collector/containers/error_collector.rb +4 -4
  23. data/lib/one_apm/collector/containers/sql_sampler.rb +2 -2
  24. data/lib/one_apm/collector/containers/transaction_event_aggregator.rb +36 -36
  25. data/lib/one_apm/collector/containers/transaction_sampler.rb +4 -4
  26. data/lib/one_apm/collector/containers/utilization_data.rb +1 -1
  27. data/lib/one_apm/collector/samplers/delayed_job_sampler.rb +7 -7
  28. data/lib/one_apm/collector/samplers/vm_sampler.rb +18 -18
  29. data/lib/one_apm/collector/stats_engine/gc_profiler.rb +6 -6
  30. data/lib/one_apm/collector/stats_engine/metric_stats.rb +1 -1
  31. data/lib/one_apm/collector/support/proc_poller.rb +2 -2
  32. data/lib/one_apm/configuration.rb +2 -2
  33. data/lib/one_apm/configuration/default_source.rb +2 -2
  34. data/lib/one_apm/configuration/environment_source.rb +5 -5
  35. data/lib/one_apm/configuration/high_security_source.rb +7 -7
  36. data/lib/one_apm/errors/noticed_error.rb +2 -2
  37. data/lib/one_apm/inst/dispatcher/puma.rb +7 -4
  38. data/lib/one_apm/inst/framework/grape.rb +9 -9
  39. data/lib/one_apm/inst/framework/sinatra/transaction_namer.rb +2 -2
  40. data/lib/one_apm/inst/http_clients/curb.rb +2 -2
  41. data/lib/one_apm/inst/http_clients/excon.rb +7 -7
  42. data/lib/one_apm/inst/http_clients/httpclient.rb +2 -2
  43. data/lib/one_apm/inst/http_clients/typhoeus.rb +2 -2
  44. data/lib/one_apm/inst/nosql/memcache.rb +5 -5
  45. data/lib/one_apm/inst/nosql/mongo2.rb +8 -8
  46. data/lib/one_apm/inst/orm/active_record.rb +2 -2
  47. data/lib/one_apm/inst/rails3/action_controller.rb +1 -1
  48. data/lib/one_apm/inst/rails4/action_view_subscriber.rb +2 -2
  49. data/lib/one_apm/inst/rails4/active_record_subscriber.rb +3 -3
  50. data/lib/one_apm/inst/support/queue_time.rb +14 -14
  51. data/lib/one_apm/logger/agent_logger.rb +4 -4
  52. data/lib/one_apm/metrics/metric_spec.rb +10 -10
  53. data/lib/one_apm/rack/browser_monitoring.rb +135 -144
  54. data/lib/one_apm/rack/developer_mode.rb +22 -33
  55. data/lib/one_apm/rack/developer_mode/helper.rb +1 -1
  56. data/lib/one_apm/rack/middleware_base.rb +2 -0
  57. data/lib/one_apm/rack/middleware_helper.rb +21 -0
  58. data/lib/one_apm/rack/middleware_hooks.rb +10 -8
  59. data/lib/one_apm/rack/middleware_tracing.rb +47 -44
  60. data/lib/one_apm/rack/middleware_wrapper.rb +63 -57
  61. data/lib/one_apm/support/backtrace/backtrace_node.rb +4 -4
  62. data/lib/one_apm/support/backtrace/backtrace_service.rb +7 -7
  63. data/lib/one_apm/support/collection_helper.rb +4 -4
  64. data/lib/one_apm/support/event_buffer/synthetics_event_buffer.rb +2 -2
  65. data/lib/one_apm/support/json_marshaller.rb +2 -2
  66. data/lib/one_apm/support/method_tracer.rb +2 -2
  67. data/lib/one_apm/support/method_tracer/helpers.rb +2 -2
  68. data/lib/one_apm/support/obfuscator.rb +5 -5
  69. data/lib/one_apm/support/rules_engine.rb +2 -2
  70. data/lib/one_apm/support/rules_engine/replacement_rule.rb +4 -4
  71. data/lib/one_apm/support/rules_engine/segment_terms_rule.rb +8 -8
  72. data/lib/one_apm/support/supported_versions.rb +9 -13
  73. data/lib/one_apm/support/vm/rubinius_vm.rb +1 -1
  74. data/lib/one_apm/transaction.rb +8 -8
  75. data/lib/one_apm/transaction/class_methods.rb +8 -8
  76. data/lib/one_apm/transaction/instance_helpers.rb +1 -1
  77. data/lib/one_apm/transaction/metric_constants.rb +27 -27
  78. data/lib/one_apm/transaction/sample_buffer/developer_mode_sample_buffer.rb +3 -3
  79. data/lib/one_apm/transaction/sample_buffer/force_persist_sample_buffer.rb +2 -2
  80. data/lib/one_apm/transaction/sample_buffer/slowest_sample_buffer.rb +2 -2
  81. data/lib/one_apm/transaction/sample_buffer/transaction_sample_buffer.rb +3 -3
  82. data/lib/one_apm/transaction/segment.rb +2 -2
  83. data/lib/one_apm/transaction/transaction_finish_append.rb +3 -3
  84. data/lib/one_apm/transaction/transaction_jruby_functions.rb +3 -3
  85. data/lib/one_apm/transaction/transaction_name.rb +3 -3
  86. data/lib/one_apm/transaction/transaction_namer.rb +7 -7
  87. data/lib/one_apm/transaction/transaction_sample_builder.rb +3 -3
  88. data/lib/one_apm/transaction/transaction_summary.rb +4 -4
  89. data/lib/one_apm/transaction/transaction_timings.rb +1 -1
  90. data/lib/one_apm/version.rb +3 -2
  91. metadata +3 -2
@@ -3,14 +3,14 @@
3
3
  LibraryDetection.defer do
4
4
  named :httpclient
5
5
 
6
- HTTPCLIENT_MINIMUM_VERSION = '2.2.0'
6
+ OA_HTTPCLIENT_MINIMUM_VERSION = '2.2.0'
7
7
 
8
8
  depends_on do
9
9
  defined?(HTTPClient) && defined?(HTTPClient::VERSION)
10
10
  end
11
11
 
12
12
  depends_on do
13
- minimum_supported_version = OneApm::VersionNumber.new(HTTPCLIENT_MINIMUM_VERSION)
13
+ minimum_supported_version = OneApm::VersionNumber.new(OA_HTTPCLIENT_MINIMUM_VERSION)
14
14
  current_version = OneApm::VersionNumber.new(HTTPClient::VERSION)
15
15
 
16
16
  current_version >= minimum_supported_version
@@ -48,10 +48,10 @@ end
48
48
 
49
49
  module OneApm::Agent::Instrumentation::TyphoeusTracing
50
50
 
51
- EARLIEST_VERSION = OneApm::VersionNumber.new("0.5.3")
51
+ OA_EARLIEST_VERSION = OneApm::VersionNumber.new("0.5.3")
52
52
 
53
53
  def self.is_supported_version?
54
- OneApm::VersionNumber.new(Typhoeus::VERSION) >= OneApm::Agent::Instrumentation::TyphoeusTracing::EARLIEST_VERSION
54
+ OneApm::VersionNumber.new(Typhoeus::VERSION) >= OneApm::Agent::Instrumentation::TyphoeusTracing::OA_EARLIEST_VERSION
55
55
  end
56
56
 
57
57
  def self.request_is_hydra_enabled?(request)
@@ -12,7 +12,7 @@ module OneApm
12
12
  !OneApm::Manager.config[:disable_memcache]
13
13
  end
14
14
 
15
- METHODS = [:get, :get_multi, :set, :add, :incr, :decr, :delete, :replace, :append,
15
+ OA_METHODS = [:get, :get_multi, :set, :add, :incr, :decr, :delete, :replace, :append,
16
16
  :prepend, :cas, :single_get, :multi_get, :single_cas, :multi_cas]
17
17
 
18
18
  def supported_methods_for(client_class, methods)
@@ -21,7 +21,7 @@ module OneApm
21
21
  end
22
22
  end
23
23
 
24
- def instrument_methods(client_class, requested_methods = METHODS)
24
+ def instrument_methods(client_class, requested_methods = OA_METHODS)
25
25
  supported_methods_for(client_class, requested_methods).each do |method_name|
26
26
 
27
27
  visibility = OneApm::Helper.instance_method_visibility client_class, method_name
@@ -120,15 +120,15 @@ LibraryDetection.defer do
120
120
  # re-evaluate after they've done that require.
121
121
  defined?(::Dalli::Client) &&
122
122
  ::OneApm::Agent::Instrumentation::Memcache.supported_methods_for(::Dalli::Client,
123
- CAS_CLIENT_METHODS).any?
123
+ OA_CAS_CLIENT_METHODS).any?
124
124
  end
125
125
 
126
- CAS_CLIENT_METHODS = [:get_cas, :get_multi_cas, :set_cas, :replace_cas,
126
+ OA_CAS_CLIENT_METHODS = [:get_cas, :get_multi_cas, :set_cas, :replace_cas,
127
127
  :delete_cas]
128
128
 
129
129
  executes do
130
130
  OneApm::Manager.logger.info 'Installing Dalli CAS Client Memcache instrumentation'
131
131
  ::OneApm::Agent::Instrumentation::Memcache.instrument_methods(::Dalli::Client,
132
- CAS_CLIENT_METHODS)
132
+ OA_CAS_CLIENT_METHODS)
133
133
  end
134
134
  end
@@ -5,26 +5,26 @@ module OneApm
5
5
  module Instrumentation
6
6
  class MongoCommandSubscriber
7
7
 
8
- MONGODB = 'MongoDB'.freeze
9
- STARTED = 'STARTED'.freeze
10
- SUCCEEDED = 'SUCCEEDED'.freeze
11
- FAILED = 'FAILED'.freeze
8
+ OA_MONGODB = 'MongoDB'.freeze
9
+ OA_STARTED = 'STARTED'.freeze
10
+ OA_SUCCEEDED = 'SUCCEEDED'.freeze
11
+ OA_FAILED = 'FAILED'.freeze
12
12
 
13
13
  def started(event)
14
14
  begin
15
15
  return unless OneApm::Manager.tl_is_execution_traced?
16
16
  operations[event.operation_id] = event
17
17
  rescue Exception => e
18
- log_operations_error(STARTED, e)
18
+ log_operations_error(OA_STARTED, e)
19
19
  end
20
20
  end
21
21
 
22
22
  def succeeded(event)
23
- operator SUCCEEDED, event
23
+ operator OA_SUCCEEDED, event
24
24
  end
25
25
 
26
26
  def failed(event)
27
- operator FAILED, event
27
+ operator OA_FAILED, event
28
28
  end
29
29
 
30
30
  private
@@ -35,7 +35,7 @@ module OneApm
35
35
 
36
36
  def mertircs(event)
37
37
  OneApm::Agent::Datastore::MetricHelper.metrics_for(
38
- MONGODB, event.command_name, event.command.values.first
38
+ OA_MONGODB, event.command_name, event.command.values.first
39
39
  )
40
40
  end
41
41
 
@@ -7,7 +7,7 @@ module OneApm
7
7
  module Instrumentation
8
8
  module ActiveRecord
9
9
 
10
- EXPLAINER = lambda do |config, query|
10
+ OA_EXPLAINER = lambda do |config, query|
11
11
  connection = OneApm::Agent::Database.get_connection(config) do
12
12
  ::ActiveRecord::Base.send("#{config[:adapter]}_connection", config)
13
13
  end
@@ -54,7 +54,7 @@ module OneApm
54
54
  log_without_oneapm_instrumentation(*args, &block)
55
55
  ensure
56
56
  elapsed_time = (Time.now - t0).to_f
57
- OneApm::Manager.notice_sql(sql, metric, @config, elapsed_time, state, &EXPLAINER)
57
+ OneApm::Manager.notice_sql(sql, metric, @config, elapsed_time, state, &OA_EXPLAINER)
58
58
  end
59
59
  end
60
60
  end
@@ -35,7 +35,7 @@ module OneApm
35
35
  if options[:file]
36
36
  "file"
37
37
  elsif identifier.nil?
38
- OneApm::Transaction::UNKNOWN_METRIC
38
+ OneApm::Transaction::OA_UNKNOWN_METRIC
39
39
  elsif identifier.include? '/' # this is a filepath
40
40
  identifier.split('/')[-2..-1].join('/')
41
41
  else
@@ -49,7 +49,7 @@ module OneApm
49
49
  def recordable?
50
50
  name[0] == '!' ||
51
51
  metric_name == 'View/text template/Rendering' ||
52
- metric_name == "View/#{OneApm::Transaction::UNKNOWN_METRIC}/Partial"
52
+ metric_name == "View/#{OneApm::Transaction::OA_UNKNOWN_METRIC}/Partial"
53
53
  end
54
54
 
55
55
  def metric_name
@@ -75,7 +75,7 @@ module OneApm
75
75
  elsif (parts = identifier.split('/')).size > 1
76
76
  parts[-2..-1].join('/')
77
77
  else
78
- OneApm::Transaction::UNKNOWN_METRIC
78
+ OneApm::Transaction::OA_UNKNOWN_METRIC
79
79
  end
80
80
  end
81
81
 
@@ -9,10 +9,10 @@ module OneApm
9
9
  module Agent
10
10
  module Instrumentation
11
11
  class ActiveRecordSubscriber < EventedSubscriber
12
- CACHED_QUERY_NAME = 'CACHE'.freeze unless defined? CACHED_QUERY_NAME
12
+ OA_CACHED_QUERY_NAME = 'CACHE'.freeze unless defined? OA_CACHED_QUERY_NAME
13
13
 
14
14
  def start(name, id, payload)
15
- return if payload[:name] == CACHED_QUERY_NAME
15
+ return if payload[:name] == OA_CACHED_QUERY_NAME
16
16
  return unless OneApm::Manager.tl_is_execution_traced?
17
17
  super
18
18
  rescue => e
@@ -20,7 +20,7 @@ module OneApm
20
20
  end
21
21
 
22
22
  def finish(name, id, payload)
23
- return if payload[:name] == CACHED_QUERY_NAME
23
+ return if payload[:name] == OA_CACHED_QUERY_NAME
24
24
  state = OneApm::TransactionState.tl_get
25
25
  return unless state.is_execution_traced?
26
26
  event = pop_event(id)
@@ -4,22 +4,22 @@ module OneApm
4
4
  module Agent
5
5
  module Instrumentation
6
6
  module QueueTime
7
- unless defined?(REQUEST_START_HEADER)
8
- REQUEST_START_HEADER = 'HTTP_X_REQUEST_START'.freeze
9
- QUEUE_START_HEADER = 'HTTP_X_QUEUE_START'.freeze
10
- MIDDLEWARE_START_HEADER = 'HTTP_X_MIDDLEWARE_START'.freeze
11
- ALL_QUEUE_METRIC = 'WebFrontend/QueueTime'.freeze
7
+ unless defined?(OA_REQUEST_START_HEADER)
8
+ OA_REQUEST_START_HEADER = 'HTTP_X_REQUEST_START'.freeze
9
+ OA_QUEUE_START_HEADER = 'HTTP_X_QUEUE_START'.freeze
10
+ OA_MIDDLEWARE_START_HEADER = 'HTTP_X_MIDDLEWARE_START'.freeze
11
+ OA_ALL_QUEUE_METRIC = 'WebFrontend/QueueTime'.freeze
12
12
  # any timestamps before this are thrown out and the parser
13
13
  # will try again with a larger unit (2000/1/1 UTC)
14
- EARLIEST_ACCEPTABLE_TIME = Time.at(946684800)
14
+ OA_EARLIEST_ACCEPTABLE_TIME = Time.at(946684800)
15
15
 
16
- CANDIDATE_HEADERS = [
17
- REQUEST_START_HEADER,
18
- QUEUE_START_HEADER,
19
- MIDDLEWARE_START_HEADER
16
+ OA_CANDIDATE_HEADERS = [
17
+ OA_REQUEST_START_HEADER,
18
+ OA_QUEUE_START_HEADER,
19
+ OA_MIDDLEWARE_START_HEADER
20
20
  ].freeze
21
21
 
22
- DIVISORS = [1_000_000, 1_000, 1]
22
+ OA_DIVISORS = [1_000_000, 1_000, 1]
23
23
  end
24
24
 
25
25
  module_function
@@ -27,7 +27,7 @@ module OneApm
27
27
  def parse_frontend_timestamp(headers, now=Time.now)
28
28
  earliest = nil
29
29
 
30
- CANDIDATE_HEADERS.each do |header|
30
+ OA_CANDIDATE_HEADERS.each do |header|
31
31
  if headers[header]
32
32
  parsed = parse_timestamp(timestamp_string_from_header_value(headers[header]))
33
33
  if parsed && (!earliest || parsed < earliest)
@@ -54,10 +54,10 @@ module OneApm
54
54
  end
55
55
 
56
56
  def parse_timestamp(string)
57
- DIVISORS.each do |divisor|
57
+ OA_DIVISORS.each do |divisor|
58
58
  begin
59
59
  t = Time.at(string.to_f / divisor)
60
- return t if t > EARLIEST_ACCEPTABLE_TIME
60
+ return t if t > OA_EARLIEST_ACCEPTABLE_TIME
61
61
  rescue RangeError
62
62
  # On Ruby versions built with a 32-bit time_t, attempting to
63
63
  # instantiate a Time object in the far future raises a RangeError,
@@ -39,7 +39,7 @@ module OneApm
39
39
  format_and_send(:debug, msgs, &blk)
40
40
  end
41
41
 
42
- NUM_LOG_ONCE_KEYS = 1000
42
+ OA_NUM_LOG_ONCE_KEYS = 1000
43
43
 
44
44
  def log_once(level, key, *msgs)
45
45
  # Since `already_logged` might change between calls, just grab it once
@@ -48,7 +48,7 @@ module OneApm
48
48
 
49
49
  return if logged.include?(key)
50
50
 
51
- if logged.size >= NUM_LOG_ONCE_KEYS && key.kind_of?(String)
51
+ if logged.size >= OA_NUM_LOG_ONCE_KEYS && key.kind_of?(String)
52
52
  # The reason for preventing too many keys in `logged` is for
53
53
  # memory concerns.
54
54
  # The reason for checking the type of the key is that we always want
@@ -168,7 +168,7 @@ module OneApm
168
168
  @log.level = AgentLogger.log_level_for(OneApm::Manager.config[:log_level])
169
169
  end
170
170
 
171
- LOG_LEVELS = {
171
+ OA_LOG_LEVELS = {
172
172
  "debug" => ::Logger::DEBUG,
173
173
  "info" => ::Logger::INFO,
174
174
  "warn" => ::Logger::WARN,
@@ -177,7 +177,7 @@ module OneApm
177
177
  }
178
178
 
179
179
  def self.log_level_for(level)
180
- LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
180
+ OA_LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
181
181
  end
182
182
 
183
183
  def set_log_format!
@@ -5,25 +5,25 @@ module OneApm
5
5
  attr_reader :name, :scope
6
6
 
7
7
  # the maximum length of a metric name or metric scope
8
- MAX_LENGTH = 255
9
- LENGTH_RANGE = (0...MAX_LENGTH)
10
- EMPTY_SCOPE = ''.freeze
8
+ OA_MAX_LENGTH = 255
9
+ OA_LENGTH_RANGE = (0...OA_MAX_LENGTH)
10
+ OA_EMPTY_SCOPE = ''.freeze
11
11
 
12
12
  def initialize(metric_name='', metric_scope=nil)
13
- if metric_name.to_s.length > MAX_LENGTH
14
- @name = metric_name.to_s[LENGTH_RANGE]
13
+ if metric_name.to_s.length > OA_MAX_LENGTH
14
+ @name = metric_name.to_s[OA_LENGTH_RANGE]
15
15
  else
16
16
  @name = metric_name.to_s
17
17
  end
18
18
 
19
19
  if metric_scope
20
- if metric_scope.to_s.length > MAX_LENGTH
21
- @scope = metric_scope.to_s[LENGTH_RANGE]
20
+ if metric_scope.to_s.length > OA_MAX_LENGTH
21
+ @scope = metric_scope.to_s[OA_LENGTH_RANGE]
22
22
  else
23
23
  @scope = metric_scope.to_s
24
24
  end
25
25
  else
26
- @scope = EMPTY_SCOPE
26
+ @scope = OA_EMPTY_SCOPE
27
27
  end
28
28
  end
29
29
 
@@ -45,10 +45,10 @@ module OneApm
45
45
  OneApm::Manager.logger.warn("The sub method on metric specs is deprecated") rescue nil
46
46
  return nil if name !~ pattern &&
47
47
  (!apply_to_scope || scope.nil? || scope !~ pattern)
48
- new_name = name.sub(pattern, replacement)[LENGTH_RANGE]
48
+ new_name = name.sub(pattern, replacement)[OA_LENGTH_RANGE]
49
49
 
50
50
  if apply_to_scope
51
- new_scope = (scope && scope.sub(pattern, replacement)[LENGTH_RANGE])
51
+ new_scope = (scope && scope.sub(pattern, replacement)[OA_LENGTH_RANGE])
52
52
  else
53
53
  new_scope = scope
54
54
  end
@@ -5,185 +5,176 @@ require 'ipaddr'
5
5
  require 'one_apm/rack/middleware_base'
6
6
  require 'one_apm/rack/middleware_wrapper'
7
7
 
8
- module OneApm::Rack
9
- class BrowserMonitoring < MiddlewareBase
10
8
 
11
- SCAN_LIMIT = 50_000
12
- ALREADY_INSTRUMENTED_KEY = "oneapm.browser_monitoring_already_instrumented"
13
- REMOTE_IP = "action_dispatch.remote_ip"
9
+ module OneApm
10
+ module Rack
11
+ class BrowserMonitoring < MiddlewareBase
14
12
 
15
- CHARSET_RE = /<\s*meta[^>]+charset\s*=[^>]*>/im.freeze
16
- X_UA_COMPATIBLE_RE = /<\s*meta[^>]+http-equiv\s*=\s*['"]x-ua-compatible['"][^>]*>/im.freeze
13
+ OA_SCAN_LIMIT = 50_000
14
+ OA_ALREADY_INSTRUMENTED_KEY = "oneapm.browser_monitoring_already_instrumented"
15
+ OA_REMOTE_IP = "action_dispatch.remote_ip"
17
16
 
18
- def traced_call(env)
19
- result = @app.call(env) # [status, headers, response]
17
+ OA_CHARSET_RE = /<\s*meta[^>]+charset\s*=[^>]*>/im.freeze
18
+ OA_X_UA_COMPATIBLE_RE = /<\s*meta[^>]+http-equiv\s*=\s*['"]x-ua-compatible['"][^>]*>/im.freeze
20
19
 
21
- js_to_inject = OneApm::Manager.browser_timing_header
22
- if (js_to_inject != "") && should_instrument?(env, result[0], result[1])
23
- response_string = autoinstrument_source(result[2], result[1], js_to_inject)
20
+ def traced_call(env)
21
+ result = @app.call(env) # [status, headers, response]
24
22
 
25
- env[ALREADY_INSTRUMENTED_KEY] = true
26
- if response_string
27
- response = Rack::Response.new(response_string, result[0], result[1])
28
- response.finish
23
+ js_to_inject = OneApm::Manager.browser_timing_header
24
+ if (js_to_inject != "") && should_instrument?(env, result[0], result[1])
25
+ response_string = autoinstrument_source(result[2], result[1], js_to_inject)
26
+
27
+ env[OA_ALREADY_INSTRUMENTED_KEY] = true
28
+ if response_string
29
+ response = ::Rack::Response.new(response_string, result[0], result[1])
30
+ response.finish
31
+ else
32
+ result
33
+ end
29
34
  else
30
35
  result
31
36
  end
32
- else
33
- result
34
37
  end
35
- end
36
38
 
37
- def should_instrument?(env, status, headers)
38
- OneApm::Manager.config[:'browser_monitoring.auto_instrument'] &&
39
- status == 200 &&
40
- !env[ALREADY_INSTRUMENTED_KEY] &&
41
- is_html?(headers) &&
42
- !is_attachment?(headers) &&
43
- !is_streaming?(env) &&
44
- ip_valid?(env)
45
- end
39
+ def should_instrument?(env, status, headers)
40
+ OneApm::Manager.config[:'browser_monitoring.auto_instrument'] &&
41
+ status == 200 &&
42
+ !env[OA_ALREADY_INSTRUMENTED_KEY] &&
43
+ is_html?(headers) &&
44
+ !is_attachment?(headers) &&
45
+ !is_streaming?(env) &&
46
+ ip_valid?(env)
47
+ end
46
48
 
47
- def is_html?(headers)
48
- headers["Content-Type"] && headers["Content-Type"].include?("text/html")
49
- end
49
+ def is_html?(headers)
50
+ headers["Content-Type"] && headers["Content-Type"].include?("text/html")
51
+ end
50
52
 
51
- def is_attachment?(headers)
52
- headers['Content-Disposition'].to_s.include?('attachment')
53
- end
53
+ def is_attachment?(headers)
54
+ headers['Content-Disposition'].to_s.include?('attachment')
55
+ end
54
56
 
55
- def is_streaming?(env)
56
- return false unless defined?(ActionController::Live)
57
- env['action_controller.instance'].class.included_modules.include?(ActionController::Live)
58
- end
57
+ def is_streaming?(env)
58
+ return false unless defined?(ActionController::Live)
59
+ env['action_controller.instance'].class.included_modules.include?(ActionController::Live)
60
+ end
59
61
 
60
- def ip_valid?(env)
61
- whitelist_ips = OneApm::Manager.config[:'browser_monitoring.whitelist_ips']
62
- return true if whitelist_ips.empty? || env[REMOTE_IP].to_s.empty?
63
- OneApm::Manager.logger.debug "Remote IP: #{env[REMOTE_IP]}"
64
- begin
65
- client = IPAddr.new(env[REMOTE_IP].to_s).to_i
66
- whitelist_ips.split(",").any? do |ip|
67
- low_ip, high_ip = ip.split("-").map(&:strip)
68
- low = IPAddr.new(low_ip).to_i
69
- if high_ip
70
- high = IPAddr.new(high_ip).to_i
71
- (low..high) === client
72
- else
73
- low == client
62
+ def ip_valid?(env)
63
+ whitelist_ips = OneApm::Manager.config[:'browser_monitoring.whitelist_ips']
64
+ return true if whitelist_ips.empty? || env[OA_REMOTE_IP].to_s.empty?
65
+ OneApm::Manager.logger.debug "Remote IP: #{env[OA_REMOTE_IP]}"
66
+ begin
67
+ client = IPAddr.new(env[OA_REMOTE_IP].to_s).to_i
68
+ whitelist_ips.split(",").any? do |ip|
69
+ low_ip, high_ip = ip.split("-").map(&:strip)
70
+ low = IPAddr.new(low_ip).to_i
71
+ if high_ip
72
+ high = IPAddr.new(high_ip).to_i
73
+ (low..high) === client
74
+ else
75
+ low == client
76
+ end
74
77
  end
78
+ rescue => e
79
+ OneApm::Manager.logger.error "Configuration for browser_monitoring.whitelist_ips has problems:#{whitelist_ips}"
80
+ true
81
+ end
82
+ end
83
+
84
+ def autoinstrument_source(response, headers, js_to_inject)
85
+ begin
86
+ source = gather_source(response)
87
+ close_old_response(response)
88
+ return nil unless source
89
+ inject_js(source, headers, js_to_inject)
90
+ rescue => e
91
+ OneApm::Manager.logger.debug "Skipping RUM instrumentation on exception.", e
92
+ nil
75
93
  end
76
- rescue => e
77
- OneApm::Manager.logger.error "Configuration for browser_monitoring.whitelist_ips has problems:#{whitelist_ips}"
78
- true
79
- end
80
- end
81
-
82
- def autoinstrument_source(response, headers, js_to_inject)
83
- begin
84
- source = gather_source(response)
85
- close_old_response(response)
86
- return nil unless source
87
- inject_js(source, headers, js_to_inject)
88
- rescue => e
89
- OneApm::Manager.logger.debug "Skipping RUM instrumentation on exception.", e
90
- nil
91
94
  end
92
- end
93
95
 
94
- def inject_js source, headers, js_to_inject
95
- position = OneApm::Manager.config[:'browser_monitoring.position']
96
- insertion_index = (position.empty? || position.to_sym != :footer) ? header_index(source) : footer_index(source)
97
- if insertion_index
98
- source = source[0...insertion_index] \
99
- << js_to_inject \
100
- << source[insertion_index..-1]
101
- if headers['Content-Length']
102
- headers['Content-Length'] = calculate_content_length(source).to_s
96
+ def inject_js source, headers, js_to_inject
97
+ position = OneApm::Manager.config[:'browser_monitoring.position']
98
+ insertion_index = (position.empty? || position.to_sym != :footer) ? header_index(source) : footer_index(source)
99
+ if insertion_index
100
+ source = source[0...insertion_index] \
101
+ << js_to_inject \
102
+ << source[insertion_index..-1]
103
+ if headers['Content-Length']
104
+ headers['Content-Length'] = calculate_content_length(source).to_s
105
+ end
106
+ else
107
+ OneApm::Manager.logger.debug "Skipping RUM instrumentation. Could not properly determine location to inject script."
103
108
  end
104
- else
105
- OneApm::Manager.logger.debug "Skipping RUM instrumentation. Could not properly determine location to inject script."
109
+ source
106
110
  end
107
- source
108
- end
109
111
 
110
- def header_index source
111
- beginning_of_source = source[0..SCAN_LIMIT]
112
- if body_start = find_body_start(beginning_of_source)
113
- meta_tag_positions = [
114
- find_x_ua_compatible_position(beginning_of_source),
115
- find_charset_position(beginning_of_source)
116
- ].compact
117
112
 
118
- if !meta_tag_positions.empty?
119
- insertion_index = meta_tag_positions.max
113
+ def header_index source
114
+ beginning_of_source = source[0..OA_SCAN_LIMIT]
115
+ if body_start = find_body_start(beginning_of_source)
116
+ meta_tag_positions = [
117
+ find_x_ua_compatible_position(beginning_of_source),
118
+ find_charset_position(beginning_of_source)
119
+ ].compact
120
+
121
+ if !meta_tag_positions.empty?
122
+ insertion_index = meta_tag_positions.max
123
+ else
124
+ insertion_index = find_end_of_head_open(beginning_of_source) || body_start
125
+ end
126
+ insertion_index
120
127
  else
121
- insertion_index = find_end_of_head_open(beginning_of_source) || body_start
128
+ msg = "Skipping RUM instrumentation. Unable to find <body> tag in first #{OA_SCAN_LIMIT} bytes of document."
129
+ OneApm::Manager.logger.log_once(:warn, :rum_insertion_failure, msg)
130
+ OneApm::Manager.logger.debug(msg)
131
+ nil
122
132
  end
123
- insertion_index
124
- else
125
- msg = "Skipping RUM instrumentation. Unable to find <body> tag in first #{SCAN_LIMIT} bytes of document."
126
- OneApm::Manager.logger.log_once(:warn, :rum_insertion_failure, msg)
127
- OneApm::Manager.logger.debug(msg)
128
- nil
129
133
  end
130
- end
131
134
 
132
- def footer_index source
133
- if body_end = find_body_end(source)
134
- body_end
135
- else
136
- msg = "Skipping RUM instrumentation. Unable to find </body> tag from document."
137
- OneApm::Manager.logger.log_once(:warn, :rum_insertion_failure, msg)
138
- OneApm::Manager.logger.debug(msg)
139
- nil
135
+ def footer_index source
136
+ if body_end = find_body_end(source)
137
+ body_end
138
+ else
139
+ msg = "Skipping RUM instrumentation. Unable to find </body> tag from document."
140
+ OneApm::Manager.logger.log_once(:warn, :rum_insertion_failure, msg)
141
+ OneApm::Manager.logger.debug(msg)
142
+ nil
143
+ end
140
144
  end
141
- end
142
145
 
143
- def gather_source(response)
144
- source = nil
145
- response.each {|fragment| source ? (source << fragment.to_s) : (source = fragment.to_s)}
146
- source
147
- end
148
-
149
- # Per "The Response > The Body" section of Rack spec, we should close
150
- # if our response is able. http://rack.rubyforge.org/doc/SPEC.html
151
- def close_old_response(response)
152
- if response.respond_to?(:close)
153
- response.close
146
+ def find_body_start(beginning_of_source)
147
+ beginning_of_source.index("<body")
154
148
  end
155
- end
156
149
 
157
- def find_body_start(beginning_of_source)
158
- beginning_of_source.index("<body")
159
- end
150
+ def find_body_end source
151
+ source.rindex("</body>")
152
+ end
160
153
 
161
- def find_body_end source
162
- source.rindex("</body>")
163
- end
164
154
 
165
- def find_x_ua_compatible_position(beginning_of_source)
166
- match = X_UA_COMPATIBLE_RE.match(beginning_of_source)
167
- match.end(0) if match
168
- end
155
+ def find_x_ua_compatible_position(beginning_of_source)
156
+ match = OA_X_UA_COMPATIBLE_RE.match(beginning_of_source)
157
+ match.end(0) if match
158
+ end
169
159
 
170
- def find_charset_position(beginning_of_source)
171
- match = CHARSET_RE.match(beginning_of_source)
172
- match.end(0) if match
173
- end
160
+ def find_charset_position(beginning_of_source)
161
+ match = OA_CHARSET_RE.match(beginning_of_source)
162
+ match.end(0) if match
163
+ end
174
164
 
175
- def find_end_of_head_open(beginning_of_source)
176
- head_open = beginning_of_source.index("<head")
177
- beginning_of_source.index(">", head_open) + 1 if head_open
178
- end
165
+ def find_end_of_head_open(beginning_of_source)
166
+ head_open = beginning_of_source.index("<head")
167
+ beginning_of_source.index(">", head_open) + 1 if head_open
168
+ end
179
169
 
180
- # String does not respond to 'bytesize' in 1.8.6. Fortunately String#length
181
- # returns bytes rather than characters in 1.8.6 so we can use that instead.
182
- def calculate_content_length(source)
183
- if source.respond_to?(:bytesize)
184
- source.bytesize
185
- else
186
- source.length
170
+ # String does not respond to 'bytesize' in 1.8.6. Fortunately String#length
171
+ # returns bytes rather than characters in 1.8.6 so we can use that instead.
172
+ def calculate_content_length(source)
173
+ if source.respond_to?(:bytesize)
174
+ source.bytesize
175
+ else
176
+ source.length
177
+ end
187
178
  end
188
179
  end
189
180
  end