newrelic_rpm 3.9.7.266 → 3.9.8.273

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +44 -1
  3. data/lib/new_relic/agent.rb +31 -0
  4. data/lib/new_relic/agent/agent.rb +34 -5
  5. data/lib/new_relic/agent/configuration/default_source.rb +25 -1
  6. data/lib/new_relic/agent/configuration/high_security_source.rb +1 -0
  7. data/lib/new_relic/agent/cross_app_monitor.rb +1 -1
  8. data/lib/new_relic/agent/custom_event_aggregator.rb +2 -4
  9. data/lib/new_relic/agent/error_collector.rb +17 -12
  10. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +9 -8
  11. data/lib/new_relic/agent/instrumentation/grape.rb +67 -0
  12. data/lib/new_relic/agent/new_relic_service.rb +93 -43
  13. data/lib/new_relic/agent/pipe_service.rb +4 -0
  14. data/lib/new_relic/agent/synthetics_event_buffer.rb +42 -0
  15. data/lib/new_relic/agent/system_info.rb +44 -18
  16. data/lib/new_relic/agent/transaction_event_aggregator.rb +9 -2
  17. data/lib/new_relic/agent/utilization_data.rb +77 -0
  18. data/lib/new_relic/agent/vm/mri_vm.rb +3 -3
  19. data/lib/new_relic/rack/agent_hooks.rb +15 -15
  20. data/lib/new_relic/recipes/capistrano3.rb +2 -2
  21. data/lib/new_relic/version.rb +1 -1
  22. data/newrelic_rpm.gemspec +0 -1
  23. data/test/agent_helper.rb +13 -3
  24. data/test/environments/lib/environments/runner.rb +3 -19
  25. data/test/environments/rails42/Gemfile +5 -1
  26. data/test/fixtures/cross_agent_tests/README.md +1 -1
  27. data/test/fixtures/cross_agent_tests/cat_map.json +154 -88
  28. data/test/fixtures/cross_agent_tests/docker_container_id/cases.json +30 -6
  29. data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.1.2-lxc-driver.txt +10 -0
  30. data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.1.2-native-driver-fs.txt +10 -0
  31. data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.1.2-native-driver-systemd.txt +10 -0
  32. data/test/fixtures/cross_agent_tests/docker_container_id/heroku.txt +1 -0
  33. data/test/fixtures/cross_agent_tests/docker_container_id/ubuntu-14.04-lxc-container.txt +10 -0
  34. data/test/fixtures/cross_agent_tests/docker_container_id/{lxc-containers-without-docker.txt → ubuntu-14.04-no-container.txt} +0 -0
  35. data/test/fixtures/cross_agent_tests/docker_container_id/ubuntu-14.10-no-container.txt +10 -0
  36. data/test/multiverse/lib/multiverse/runner.rb +1 -0
  37. data/test/multiverse/lib/multiverse/suite.rb +6 -2
  38. data/test/multiverse/suites/active_record/.gitignore +1 -0
  39. data/test/multiverse/suites/active_record/Envfile +25 -7
  40. data/test/multiverse/suites/active_record/Rakefile +9 -0
  41. data/test/{new_relic/agent/instrumentation → multiverse/suites/active_record}/active_record_test.rb +82 -88
  42. data/test/multiverse/suites/active_record/app/models/models.rb +27 -0
  43. data/test/multiverse/suites/active_record/ar_method_aliasing.rb +5 -46
  44. data/test/multiverse/suites/active_record/before_suite.rb +23 -0
  45. data/test/multiverse/suites/active_record/config/database.rb +79 -0
  46. data/test/multiverse/suites/active_record/config/database.yml +19 -0
  47. data/test/multiverse/suites/active_record/db/migrate/20141105131800_create_users_and_aliases.rb +21 -0
  48. data/test/multiverse/suites/active_record/db/migrate/20141106082200_create_orders_and_shipments.rb +25 -0
  49. data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +4 -1
  50. data/test/multiverse/suites/agent_only/custom_analytics_events_test.rb +53 -0
  51. data/test/multiverse/suites/agent_only/keepalive_test.rb +3 -7
  52. data/test/multiverse/suites/agent_only/utilization_data_collection_test.rb +170 -0
  53. data/test/multiverse/suites/grape/Envfile +15 -0
  54. data/test/multiverse/suites/grape/config/newrelic.yml +18 -0
  55. data/test/multiverse/suites/grape/grape_test.rb +60 -0
  56. data/test/multiverse/suites/grape/grape_test_api.rb +43 -0
  57. data/test/multiverse/suites/grape/unsupported_version_test.rb +31 -0
  58. data/test/multiverse/suites/json/Envfile +3 -1
  59. data/test/multiverse/suites/rack/rack_env_mutation_test.rb +54 -0
  60. data/test/multiverse/suites/rails/Envfile +1 -1
  61. data/test/multiverse/suites/rails/view_instrumentation_test.rb +2 -1
  62. data/test/multiverse/suites/resque/resque_marshalling_test.rb +54 -0
  63. data/test/multiverse/suites/typhoeus/Envfile +4 -4
  64. data/test/new_relic/agent/agent_test.rb +37 -0
  65. data/test/new_relic/agent/configuration/default_source_test.rb +14 -0
  66. data/test/new_relic/agent/custom_event_aggregator_test.rb +3 -3
  67. data/test/new_relic/agent/error_collector/notice_error_test.rb +4 -4
  68. data/test/new_relic/agent/error_collector_test.rb +27 -4
  69. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +23 -0
  70. data/test/new_relic/agent/new_relic_service_test.rb +208 -103
  71. data/test/new_relic/agent/pipe_service_test.rb +7 -0
  72. data/test/new_relic/agent/synthetics_event_buffer_test.rb +54 -0
  73. data/test/new_relic/agent/synthetics_monitor_test.rb +0 -3
  74. data/test/new_relic/agent/system_info_test.rb +6 -6
  75. data/test/new_relic/agent/transaction_event_aggregator_test.rb +43 -2
  76. data/test/new_relic/agent/utilization_data_test.rb +18 -0
  77. data/test/new_relic/collection_helper_test.rb +0 -1
  78. data/test/new_relic/data_container_tests.rb +11 -7
  79. data/test/new_relic/fake_collector.rb +23 -0
  80. data/test/new_relic/fake_instance_metadata_service.rb +45 -0
  81. data/test/new_relic/license_test.rb +2 -0
  82. data/test/new_relic/marshalling_test_cases.rb +89 -4
  83. data/test/new_relic/transaction_sample_test.rb +1 -0
  84. data/test/test_helper.rb +1 -0
  85. metadata +33 -6
  86. metadata.gz.sig +1 -2
  87. data/test/active_record_fixtures.rb +0 -79
  88. data/test/new_relic/rack/all_test.rb +0 -14
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -1,12 +1,55 @@
1
1
  # New Relic Ruby Agent Release Notes #
2
2
 
3
+ ## v3.9.8 ##
4
+
5
+ * Custom Insights events API
6
+
7
+ In addition to attaching custom parameters to the events that the Ruby agent
8
+ generates automatically for each transaction, you can now record custom event
9
+ types into Insights with the new NewRelic::Agent.record_custom_event API.
10
+
11
+ For details, see https://docs.newrelic.com/docs/insights/new-relic-insights/adding-querying-data/inserting-custom-events-new-relic-agents
12
+
13
+ * Reduced memory usage for idling applications
14
+
15
+ Idling applications using the agent could previously appear to leak memory
16
+ because of native allocations during creation of new SSL connections to our
17
+ servers. These native allocations didn't factor into triggering Ruby's
18
+ garbage collector.
19
+
20
+ The agent will now re-use a single TCP connection to our servers for as long
21
+ as possible, resulting in improved memory usage for applications that are
22
+ idling and not having GC triggered for other reasons.
23
+
24
+ * Don't write to stderr during CPU sampling
25
+
26
+ The Ruby agent's code for gathering CPU information would write error
27
+ messages to stderr on some FreeBSD systems. This has been fixed.
28
+
29
+ * LocalJumpError on Rails 2.x
30
+
31
+ Under certain conditions, Rails 2.x controller instrumentation could fail
32
+ with a LocalJumpError when an action was not being traced. This has been
33
+ fixed.
34
+
35
+ * Fixed config lookup in warbler packaged apps
36
+
37
+ When running a Ruby application from a standalone warbler .jar file on
38
+ JRuby, the packaged config/newrelic.yml was not properly found. This has
39
+ been fixed, and thanks to Bob Beaty for the help getting it fixed!
40
+
41
+ * Hash iteration failure in middleware
42
+
43
+ If a background thread iterated over the keys in the Rack env hash, it could
44
+ cause failures in New Relic's AgentHooks middleware. This has been fixed.
45
+
3
46
  ## v3.9.7 ##
4
47
 
5
48
  * Support for New Relic Synthetics
6
49
 
7
50
  The Ruby agent now gives you additional information for requests from New
8
51
  Relic Synthetics. More transaction traces and events give you a clearer look
9
- into how your applicaiton is performing around the world.
52
+ into how your application is performing around the world.
10
53
 
11
54
  For more details, see https://docs.newrelic.com/docs/synthetics/new-relic-synthetics/getting-started/new-relic-synthetics
12
55
 
@@ -455,6 +455,37 @@ module NewRelic
455
455
  agent.pop_trace_execution_flag
456
456
  end
457
457
 
458
+ # Record a custom event to be sent to New Relic Insights.
459
+ # The recorded event will be buffered in memory until the next time the
460
+ # agent sends data to New Relic's servers.
461
+ #
462
+ # If you want to be able to tie the information recorded via this call back
463
+ # to the web request or background job that it happened in, you may want to
464
+ # instead use the add_custom_parameters API call to attach attributes to
465
+ # the Transaction event that will automatically be generated for the
466
+ # request.
467
+ #
468
+ # A timestamp will be automatically added to the recorded event when this
469
+ # method is called.
470
+ #
471
+ # @param [Symbol or String] event_type The name of the event type to record. Event
472
+ # types must consist of only alphanumeric
473
+ # characters, '_', ':', or ' '.
474
+ #
475
+ # @param [Hash] event_attrs A Hash of attributes to be attached to the event.
476
+ # Keys should be strings or symbols, and values
477
+ # may be strings, symbols, numeric values or
478
+ # booleans.
479
+ #
480
+ # @api public
481
+ #
482
+ def record_custom_event(event_type, event_attrs)
483
+ if agent && NewRelic::Agent.config[:'custom_insights_events.enabled']
484
+ agent.custom_event_aggregator.record(event_type, event_attrs)
485
+ end
486
+ nil
487
+ end
488
+
458
489
  # Check to see if we are capturing metrics currently on this thread.
459
490
  def tl_is_execution_traced?
460
491
  NewRelic::Agent::TransactionState.tl_get.is_execution_traced?
@@ -20,11 +20,13 @@ require 'new_relic/agent/commands/agent_command_router'
20
20
  require 'new_relic/agent/event_listener'
21
21
  require 'new_relic/agent/cross_app_monitor'
22
22
  require 'new_relic/agent/synthetics_monitor'
23
+ require 'new_relic/agent/synthetics_event_buffer'
23
24
  require 'new_relic/agent/transaction_event_aggregator'
24
25
  require 'new_relic/agent/custom_event_aggregator'
25
26
  require 'new_relic/agent/sampler_collection'
26
27
  require 'new_relic/agent/javascript_instrumentor'
27
28
  require 'new_relic/agent/vm/monotonic_gc_profiler'
29
+ require 'new_relic/agent/utilization_data'
28
30
  require 'new_relic/environment_report'
29
31
 
30
32
  module NewRelic
@@ -52,10 +54,11 @@ module NewRelic
52
54
  @cross_app_monitor = NewRelic::Agent::CrossAppMonitor.new(@events)
53
55
  @synthetics_monitor = NewRelic::Agent::SyntheticsMonitor.new(@events)
54
56
  @error_collector = NewRelic::Agent::ErrorCollector.new
57
+ @utilization_data = NewRelic::Agent::UtilizationData.new
55
58
  @transaction_rules = NewRelic::Agent::RulesEngine.new
56
59
  @harvest_samplers = NewRelic::Agent::SamplerCollection.new(@events)
57
- @javascript_instrumentor = NewRelic::Agent::JavascriptInstrumentor.new(@events)
58
60
  @monotonic_gc_profiler = NewRelic::Agent::VM::MonotonicGCProfiler.new
61
+ @javascript_instrumentor = NewRelic::Agent::JavascriptInstrumentor.new(@events)
59
62
 
60
63
  @harvester = NewRelic::Agent::Harvester.new(@events)
61
64
  @after_fork_lock = Mutex.new
@@ -583,6 +586,7 @@ module NewRelic
583
586
  # Never allow any data type to be reported more frequently than once
584
587
  # per second.
585
588
  MIN_ALLOWED_REPORT_PERIOD = 1.0
589
+ UTILIZATION_REPORT_PERIOD = 30 * 60 # every half hour
586
590
 
587
591
  def report_period_for(method)
588
592
  config_key = "data_report_periods.#{method}".to_sym
@@ -614,6 +618,15 @@ module NewRelic
614
618
  @event_loop.fire_every(Agent.config[:data_report_period], :report_data)
615
619
  @event_loop.fire_every(report_period_for(:analytic_event_data), :report_event_data)
616
620
  @event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
621
+
622
+ if Agent.config[:collect_utilization] && !in_resque_child_process?
623
+ @event_loop.on(:report_utilization_data) do
624
+ transmit_utilization_data
625
+ end
626
+ @event_loop.fire(:report_utilization_data)
627
+ @event_loop.fire_every(UTILIZATION_REPORT_PERIOD, :report_utilization_data)
628
+ end
629
+
617
630
  @event_loop.run
618
631
  end
619
632
 
@@ -882,6 +895,7 @@ module NewRelic
882
895
  when :transaction_sample_data then @transaction_sampler
883
896
  when :error_data then @error_collector
884
897
  when :analytic_event_data then @transaction_event_aggregator
898
+ when :custom_event_data then @custom_event_aggregator
885
899
  when :sql_trace_data then @sql_sampler
886
900
  end
887
901
  end
@@ -1043,7 +1057,11 @@ module NewRelic
1043
1057
 
1044
1058
  def harvest_and_send_analytic_event_data
1045
1059
  harvest_and_send_from_container(@transaction_event_aggregator, :analytic_event_data)
1046
- harvest_and_send_from_container(@custom_event_aggregator, :analytic_event_data)
1060
+ harvest_and_send_from_container(@custom_event_aggregator, :custom_event_data)
1061
+ end
1062
+
1063
+ def harvest_and_send_utilization_data
1064
+ harvest_and_send_from_container(@utilization_data, :utilization_data)
1047
1065
  end
1048
1066
 
1049
1067
  def check_for_and_handle_agent_commands
@@ -1071,17 +1089,27 @@ module NewRelic
1071
1089
  end
1072
1090
 
1073
1091
  def transmit_event_data
1092
+ transmit_single_data_type(:harvest_and_send_analytic_event_data, "TransactionEvent")
1093
+ end
1094
+
1095
+ def transmit_utilization_data
1096
+ transmit_single_data_type(:harvest_and_send_utilization_data, "UtilizationData")
1097
+ end
1098
+
1099
+ def transmit_single_data_type(harvest_method, supportability_name)
1074
1100
  now = Time.now
1075
- ::NewRelic::Agent.logger.debug "Sending analytics data to New Relic Service"
1101
+
1102
+ msg = "Sending #{harvest_method.to_s.gsub("harvest_and_send_", "")} to New Relic Service"
1103
+ ::NewRelic::Agent.logger.debug msg
1076
1104
 
1077
1105
  harvest_lock.synchronize do
1078
1106
  @service.session do # use http keep-alive
1079
- harvest_and_send_analytic_event_data
1107
+ self.send(harvest_method)
1080
1108
  end
1081
1109
  end
1082
1110
  ensure
1083
1111
  duration = (Time.now - now).to_f
1084
- NewRelic::Agent.record_metric('Supportability/TransactionEventHarvest', duration)
1112
+ NewRelic::Agent.record_metric("Supportability/#{supportability_name}Harvest", duration)
1085
1113
  end
1086
1114
 
1087
1115
  # This method is expected to only be called with the harvest_lock
@@ -1123,6 +1151,7 @@ module NewRelic
1123
1151
  @events.notify(:before_shutdown)
1124
1152
  transmit_data
1125
1153
  transmit_event_data
1154
+ transmit_utilization_data if NewRelic::Agent.config[:collect_utilization]
1126
1155
 
1127
1156
  if @connected_pid == $$ && !@service.kind_of?(NewRelic::Agent::NewRelicService)
1128
1157
  ::NewRelic::Agent.logger.debug "Sending New Relic service agent run shutdown message"
@@ -49,6 +49,12 @@ module NewRelic
49
49
  paths << File.join(ENV["HOME"], "newrelic.yml")
50
50
  end
51
51
 
52
+ # If we're packaged for warbler, we can tell from GEM_HOME
53
+ if ENV["GEM_HOME"] && ENV["GEM_HOME"].end_with?(".jar!")
54
+ app_name = File.basename(ENV["GEM_HOME"], ".jar!")
55
+ paths << File.join(ENV["GEM_HOME"], app_name, "config", "newrelic.yml")
56
+ end
57
+
52
58
  paths
53
59
  }
54
60
  end
@@ -1092,7 +1098,7 @@ module NewRelic
1092
1098
  :description => 'A dictionary of label names and values that will be applied to the data sent from this agent. May also be expressed as a semi-colon delimited string of colon-separated pairs (e.g. "Server:One;Data Center:Primary".'
1093
1099
  },
1094
1100
  :aggressive_keepalive => {
1095
- :default => false,
1101
+ :default => true,
1096
1102
  :public => false,
1097
1103
  :type => Boolean,
1098
1104
  :description => 'If true, attempt to keep the TCP connection to the collector alive between harvests.'
@@ -1110,6 +1116,12 @@ module NewRelic
1110
1116
  :type => String,
1111
1117
  :description => "Manual override for the path to your local CA bundle. This CA bundle will be used to validate the SSL certificate presented by New Relic's data collection service."
1112
1118
  },
1119
+ :collect_utilization => {
1120
+ :default => false,
1121
+ :public => false,
1122
+ :type => Boolean,
1123
+ :description => "Controls whether to collect processor and instance sizing data and send it to New Relic"
1124
+ },
1113
1125
  :'rules.ignore_url_regexes' => {
1114
1126
  :default => [],
1115
1127
  :public => true,
@@ -1129,12 +1141,24 @@ module NewRelic
1129
1141
  :type => Fixnum,
1130
1142
  :description => 'Maximum number of synthetics transaction events to hold for a given harvest'
1131
1143
  },
1144
+ :'custom_insights_events.enabled' => {
1145
+ :default => true,
1146
+ :public => true,
1147
+ :type => Boolean,
1148
+ :description => 'Enable or disable custom Insights event recording.'
1149
+ },
1132
1150
  :'custom_insights_events.max_samples_stored' => {
1133
1151
  :default => 1000,
1134
1152
  :public => true,
1135
1153
  :type => Fixnum,
1136
1154
  :description => 'Maximum number of custom Insights events buffered in memory at a time.',
1137
1155
  :dynamic_name => true
1156
+ },
1157
+ :disable_grape => {
1158
+ :default => false,
1159
+ :public => true,
1160
+ :type => Boolean,
1161
+ :description => 'Disables installation of Grape instrumentation.'
1138
1162
  }
1139
1163
  }.freeze
1140
1164
 
@@ -28,6 +28,7 @@ module NewRelic
28
28
  :'slow_sql.record_sql' => record_sql_setting(local_settings, :'slow_sql.record_sql'),
29
29
  :'mongo.obfuscate_queries' => true,
30
30
 
31
+ :'custom_insights_events.enabled' => false,
31
32
  :'strip_exception_messages.enabled' => true
32
33
  })
33
34
  end
@@ -80,7 +80,7 @@ module NewRelic
80
80
 
81
81
  def client_referring_transaction_trip_id(state)
82
82
  info = state.referring_transaction_info or return nil
83
- return info[2]
83
+ return info[2].is_a?(String) && info[2]
84
84
  end
85
85
 
86
86
  def client_referring_transaction_path_hash(state)
@@ -11,8 +11,6 @@ module NewRelic
11
11
 
12
12
  TYPE = 'type'.freeze
13
13
  TIMESTAMP = 'timestamp'.freeze
14
- SOURCE = 'source'.freeze
15
- AGENT_SOURCE = 'Agent'.freeze
16
14
  EVENT_PARAMS_CTX = 'recording custom event'.freeze
17
15
  EVENT_TYPE_REGEX = /^[a-zA-Z0-9:_ ]+$/.freeze
18
16
 
@@ -34,7 +32,7 @@ module NewRelic
34
32
  end
35
33
  end
36
34
 
37
- def record(type, attributes, source=AGENT_SOURCE)
35
+ def record(type, attributes)
38
36
  type = @type_strings[type]
39
37
  unless type =~ EVENT_TYPE_REGEX
40
38
  note_dropped_event(type)
@@ -42,7 +40,7 @@ module NewRelic
42
40
  end
43
41
 
44
42
  event = [
45
- { TYPE => type, TIMESTAMP => Time.now.to_i, SOURCE => source },
43
+ { TYPE => type, TIMESTAMP => Time.now.to_i },
46
44
  event_params(attributes, EVENT_PARAMS_CTX)
47
45
  ]
48
46
 
@@ -121,7 +121,8 @@ module NewRelic
121
121
  error_ids.include?(exception.object_id)
122
122
  end
123
123
 
124
- def tag_as_seen(txn, exception)
124
+ def tag_as_seen(state, exception)
125
+ txn = state.current_transaction
125
126
  txn.noticed_error_ids << exception.object_id if txn
126
127
  end
127
128
 
@@ -147,14 +148,9 @@ module NewRelic
147
148
  end
148
149
 
149
150
  # Increments a statistic that tracks total error rate
150
- # Be sure not to double-count same exception. This clears per harvest.
151
- def increment_error_count!(exception, options={}) #THREAD_LOCAL_ACCESS
152
- state = ::NewRelic::Agent::TransactionState.tl_get
151
+ def increment_error_count!(state, exception, options={})
153
152
  txn = state.current_transaction
154
153
 
155
- return if seen?(txn, exception)
156
- tag_as_seen(txn, exception)
157
-
158
154
  metric_names = aggregated_metric_names(txn)
159
155
  blamed_metric = blamed_metric_name(txn, options)
160
156
  metric_names << blamed_metric if blamed_metric
@@ -165,8 +161,11 @@ module NewRelic
165
161
  end
166
162
  end
167
163
 
168
- def skip_notice_error?(exception)
169
- disabled? || error_is_ignored?(exception) || exception.nil?
164
+ def skip_notice_error?(state, exception)
165
+ disabled? ||
166
+ error_is_ignored?(exception) ||
167
+ exception.nil? ||
168
+ seen?(state.current_transaction, exception)
170
169
  end
171
170
 
172
171
  # acts just like Hash#fetch, but deletes the key from the hash
@@ -278,13 +277,19 @@ module NewRelic
278
277
  #
279
278
  # If anything is left over, it's added to custom params
280
279
  # If exception is nil, the error count is bumped and no traced error is recorded
281
- def notice_error(exception, options={})
282
- return if skip_notice_error?(exception)
283
- increment_error_count!(exception, options)
280
+ def notice_error(exception, options={}) #THREAD_LOCAL_ACCESS
281
+ state = ::NewRelic::Agent::TransactionState.tl_get
282
+
283
+ return if skip_notice_error?(state, exception)
284
+ tag_as_seen(state, exception)
285
+
286
+ increment_error_count!(state, exception, options)
284
287
  NewRelic::Agent.instance.events.notify(:notice_error, exception, options)
288
+
285
289
  action_path = fetch_from_options(options, :metric, "")
286
290
  exception_options = error_params_from_options(options).merge(exception_info(exception))
287
291
  add_to_error_queue(NewRelic::NoticedError.new(action_path, exception_options, exception))
292
+
288
293
  exception
289
294
  rescue => e
290
295
  ::NewRelic::Agent.logger.warn("Failure when capturing error '#{exception}':", e)
@@ -330,17 +330,18 @@ module NewRelic
330
330
  state = NewRelic::Agent::TransactionState.tl_get
331
331
  state.request = newrelic_request(args)
332
332
 
333
- # Skip instrumentation based on the value of 'do_not_trace?' and if
334
- # we aren't calling directly with a block.
335
- if !block_given? && do_not_trace?
336
- state.current_transaction.ignore! if state.current_transaction
337
- NewRelic::Agent.disable_all_tracing do
338
- return perform_action_without_newrelic_trace(*args)
333
+ skip_tracing = do_not_trace? || !state.is_execution_traced?
334
+ if skip_tracing
335
+ if block_given?
336
+ return yield
337
+ else
338
+ state.current_transaction.ignore! if state.current_transaction
339
+ NewRelic::Agent.disable_all_tracing do
340
+ return perform_action_without_newrelic_trace(*args)
341
+ end
339
342
  end
340
343
  end
341
344
 
342
- return yield unless state.is_execution_traced?
343
-
344
345
  # If a block was passed in, then the arguments represent options for
345
346
  # the instrumentation, not app method arguments.
346
347
  trace_options = NR_DEFAULT_OPTIONS
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module GrapeInstrumentation
8
+ API_ENDPOINT = 'api.endpoint'.freeze
9
+ FORMAT = '(.:format)'.freeze
10
+ EMPTY_STRING = ''.freeze
11
+ MIN_VERSION = ::NewRelic::VersionNumber.new("0.2.0")
12
+ end
13
+ end
14
+ end
15
+
16
+ DependencyDetection.defer do
17
+ named :grape
18
+
19
+ depends_on do
20
+ defined?(::Grape::VERSION) &&
21
+ ::NewRelic::VersionNumber.new(::Grape::VERSION) >= ::NewRelic::Agent::GrapeInstrumentation::MIN_VERSION
22
+ end
23
+
24
+ depends_on do
25
+ false
26
+ end
27
+
28
+ executes do
29
+ NewRelic::Agent.logger.info 'Installing Grape instrumentation'
30
+ instrument_call
31
+ end
32
+
33
+ def instrument_call
34
+ ::Grape::API.class_eval do
35
+ def call_with_new_relic(env)
36
+ begin
37
+ response = call_without_new_relic(env)
38
+ ensure
39
+ # We don't want an error in our transaction naming to kill the request.
40
+ begin
41
+ endpoint = env[::NewRelic::Agent::GrapeInstrumentation::API_ENDPOINT]
42
+
43
+ if endpoint
44
+ route_obj = endpoint.route
45
+ if route_obj
46
+ action_name = route_obj.route_path.sub(::NewRelic::Agent::GrapeInstrumentation::FORMAT,
47
+ ::NewRelic::Agent::GrapeInstrumentation::EMPTY_STRING)
48
+ method_name = route_obj.route_method
49
+
50
+ txn_name = "#{self.class.name}#{action_name} (#{method_name})"
51
+ ::NewRelic::Agent.set_transaction_name(txn_name)
52
+ end
53
+ end
54
+ rescue => e
55
+ ::NewRelic::Agent.logger.warn("Error in Grape transaction naming", e)
56
+ end
57
+ end
58
+
59
+ response
60
+ end
61
+
62
+ alias_method :call_without_new_relic, :call
63
+ alias_method :call, :call_with_new_relic
64
+ end
65
+ end
66
+
67
+ end