newrelic_rpm 5.4.0.347 → 5.5.0.348

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/config.dot +0 -7
  4. data/lib/new_relic/agent/cross_app_monitor.rb +34 -64
  5. data/lib/new_relic/agent/cross_app_payload.rb +43 -0
  6. data/lib/new_relic/agent/cross_app_tracing.rb +93 -5
  7. data/lib/new_relic/agent/external.rb +17 -24
  8. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +3 -1
  9. data/lib/new_relic/agent/instrumentation/active_job.rb +12 -9
  10. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +7 -15
  11. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +8 -8
  12. data/lib/new_relic/agent/instrumentation/curb.rb +14 -6
  13. data/lib/new_relic/agent/instrumentation/data_mapper.rb +1 -1
  14. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +1 -1
  15. data/lib/new_relic/agent/instrumentation/http.rb +1 -1
  16. data/lib/new_relic/agent/instrumentation/httpclient.rb +1 -1
  17. data/lib/new_relic/agent/instrumentation/memcache.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +3 -3
  19. data/lib/new_relic/agent/instrumentation/mongo.rb +1 -1
  20. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +3 -4
  21. data/lib/new_relic/agent/instrumentation/redis.rb +3 -3
  22. data/lib/new_relic/agent/javascript_instrumentor.rb +14 -8
  23. data/lib/new_relic/agent/messaging.rb +14 -14
  24. data/lib/new_relic/agent/system_info.rb +3 -7
  25. data/lib/new_relic/agent/threading/agent_thread.rb +4 -2
  26. data/lib/new_relic/agent/transaction.rb +46 -120
  27. data/lib/new_relic/agent/transaction/abstract_segment.rb +4 -0
  28. data/lib/new_relic/agent/transaction/datastore_segment.rb +3 -2
  29. data/lib/new_relic/agent/transaction/external_request_segment.rb +3 -3
  30. data/lib/new_relic/agent/transaction/message_broker_segment.rb +1 -2
  31. data/lib/new_relic/agent/transaction/tracing.rb +1 -0
  32. data/lib/new_relic/agent/transaction_sampler.rb +1 -8
  33. data/lib/new_relic/agent/transaction_state.rb +122 -76
  34. data/lib/new_relic/version.rb +1 -1
  35. data/lib/sequel/extensions/newrelic_instrumentation.rb +2 -2
  36. data/lib/sequel/plugins/newrelic_instrumentation.rb +1 -1
  37. metadata +3 -3
  38. data/lib/new_relic/agent/transaction_timings.rb +0 -57
@@ -165,15 +165,11 @@ module NewRelic
165
165
 
166
166
  container_id = case cpu_cgroup
167
167
  # docker native driver w/out systemd (fs)
168
- when %r{^/docker/([0-9a-f]+)$} then $1
168
+ when /[0-9a-f]{64}/ then $&
169
169
  # docker native driver with systemd
170
- when %r{^/system\.slice/docker-([0-9a-f]+)\.scope$} then $1
171
- # docker lxc driver
172
- when %r{^/lxc/([0-9a-f]+)$} then $1
173
- # not in any cgroup
174
- when '/' then nil
170
+ when '/' then nil
175
171
  # in a cgroup, but we don't recognize its format
176
- when %r{docker} then
172
+ when /docker/ then
177
173
  ::NewRelic::Agent.logger.debug("Cgroup indicates docker but container_id unrecognized: '#{cpu_cgroup}'")
178
174
  ::NewRelic::Agent.increment_metric "Supportability/utilization/docker/error"
179
175
  return
@@ -38,9 +38,11 @@ module NewRelic
38
38
  profile_agent_code ? :agent : :ignore
39
39
  else
40
40
  state = TransactionState.tl_state_for(thread)
41
- if state.in_background_transaction?
41
+ txn = state.current_transaction
42
+
43
+ if txn && !txn.recording_web_transaction?
42
44
  :background
43
- elsif state.in_web_transaction?
45
+ elsif txn && txn.recording_web_transaction?
44
46
  :request
45
47
  else
46
48
  :other
@@ -2,7 +2,6 @@
2
2
  # This file is distributed under New Relic's license terms.
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
4
 
5
- require 'new_relic/agent/transaction_timings'
6
5
  require 'new_relic/agent/instrumentation/queue_time'
7
6
  require 'new_relic/agent/transaction_metrics'
8
7
  require 'new_relic/agent/method_tracer_helpers'
@@ -22,6 +21,7 @@ module NewRelic
22
21
  class Transaction
23
22
  include Tracing
24
23
  include DistributedTracing
24
+ include CrossAppTracing
25
25
 
26
26
  # for nested transactions
27
27
  SUBTRANSACTION_PREFIX = 'Nested/'.freeze
@@ -65,12 +65,12 @@ module NewRelic
65
65
  :gc_start_snapshot,
66
66
  :category,
67
67
  :frame_stack,
68
- :cat_path_hashes,
69
68
  :attributes,
70
69
  :payload,
71
70
  :nesting_max_depth,
72
71
  :segments,
73
- :end_time
72
+ :end_time,
73
+ :duration
74
74
 
75
75
  attr_writer :sampled,
76
76
  :priority
@@ -123,7 +123,7 @@ module NewRelic
123
123
  txn = state.current_transaction
124
124
 
125
125
  if txn
126
- txn.create_nested_frame(state, category, options)
126
+ txn.create_nested_frame(category, options)
127
127
  else
128
128
  txn = start_new_transaction(state, category, options)
129
129
  end
@@ -138,13 +138,13 @@ module NewRelic
138
138
  txn = Transaction.new(category, options)
139
139
  state.reset(txn)
140
140
  txn.state = state
141
- txn.start(state)
141
+ txn.start
142
142
  txn
143
143
  end
144
144
 
145
145
  FAILED_TO_STOP_MESSAGE = "Failed during Transaction.stop because there is no current transaction"
146
146
 
147
- def self.stop(state, end_time=Time.now)
147
+ def self.stop(state)
148
148
  txn = state.current_transaction
149
149
 
150
150
  if txn.nil?
@@ -155,7 +155,7 @@ module NewRelic
155
155
  nested_frame = txn.frame_stack.pop
156
156
 
157
157
  if txn.frame_stack.empty?
158
- txn.stop(state, end_time, nested_frame)
158
+ txn.stop(nested_frame) if nested_frame
159
159
  state.reset
160
160
  else
161
161
  nested_frame.finish
@@ -181,7 +181,7 @@ module NewRelic
181
181
  def self.abort_transaction! #THREAD_LOCAL_ACCESS
182
182
  state = NewRelic::Agent::TransactionState.tl_get
183
183
  txn = state.current_transaction
184
- txn.abort_transaction!(state) if txn
184
+ txn.abort_transaction! if txn
185
185
  end
186
186
 
187
187
  # See NewRelic::Agent.notice_error for options and commentary
@@ -269,6 +269,7 @@ module NewRelic
269
269
  @category = category
270
270
  @start_time = Time.now
271
271
  @end_time = nil
272
+ @duration = nil
272
273
  @apdex_start = options[:apdex_start_time] || @start_time
273
274
  @jruby_cpu_start = jruby_cpu_time
274
275
  @process_cpu_start = process_cpu
@@ -278,7 +279,6 @@ module NewRelic
278
279
  @exceptions = {}
279
280
  @metrics = TransactionMetrics.new
280
281
  @guid = generate_guid
281
- @cat_path_hashes = nil
282
282
 
283
283
  @ignore_this_transaction = false
284
284
  @ignore_apdex = options.fetch(:ignore_apdex, false)
@@ -401,10 +401,6 @@ module NewRelic
401
401
  alias_method :transaction_name, :best_name
402
402
 
403
403
  attr_accessor :xray_session_id
404
-
405
- def duration
406
- (@end_time - @start_time).to_f
407
- end
408
404
  # End common interface
409
405
 
410
406
  def name_set?
@@ -442,7 +438,7 @@ module NewRelic
442
438
  @frozen_name ? true : false
443
439
  end
444
440
 
445
- def start(state)
441
+ def start
446
442
  return if !state.is_execution_traced?
447
443
 
448
444
  sql_sampler.on_start_transaction(state, start_time, request_path)
@@ -481,7 +477,7 @@ module NewRelic
481
477
  segment
482
478
  end
483
479
 
484
- def create_nested_frame(state, category, options)
480
+ def create_nested_frame(category, options)
485
481
  if options[:filtered_params] && !options[:filtered_params].empty?
486
482
  @filtered_params = options[:filtered_params]
487
483
  merge_request_parameters(options[:filtered_params])
@@ -503,7 +499,7 @@ module NewRelic
503
499
 
504
500
  # Call this to ensure that the current transaction trace is not saved
505
501
  # To fully ignore all metrics and errors, use ignore! instead.
506
- def abort_transaction!(state)
502
+ def abort_transaction!
507
503
  @ignore_trace = true
508
504
  end
509
505
 
@@ -531,10 +527,12 @@ module NewRelic
531
527
  name.start_with?(MIDDLEWARE_PREFIX)
532
528
  end
533
529
 
534
- def stop(state, end_time, outermost_frame)
530
+ def stop(outermost_frame = nil)
535
531
  return if !state.is_execution_traced?
532
+ return self.class.stop(state) unless outermost_frame
536
533
 
537
- @end_time = end_time
534
+ @end_time = Time.now
535
+ @duration = @end_time.to_f - @start_time.to_f
538
536
  freeze_name_and_execute_if_not_ignored
539
537
 
540
538
  if nesting_max_depth == 1
@@ -543,9 +541,9 @@ module NewRelic
543
541
 
544
542
  outermost_frame.finish
545
543
 
546
- NewRelic::Agent::TransactionTimeAggregator.transaction_stop(end_time)
544
+ NewRelic::Agent::TransactionTimeAggregator.transaction_stop(@end_time)
547
545
 
548
- commit!(state, end_time, outermost_frame.name) unless @ignore_this_transaction
546
+ commit!(outermost_frame.name) unless @ignore_this_transaction
549
547
  end
550
548
 
551
549
  def user_defined_rules_ignore?
@@ -557,22 +555,22 @@ module NewRelic
557
555
  end
558
556
  end
559
557
 
560
- def commit!(state, end_time, outermost_node_name)
561
- generate_payload(state, start_time, end_time)
558
+ def commit!(outermost_node_name)
559
+ generate_payload
562
560
 
563
561
  assign_agent_attributes
564
- assign_intrinsics(state)
562
+ assign_intrinsics
565
563
 
566
564
  finalize_segments
567
565
 
568
- @transaction_trace = transaction_sampler.on_finishing_transaction(state, self, end_time)
566
+ @transaction_trace = transaction_sampler.on_finishing_transaction(self)
569
567
  sql_sampler.on_finishing_transaction(state, @frozen_name)
570
568
 
571
- record_summary_metrics(outermost_node_name, end_time)
569
+ record_summary_metrics(outermost_node_name)
572
570
  record_total_time_metrics
573
- record_apdex(state, end_time) unless ignore_apdex?
571
+ record_apdex unless ignore_apdex?
574
572
  record_queue_time
575
- record_client_application_metric state
573
+ record_cross_app_metrics
576
574
  record_distributed_tracing_metrics
577
575
 
578
576
  record_exceptions
@@ -608,7 +606,7 @@ module NewRelic
608
606
  end
609
607
  end
610
608
 
611
- def assign_intrinsics(state)
609
+ def assign_intrinsics
612
610
  attributes.add_intrinsic_attribute(:priority, priority)
613
611
 
614
612
  if gc_time = calculate_gc_time
@@ -627,9 +625,8 @@ module NewRelic
627
625
 
628
626
  if Agent.config[:'distributed_tracing.enabled']
629
627
  assign_distributed_trace_intrinsics
630
- elsif state.is_cross_app?
631
- attributes.add_intrinsic_attribute(:trip_id, cat_trip_id)
632
- attributes.add_intrinsic_attribute(:path_hash, cat_path_hash)
628
+ elsif is_cross_app?
629
+ assign_cross_app_intrinsics
633
630
  end
634
631
  end
635
632
 
@@ -640,10 +637,10 @@ module NewRelic
640
637
 
641
638
  # The summary metrics recorded by this method all end up with a duration
642
639
  # equal to the transaction itself, and an exclusive time of zero.
643
- def record_summary_metrics(outermost_node_name, end_time)
640
+ def record_summary_metrics(outermost_node_name)
644
641
  metrics = summary_metrics
645
642
  metrics << @frozen_name unless @frozen_name == outermost_node_name
646
- @metrics.record_unscoped(metrics, end_time.to_f - start_time.to_f, 0)
643
+ @metrics.record_unscoped(metrics, duration, 0)
647
644
  end
648
645
 
649
646
  # This event is fired when the transaction is fully completed. The metric
@@ -652,8 +649,7 @@ module NewRelic
652
649
  agent.events.notify(:transaction_finished, payload)
653
650
  end
654
651
 
655
- def generate_payload(state, start_time, end_time)
656
- duration = end_time.to_f - start_time.to_f
652
+ def generate_payload
657
653
  @payload = {
658
654
  :name => @frozen_name,
659
655
  :bucket => recording_web_transaction? ? :request : :background,
@@ -665,38 +661,14 @@ module NewRelic
665
661
  :priority => priority
666
662
  }
667
663
 
668
- append_cat_info(state, duration, @payload)
664
+ append_cat_info(@payload)
669
665
  append_distributed_trace_info(@payload)
670
- append_apdex_perf_zone(duration, @payload)
671
- append_synthetics_to(state, @payload)
672
- append_referring_transaction_guid_to(state, @payload)
673
- end
674
-
675
- def include_guid?(state, duration)
676
- state.is_cross_app? || is_synthetics_request?
677
- end
678
-
679
- def cat_trip_id
680
- NewRelic::Agent.instance.cross_app_monitor.client_referring_transaction_trip_id(state) || guid
681
- end
682
-
683
- def cat_path_hash
684
- referring_path_hash = cat_referring_path_hash(state) || '0'
685
- seed = referring_path_hash.to_i(16)
686
- result = NewRelic::Agent.instance.cross_app_monitor.path_hash(best_name, seed)
687
- record_cat_path_hash(result)
688
- result
689
- end
690
-
691
- def record_cat_path_hash(hash)
692
- @cat_path_hashes ||= []
693
- if @cat_path_hashes.size < 10 && !@cat_path_hashes.include?(hash)
694
- @cat_path_hashes << hash
695
- end
666
+ append_apdex_perf_zone(@payload)
667
+ append_synthetics_to(@payload)
696
668
  end
697
669
 
698
- def cat_referring_path_hash(state)
699
- NewRelic::Agent.instance.cross_app_monitor.client_referring_transaction_path_hash(state)
670
+ def include_guid?
671
+ is_cross_app? || is_synthetics_request?
700
672
  end
701
673
 
702
674
  def is_synthetics_request?
@@ -732,7 +704,7 @@ module NewRelic
732
704
  APDEX_T = 'T'.freeze
733
705
  APDEX_F = 'F'.freeze
734
706
 
735
- def append_apdex_perf_zone(duration, payload)
707
+ def append_apdex_perf_zone(payload)
736
708
  if recording_web_transaction?
737
709
  bucket = apdex_bucket(duration, apdex_t)
738
710
  elsif background_apdex_t = transaction_specific_apdex_t
@@ -750,29 +722,7 @@ module NewRelic
750
722
  payload[:apdex_perf_zone] = bucket_str if bucket_str
751
723
  end
752
724
 
753
- def append_cat_info(state, duration, payload)
754
- return unless include_guid?(state, duration)
755
- payload[:guid] = guid
756
-
757
- return unless state.is_cross_app?
758
- trip_id = cat_trip_id
759
- path_hash = cat_path_hash
760
- referring_path_hash = cat_referring_path_hash(state)
761
-
762
- payload[:cat_trip_id] = trip_id if trip_id
763
- payload[:cat_referring_path_hash] = referring_path_hash if referring_path_hash
764
-
765
- if path_hash
766
- payload[:cat_path_hash] = path_hash
767
-
768
- alternate_path_hashes = cat_path_hashes - [path_hash]
769
- unless alternate_path_hashes.empty?
770
- payload[:cat_alternate_path_hashes] = alternate_path_hashes
771
- end
772
- end
773
- end
774
-
775
- def append_synthetics_to(state, payload)
725
+ def append_synthetics_to(payload)
776
726
  return unless is_synthetics_request?
777
727
 
778
728
  payload[:synthetics_resource_id] = synthetics_resource_id
@@ -780,13 +730,6 @@ module NewRelic
780
730
  payload[:synthetics_monitor_id] = synthetics_monitor_id
781
731
  end
782
732
 
783
- def append_referring_transaction_guid_to(state, payload)
784
- referring_guid = NewRelic::Agent.instance.cross_app_monitor.client_referring_transaction_guid(state)
785
- if referring_guid
786
- payload[:referring_transaction_guid] = referring_guid
787
- end
788
- end
789
-
790
733
  def merge_metrics
791
734
  NewRelic::Agent.instance.stats_engine.merge_transaction_metrics!(@metrics, best_name)
792
735
  end
@@ -834,12 +777,6 @@ module NewRelic
834
777
  end
835
778
  end
836
779
 
837
- def record_client_application_metric state
838
- if id = state.client_cross_app_id
839
- NewRelic::Agent.record_metric "ClientApplication/#{id}/all", state.timings.app_time_in_seconds
840
- end
841
- end
842
-
843
780
  APDEX_ALL_METRIC = 'ApdexAll'.freeze
844
781
 
845
782
  APDEX_METRIC = 'Apdex'.freeze
@@ -862,28 +799,26 @@ module NewRelic
862
799
  self.class.apdex_bucket(duration, had_error_affecting_apdex?, current_apdex_t)
863
800
  end
864
801
 
865
- def record_apdex(state, end_time=Time.now)
802
+ def record_apdex
866
803
  return unless state.is_execution_traced?
867
804
 
868
805
  freeze_name_and_execute_if_not_ignored do
869
- total_duration = end_time - apdex_start
870
- action_duration = end_time - start_time
871
-
872
806
  if recording_web_transaction?
873
- record_apdex_metrics(APDEX_METRIC, APDEX_TXN_METRIC_PREFIX,
874
- total_duration, action_duration, apdex_t)
807
+ record_apdex_metrics(APDEX_METRIC, APDEX_TXN_METRIC_PREFIX, apdex_t)
875
808
  else
876
- record_apdex_metrics(APDEX_OTHER_METRIC, APDEX_OTHER_TXN_METRIC_PREFIX,
877
- total_duration, action_duration, transaction_specific_apdex_t)
809
+ record_apdex_metrics(APDEX_OTHER_METRIC,
810
+ APDEX_OTHER_TXN_METRIC_PREFIX,
811
+ transaction_specific_apdex_t)
878
812
  end
879
813
  end
880
814
  end
881
815
 
882
- def record_apdex_metrics(rollup_metric, transaction_prefix, total_duration, action_duration, current_apdex_t)
816
+ def record_apdex_metrics(rollup_metric, transaction_prefix, current_apdex_t)
883
817
  return unless current_apdex_t
884
818
 
819
+ total_duration = end_time - apdex_start
885
820
  apdex_bucket_global = apdex_bucket(total_duration, current_apdex_t)
886
- apdex_bucket_txn = apdex_bucket(action_duration, current_apdex_t)
821
+ apdex_bucket_txn = apdex_bucket(duration, current_apdex_t)
887
822
 
888
823
  @metrics.record_unscoped(rollup_metric, apdex_bucket_global, current_apdex_t)
889
824
  @metrics.record_unscoped(APDEX_ALL_METRIC, apdex_bucket_global, current_apdex_t)
@@ -983,15 +918,6 @@ module NewRelic
983
918
  @ignore_trace
984
919
  end
985
920
 
986
- def add_message_cat_headers headers
987
- state.is_cross_app_caller = true
988
- CrossAppTracing.insert_message_headers headers,
989
- guid,
990
- cat_trip_id,
991
- cat_path_hash,
992
- raw_synthetics_header
993
- end
994
-
995
921
  private
996
922
 
997
923
  def process_cpu
@@ -115,6 +115,10 @@ module NewRelic
115
115
  sprintf('#<%s:0x%x %s>', self.class.name, object_id, ivars.join(', '))
116
116
  end
117
117
 
118
+ # callback for subclasses to override
119
+ def transaction_assigned
120
+ end
121
+
118
122
  protected
119
123
 
120
124
  attr_writer :range_recorded
@@ -15,7 +15,7 @@ module NewRelic
15
15
  UNKNOWN = 'unknown'.freeze
16
16
 
17
17
  attr_reader :product, :operation, :collection, :sql_statement, :nosql_statement, :host, :port_path_or_id
18
- attr_accessor :database_name
18
+ attr_accessor :database_name, :record_sql
19
19
 
20
20
 
21
21
  def initialize product, operation, collection = nil, host = nil, port_path_or_id = nil, database_name = nil, start_time = nil
@@ -24,6 +24,7 @@ module NewRelic
24
24
  @collection = collection
25
25
  @sql_statement = nil
26
26
  @nosql_statement = nil
27
+ @record_sql = true
27
28
  set_instance_info host, port_path_or_id
28
29
  @database_name = database_name ? database_name.to_s : nil
29
30
  super Datastores::MetricHelper.scoped_metric_for(product, operation, collection),
@@ -135,7 +136,7 @@ module NewRelic
135
136
  end
136
137
 
137
138
  def record_sql?
138
- transaction_state.is_sql_recorded?
139
+ transaction_state.is_sql_recorded? && @record_sql
139
140
  end
140
141
 
141
142
  def record_span_event