tingyun_rpm 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/lib/ting_yun/agent/agent.rb +8 -0
  4. data/lib/ting_yun/agent/collector/stats_engine/base_quantile_hash.rb +20 -0
  5. data/lib/ting_yun/agent/collector/stats_engine/metric_stats.rb +10 -0
  6. data/lib/ting_yun/agent/collector/stats_engine.rb +9 -0
  7. data/lib/ting_yun/agent/collector/transaction_sampler/class_method.rb +2 -2
  8. data/lib/ting_yun/agent/cross_app/cross_app_tracing.rb +16 -10
  9. data/lib/ting_yun/agent/datastore/metric_helper.rb +31 -7
  10. data/lib/ting_yun/agent/datastore.rb +6 -11
  11. data/lib/ting_yun/agent/dispatcher.rb +5 -1
  12. data/lib/ting_yun/agent/instance_methods/container_data_manager.rb +5 -1
  13. data/lib/ting_yun/agent/instance_methods/start_worker_thread.rb +5 -0
  14. data/lib/ting_yun/agent/method_tracer_helpers.rb +8 -4
  15. data/lib/ting_yun/agent/transaction/attributes.rb +6 -2
  16. data/lib/ting_yun/agent/transaction/class_method.rb +14 -5
  17. data/lib/ting_yun/agent/transaction/instance_method.rb +20 -4
  18. data/lib/ting_yun/agent/transaction/trace.rb +2 -1
  19. data/lib/ting_yun/agent/transaction/trace_node.rb +10 -2
  20. data/lib/ting_yun/agent/transaction/traced_method_stack.rb +2 -2
  21. data/lib/ting_yun/agent/transaction/transaction_sample_builder.rb +2 -1
  22. data/lib/ting_yun/agent/transaction/transaction_state.rb +22 -1
  23. data/lib/ting_yun/agent/transaction/transaction_timings.rb +1 -2
  24. data/lib/ting_yun/agent/transaction.rb +13 -7
  25. data/lib/ting_yun/configuration/default_source.rb +44 -7
  26. data/lib/ting_yun/configuration/yaml_source.rb +1 -0
  27. data/lib/ting_yun/frameworks/instrumentation.rb +6 -1
  28. data/lib/ting_yun/frameworks/rails5.rb +10 -0
  29. data/lib/ting_yun/frameworks.rb +1 -1
  30. data/lib/ting_yun/http/http_client_request.rb +39 -0
  31. data/lib/ting_yun/http/net_http_request.rb +4 -0
  32. data/lib/ting_yun/instrumentation/active_record.rb +11 -5
  33. data/lib/ting_yun/instrumentation/bunny.rb +142 -0
  34. data/lib/ting_yun/instrumentation/data_mapper.rb +167 -0
  35. data/lib/ting_yun/instrumentation/grape.rb +39 -0
  36. data/lib/ting_yun/instrumentation/http_client.rb +70 -0
  37. data/lib/ting_yun/instrumentation/kafka.rb +218 -0
  38. data/lib/ting_yun/instrumentation/memcached.rb +135 -0
  39. data/lib/ting_yun/instrumentation/middleware_proxy.rb +1 -4
  40. data/lib/ting_yun/instrumentation/middleware_tracing.rb +5 -1
  41. data/lib/ting_yun/instrumentation/mongo.rb +18 -6
  42. data/lib/ting_yun/instrumentation/mongo2.rb +5 -1
  43. data/lib/ting_yun/instrumentation/mongo_command_log_subscriber.rb +5 -5
  44. data/lib/ting_yun/instrumentation/moped.rb +4 -3
  45. data/lib/ting_yun/instrumentation/net.rb +3 -3
  46. data/lib/ting_yun/instrumentation/rails3/action_controller.rb +8 -4
  47. data/lib/ting_yun/instrumentation/rails3/action_view.rb +8 -4
  48. data/lib/ting_yun/instrumentation/rails4/action_controller.rb +29 -0
  49. data/lib/ting_yun/instrumentation/rails4/action_view.rb +29 -0
  50. data/lib/ting_yun/instrumentation/rails4/active_record.rb +30 -0
  51. data/lib/ting_yun/instrumentation/rails5/action_cable.rb +31 -0
  52. data/lib/ting_yun/instrumentation/rails5/action_controller.rb +29 -0
  53. data/lib/ting_yun/instrumentation/rails5/action_view.rb +28 -0
  54. data/lib/ting_yun/instrumentation/rails5/active_record.rb +30 -0
  55. data/lib/ting_yun/instrumentation/rake.rb +3 -2
  56. data/lib/ting_yun/instrumentation/redis.rb +6 -5
  57. data/lib/ting_yun/instrumentation/sidekiq.rb +61 -0
  58. data/lib/ting_yun/instrumentation/sinatra/action.rb +95 -0
  59. data/lib/ting_yun/instrumentation/sinatra/view.rb +67 -0
  60. data/lib/ting_yun/instrumentation/support/action_cable_subscriber.rb +83 -0
  61. data/lib/ting_yun/instrumentation/{rails4 → support}/action_controller_subscriber.rb +5 -29
  62. data/lib/ting_yun/instrumentation/{rails4 → support}/action_view_subscriber.rb +2 -24
  63. data/lib/ting_yun/instrumentation/support/active_record_helper.rb +23 -6
  64. data/lib/ting_yun/instrumentation/{rails4 → support}/active_record_subscriber.rb +13 -37
  65. data/lib/ting_yun/instrumentation/support/controller_instrumentation.rb +204 -1
  66. data/lib/ting_yun/instrumentation/support/database.rb +2 -1
  67. data/lib/ting_yun/instrumentation/support/external_error.rb +2 -2
  68. data/lib/ting_yun/instrumentation/support/external_helper.rb +30 -0
  69. data/lib/ting_yun/instrumentation/support/method_instrumentation.rb +228 -0
  70. data/lib/ting_yun/instrumentation/support/metric_translator.rb +4 -1
  71. data/lib/ting_yun/instrumentation/support/sinatra_helper.rb +20 -0
  72. data/lib/ting_yun/instrumentation/support/transaction_namer.rb +3 -1
  73. data/lib/ting_yun/instrumentation/thrift.rb +5 -6
  74. data/lib/ting_yun/logger/agent_logger.rb +1 -0
  75. data/lib/ting_yun/logger/create_logger_helper.rb +16 -2
  76. data/lib/ting_yun/metrics/metric_data.rb +8 -2
  77. data/lib/ting_yun/metrics/metric_spec.rb +2 -1
  78. data/lib/ting_yun/support/helper.rb +4 -0
  79. data/lib/ting_yun/support/quantile_p2.rb +204 -0
  80. data/lib/ting_yun/ting_yun_service/upload_service.rb +38 -12
  81. data/lib/ting_yun/ting_yun_service.rb +4 -7
  82. data/lib/ting_yun/version.rb +3 -1
  83. data/lib/tingyun_rpm.rb +0 -4
  84. data/tingyun_rpm.gemspec +3 -3
  85. metadata +35 -13
  86. data/CODE_OF_CONDUCT.md +0 -13
  87. data/lib/ting_yun/agent/method_tracer.rb +0 -256
@@ -12,7 +12,7 @@ module TingYun
12
12
  @queue_time_in_seconds = clamp_to_positive(queue_time_in_seconds.to_f)
13
13
  @start_time_in_seconds = clamp_to_positive(start_time_in_seconds.to_f)
14
14
 
15
- @timings = TingYun::Agent::TransactionTimings::Timings.new(0.0,0.0,0.0,0.0,0.0)
15
+ @timings = TingYun::Agent::TransactionTimings::Timings.new(0.0, 0.0, 0.0, 0.0, 0.0)
16
16
  end
17
17
 
18
18
 
@@ -27,7 +27,6 @@ module TingYun
27
27
  :mon_duration, :mon_duration=
28
28
 
29
29
 
30
-
31
30
  def start_time_as_time
32
31
  Time.at(@start_time_in_seconds)
33
32
  end
@@ -26,13 +26,16 @@ module TingYun
26
26
 
27
27
  SUBTRANSACTION_PREFIX = 'Nested/'.freeze
28
28
  CONTROLLER_PREFIX = 'WebAction/'.freeze
29
+ BACKGROUND_PREFIX = 'BackgroundAction/'.freeze
29
30
  RAKE_TRANSACTION_PREFIX = 'BackgroundAction/Rake'.freeze
30
31
  TASK_PREFIX = 'OtherTransaction/Background/'.freeze
31
32
  RACK_PREFIX = 'Rack/'.freeze
32
- SINATRA_PREFIX = 'Sinatra/'.freeze
33
+ SINATRA_PREFIX = 'WebAction/Sinatra/'.freeze
33
34
  MIDDLEWARE_PREFIX = 'Middleware/Rack/'.freeze
34
- GRAPE_PREFIX = 'Grape/'.freeze
35
- RAKE_PREFIX = 'Rake'.freeze
35
+ GRAPE_PREFIX = 'WebAction/Grape/'.freeze
36
+ RAKE_PREFIX = 'WebAction/Rake'.freeze
37
+ CABLE_PREFIX = 'WebAction/ActionCable'.freeze
38
+
36
39
 
37
40
  EMPTY_SUMMARY_METRICS = [].freeze
38
41
  MIDDLEWARE_SUMMARY_METRICS = ['Middleware/all'.freeze].freeze
@@ -57,7 +60,8 @@ module TingYun
57
60
  :guid,
58
61
  :category,
59
62
  :default_name,
60
- :start_time
63
+ :start_time,
64
+ :base_quantile_hash
61
65
 
62
66
 
63
67
 
@@ -75,6 +79,7 @@ module TingYun
75
79
  @guid = client_transaction_id || generate_guid
76
80
  @frame_stack = []
77
81
  @frozen_name = nil
82
+ @base_quantile_hash = {}
78
83
  @default_name = TingYun::Helper.correctly_encoded(options[:transaction_name])
79
84
 
80
85
  if request = options[:request]
@@ -108,7 +113,7 @@ module TingYun
108
113
 
109
114
 
110
115
 
111
- def stop(state, end_time, outermost_frame)
116
+ def stop(state, end_time, outermost_frame, summary_metrics = [])
112
117
 
113
118
  freeze_name_and_execute
114
119
 
@@ -125,7 +130,7 @@ module TingYun
125
130
  else
126
131
  summary_metrics_with_exclusive_time = EMPTY_SUMMARY_METRICS
127
132
  end
128
-
133
+ summary_metrics_with_exclusive_time = summary_metrics unless summary_metrics.empty?
129
134
 
130
135
  TingYun::Agent::MethodTracerHelpers.trace_execution_scoped_footer(
131
136
  state,
@@ -149,12 +154,13 @@ module TingYun
149
154
 
150
155
  TingYun::Agent.instance.sql_sampler.on_finishing_transaction(state, @frozen_name)
151
156
 
152
- record_summary_metrics(outermost_node_name, end_time)
157
+ record_summary_metrics(state, outermost_node_name, end_time)
153
158
  @apdex.record_apdex(@frozen_name, end_time, @exceptions.had_error?)
154
159
  @exceptions.record_exceptions(@attributes)
155
160
 
156
161
 
157
162
  TingYun::Agent.instance.stats_engine.merge_transaction_metrics!(@metrics, best_name)
163
+ TingYun::Agent.instance.stats_engine.record_base_quantile(@base_quantile_hash) if @exceptions.exceptions.empty?
158
164
  end
159
165
 
160
166
  end
@@ -46,6 +46,8 @@ module TingYun
46
46
  :rails3
47
47
  when 4
48
48
  :rails4
49
+ when 5
50
+ :rails5
49
51
  else
50
52
  ::TingYun::Agent.logger.error "Detected unsupported Rails version #{Rails::VERSION::STRING}"
51
53
  end
@@ -85,13 +87,6 @@ module TingYun
85
87
  Proc.new { ::TingYun::Frameworks.framework.local_env.discovered_dispatcher }
86
88
  end
87
89
 
88
-
89
- def self.audit_log_path
90
- Proc.new {
91
- File.join(TingYun::Agent.config[:log_file_path], 'newrelic_audit.log')
92
- }
93
- end
94
-
95
90
  # On Rubies with string encodings support (1.9.x+), default to always
96
91
  # normalize encodings since it's safest and fast. Without that support
97
92
  # the conversions are too expensive, so only enable if overridden to.
@@ -348,6 +343,27 @@ module TingYun
348
343
  :allowed_from_server => false,
349
344
  :description => 'log filename.'
350
345
  },
346
+ :agent_log_file_size => {
347
+ :default => 500,
348
+ :public => true,
349
+ :type => Fixnum,
350
+ :allowed_from_server => false,
351
+ :description => "Create a new logfile once it reaches this value. and this value's unit is MB."
352
+ },
353
+ :agent_log_file_number => {
354
+ :default => 10,
355
+ :public => true,
356
+ :type => Fixnum,
357
+ :allowed_from_server => false,
358
+ :description => "The remaining number of log file, delete the earliest when more than this value."
359
+ },
360
+ :agent_log_file_check_days => {
361
+ :default => 7,
362
+ :public => true,
363
+ :type => Fixnum,
364
+ :allowed_from_server => false,
365
+ :description => "Check for create new logfile when reach days of this value."
366
+ },
351
367
  :config_search_paths => {
352
368
  :default => DefaultSource.config_search_paths,
353
369
  :public => false,
@@ -645,6 +661,27 @@ module TingYun
645
661
  :type => Boolean,
646
662
  :allowed_from_server => true,
647
663
  :description => 'Enable or disable the thrift cross application feature'
664
+ },
665
+ :restart_thread_in_children => {
666
+ :default => true,
667
+ :public => false,
668
+ :type => Boolean,
669
+ :allowed_from_server => false,
670
+ :description => 'Controls whether to check on running a transaction whether to respawn the harvest thread.'
671
+ },
672
+ :'nbs.quantile' => {
673
+ :default => nil,
674
+ :public => true,
675
+ :type => String,
676
+ :allowed_from_server => true,
677
+ :description => 'Quantile'
678
+ },
679
+ :'nbs.mq.conume' => {
680
+ :default => false,
681
+ :public => true,
682
+ :type => Boolean,
683
+ :allowed_from_server => true,
684
+ :description => 'Enable or disable the mq feature'
648
685
  }
649
686
  }.freeze
650
687
  end
@@ -2,6 +2,7 @@
2
2
  require 'ting_yun/configuration/dotted_hash'
3
3
  require 'ting_yun/support/language_support'
4
4
  require 'erb'
5
+ require 'yaml'
5
6
 
6
7
  module TingYun
7
8
  module Configuration
@@ -32,7 +32,12 @@ module TingYun
32
32
  def load_instrumentation_files(pattern)
33
33
  Dir.glob(pattern) do |file|
34
34
  begin
35
- require file.to_s
35
+ if file.to_s.include?('instrumentation/kafka.rb')
36
+ # (**options) will report syntax error when ruby version under 2.0.0
37
+ require file.to_s if (defined? RUBY_VERSION) && (TingYun::Support::VersionNumber.new(RUBY_VERSION) >= TingYun::Support::VersionNumber.new('2.0.0'.freeze))
38
+ else
39
+ require file.to_s
40
+ end
36
41
  rescue LoadError => e
37
42
  TingYun::Agent.logger.warn "Error loading instrumentation file '#{file}':", e
38
43
  end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ require 'ting_yun/frameworks/rails4'
4
+
5
+ module TingYun
6
+ module Frameworks
7
+ class Rails5 < TingYun::Frameworks::Rails4
8
+ end
9
+ end
10
+ end
@@ -2,7 +2,7 @@
2
2
  # This file is distributed under Ting Yun's license terms.
3
3
  require 'ting_yun/frameworks/instance_methods'
4
4
  require 'ting_yun/frameworks/class_methods'
5
-
5
+ require 'yaml'
6
6
 
7
7
  module TingYun
8
8
  module Frameworks
@@ -0,0 +1,39 @@
1
+ require 'ting_yun/http/generic_request'
2
+ module TingYun
3
+ module Http
4
+ class HttpClientRequest < GenericRequest
5
+ attr_reader :method, :header
6
+
7
+ def initialize(proxy, *args, &block)
8
+ @method, @uri, @query, @body, @header = args
9
+ @proxy = proxy
10
+ @block = block
11
+ end
12
+
13
+ def type
14
+ 'HTTPClient'
15
+ end
16
+
17
+ def from
18
+ "http_client%2Fhttp"
19
+ end
20
+
21
+ def [](key)
22
+ @header[key]
23
+ end
24
+
25
+ def []=(key, value)
26
+ @header[key] = value
27
+ end
28
+
29
+ def uri
30
+ return @uri if @uri.scheme && @uri.host && @uri.port
31
+ URI("#{@proxy.scheme.downcase}://#{@proxy.host}:#{@proxy.port}#{@uri}")
32
+ end
33
+
34
+ def args
35
+ return @method, @uri, @query, @body, @header
36
+ end
37
+ end
38
+ end
39
+ end
@@ -11,6 +11,10 @@ module TingYun
11
11
  'Net::HTTP'
12
12
  end
13
13
 
14
+ def from
15
+ "net%2Fhttp"
16
+ end
17
+
14
18
  def host
15
19
  if hostname = self['host']
16
20
  hostname.split(':').first
@@ -2,10 +2,11 @@
2
2
  require 'ting_yun/agent/transaction/transaction_state'
3
3
  require 'ting_yun/instrumentation/support/active_record_helper'
4
4
  require 'ting_yun/support/helper'
5
- require 'ting_yun/agent/method_tracer'
5
+ require 'ting_yun/agent/method_tracer_helpers'
6
6
  require 'ting_yun/agent/collector/transaction_sampler'
7
7
  require 'ting_yun/agent/collector/sql_sampler'
8
8
  require 'ting_yun/agent/database'
9
+ require 'ting_yun/instrumentation/support/sinatra_helper'
9
10
 
10
11
  module TingYun
11
12
  module Instrumentation
@@ -43,14 +44,14 @@ module TingYun
43
44
 
44
45
  state = TingYun::Agent::TransactionState.tl_get
45
46
  sql, name, _ = args
46
- metrics = ::TingYun::Instrumentation::Support::ActiveRecordHelper.metrics_for(
47
+ klass_name, *metrics = ::TingYun::Instrumentation::Support::ActiveRecordHelper.metrics_for(
47
48
  TingYun::Helper.correctly_encoded(name),
48
49
  TingYun::Helper.correctly_encoded(sql),
49
- @config && @config[:adapter])
50
+ @config)
50
51
 
51
52
  scoped_metric = metrics.first
52
53
 
53
- TingYun::Agent::MethodTracer.trace_execution_scoped(metrics) do
54
+ TingYun::Agent::MethodTracerHelpers.trace_execution_scoped(metrics, {}, nil, klass_name) do
54
55
  t0 = Time.now
55
56
  begin
56
57
  log_without_tingyun_instrumentation(*args, &block)
@@ -72,10 +73,15 @@ end
72
73
  TingYun::Support::LibraryDetection.defer do
73
74
  named :active_record
74
75
 
76
+ depends_on do
77
+ !::TingYun::Agent.config[:disable_active_record]
78
+ end
79
+
75
80
  depends_on do
76
81
  defined?(::ActiveRecord) && defined?(::ActiveRecord::Base) &&
77
82
  (!defined?(::ActiveRecord::VERSION) ||
78
- ::ActiveRecord::VERSION::MAJOR.to_i <= 3)
83
+ ::ActiveRecord::VERSION::MAJOR.to_i <= 3 ||
84
+ (defined?(::Sinatra) && defined?(::Sinatra::Base) && TingYun::Instrumentation::Support::SinatraHelper.version_supported?))
79
85
  end
80
86
 
81
87
  executes do
@@ -0,0 +1,142 @@
1
+ TingYun::Support::LibraryDetection.defer do
2
+ named :bunny
3
+
4
+ depends_on do
5
+ defined?(::Bunny::VERSION) && false
6
+ end
7
+
8
+
9
+ executes do
10
+ TingYun::Agent.logger.info 'Installing bunny(for rabbitmq) Instrumentation'
11
+ require 'ting_yun/support/helper'
12
+ require 'ting_yun/instrumentation/support/external_helper'
13
+ end
14
+
15
+ executes do
16
+ ::Bunny::Exchange.class_eval do
17
+
18
+ if public_method_defined? :publish
19
+ include TingYun::Instrumentation::Support::ExternalHelper
20
+ def publish_with_tingyun(payload, opts = {})
21
+ begin
22
+ state = TingYun::Agent::TransactionState.tl_get
23
+ return publish_without_tingyun(payload, opts) unless state.execution_traced?
24
+ queue_name = opts[:routing_key]
25
+ opts[:headers] = {} unless opts[:headers]
26
+ opts[:headers][:TingyunID] = create_tingyun_id("mq")
27
+ metric_name = "Message RabbitMQ/#{@channel.connection.host}:#{@channel.connection.port}%2F"
28
+ if name.empty?
29
+ metric_name << "Queue%2F#{queue_name}/Produce"
30
+ else
31
+ metric_name << "Exchange%2F#{name}/Produce"
32
+ end
33
+
34
+ summary_metrics = TingYun::Agent::Datastore::MetricHelper.metrics_for_message('RabbitMQ', "#{@channel.connection.host}:#{@channel.connection.port}", 'Produce')
35
+ TingYun::Agent::Transaction.wrap(state, metric_name , :RabbitMq, {}, summary_metrics) do
36
+ TingYun::Agent.record_metric("#{metric_name}%2FByte",payload.bytesize) if payload
37
+ publish_without_tingyun(payload, opts)
38
+ end
39
+ rescue => e
40
+ TingYun::Agent.logger.error("Failed to Bunny publish_with_tingyun : ", e)
41
+ publish_without_tingyun(payload, opts)
42
+ end
43
+ end
44
+
45
+
46
+
47
+
48
+ alias_method :publish_without_tingyun, :publish
49
+ alias_method :publish, :publish_with_tingyun
50
+ end
51
+
52
+ end
53
+
54
+ ::Bunny::Consumer.class_eval do
55
+
56
+ if public_method_defined?(:call) && TingYun::Agent.config[:'nbs.mq.conume']
57
+
58
+ def call_with_tingyun(*args)
59
+ begin
60
+ headers = args[1]&&args[1][:headers].clone
61
+ tingyun_id_secret = headers["TingyunID"]
62
+ state = TingYun::Agent::TransactionState.tl_get
63
+ metric_name = "#{@channel.connection.host}:#{@channel.connection.port}%2FQueue%2F#{queue_name}/Consume"
64
+ summary_metrics = TingYun::Agent::Datastore::MetricHelper.metrics_for_message('RabbitMQ', "#{@channel.connection.host}:#{@channel.connection.port}", 'Consume')
65
+ TingYun::Agent::Transaction.start(state,:message, { :transaction_name => "WebAction/RabbitMQ/Queue%2F#{queue_name}/Consume"})
66
+ state.save_referring_transaction_info(tingyun_id_secret.split(';')) if cross_app_enabled?(tingyun_id_secret)
67
+ TingYun::Agent::Transaction.wrap(state, "Message RabbitMQ/#{metric_name}" , :RabbitMq, {}, summary_metrics) do
68
+ TingYun::Agent.record_metric("Message RabbitMQ/#{metric_name}%2FByte",args[2].bytesize) if args[2]
69
+ TingYun::Agent.record_metric("Message RabbitMQ/#{metric_name}%2FWait", TingYun::Helper.time_to_millis(Time.now)-state.externel_time.to_i) rescue nil
70
+ if state.current_transaction
71
+ state.add_custom_params("message.byte",args[2].bytesize)
72
+ state.add_custom_params("message.wait",TingYun::Helper.time_to_millis(Time.now)-state.externel_time.to_i)
73
+ state.add_custom_params("message.routingkey",queue_name)
74
+ headers.delete("TingyunID")
75
+ state.merge_request_parameters(headers)
76
+ end
77
+ call_without_tingyun(*args)
78
+ state.current_transaction.attributes.add_agent_attribute(:entryTrace, build_payload(state)) if state.same_account?
79
+ end
80
+ rescue => e
81
+ TingYun::Agent.logger.error("Failed to Bunny call_with_tingyun : ", e)
82
+ call_without_tingyun(*args)
83
+ ensure
84
+ TingYun::Agent::Transaction.stop(state, Time.now, summary_metrics)
85
+ end
86
+
87
+ end
88
+ alias_method :call_without_tingyun, :call
89
+ alias_method :call, :call_with_tingyun
90
+
91
+ end
92
+
93
+ def cross_app_enabled?(tingyun_id_secret)
94
+ tingyun_id_secret && ::TingYun::Agent.config[:tingyunIdSecret]
95
+ end
96
+
97
+ def build_payload(state)
98
+ timings = state.timings
99
+ payload = {
100
+ :applicationId => TingYun::Agent.config[:tingyunIdSecret].split('|')[1],
101
+ :transactionId => state.client_transaction_id,
102
+ :externalId => state.extenel_req_id,
103
+ :time => {
104
+ :duration => timings.app_time_in_millis,
105
+ :qu => timings.queue_time_in_millis,
106
+ :db => timings.sql_duration,
107
+ :ex => timings.external_duration,
108
+ :rds => timings.rds_duration,
109
+ :mc => timings.mc_duration,
110
+ :mon => timings.mon_duration,
111
+ :code => timings.app_execute_duration
112
+ }
113
+ }
114
+ payload
115
+ end
116
+ end
117
+
118
+ ::Bunny::Channel.class_eval do
119
+ if public_method_defined?(:basic_get)&& TingYun::Agent.config[:'nbs.mq.conume']
120
+ def basic_get_with_tingyun(*args)
121
+ begin
122
+ state = TingYun::Agent::TransactionState.tl_get
123
+ metric_name = "#{@connection.host}:#{@connection.port}%2FQueue%2F#{args[0]}/Consume"
124
+ summary_metrics = TingYun::Agent::Datastore::MetricHelper.metrics_for_message('RabbitMQ', "#{connection.host}:#{connection.port}", 'Consume')
125
+ TingYun::Agent::Transaction.wrap(state, "Message RabbitMQ/#{metric_name}" , :RabbitMq, {}, summary_metrics) do
126
+ basic_get_without_tingyun(*args)
127
+ end
128
+ rescue =>e
129
+ TingYun::Agent.logger.error("Failed to Bunny basic_get_with_tingyun : ", e)
130
+ basic_get_without_tingyun(*args)
131
+ ensure
132
+ TingYun::Agent::Transaction.stop(state, Time.now, summary_metrics)
133
+ end
134
+ end
135
+
136
+ alias_method :basic_get_without_tingyun, :basic_get
137
+ alias_method :basic_get, :basic_get_with_tingyun
138
+ end
139
+ end
140
+ end
141
+
142
+ end
@@ -0,0 +1,167 @@
1
+ # encoding: utf-8
2
+ require 'ting_yun/agent/transaction/transaction_state'
3
+ require 'ting_yun/instrumentation/support/active_record_helper'
4
+ require 'ting_yun/agent/method_tracer_helpers'
5
+
6
+ module TingYun::Instrumentation::DataMapper
7
+
8
+ MIN_SUPPORT_VERSION = '1.1.0.rc1'.freeze
9
+
10
+ def self.supported_version?
11
+ ::TingYun::Support::VersionNumber.new(::DataMapper::VERSION) >= ::TingYun::Support::VersionNumber.new(MIN_SUPPORT_VERSION)
12
+ end
13
+
14
+ def self.support_data_mapper?
15
+ defined?(::DataMapper) &&
16
+ ((defined?(::DataMapper::Adapters) && defined?(::DataMapper::Adapters::DataObjectsAdapter)) ||
17
+ (defined?(::DataMapper::Aggregates) && defined?(::DataMapper::Aggregates::DataObjectsAdapter))) &&
18
+ supported_version?
19
+ end
20
+
21
+ end
22
+
23
+ TingYun::Support::LibraryDetection.defer do
24
+ named :data_mapper
25
+
26
+ depends_on do
27
+ !::TingYun::Agent.config[:disable_data_mapper]
28
+ end
29
+
30
+ depends_on do
31
+ begin
32
+ require 'dm-do-adapter'
33
+ TingYun::Instrumentation::DataMapper.support_data_mapper?
34
+ rescue LoadError
35
+ false
36
+ end
37
+ end
38
+
39
+ executes do
40
+ ::TingYun::Agent.logger.info 'Installing DataMapper instrumentation'
41
+ end
42
+
43
+ executes do
44
+
45
+ if defined?(::DataMapper::Adapters) && defined?(::DataMapper::Adapters::DataObjectsAdapter)
46
+ ::DataMapper::Adapters::DataObjectsAdapter.class_eval do
47
+
48
+ def create(resources)
49
+ name = self.name
50
+
51
+ resources.each do |resource|
52
+ model = resource.model
53
+ state = TingYun::Agent::TransactionState.tl_get
54
+ *params = get_metrics_params(:create, model)
55
+ klass_name, *metrics = ::TingYun::Instrumentation::Support::ActiveRecordHelper.metrics_for_data_mapper(*params)
56
+
57
+ TingYun::Agent::MethodTracerHelpers.trace_execution_scoped(metrics, {}, nil, klass_name) do
58
+ t0 = Time.now
59
+ begin
60
+ serial = model.serial(name)
61
+ attributes = resource.dirty_attributes
62
+
63
+ properties = []
64
+ bind_values = []
65
+
66
+ # make the order of the properties consistent
67
+ model.properties(name).each do |property|
68
+ next unless attributes.key?(property)
69
+
70
+ bind_value = attributes[property]
71
+
72
+ # skip insering NULL for columns that are serial or without a default
73
+ next if bind_value.nil? && (property.serial? || !property.default?)
74
+
75
+ # if serial is being set explicitly, do not set it again
76
+ if property.equal?(serial)
77
+ serial = nil
78
+ end
79
+
80
+ properties << property
81
+ bind_values << bind_value
82
+ end
83
+
84
+ statement = insert_statement(model, properties, serial)
85
+
86
+ result = with_connection do |connection|
87
+ connection.create_command(statement).execute_non_query(*bind_values)
88
+ end
89
+
90
+ if result.affected_rows == 1 && serial
91
+ serial.set!(resource, result.insert_id)
92
+ end
93
+ ensure
94
+ elapsed_time = (Time.now - t0).to_f
95
+ state.timings.sql_duration = state.timings.sql_duration + elapsed_time * 1000
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ [:read, :update, :delete, :select, :execute].each do |method|
102
+ next unless public_method_defined? method
103
+ alias_method "#{method}_without_tingyun_trace".to_sym, method.to_sym
104
+
105
+ define_method method do |*args, &block|
106
+ state = TingYun::Agent::TransactionState.tl_get
107
+ *params = get_metrics_params(method, *args, &block)
108
+ klass_name, *metrics = ::TingYun::Instrumentation::Support::ActiveRecordHelper.metrics_for_data_mapper(*params)
109
+
110
+ TingYun::Agent::MethodTracerHelpers.trace_execution_scoped(metrics, {}, nil, klass_name) do
111
+ t0 = Time.now
112
+ begin
113
+ send "#{method}_without_tingyun_trace", *args, &block
114
+ ensure
115
+ elapsed_time = (Time.now - t0).to_f
116
+ state.timings.sql_duration = state.timings.sql_duration + elapsed_time * 1000
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ def get_metrics_params(method, *args, &block)
123
+ case method
124
+ when :read
125
+ query = args[0]
126
+ return TingYun::Helper.correctly_encoded('SELECT'), nil, self.normalized_uri, DataMapper::Inflector.classify(query.model.storage_name(name))
127
+ when :update
128
+ collection = args[1]
129
+ return TingYun::Helper.correctly_encoded('UPDATE'), nil, self.normalized_uri, DataMapper::Inflector.classify(collection.query.model.storage_name(name))
130
+ when :delete
131
+ collection = args[0]
132
+ return TingYun::Helper.correctly_encoded('DELETE'), nil, self.normalized_uri, DataMapper::Inflector.classify(collection.query.model.storage_name(name))
133
+ when :create
134
+ model = args[0]
135
+ return TingYun::Helper.correctly_encoded('INSERT'), nil, self.normalized_uri, DataMapper::Inflector.classify(model.storage_name(name))
136
+ when :select, :execute
137
+ sql = args[0]
138
+ return nil, sql, self.normalized_uri
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ if defined?(::DataMapper::Aggregates) && defined?(::DataMapper::Aggregates::DataObjectsAdapter)
145
+ ::DataMapper::Aggregates::DataObjectsAdapter.class_eval do
146
+
147
+ alias_method :aggregate_without_tingyun_trace, :aggregate
148
+
149
+ def aggregate(*args, &block)
150
+ state = TingYun::Agent::TransactionState.tl_get
151
+ *params = get_metrics_params(:read, *args, &block)
152
+ klass_name, *metrics = ::TingYun::Instrumentation::Support::ActiveRecordHelper.metrics_for_data_mapper(*params)
153
+
154
+ TingYun::Agent::MethodTracerHelpers.trace_execution_scoped(metrics, {}, nil, klass_name) do
155
+ t0 = Time.now
156
+ begin
157
+ aggregate_without_tingyun_trace(*args, &block)
158
+ ensure
159
+ elapsed_time = (Time.now - t0).to_f
160
+ state.timings.sql_duration = state.timings.sql_duration + elapsed_time * 1000
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ require 'ting_yun/agent/transaction'
3
+ require 'ting_yun/agent/transaction/transaction_state'
4
+
5
+ TingYun::Support::LibraryDetection.defer do
6
+ named :grape
7
+
8
+ depends_on do
9
+ defined?(::Grape) && defined?(::Grape::Endpoint)
10
+ end
11
+
12
+ executes do
13
+ TingYun::Agent.logger.info 'Installing grape instrumentation'
14
+ end
15
+
16
+
17
+ executes do
18
+ ::Grape::Endpoint.class_eval do
19
+ def run_with_tingyun(*args)
20
+ begin
21
+ name = ["Grape",
22
+ self.options[:method].first,
23
+ self.options[:for].to_s,
24
+ self.namespace.sub(%r{\A/}, ''), # removing leading slashes
25
+ self.options[:path].first.sub(%r{\A/}, ''),
26
+ ].compact.select{ |n| n.to_s unless n.to_s.empty? }.join("/")
27
+ TingYun::Agent::Transaction.set_default_transaction_name(name, :controller)
28
+ run_without_tingyun(*args)
29
+ rescue => e
30
+ TingYun::Agent.logger.info("Error getting Grape Endpoint Name. Error: #{e.message}. Options: #{self.options.inspect}")
31
+ end
32
+
33
+ end
34
+ alias run_without_tingyun run
35
+ alias run run_with_tingyun
36
+ end
37
+
38
+ end
39
+ end