oneapm_rpm 1.3.7 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +3 -2
  3. data/Gemfile +1 -1
  4. data/lib/one_apm/agent.rb +17 -10
  5. data/lib/one_apm/agent/agent/connect.rb +9 -3
  6. data/lib/one_apm/agent/agent/container_data_manager.rb +20 -3
  7. data/lib/one_apm/agent/agent/cross_app_samples_sender.rb +22 -0
  8. data/lib/one_apm/agent/agent/rule_fetcher.rb +15 -0
  9. data/lib/one_apm/agent/agent/start.rb +15 -3
  10. data/lib/one_apm/agent/agent/start_worker_thread.rb +8 -2
  11. data/lib/one_apm/agent/cross_app/cross_app_monitor.rb +7 -6
  12. data/lib/one_apm/agent/cross_app/cross_app_tracing.rb +45 -9
  13. data/lib/one_apm/agent/cross_app/cross_app_tracing_message.rb +130 -0
  14. data/lib/one_apm/agent/database/active_record_helper.rb +104 -50
  15. data/lib/one_apm/agent/datastore.rb +8 -0
  16. data/lib/one_apm/agent/datastore/metric_helper.rb +37 -6
  17. data/lib/one_apm/agent/synthetics_monitor.rb +1 -1
  18. data/lib/one_apm/collector/collector/helper.rb +5 -1
  19. data/lib/one_apm/collector/collector/http_connection.rb +16 -8
  20. data/lib/one_apm/collector/collector_service.rb +6 -4
  21. data/lib/one_apm/collector/containers/transaction_event_aggregator.rb +52 -75
  22. data/lib/one_apm/collector/containers/transaction_sampler.rb +6 -2
  23. data/lib/one_apm/configuration.rb +8 -4
  24. data/lib/one_apm/configuration/default_source.rb +24 -3
  25. data/lib/one_apm/configuration/server_source.rb +1 -1
  26. data/lib/one_apm/inst/http_clients/curb.rb +4 -1
  27. data/lib/one_apm/inst/http_clients/thrift.rb +57 -20
  28. data/lib/one_apm/inst/nosql/memcache.rb +21 -2
  29. data/lib/one_apm/inst/nosql/mongo2.rb +11 -8
  30. data/lib/one_apm/inst/nosql/redis.rb +8 -3
  31. data/lib/one_apm/inst/orm/active_record.rb +13 -7
  32. data/lib/one_apm/inst/rails4/active_record_subscriber.rb +16 -13
  33. data/lib/one_apm/inst/transaction_base.rb +0 -1
  34. data/lib/one_apm/logger/audit_logger.rb +19 -2
  35. data/lib/one_apm/manager.rb +1 -0
  36. data/lib/one_apm/probe/instance_methods.rb +0 -1
  37. data/lib/one_apm/rack/middleware_tracing.rb +1 -0
  38. data/lib/one_apm/support/event_buffer/sampled_buffer.rb +4 -0
  39. data/lib/one_apm/support/helper.rb +16 -0
  40. data/lib/one_apm/support/http_clients/curb_wrappers.rb +20 -0
  41. data/lib/one_apm/support/http_clients/excon_wrappers.rb +25 -0
  42. data/lib/one_apm/support/http_clients/httpclient_wrappers.rb +20 -0
  43. data/lib/one_apm/support/http_clients/net_http_wrappers.rb +20 -0
  44. data/lib/one_apm/support/http_clients/thrift_tracer.rb +64 -0
  45. data/lib/one_apm/support/http_clients/typhoeus_wrappers.rb +21 -1
  46. data/lib/one_apm/support/http_clients/uri_util.rb +1 -0
  47. data/lib/one_apm/support/ip.rb +15 -0
  48. data/lib/one_apm/support/rename_rules_engine.rb +39 -0
  49. data/lib/one_apm/support/rename_rules_engine/external_rename_rule.rb +84 -0
  50. data/lib/one_apm/support/rename_rules_engine/match_expression/base.rb +46 -0
  51. data/lib/one_apm/support/rename_rules_engine/match_expression/engine.rb +35 -0
  52. data/lib/one_apm/support/rename_rules_engine/match_expression/method.rb +20 -0
  53. data/lib/one_apm/support/rename_rules_engine/match_expression/split_object.rb +19 -0
  54. data/lib/one_apm/support/rename_rules_engine/match_expression/url.rb +19 -0
  55. data/lib/one_apm/support/rename_rules_engine/rename/base.rb +25 -0
  56. data/lib/one_apm/support/rename_rules_engine/rename/engine.rb +36 -0
  57. data/lib/one_apm/support/rename_rules_engine/rename/header.rb +17 -0
  58. data/lib/one_apm/support/rename_rules_engine/rename/parameter.rb +18 -0
  59. data/lib/one_apm/support/rename_rules_engine/rename/segment.rb +41 -0
  60. data/lib/one_apm/transaction.rb +11 -2
  61. data/lib/one_apm/transaction/class_methods.rb +3 -3
  62. data/lib/one_apm/transaction/event_analytic_data.rb +51 -0
  63. data/lib/one_apm/transaction/event_analytic_sample.rb +35 -0
  64. data/lib/one_apm/transaction/instance_helpers.rb +1 -1
  65. data/lib/one_apm/transaction/sample_buffer/cross_sample_buffer.rb +47 -0
  66. data/lib/one_apm/transaction/segment.rb +2 -1
  67. data/lib/one_apm/transaction/transaction_finish_append.rb +4 -0
  68. data/lib/one_apm/transaction/transaction_name.rb +1 -1
  69. data/lib/one_apm/transaction/transaction_sample.rb +12 -7
  70. data/lib/one_apm/version.rb +2 -2
  71. data/lib/sequel/extensions/oneapm_instrumentation.rb +16 -9
  72. data/lib/sequel/plugins/oneapm_instrumentation.rb +3 -2
  73. data/oneapm_rpm.gemspec +2 -1
  74. metadata +41 -21
@@ -30,9 +30,28 @@ module OneApm
30
30
  client_class.class_eval do
31
31
  alias_method method_name_without, method_name
32
32
 
33
+ if defined?(::MemCache)
34
+ def oneapm_product
35
+ @product ||= begin
36
+ s = Array(servers)
37
+ host, port = s.first.host, s.first.port if s.first rescue nil
38
+ OneApm::Agent::Datastore.oneapm_product("Memcached", host, port)
39
+ end
40
+ end
41
+ private :oneapm_product
42
+ else
43
+ def oneapm_product
44
+ @product ||= begin
45
+ s = Array(@servers || servers)
46
+ host, port, weight = s.first.split(":") if s.first && s.first.to_s.include?(':') rescue nil
47
+ OneApm::Agent::Datastore.oneapm_product("Memcached", host, port)
48
+ end
49
+ end
50
+ private :oneapm_product
51
+ end
52
+
33
53
  define_method method_name do |*args, &block|
34
- metrics = Datastore::MetricHelper.metrics_for("Memcached", method_name)
35
-
54
+ metrics = Datastore::MetricHelper.metrics_for(oneapm_product, method_name)
36
55
  OneApm::Support::MethodTracer.trace_execution_scoped(metrics) do
37
56
  t0 = Time.now
38
57
  begin
@@ -33,10 +33,13 @@ module OneApm
33
33
  @operations ||= {}
34
34
  end
35
35
 
36
- def mertircs(event)
37
- OneApm::Agent::Datastore::MetricHelper.metrics_for(
38
- OA_MONGODB, event.command_name, event.command.values.first
39
- )
36
+ def generate_metrics(event)
37
+ @product ||= begin
38
+ host = event.address.host rescue nil
39
+ port = event.address.port rescue nil
40
+ OneApm::Agent::Datastore.oneapm_product(OA_MONGODB, host, port)
41
+ end
42
+ OneApm::Agent::Datastore::MetricHelper.metrics_for(@product, event.command_name, event.command.values.first)
40
43
  end
41
44
 
42
45
  def operator(operator_type, event)
@@ -44,7 +47,7 @@ module OneApm
44
47
  state = OneApm::TransactionState.tl_get
45
48
  return unless state.is_execution_traced?
46
49
  stared_event = operations.delete(event.operation_id)
47
- one_apm_generate_metrics(stared_event, event.duration)
50
+ one_apm_record_metrics(stared_event, event.duration)
48
51
  one_apm_notice_statement(stared_event, operator_type, event.duration)
49
52
  one_apm_notice_sql(state, stared_event, operator_type, event.duration)
50
53
  rescue => e
@@ -52,8 +55,8 @@ module OneApm
52
55
  end
53
56
  end
54
57
 
55
- def one_apm_generate_metrics(event, duration)
56
- base, *other_metrics = mertircs(event)
58
+ def one_apm_record_metrics(event, duration)
59
+ base, *other_metrics = generate_metrics(event)
57
60
  OneApm::Manager.agent.stats_engine.tl_record_scoped_and_unscoped_metrics(
58
61
  base, other_metrics, duration
59
62
  )
@@ -61,7 +64,7 @@ module OneApm
61
64
 
62
65
  def one_apm_notice_sql(state, event, status, duration)
63
66
  stack = state.traced_method_stack
64
- base, *other_metrics = mertircs(event)
67
+ base, *other_metrics = generate_metrics(event)
65
68
 
66
69
  started_time = Time.now.to_f
67
70
  frame = stack.push_frame(state, :mongo_tracer, started_time - duration)
@@ -21,6 +21,11 @@ LibraryDetection.defer do
21
21
  # +raw_call_command+.
22
22
 
23
23
  call_method = ::Redis::Client.new.respond_to?(:call) ? :call : :raw_call_command
24
+
25
+ def oneapm_product
26
+ @product ||= OneApm::Agent::Datastore.oneapm_product("Redis", host, port)
27
+ end
28
+ private :oneapm_product
24
29
 
25
30
  def call_with_oneapm_trace(*args, &blk)
26
31
  method_name = args[0].is_a?(Array) ? args[0][0] : args[0]
@@ -28,7 +33,7 @@ LibraryDetection.defer do
28
33
  callback = proc do |result, metric, elapsed|
29
34
  _send_to_one_apm(args, elapsed)
30
35
  end
31
- OneApm::Agent::Datastore.wrap("Redis", filtered_command, nil, callback) do
36
+ OneApm::Agent::Datastore.wrap(oneapm_product, filtered_command, nil, callback) do
32
37
  call_without_oneapm_trace(*args, &blk)
33
38
  end
34
39
  end
@@ -45,7 +50,7 @@ LibraryDetection.defer do
45
50
  # user can at least see what all the commands were.
46
51
  additional = commands.map do |c|
47
52
  name = c.kind_of?(Array) ? c[0] : c
48
- "Datastore/operation/Redis/#{name.to_s.downcase}_pipelined"
53
+ "Datastore/operation/#{oneapm_product}/#{name.to_s.downcase}_pipelined"
49
54
  end
50
55
 
51
56
  callback = proc do |result, metric, elapsed|
@@ -57,7 +62,7 @@ LibraryDetection.defer do
57
62
  end
58
63
  end
59
64
 
60
- OneApm::Agent::Datastore.wrap("Redis", "pipelined", nil, callback) do
65
+ OneApm::Agent::Datastore.wrap(oneapm_product, 'pipelined', nil, callback) do
61
66
  call_pipelined_without_oneapm_trace commands, *rest
62
67
  end
63
68
  end
@@ -32,6 +32,12 @@ module OneApm
32
32
  end
33
33
  end
34
34
 
35
+ def generate_metrics(operation, name)
36
+ @product ||= ActiveRecordHelper.database_info(@config)
37
+ model_name = ActiveRecordHelper.model_for_name(name)
38
+ ActiveRecordHelper.metric_for(@product, operation, model_name).compact
39
+ end
40
+
35
41
  def log_with_oneapm_instrumentation(*args, &block)
36
42
  state = OneApm::TransactionState.tl_get
37
43
 
@@ -40,21 +46,21 @@ module OneApm
40
46
  end
41
47
 
42
48
  sql, name, _ = args
43
- metric = ActiveRecordHelper.metric_for_name(OneApm::Helper.correctly_encoded(name)) ||
44
- ActiveRecordHelper.metric_for_sql(OneApm::Helper.correctly_encoded(sql))
45
-
46
- if !metric
49
+ operation = ActiveRecordHelper.operator_for_name(OneApm::Helper.correctly_encoded(name)) ||
50
+ ActiveRecordHelper.operator_for_sql(OneApm::Helper.correctly_encoded(sql))
51
+
52
+ if !operation
47
53
  log_without_oneapm_instrumentation(*args, &block)
48
54
  else
49
- metrics = [metric, remote_service_metric].compact
50
- metrics += ActiveRecordHelper.rollup_metrics_for(metric)
55
+
56
+ metrics = generate_metrics(operation, name)
51
57
  self.class.trace_execution_scoped(metrics) do
52
58
  t0 = Time.now
53
59
  begin
54
60
  log_without_oneapm_instrumentation(*args, &block)
55
61
  ensure
56
62
  elapsed_time = (Time.now - t0).to_f
57
- OneApm::Manager.notice_sql(sql, metric, @config, elapsed_time, state, &OA_EXPLAINER)
63
+ OneApm::Manager.notice_sql(sql, metrics.first, @config, elapsed_time, state, &OA_EXPLAINER)
58
64
  end
59
65
  end
60
66
  end
@@ -43,7 +43,8 @@ module OneApm
43
43
  def notice_sql(state, event)
44
44
  stack = state.traced_method_stack
45
45
  config = active_record_config_for_event(event)
46
- metric = base_metric(event)
46
+
47
+ base, *other_metrics = generate_metrics(event)
47
48
 
48
49
  # enter transaction trace segment
49
50
  frame = stack.push_frame(state, :active_record, event.time)
@@ -54,22 +55,24 @@ module OneApm
54
55
  state, &method(:get_explain_plan))
55
56
 
56
57
  OneApm::Manager.agent.sql_sampler \
57
- .notice_sql(event.payload[:sql], metric, config,
58
+ .notice_sql(event.payload[:sql], base, config,
58
59
  Helper.milliseconds_to_seconds(event.duration),
59
60
  state, &method(:get_explain_plan))
60
61
 
61
62
  # exit transaction trace segment
62
- stack.pop_frame(state, frame, metric, event.end)
63
+ stack.pop_frame(state, frame, base, event.end)
63
64
  end
64
65
 
65
- def record_metrics(event)
66
- base = base_metric(event)
66
+ def generate_metrics(event)
67
+ @config ||= active_record_config_for_event(event)
68
+ @product ||= ActiveRecordHelper.database_info(@config)
69
+ operation = operation(event)
70
+ model_name = ActiveRecordHelper.model_for_name(event.payload[:name])
71
+ ActiveRecordHelper.metric_for(@product, operation, model_name)
72
+ end
67
73
 
68
- other_metrics = ActiveRecordHelper.rollup_metrics_for(base)
69
- if config = active_record_config_for_event(event)
70
- other_metrics << ActiveRecordHelper.remote_service_metric(config[:adapter], config[:host])
71
- end
72
- other_metrics.compact!
74
+ def record_metrics(event)
75
+ base, *other_metrics = generate_metrics(event)
73
76
 
74
77
  OneApm::Manager.agent.stats_engine.tl_record_scoped_and_unscoped_metrics(
75
78
  base, other_metrics,
@@ -77,9 +80,9 @@ module OneApm
77
80
  )
78
81
  end
79
82
 
80
- def base_metric(event)
81
- ActiveRecordHelper.metric_for_name(event.payload[:name]) ||
82
- ActiveRecordHelper.metric_for_sql(OneApm::Helper.correctly_encoded(event.payload[:sql]))
83
+ def operation(event)
84
+ ActiveRecordHelper.operator_for_name(event.payload[:name]) ||
85
+ ActiveRecordHelper.operator_for_sql(OneApm::Helper.correctly_encoded(event.payload[:sql]))
83
86
  end
84
87
 
85
88
  def active_record_config_for_event(event)
@@ -300,7 +300,6 @@ module OneApm
300
300
  trace_options = args.last.is_a?(Hash) ? args.last : OA_DEFAULT_OPTIONS
301
301
  category = trace_options[:category] || :controller
302
302
  txn_options = create_transaction_options(trace_options, category, state)
303
-
304
303
  begin
305
304
  txn = Transaction.start(state, category, txn_options)
306
305
 
@@ -30,8 +30,25 @@ module OneApm
30
30
  else
31
31
  marshaller.prepare(data, :encoder => @encoder).inspect
32
32
  end
33
- @log.info("REQUEST: #{uri}")
34
- @log.info("REQUEST BODY: #{request_body}")
33
+ if uri =~ /analytic_event_data/
34
+ @log.info("REQUEST: #{uri}")
35
+ @log.info("REQUEST BODY: #{request_body}")
36
+ else
37
+ @log.info("REQUEST: #{uri}")
38
+ @log.info("REQUEST BODY: #{request_body}")
39
+ end
40
+ end
41
+ rescue StandardError, SystemStackError, SystemCallError => e
42
+ OneApm::Manager.logger.warn("Failed writing to audit log", e)
43
+ rescue Exception => e
44
+ OneApm::Manager.logger.warn("Failed writing to audit log with exception. Re-raising in case of interupt.", e)
45
+ raise
46
+ end
47
+
48
+ def log_response(response)
49
+ if enabled?
50
+ setup_logger unless setup?
51
+ @log.info("RESPONSE: #{response.inspect}")
35
52
  end
36
53
  rescue StandardError, SystemStackError, SystemCallError => e
37
54
  OneApm::Manager.logger.warn("Failed writing to audit log", e)
@@ -7,6 +7,7 @@ require 'one_apm/support/timer_lib'
7
7
  require 'one_apm/support/json_wrapper'
8
8
  require 'one_apm/support/chained_call'
9
9
  require 'one_apm/support/rules_engine'
10
+ require 'one_apm/support/rename_rules_engine'
10
11
  require 'one_apm/support/http_clients/uri_util'
11
12
  require 'one_apm/support/system_info'
12
13
 
@@ -52,7 +52,6 @@ module OneApm
52
52
  def configure_agent(env, options)
53
53
  manual = OneApm::Configuration::ManualSource.new(options)
54
54
  OneApm::Manager.config.replace_or_add_config(manual)
55
-
56
55
  config_file_path = @config_file_override || OneApm::Manager.config[:config_path]
57
56
  OneApm::Manager.config.replace_or_add_config(OneApm::Configuration::YamlSource.new(config_file_path, env))
58
57
 
@@ -61,6 +61,7 @@ module OneApm
61
61
  options = build_transaction_options(env, first_middleware)
62
62
 
63
63
  current_transaction = OneApm::Transaction.start(state, category, options)
64
+
64
65
  current_transaction.ignore_frames << options[:transaction_name] if respond_to?(:middleware_ignore?) && middleware_ignore?
65
66
 
66
67
  events.notify(:before_call, env) if first_middleware
@@ -2,12 +2,15 @@
2
2
 
3
3
  # http://xlinux.nist.gov/dads/HTML/reservoirSampling.html
4
4
 
5
+ require 'forwardable'
5
6
  require 'one_apm/support/event_buffer'
6
7
 
7
8
  module OneApm
8
9
  module Agent
9
10
  class SampledBuffer < EventBuffer
11
+ extend Forwardable
10
12
  attr_reader :seen_lifetime, :captured_lifetime
13
+ def_delegators :@items, :select
11
14
 
12
15
  def initialize(capacity)
13
16
  super
@@ -37,6 +40,7 @@ module OneApm
37
40
  end
38
41
  end
39
42
 
43
+
40
44
  def sample_rate_lifetime
41
45
  @captured_lifetime > 0 ? (@captured_lifetime.to_f / @seen_lifetime) : 0.0
42
46
  end
@@ -45,5 +45,21 @@ module OneApm
45
45
  def milliseconds_to_seconds(milliseconds)
46
46
  milliseconds / 1000.0
47
47
  end
48
+
49
+ HEX_DIGITS = (0..15).map{|i| i.to_s(16)}
50
+ GUID_LENGTH = 16
51
+
52
+ # generate a random 16 length uuid
53
+ def generate_guid
54
+ guid = ''
55
+ GUID_LENGTH.times do |a|
56
+ guid << HEX_DIGITS[rand(16)]
57
+ end
58
+ guid
59
+ end
60
+
61
+ def obfuscator
62
+ @obfuscator ||= OneApm::Agent::Obfuscator.new(OneApm::Manager.config[:encoding_key])
63
+ end
48
64
  end
49
65
  end
@@ -17,6 +17,10 @@ module OneApm
17
17
  self["host"] || self["Host"] || self.uri.host
18
18
  end
19
19
 
20
+ def port
21
+ self["port"] || self["port"] || self.uri.port
22
+ end
23
+
20
24
  def method
21
25
  @curlobj._oa_http_verb
22
26
  end
@@ -32,6 +36,22 @@ module OneApm
32
36
  def uri
33
37
  @uri ||= OneApm::Support::HTTPClients::URIUtil.parse_url(@curlobj.url)
34
38
  end
39
+
40
+ def query
41
+ @uri.query.nil?? {} : CGI.parse(@uri.query)
42
+ end
43
+
44
+ def body
45
+ @curlobj._oa_http_params
46
+ end
47
+
48
+ def post_params
49
+ body.nil?? {} : CGI.parse(body)
50
+ end
51
+
52
+ def params
53
+ post_params.merge(query)
54
+ end
35
55
  end
36
56
 
37
57
 
@@ -41,6 +41,15 @@ module OneApm
41
41
  end
42
42
  end
43
43
 
44
+ def port
45
+ if hostname = (self['host'] || self['Host'])
46
+ hostname.split(':').last
47
+ else
48
+ @datum[:port]
49
+ end
50
+ end
51
+
52
+
44
53
  def method
45
54
  @datum[:method].to_s.upcase
46
55
  end
@@ -57,6 +66,22 @@ module OneApm
57
66
  def uri
58
67
  URI.parse("#{@datum[:scheme]}://#{@datum[:host]}:#{@datum[:port]}#{@datum[:path]}")
59
68
  end
69
+
70
+ def query
71
+ uri.query.nil?? {} : CGI.parse(uri.query)
72
+ end
73
+
74
+ def body
75
+ @datum[:body]
76
+ end
77
+
78
+ def post_params
79
+ body.nil?? {} : CGI.parse(body)
80
+ end
81
+
82
+ def params
83
+ post_params.merge(query)
84
+ end
60
85
  end
61
86
  end
62
87
  end
@@ -48,6 +48,10 @@ module OneApm
48
48
  end
49
49
  end
50
50
 
51
+ def port
52
+ uri.port
53
+ end
54
+
51
55
  def [](key)
52
56
  request.headers[key]
53
57
  end
@@ -55,6 +59,22 @@ module OneApm
55
59
  def []=(key, value)
56
60
  request.http_header[key] = value
57
61
  end
62
+
63
+ def query
64
+ @uri.query.nil?? {} : CGI.parse(@uri.query)
65
+ end
66
+
67
+ def body
68
+ request.http_body.instance_values['body']
69
+ end
70
+
71
+ def post_params
72
+ body.nil?? {} : CGI.parse(body)
73
+ end
74
+
75
+ def params
76
+ post_params.merge(query)
77
+ end
58
78
  end
59
79
  end
60
80
  end
@@ -21,6 +21,10 @@ module OneApm
21
21
  end
22
22
  end
23
23
 
24
+ def port
25
+ @connection.port
26
+ end
27
+
24
28
  def method
25
29
  @request.method
26
30
  end
@@ -42,6 +46,22 @@ module OneApm
42
46
  URI("#{scheme}://#{@connection.address}:#{@connection.port}#{@request.path}")
43
47
  end
44
48
  end
49
+
50
+ def query
51
+ uri.query.nil?? {} : CGI.parse(uri.query)
52
+ end
53
+
54
+ def body
55
+ @request.body
56
+ end
57
+
58
+ def post_params
59
+ body.nil?? {} : CGI.parse(body)
60
+ end
61
+
62
+ def params
63
+ post_params.merge(query)
64
+ end
45
65
  end
46
66
  end
47
67
  end