newrelic_rpm 8.10.0 → 8.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +12 -3
  4. data/.rubocop_todo.yml +243 -0
  5. data/.simplecov +9 -2
  6. data/CHANGELOG.md +23 -1
  7. data/Thorfile +6 -0
  8. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +8 -4
  9. data/lib/new_relic/agent/instrumentation/grpc/client/chain.rb +0 -8
  10. data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +10 -8
  11. data/lib/new_relic/agent/instrumentation/grpc/client/prepend.rb +0 -5
  12. data/lib/new_relic/agent/instrumentation/grpc/helper.rb +2 -0
  13. data/lib/new_relic/agent/threading/agent_thread.rb +10 -6
  14. data/lib/new_relic/agent/tracer.rb +5 -3
  15. data/lib/new_relic/control/frameworks/external.rb +0 -0
  16. data/lib/new_relic/control/frameworks/sinatra.rb +0 -0
  17. data/lib/new_relic/language_support.rb +5 -0
  18. data/lib/new_relic/version.rb +1 -1
  19. data/lib/tasks/coverage_report.rake +21 -11
  20. data/lib/tasks/instrumentation_generator/README.md +63 -0
  21. data/lib/tasks/instrumentation_generator/TODO.md +33 -0
  22. data/lib/tasks/instrumentation_generator/instrumentation.thor +96 -0
  23. data/lib/tasks/instrumentation_generator/templates/Envfile.tt +10 -0
  24. data/lib/tasks/instrumentation_generator/templates/chain.tt +22 -0
  25. data/lib/tasks/instrumentation_generator/templates/chain_method.tt +7 -0
  26. data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +30 -0
  27. data/lib/tasks/instrumentation_generator/templates/instrumentation.tt +13 -0
  28. data/lib/tasks/instrumentation_generator/templates/instrumentation_method.tt +3 -0
  29. data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +19 -0
  30. data/lib/tasks/instrumentation_generator/templates/prepend.tt +14 -0
  31. data/lib/tasks/instrumentation_generator/templates/prepend_method.tt +3 -0
  32. data/lib/tasks/instrumentation_generator/templates/test.tt +16 -0
  33. data/newrelic_rpm.gemspec +13 -17
  34. data/test/agent_helper.rb +5 -19
  35. metadata +41 -98
  36. data/bin/mongrel_rpm +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9556e153e6ae6bb4ea2894bc62e6c0745a08f2347c25074a97316fe6818ca6d
4
- data.tar.gz: 1e07fc83567ff8b0e83a1c502265076fca5409021ff724801455c6e4ee5086ff
3
+ metadata.gz: 5293c4968708ee7ff95720c57446722d8649e7095fd44f03b88f562d156b7cbf
4
+ data.tar.gz: df7b918b393af7aa8852bbb2867e0f7468a0ce7e78316f3a0cb8e0cedeb2aaeb
5
5
  SHA512:
6
- metadata.gz: 9bb9efe02ea356b8969d3466bde7c76e2f20cb8880d93628d707ee92c05338e91262d456c4b5e0b9943ad1ee50e8edf512cb82096a3f5f2ea166a6b5b1bfdb0b
7
- data.tar.gz: 1e13ef2b0b0ab49ef8c08f5d54536a37a3b3f5812b8a0ef884f2b1df670842499edcef344297aae59822cc43d456b47f3164ba86daf678e62080c09912a871a7
6
+ metadata.gz: 863115396ffd0b911d11da3d0ccbe8a4e7bc98f6d406080261c4a41272a78139406146524e0f3f121ae0f729635235b40c8666caf8b70b9e20182d82b178789c
7
+ data.tar.gz: 24f7b15184ec2fd778712a215e4f6fc7d029c37b3cfb3f1efe9d0d085999abe2e795b6f644c6ac420904de3a5c7759797e462c94deb73173566c536c8bf3cb54
data/.gitignore CHANGED
@@ -16,6 +16,7 @@ tags
16
16
  *.swo
17
17
 
18
18
  coverage
19
+ coverage_*
19
20
  /doc/
20
21
  /log/
21
22
  /lerg/
data/.rubocop.yml CHANGED
@@ -1,5 +1,12 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
1
3
  require:
4
+ # Default minitest configurations: https://github.com/rubocop/rubocop-minitest/blob/master/config/default.yml
5
+ - rubocop-minitest
6
+ # Default performance configurations: https://github.com/rubocop/rubocop-performance/blob/master/config/default.yml
2
7
  - rubocop-performance
8
+ # Default rake configurations: https://github.com/rubocop/rubocop-rake/blob/master/config/default.yml
9
+ <%= '- rubocop-rake' if RUBY_VERSION >= '2.4.0' %>
3
10
 
4
11
  AllCops:
5
12
  TargetRubyVersion: 2.7
@@ -256,7 +263,9 @@ Layout/LineEndStringConcatenationIndentation:
256
263
  Enabled: false
257
264
 
258
265
  Layout/LineLength:
259
- Enabled: false
266
+ # TODO: get this down to something closer to the 80 col ideal
267
+ # we should be able to manage 120
268
+ Max: 576
260
269
 
261
270
  Layout/MultilineArrayBraceLayout:
262
271
  Enabled: true
@@ -1466,7 +1475,7 @@ Style/MapToHash:
1466
1475
 
1467
1476
  Style/MethodCallWithArgsParentheses:
1468
1477
  Enabled: true
1469
- IgnoredMethods:
1478
+ AllowedMethods:
1470
1479
  - puts
1471
1480
  - require
1472
1481
  - raise
@@ -1479,7 +1488,7 @@ Style/MethodCallWithArgsParentheses:
1479
1488
 
1480
1489
  Style/MethodCallWithoutArgsParentheses:
1481
1490
  Enabled: false
1482
- IgnoredMethods: []
1491
+ AllowedMethods: []
1483
1492
 
1484
1493
  Style/MethodCalledOnDoEndBlock:
1485
1494
  Enabled: false
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,243 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2022-09-09 22:01:39 UTC using RuboCop version 1.36.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 4
10
+ # This cop supports safe autocorrection (--autocorrect).
11
+ # Configuration parameters: EnforcedStyle.
12
+ # SupportedStyles: empty_lines, no_empty_lines
13
+ Layout/EmptyLinesAroundBlockBody:
14
+ Exclude:
15
+ - 'test/multiverse/suites/active_record/db/schema.rb'
16
+ - 'test/multiverse/suites/active_record_pg/db/schema.rb'
17
+
18
+ # Offense count: 52
19
+ # This cop supports safe autocorrection (--autocorrect).
20
+ Minitest/AssertEmptyLiteral:
21
+ Enabled: false
22
+
23
+ # Offense count: 13
24
+ # This cop supports safe autocorrection (--autocorrect).
25
+ Minitest/AssertEqual:
26
+ Exclude:
27
+ - 'test/multiverse/suites/config_file_loading/config_file_loading_test.rb'
28
+ - 'test/new_relic/agent/configuration/default_source_test.rb'
29
+ - 'test/new_relic/agent/error_trace_aggregator_test.rb'
30
+ - 'test/new_relic/agent/method_tracer_helpers_test.rb'
31
+ - 'test/new_relic/agent/method_tracer_test.rb'
32
+ - 'test/new_relic/agent/transaction_sampler_test.rb'
33
+ - 'test/new_relic/metric_data_test.rb'
34
+
35
+ # Offense count: 145
36
+ # This cop supports safe autocorrection (--autocorrect).
37
+ Minitest/AssertInDelta:
38
+ Enabled: false
39
+
40
+ # Offense count: 22
41
+ # This cop supports safe autocorrection (--autocorrect).
42
+ Minitest/AssertIncludes:
43
+ Exclude:
44
+ - 'test/agent_helper.rb'
45
+ - 'test/multiverse/suites/rails/active_support_logger_test.rb'
46
+ - 'test/multiverse/suites/sequel/sequel_plugin_test.rb'
47
+ - 'test/multiverse/suites/sinatra_agent_disabled/shim_test.rb'
48
+ - 'test/new_relic/agent/audit_logger_test.rb'
49
+ - 'test/new_relic/agent/configuration/manager_test.rb'
50
+ - 'test/new_relic/agent/configuration/orphan_configuration_test.rb'
51
+ - 'test/new_relic/agent/error_trace_aggregator_test.rb'
52
+ - 'test/new_relic/agent/javascript_instrumentor_test.rb'
53
+ - 'test/new_relic/agent/method_visibility_test.rb'
54
+ - 'test/new_relic/agent/sampler_test.rb'
55
+ - 'test/new_relic/agent/tracer_state_test.rb'
56
+ - 'test/new_relic/control/instance_methods_test.rb'
57
+ - 'test/new_relic/environment_report_test.rb'
58
+ - 'test/new_relic/metric_data_test.rb'
59
+
60
+ # Offense count: 4
61
+ # This cop supports safe autocorrection (--autocorrect).
62
+ Minitest/AssertKindOf:
63
+ Exclude:
64
+ - 'test/new_relic/agent/agent_test.rb'
65
+ - 'test/new_relic/agent/pipe_channel_manager_test.rb'
66
+ - 'test/new_relic/agent_test.rb'
67
+
68
+ # Offense count: 4
69
+ # This cop supports safe autocorrection (--autocorrect).
70
+ Minitest/AssertNil:
71
+ Exclude:
72
+ - 'test/multiverse/suites/agent_only/log_events_test.rb'
73
+
74
+ # Offense count: 5
75
+ # This cop supports safe autocorrection (--autocorrect).
76
+ Minitest/AssertPathExists:
77
+ Exclude:
78
+ - 'infinite_tracing/test/support/fixtures.rb'
79
+ - 'test/multiverse/suites/mongo/helpers/mongo_server_test.rb'
80
+
81
+ # Offense count: 140
82
+ # This cop supports safe autocorrection (--autocorrect).
83
+ Minitest/AssertPredicate:
84
+ Enabled: false
85
+
86
+ # Offense count: 6
87
+ Minitest/AssertRaisesCompoundBody:
88
+ Exclude:
89
+ - 'test/new_relic/agent/collector_response_code_test.rb'
90
+ - 'test/new_relic/agent/new_relic_service_test.rb'
91
+ - 'test/new_relic/cli/commands/deployments_test.rb'
92
+
93
+ # Offense count: 9
94
+ # This cop supports safe autocorrection (--autocorrect).
95
+ Minitest/AssertRespondTo:
96
+ Exclude:
97
+ - 'test/multiverse/suites/sequel/sequel_plugin_test.rb'
98
+ - 'test/multiverse/suites/sinatra_agent_disabled/shim_test.rb'
99
+ - 'test/new_relic/agent/configuration/default_source_test.rb'
100
+ - 'test/new_relic/collection_helper_test.rb'
101
+ - 'test/new_relic/data_container_tests.rb'
102
+
103
+ # Offense count: 35
104
+ # This cop supports safe autocorrection (--autocorrect).
105
+ Minitest/AssertTruthy:
106
+ Exclude:
107
+ - 'test/multiverse/suites/agent_only/error_events_test.rb'
108
+ - 'test/multiverse/suites/rack/puma_rack_urlmap_test.rb'
109
+ - 'test/multiverse/suites/sequel/sequel_safety_test.rb'
110
+ - 'test/new_relic/agent/commands/thread_profiler_session_test.rb'
111
+ - 'test/new_relic/agent/configuration/environment_source_test.rb'
112
+ - 'test/new_relic/agent/configuration/manager_test.rb'
113
+ - 'test/new_relic/agent/configuration/security_policy_source_test.rb'
114
+ - 'test/new_relic/agent/configuration/yaml_source_test.rb'
115
+ - 'test/new_relic/agent/distributed_tracing/distributed_trace_payload_test.rb'
116
+ - 'test/new_relic/agent/distributed_tracing/trace_context_payload_test.rb'
117
+ - 'test/new_relic/agent/priority_sampled_buffer_test.rb'
118
+ - 'test/new_relic/agent/transaction/distributed_tracing_test.rb'
119
+ - 'test/new_relic/agent_test.rb'
120
+ - 'test/new_relic/gem_notifications_tests.rb'
121
+ - 'test/new_relic/language_support_test.rb'
122
+
123
+ # Offense count: 27
124
+ Minitest/AssertWithExpectedArgument:
125
+ Exclude:
126
+ - 'infinite_tracing/test/infinite_tracing/worker_test.rb'
127
+ - 'test/agent_helper.rb'
128
+ - 'test/multiverse/suites/grpc/grpc_client_test.rb'
129
+ - 'test/multiverse/suites/rails/error_tracing_test.rb'
130
+ - 'test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb'
131
+ - 'test/new_relic/agent/agent_test.rb'
132
+ - 'test/new_relic/agent/configuration/default_source_test.rb'
133
+ - 'test/new_relic/agent/configuration/orphan_configuration_test.rb'
134
+ - 'test/new_relic/agent/datastores/redis_test.rb'
135
+ - 'test/new_relic/agent/distributed_tracing/distributed_tracing_cross_agent_test.rb'
136
+ - 'test/new_relic/agent/method_tracer_helpers_test.rb'
137
+ - 'test/new_relic/control_test.rb'
138
+
139
+ # Offense count: 4
140
+ Minitest/DuplicateTestRun:
141
+ Exclude:
142
+ - 'test/multiverse/suites/rails/error_tracing_test.rb'
143
+ - 'test/multiverse/suites/sinatra/ignoring_test.rb'
144
+
145
+ # Offense count: 38
146
+ # This cop supports safe autocorrection (--autocorrect).
147
+ Minitest/LiteralAsActualArgument:
148
+ Exclude:
149
+ - 'test/multiverse/suites/rails/active_support_logger_test.rb'
150
+ - 'test/new_relic/agent/configuration/environment_source_test.rb'
151
+ - 'test/new_relic/agent/connect/request_builder_test.rb'
152
+ - 'test/new_relic/agent/error_trace_aggregator_test.rb'
153
+ - 'test/new_relic/agent/instrumentation/controller_instrumentation_test.rb'
154
+ - 'test/new_relic/agent/new_relic_service_test.rb'
155
+ - 'test/new_relic/agent/samplers/cpu_sampler_test.rb'
156
+ - 'test/new_relic/agent/samplers/memory_sampler_test.rb'
157
+ - 'test/new_relic/agent/stats_test.rb'
158
+ - 'test/new_relic/agent/transaction/abstract_segment_test.rb'
159
+ - 'test/new_relic/agent/transaction/datastore_segment_test.rb'
160
+ - 'test/new_relic/agent/transaction_sampler_test.rb'
161
+ - 'test/new_relic/gem_notifications_tests.rb'
162
+ - 'test/new_relic/marshalling_test_cases.rb'
163
+ - 'test/new_relic/noticed_error_test.rb'
164
+
165
+ # Offense count: 260
166
+ Minitest/MultipleAssertions:
167
+ Max: 28
168
+
169
+ # Offense count: 9
170
+ # This cop supports safe autocorrection (--autocorrect).
171
+ Minitest/RefuteEqual:
172
+ Exclude:
173
+ - 'test/agent_helper.rb'
174
+ - 'test/multiverse/suites/config_file_loading/config_file_loading_test.rb'
175
+ - 'test/new_relic/agent/agent_test.rb'
176
+ - 'test/new_relic/agent/configuration/manager_test.rb'
177
+ - 'test/new_relic/marshalling_test_cases.rb'
178
+
179
+ # Offense count: 121
180
+ # This cop supports safe autocorrection (--autocorrect).
181
+ Minitest/RefuteFalse:
182
+ Enabled: false
183
+
184
+ # Offense count: 16
185
+ # This cop supports safe autocorrection (--autocorrect).
186
+ Minitest/RefuteIncludes:
187
+ Exclude:
188
+ - 'test/multiverse/suites/datamapper/datamapper_test.rb'
189
+ - 'test/multiverse/suites/grpc/grpc_server_test.rb'
190
+ - 'test/multiverse/suites/mongo/helpers/mongo_operation_tests.rb'
191
+ - 'test/multiverse/suites/mongo/mongo2_instrumentation_test.rb'
192
+ - 'test/multiverse/suites/rack/rack_cascade_test.rb'
193
+ - 'test/new_relic/agent/configuration/manager_test.rb'
194
+ - 'test/new_relic/control/instance_methods_test.rb'
195
+
196
+ # Offense count: 3
197
+ # This cop supports safe autocorrection (--autocorrect).
198
+ Minitest/RefutePathExists:
199
+ Exclude:
200
+ - 'test/multiverse/suites/mongo/helpers/mongo_server_test.rb'
201
+
202
+ # Offense count: 96
203
+ # This cop supports safe autocorrection (--autocorrect).
204
+ Minitest/RefutePredicate:
205
+ Enabled: false
206
+
207
+ # Offense count: 27
208
+ # This cop supports safe autocorrection (--autocorrect).
209
+ Minitest/TestMethodName:
210
+ Enabled: false
211
+
212
+ # Offense count: 2
213
+ # This cop supports safe autocorrection (--autocorrect).
214
+ Rake/Desc:
215
+ Exclude:
216
+ - 'Rakefile'
217
+ - 'lib/tasks/config.rake'
218
+
219
+ # Offense count: 15
220
+ Rake/MethodDefinitionInTask:
221
+ Exclude:
222
+ - 'Rakefile'
223
+ - 'infinite_tracing/tasks/proto.rake'
224
+ - 'lib/tasks/config.rake'
225
+ - 'lib/tasks/tests.rake'
226
+
227
+ # Offense count: 2
228
+ # This cop supports unsafe autocorrection (--autocorrect-all).
229
+ # Configuration parameters: EnforcedStyle.
230
+ # SupportedStyles: always, always_true, never
231
+ Style/FrozenStringLiteralComment:
232
+ Exclude:
233
+ - 'test/multiverse/suites/active_record/db/schema.rb'
234
+ - 'test/multiverse/suites/active_record_pg/db/schema.rb'
235
+
236
+ # Offense count: 26
237
+ # This cop supports safe autocorrection (--autocorrect).
238
+ # Configuration parameters: IgnoreMacros, AllowedMethods, IgnoredMethods, AllowedPatterns, IgnoredPatterns, IncludedMacros, AllowParenthesesInMultilineCall, AllowParenthesesInChaining, AllowParenthesesInCamelCaseMethod, AllowParenthesesInStringInterpolation, EnforcedStyle.
239
+ # SupportedStyles: require_parentheses, omit_parentheses
240
+ Style/MethodCallWithArgsParentheses:
241
+ Exclude:
242
+ - 'test/multiverse/suites/active_record/db/schema.rb'
243
+ - 'test/multiverse/suites/active_record_pg/db/schema.rb'
data/.simplecov CHANGED
@@ -1,6 +1,13 @@
1
1
  # frozen_string_literal: true
2
+ require 'securerandom'
3
+
4
+ random = SecureRandom.uuid
5
+ SimpleCov.command_name(random)
6
+ SimpleCov.coverage_dir("coverage_#{random}")
7
+
2
8
  SimpleCov.start do
3
- enable_coverage :branch
9
+ enable_coverage(:branch)
4
10
  SimpleCov.root(File.join(File.dirname(__FILE__), '/lib'))
5
- track_files "**/*.rb"
11
+ track_files("**/*.rb")
12
+ formatter(SimpleCov::Formatter::SimpleFormatter)
6
13
  end
data/CHANGELOG.md CHANGED
@@ -1,6 +1,23 @@
1
1
  # New Relic Ruby Agent Release Notes #
2
2
 
3
3
 
4
+ ## v8.10.1
5
+
6
+
7
+ * **Bugfix: Missing unscoped metrics when instrumentation.thread.tracing is enabled**
8
+
9
+ Previously, when `instrumentation.thread.tracing` was set to true, some puma applications encountered a bug where a varying number of unscoped metrics would be missing. The agent now will correctly store and send all unscoped metrics.
10
+
11
+ Thank you to @texpert for providing details of their situation to help resolve the issue.
12
+
13
+
14
+ * **Bugfix: gRPC instrumentation causes ArgumentError when other Google gems are present**
15
+
16
+ Previously, when the agent had gRPC instrumentation enabled in an application using other gems (such as google-ads-googleads), the instrumentation could cause the error `ArgumentError: wrong number of arguments (given 3, expected 2)`. The gRPC instrumentation has been updated to prevent this issue from occurring in the future.
17
+
18
+ Thank you to @FeminismIsAwesome for bringing this issue to our attention.
19
+
20
+
4
21
  ## v8.10.0
5
22
 
6
23
 
@@ -17,12 +34,17 @@
17
34
  | `instrumentation.grpc.host_denylist` | "" | Provide a comma delimited list of host regex patterns (ex: "private.com$,exception.*") |
18
35
 
19
36
 
37
+ * **Code-level metrics functionality is enabled by default**
38
+
39
+ The code-level metrics functionality for the Ruby agent's [CodeStream integration](https://docs.newrelic.com/docs/apm/agents/ruby-agent/features/ruby-codestream-integration) is now enabled by default after we have received positive feedback and no open bugs for the past two releases.
40
+
41
+
20
42
  * **Performance: Rework timing range overlap calculations for multiple transaction segments**
21
43
 
22
44
  Many thanks to GitHub community members @bmulholland and @hkdnet. @bmulholland alerted us to [rmosolgo/graphql-ruby#3945](https://github.com/rmosolgo/graphql-ruby/issues/3945). That Issue essentially notes that the New Relic Ruby agent incurs a significant perfomance hit when the `graphql` RubyGem (which ships with New Relic Ruby agent support) is used with DataLoader to generate a high number of transactions. Then @hkdnet diagnosed the root cause in the Ruby agent and put together both a proof of concept fix and a full blown PR to resolve the problem. The agent keeps track multiple segments that are concurrently in play for a given transaction in order to merge the ones whose start and stop times intersect. The logic for doing this find-and-merge operation has been reworked to a) be deferred entirely until the transaction is ready to be recorded, and b) made more performant when it is needed. GraphQL DataLoader users and other users who generate lots of activity for monitoring within a short amount of time will hopefully see some good performance gains from these changes.
23
45
 
24
46
 
25
- * **Performance: Make frozen string literals the default for the agent
47
+ * **Performance: Make frozen string literals the default for the agent**
26
48
 
27
49
  The Ruby `frozen_string_literal: true` magic source code comment has now been applied consistently across all Ruby files belonging to the agent. This can provide a performance boost, given that Ruby can rely on the strings remaining immutable. Previously only about a third of the agent's code was freezing string literals by default. Now that 100% of the code freezes string literals by default, we have internally observed some related performance gains through testing. We are hopeful that these will translate into some real world gains in production capacities.
28
50
 
data/Thorfile ADDED
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+ # frozen_string_literal: true
5
+
6
+ Dir["./lib/tasks/**/*.thor"].sort.each { |f| load f }
@@ -12,13 +12,10 @@ module NewRelic
12
12
  module Instrumentation
13
13
  class ActionControllerSubscriber < NotificationsSubscriber
14
14
  def start(name, id, payload) # THREAD_LOCAL_ACCESS
15
- # @req is a historically stable but not guaranteed Rails header property
16
- request = payload[:headers].instance_variable_get(:@req)
17
-
18
15
  controller_class = controller_class(payload)
19
16
 
20
17
  if state.is_execution_traced? && !should_ignore(payload, controller_class)
21
- finishable = start_transaction_or_segment(payload, request, controller_class)
18
+ finishable = start_transaction_or_segment(payload, request_for_payload(payload), controller_class)
22
19
  push_segment(id, finishable)
23
20
  else
24
21
  # if this transaction is ignored, make sure child
@@ -98,6 +95,13 @@ module NewRelic
98
95
  QueueTime.parse_frontend_timestamp(request.env, Process.clock_gettime(Process::CLOCK_REALTIME))
99
96
  end
100
97
  end
98
+
99
+ def request_for_payload(payload)
100
+ # @req is a historically stable but not guaranteed Rails header property
101
+ return unless payload[:headers].instance_variables.include?(:@req)
102
+
103
+ payload[:headers].instance_variable_get(:@req)
104
+ end
101
105
  end
102
106
  end
103
107
  end
@@ -13,14 +13,6 @@ module NewRelic::Agent::Instrumentation
13
13
  ::GRPC::ClientStub.class_eval do
14
14
  include NewRelic::Agent::Instrumentation::GRPC::Client
15
15
 
16
- def initialize_with_newrelic_trace(*args)
17
- @trace_with_newrelic = trace_with_newrelic?(args.first)
18
- initialize_without_newrelic_trace(*args)
19
- end
20
-
21
- alias initialize_without_newrelic_trace initialize
22
- alias initialize initialize_with_newrelic_trace
23
-
24
16
  def bidi_streamer_with_new_relic_trace(method, requests, marshal, unmarshal,
25
17
  deadline: nil,
26
18
  return_op: false,
@@ -70,16 +70,18 @@ module NewRelic
70
70
  "grpc://#{@host}/#{method}"
71
71
  end
72
72
 
73
- def trace_with_newrelic?(host = nil)
74
- return false if self.class.name.eql?('GRPC::InterceptorRegistry')
75
-
76
- do_trace = instance_variable_get(:@trace_with_newrelic)
77
- return do_trace unless do_trace.nil? # check for nil, not falsey
73
+ def interceptor?
74
+ self.class.name.eql?('GRPC::InterceptorRegistry')
75
+ end
78
76
 
79
- host ||= @host
80
- return false unless host && !host_denylisted?(host)
77
+ def trace_with_newrelic?
78
+ return @trace_with_newrelic unless @trace_with_newrelic.nil? # check for nil, not false
81
79
 
82
- true
80
+ @trace_with_newrelic = if interceptor?
81
+ false
82
+ else
83
+ !host_denylisted?(@host)
84
+ end
83
85
  end
84
86
  end
85
87
  end
@@ -13,11 +13,6 @@ module NewRelic
13
13
  module Prepend
14
14
  include NewRelic::Agent::Instrumentation::GRPC::Client
15
15
 
16
- def initialize(*args)
17
- @trace_with_newrelic = trace_with_newrelic?(args.first)
18
- super(*args)
19
- end
20
-
21
16
  def bidi_streamer(method, requests, marshal, unmarshal,
22
17
  deadline: nil,
23
18
  return_op: false,
@@ -18,6 +18,8 @@ module NewRelic
18
18
  end
19
19
 
20
20
  def host_denylisted?(host)
21
+ return false unless host
22
+
21
23
  ignore_patterns.any? { |regex| host.match?(regex) }
22
24
  end
23
25
 
@@ -8,21 +8,25 @@ module NewRelic
8
8
  module Threading
9
9
  class AgentThread
10
10
  def self.create(label, &blk)
11
- ::NewRelic::Agent.logger.debug("Creating New Relic thread: #{label}")
11
+ ::NewRelic::Agent.logger.debug("Creating AgentThread: #{label}")
12
12
  wrapped_blk = Proc.new do
13
+ if ::Thread.current[:newrelic_tracer_state] && Thread.current[:newrelic_tracer_state].current_transaction
14
+ txn = ::Thread.current[:newrelic_tracer_state].current_transaction
15
+ ::NewRelic::Agent.logger.warn("AgentThread created with current transaction #{txn.best_name}")
16
+ end
13
17
  begin
14
18
  blk.call
15
19
  rescue => e
16
- ::NewRelic::Agent.logger.error("Thread #{label} exited with error", e)
20
+ ::NewRelic::Agent.logger.error("AgentThread #{label} exited with error", e)
17
21
  rescue Exception => e
18
- ::NewRelic::Agent.logger.error("Thread #{label} exited with exception. Re-raising in case of interrupt.", e)
22
+ ::NewRelic::Agent.logger.error("AgentThread #{label} exited with exception. Re-raising in case of interrupt.", e)
19
23
  raise
20
24
  ensure
21
- ::NewRelic::Agent.logger.debug("Exiting New Relic thread: #{label}")
25
+ ::NewRelic::Agent.logger.debug("Exiting AgentThread: #{label}")
22
26
  end
23
27
  end
24
-
25
- thread = backing_thread_class.new(&wrapped_blk)
28
+ thread = nil
29
+ NewRelic::Agent.disable_all_tracing { thread = backing_thread_class.new(&wrapped_blk) }
26
30
  thread[:newrelic_label] = label
27
31
  thread
28
32
  end
@@ -407,11 +407,13 @@ module NewRelic
407
407
  alias_method :tl_clear, :clear_state
408
408
 
409
409
  def thread_block_with_current_transaction(*args, &block)
410
- current_txn = ::Thread.current[:newrelic_tracer_state].current_transaction if ::Thread.current[:newrelic_tracer_state]
410
+ current_txn = ::Thread.current[:newrelic_tracer_state].current_transaction if ::Thread.current[:newrelic_tracer_state] && ::Thread.current[:newrelic_tracer_state].is_execution_traced?
411
411
  Proc.new do
412
412
  begin
413
- NewRelic::Agent::Tracer.state.current_transaction = current_txn
414
- segment = NewRelic::Agent::Tracer.start_segment(name: "Ruby/Thread/#{::Thread.current.object_id}")
413
+ if current_txn
414
+ NewRelic::Agent::Tracer.state.current_transaction = current_txn
415
+ segment = NewRelic::Agent::Tracer.start_segment(name: "Ruby/Thread/#{::Thread.current.object_id}")
416
+ end
415
417
  block.call(*args) if block.respond_to?(:call)
416
418
  ensure
417
419
  segment.finish if segment
File without changes
File without changes
@@ -73,6 +73,11 @@ module NewRelic
73
73
  end
74
74
  end
75
75
 
76
+ def camelize(string)
77
+ camelized = string.downcase
78
+ camelized.split(/\-|\_/).map(&:capitalize).join
79
+ end
80
+
76
81
  def bundled_gem?(gem_name)
77
82
  defined?(Bundler) && Bundler.rubygems.all_specs.map(&:name).include?(gem_name)
78
83
  rescue => e
@@ -8,7 +8,7 @@ module NewRelic
8
8
  module VERSION # :nodoc:
9
9
  MAJOR = 8
10
10
  MINOR = 10
11
- TINY = 0
11
+ TINY = 1
12
12
 
13
13
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
14
14
  end
@@ -7,17 +7,27 @@ namespace :coverage do
7
7
  desc "Collates all result sets generated by the different test runners"
8
8
  task :report do
9
9
  require 'simplecov'
10
- require 'simplecov_json_formatter'
11
- unless ENV['CI']
12
- puts 'This task is intended to be run only on the CI.'
13
- return
14
- end
15
- SimpleCov.collate(Dir["coverage*/.resultset.json"]) do
16
- formatter SimpleCov::Formatter::MultiFormatter.new([
17
- SimpleCov::Formatter::JSONFormatter,
18
- SimpleCov::Formatter::HTMLFormatter
19
- ])
20
- refuse_coverage_drop
10
+ require 'fileutils'
11
+
12
+ SimpleCov.coverage_dir('coverage_results')
13
+
14
+ if ENV['CI']
15
+ SimpleCov.collate(Dir['*/coverage_*/.resultset.json']) do
16
+ formatter SimpleCov::Formatter::HTMLFormatter
17
+ refuse_coverage_drop
18
+ end
19
+ else
20
+ SimpleCov.collate(Dir['lib/coverage_*/.resultset.json']) do
21
+ formatter SimpleCov::Formatter::HTMLFormatter
22
+ end
21
23
  end
24
+
25
+ Dir['lib/coverage_{[!r][!e][!s][!u][!l][!t][!s]}*'].each { |dir| FileUtils.rm_rf(dir) }
26
+ end
27
+
28
+ desc "Removes all coverage_* directories"
29
+ task :clear do
30
+ require 'fileutils'
31
+ Dir["lib/coverage_*"].each { |dir| FileUtils.rm_rf(dir) }
22
32
  end
23
33
  end
@@ -0,0 +1,63 @@
1
+ # Instrumentation Generator
2
+
3
+ ## Usage
4
+
5
+ `thor list` can be passed to get a list of all available thor commands
6
+
7
+ ### instrumentation:scaffold
8
+
9
+ This task requires one parameter by default: the name of the library or class you are instrumenting. This task generates the basic file structure needed to add new instrumentation to the Ruby agent.
10
+
11
+ Run it using:
12
+
13
+ `thor instrumentation:scaffold gem_name`
14
+
15
+ It accepts two optional parameters:
16
+
17
+ - `--method`: the name of a method to instrument. Only one method can be accepted at this time. Defaults to `method_to_instrument`
18
+ - `--args`: the arguments for the instrumented method. A comma-separated list can be given if there are multiple arguments. Defaults to `*args`.
19
+
20
+ With the optional parameters, the task can be run like so:
21
+
22
+ `thor instrumentation:scaffold gem_name --method=method_to_instrument --args=arg1,arg2,arg3`
23
+
24
+ ### WIP: instrumentation:add_new_method
25
+
26
+ Are you trying add instrumentation for a method within library we already instrument? This task is for you! Instead of building the entire scaffold, this task inserts only the changes needed within the `instrumentation.rb` and test files to instrument the new method. It requires one argument, the name of the existing instrumentation to add the method to. If the instrumented library does not already exist, it will create a new scaffold for that library.
27
+
28
+ Run it using:
29
+
30
+ `thor instrumentation:scaffold gem_name`
31
+
32
+ It accepts two optional paramters:
33
+
34
+ - `--method`: the name of a method to instrument. Only one method can be accepted at this time. Defaults to `method_to_instrument`
35
+ - `--args`: the arguments for the instrumented method. A comma-separated list can be given if there are multiple arguments. Defaults to `*args`.
36
+
37
+ With the optional parameters, the task can be run like so:
38
+
39
+ `thor instrumentation:add_new_method gem_name --method=method_to_instrument --args=arg1,arg2,arg3`
40
+
41
+ ## Idea
42
+
43
+ Create a CLI, similar to Rails’ generators and scaffold scripts, to create the required files and basic classes for instrumenting new libraries. The hope is that the parts of adding new instrumentation that is repetitive can be eliminated and/or reduced so that it takes less time to add new instrumentation and we can spend development time considering the best attributes to collect and interactions to measure. I also hope this project will reduce the overall toil related to adding new instrumentation.
44
+
45
+ The files we create with little variation besides library and method names are:
46
+
47
+ - Lib
48
+ - Dependency detection
49
+ - Chain
50
+ - Prepend
51
+ - Instrumentation
52
+ - Tests
53
+ - configuration/newrelic.yml
54
+ - Envfile
55
+ - Test file
56
+
57
+ Furthermore, we also create very similar snippets inside the default source configuration file that could be generated by this project as well.
58
+
59
+ ## Outcome
60
+
61
+ A prototype outside the agent has been created that generates the required files to create new instrumentation. This prototype accepts three arguments: name (name of the library), method (method to instrument), args (arguments for the method).
62
+
63
+ The Ruby gem Thor, a toolkit for building powerful command-line interfaces used in Bundler, Vagrant, Rails and others powers this CLI.