newrelic_rpm 9.11.0 → 9.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +74 -0
- data/README.md +1 -1
- data/lib/new_relic/agent/agent_logger.rb +1 -0
- data/lib/new_relic/agent/configuration/default_source.rb +106 -3
- data/lib/new_relic/agent/database/obfuscator.rb +1 -0
- data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +14 -0
- data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/logstasher/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/logstasher/instrumentation.rb +24 -0
- data/lib/new_relic/agent/instrumentation/logstasher/prepend.rb +13 -0
- data/lib/new_relic/agent/instrumentation/logstasher.rb +27 -0
- data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +3 -0
- data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +9 -5
- data/lib/new_relic/agent/instrumentation/redis/cluster_middleware.rb +26 -0
- data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +14 -11
- data/lib/new_relic/agent/instrumentation/redis/middleware.rb +3 -0
- data/lib/new_relic/agent/instrumentation/redis.rb +5 -0
- data/lib/new_relic/agent/local_log_decorator.rb +8 -1
- data/lib/new_relic/agent/log_event_aggregator.rb +91 -26
- data/lib/new_relic/control/instance_methods.rb +1 -0
- data/lib/new_relic/control/private_instance_methods.rb +4 -0
- data/lib/new_relic/control/security_interface.rb +57 -0
- data/lib/new_relic/control.rb +1 -1
- data/lib/new_relic/rack/browser_monitoring.rb +11 -7
- data/lib/new_relic/version.rb +1 -1
- data/lib/tasks/config.rake +5 -2
- data/lib/tasks/helpers/config.html.erb +1 -1
- data/lib/tasks/helpers/format.rb +1 -1
- data/lib/tasks/helpers/newrelicyml.rb +3 -2
- data/lib/tasks/instrumentation_generator/instrumentation.thor +1 -0
- data/newrelic.yml +200 -137
- data/test/agent_helper.rb +9 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c551a88ec42cceb53ade85126fe41272598c367b11d70e5167d374556b6fe8d
|
4
|
+
data.tar.gz: 912ff4f8d33e2ba318b4ec74fa8a3e0680c21fda3521a2382658855219ec81d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61472afe9cf52eea1a86e4394b613666372c6a0086ea1173c28d8341ff417cf980feb6fd7a25f23ec2e78bb02cc4a32efeb5102f1f42175300d0a0f8ba7eea1b
|
7
|
+
data.tar.gz: e3de1701d6f580a18ceb05c1607d3eada9081012e6bc8edec503b2e945d7128312224c63604dd40debb8554fcc13621a731251f4e349dbcdef909cf09c60c867
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,79 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes
|
2
2
|
|
3
|
+
## v9.12.0
|
4
|
+
|
5
|
+
Version 9.12.0 adds support for the `newrelic_security` agent, introduces instrumentation for the LogStasher gem, improves instrumentation for the `redis-clustering` gem, and updates the Elasticsearch instrumentation to only attempt to get the cluster name once per client, even if it fails.
|
6
|
+
|
7
|
+
- **Feature: Add support for the newrelic_security agent**
|
8
|
+
|
9
|
+
[New Relic Interactive Application Security Testing (IAST)](https://docs.newrelic.com/docs/iast/introduction/) can help you prevent cyberattacks and breaches on your applications by probing your running code for exploitable vulnerabilities.
|
10
|
+
|
11
|
+
The `newrelic_security` gem provides this feature for Ruby. It depends on `newrelic_rpm`. This is the first version of `newrelic_rpm` compatible with `newrelic_security`.
|
12
|
+
|
13
|
+
At this time, the security agent is intended for use only within a dedicated security testing environment with data that can tolerate modification or deletion. The security agent is available as a separate Ruby gem, `newrelic_security`. It is recommended that this separate gem only be introduced to a security testing environment by leveraging Bundler grouping like so:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
# Gemfile
|
17
|
+
gem 'newrelic_rpm' # New Relic APM observability agent
|
18
|
+
gem 'newrelic-infinite_tracing' # New Relic Infinite Tracing
|
19
|
+
|
20
|
+
group :security do
|
21
|
+
gem 'newrelic_security', require: false # New Relic security agent
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
In order to run the security agent, you need to update your configuration. At a minimum, `security.agent.enabled` and `security.enabled` must be set to `true`. They are `false` by default. Similar to the gem installation, we recommend you set these configurations for a special security testing environment only.
|
26
|
+
|
27
|
+
Here's an example using `newrelic.yml`:
|
28
|
+
|
29
|
+
```yaml
|
30
|
+
common: &default_settings
|
31
|
+
license_key: <%= ENV['NEW_RELIC_LICENSE_KEY'] %>
|
32
|
+
app_name: "Example app"
|
33
|
+
|
34
|
+
development:
|
35
|
+
<<: *default_settings
|
36
|
+
app_name: <%= app_name %> (Development)
|
37
|
+
|
38
|
+
security:
|
39
|
+
<<: *default_settings
|
40
|
+
security.enabled: true
|
41
|
+
security.agent.enabled: true
|
42
|
+
|
43
|
+
production:
|
44
|
+
<<: *default_settings
|
45
|
+
```
|
46
|
+
|
47
|
+
The following configuration relate to the `newrelic_security` gem:
|
48
|
+
|
49
|
+
| Configuration name | Default | Behavior |
|
50
|
+
| ------------------ | ------- |----------|
|
51
|
+
| security.agent.enabled | `false` | If `true`, the security agent is loaded (a Ruby 'require' is performed) |
|
52
|
+
| security.enabled | `false` | If `true`, the security agent is started (the agent runs in its event loop) |
|
53
|
+
| security.mode | `'IAST'` | Defines the mode for the security agent to operate in. Currently only 'IAST' is supported |
|
54
|
+
| security.validator_service_url | `'wss://csec.nr-data.net'` | Defines the endpoint URL for posting security related data |
|
55
|
+
| security.detection.rci.enabled | `true` | If `true`, enables RCI (remote code injection) detection |
|
56
|
+
| security.detection.rxss.enabled | `true` | If `true`, enables RXSS (reflected cross-site scripting) detection |
|
57
|
+
| security.detection.deserialization.enabled | `true` | If `true`, enables deserialization detection |
|
58
|
+
| security.application_info.port | `nil` | An Integer representing the port the application is listening on. This setting is mandatory for Passenger servers. Other servers should be detected by default. |
|
59
|
+
|
60
|
+
- **Feature: Add instrumentation for LogStasher**
|
61
|
+
|
62
|
+
The agent will now record logs generated by [LogStasher](https://github.com/shadabahmed/logstasher). Versions 1.0.0 and above of the LogStasher gem are supported. [PR#2559](https://github.com/newrelic/newrelic-ruby-agent/pull/2559)
|
63
|
+
|
64
|
+
- **Feature: Add instrumentation for redis-clustering**
|
65
|
+
|
66
|
+
Version 5.x of the `redis` gem moved cluster behavior into a different gem, `redis-clustering`. This gem can access instrumentation registered through `RedisClient::Middleware`. Previously, the agent only instrumented the `call_pipelined` method through this approach, but now users of the `redis-clustering` gem will also have instrumentation registered for `connect` and `call` methods. In addition, the way the `database_name` attribute is set for Redis datastore spans is now compatible with all versions of Redis supported by the New Relic Ruby agent. Thank you, [@praveen-ks](https://github.com/praveen-ks) for bringing this to our attention. [Issue#2444](https://github.com/newrelic/newrelic-ruby-agent/issues/2444) [PR#2720](https://github.com/newrelic/newrelic-ruby-agent/pull/2720)
|
67
|
+
|
68
|
+
- **Bugfix: Update Elasticsearch instrumentation to only attempt to get the cluster name once per client**
|
69
|
+
|
70
|
+
Previously, the agent would attempt to get the cluster name every time a call was made if it was not already captured. This could lead to a large number of failures if the cluster name could not be retrieved. Now, the agent will only attempt to get the cluster name once per client, even if it fails. Thank you, [@ascoppa](https://github.com/ascoppa) for bringing this to our attention. [Issue#2730](https://github.com/newrelic/newrelic-ruby-agent/issues/2730) [PR#2743](https://github.com/newrelic/newrelic-ruby-agent/pull/2743)
|
71
|
+
|
72
|
+
- **Feature: Produce metrics for 4 additional Action Controller Rails notifications**
|
73
|
+
|
74
|
+
Four additional Action Controller related Rails notifications are now subscribed to by the agent to produce telemetry. These 4 are `exist_fragment?`, `expire_fragment`, `read_fragment`, and `write_fragment`. As with instrumentation for Action Controller itself, these notifications are enabled by default and can be disabled by setting `:disable_action_controller` to `true` in the agent's `newrelic.yml` configuration file. [PR#2745](https://github.com/newrelic/newrelic-ruby-agent/pull/2745)
|
75
|
+
|
76
|
+
|
3
77
|
## v9.11.0
|
4
78
|
|
5
79
|
Version 9.11.0 introduces instrumentation for the aws-sdk-sqs gem, fixes a bug related to expected errors not bearing a "true" value for the "expected" attribute if expected as a result of an HTTP status code match and changes the way Stripe instrumentation metrics are named to prevent high-cardinality issues.
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ You can also monitor non-web applications. Refer to the "Other
|
|
24
24
|
Environments" section below.
|
25
25
|
|
26
26
|
We offer an AWS Lambda layer for instrumenting your serverless Ruby functions.
|
27
|
-
Details can be found on our [getting started guide](https://docs.newrelic.com/docs/serverless-function-monitoring/aws-lambda-monitoring/
|
27
|
+
Details can be found on our [getting started guide](https://docs.newrelic.com/docs/serverless-function-monitoring/aws-lambda-monitoring/instrument-lambda-function/instrument-your-own/).
|
28
28
|
|
29
29
|
## Installing and Using
|
30
30
|
|
@@ -72,7 +72,7 @@ module NewRelic
|
|
72
72
|
value_from_defaults(key, :transform)
|
73
73
|
end
|
74
74
|
|
75
|
-
def self.config_search_paths
|
75
|
+
def self.config_search_paths
|
76
76
|
proc {
|
77
77
|
yaml = 'newrelic.yml'
|
78
78
|
config_yaml = File.join('config', yaml)
|
@@ -1112,7 +1112,7 @@ module NewRelic
|
|
1112
1112
|
:public => true,
|
1113
1113
|
:type => Boolean,
|
1114
1114
|
:allowed_from_server => true,
|
1115
|
-
:description => "If `true`, the agent will report source code level metrics for traced methods.\
|
1115
|
+
:description => "If `true`, the agent will report source code level metrics for traced methods.\nSee: " \
|
1116
1116
|
'https://docs.newrelic.com/docs/apm/agents/ruby-agent/features/ruby-codestream-integration/'
|
1117
1117
|
},
|
1118
1118
|
# Cross application tracer
|
@@ -1150,7 +1150,7 @@ module NewRelic
|
|
1150
1150
|
:allowed_from_server => true,
|
1151
1151
|
:dynamic_name => true,
|
1152
1152
|
:description => <<~DESC
|
1153
|
-
* Specify a maximum number of custom events to buffer in memory at a time.
|
1153
|
+
* Specify a maximum number of custom events to buffer in memory at a time.
|
1154
1154
|
* When configuring the agent for [AI monitoring](/docs/ai-monitoring/intro-to-ai-monitoring), \
|
1155
1155
|
set to max value `100000`. This ensures the agent captures the maximum amount of LLM events.
|
1156
1156
|
DESC
|
@@ -1444,6 +1444,7 @@ module NewRelic
|
|
1444
1444
|
},
|
1445
1445
|
:'instrumentation.async_http' => {
|
1446
1446
|
:default => 'auto',
|
1447
|
+
:documentation_default => 'auto',
|
1447
1448
|
:public => true,
|
1448
1449
|
:type => String,
|
1449
1450
|
:dynamic_name => true,
|
@@ -1452,6 +1453,7 @@ module NewRelic
|
|
1452
1453
|
},
|
1453
1454
|
:'instrumentation.bunny' => {
|
1454
1455
|
:default => 'auto',
|
1456
|
+
:documentation_default => 'auto',
|
1455
1457
|
:public => true,
|
1456
1458
|
:type => String,
|
1457
1459
|
:dynamic_name => true,
|
@@ -1468,6 +1470,7 @@ module NewRelic
|
|
1468
1470
|
},
|
1469
1471
|
:'instrumentation.dynamodb' => {
|
1470
1472
|
:default => 'auto',
|
1473
|
+
:documentation_default => 'auto',
|
1471
1474
|
:public => true,
|
1472
1475
|
:type => String,
|
1473
1476
|
:dynamic_name => true,
|
@@ -1476,6 +1479,7 @@ module NewRelic
|
|
1476
1479
|
},
|
1477
1480
|
:'instrumentation.fiber' => {
|
1478
1481
|
:default => 'auto',
|
1482
|
+
:documentation_default => 'auto',
|
1479
1483
|
:public => true,
|
1480
1484
|
:type => String,
|
1481
1485
|
:dynamic_name => true,
|
@@ -1484,6 +1488,7 @@ module NewRelic
|
|
1484
1488
|
},
|
1485
1489
|
:'instrumentation.concurrent_ruby' => {
|
1486
1490
|
:default => 'auto',
|
1491
|
+
:documentation_default => 'auto',
|
1487
1492
|
:public => true,
|
1488
1493
|
:type => String,
|
1489
1494
|
:dynamic_name => true,
|
@@ -1510,6 +1515,7 @@ module NewRelic
|
|
1510
1515
|
},
|
1511
1516
|
:'instrumentation.elasticsearch' => {
|
1512
1517
|
:default => 'auto',
|
1518
|
+
:documentation_default => 'auto',
|
1513
1519
|
:public => true,
|
1514
1520
|
:type => String,
|
1515
1521
|
:dynamic_name => true,
|
@@ -1518,6 +1524,7 @@ module NewRelic
|
|
1518
1524
|
},
|
1519
1525
|
:'instrumentation.ethon' => {
|
1520
1526
|
:default => 'auto',
|
1527
|
+
:documentation_default => 'auto',
|
1521
1528
|
:public => true,
|
1522
1529
|
:type => String,
|
1523
1530
|
:dynamic_name => true,
|
@@ -1535,6 +1542,7 @@ module NewRelic
|
|
1535
1542
|
},
|
1536
1543
|
:'instrumentation.grape' => {
|
1537
1544
|
:default => 'auto',
|
1545
|
+
:documentation_default => 'auto',
|
1538
1546
|
:public => true,
|
1539
1547
|
:type => String,
|
1540
1548
|
:dynamic_name => true,
|
@@ -1603,8 +1611,18 @@ module NewRelic
|
|
1603
1611
|
:allowed_from_server => false,
|
1604
1612
|
:description => 'Controls auto-instrumentation of Ruby standard library Logger at start-up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
1605
1613
|
},
|
1614
|
+
:'instrumentation.logstasher' => {
|
1615
|
+
:default => instrumentation_value_from_boolean(:'application_logging.enabled'),
|
1616
|
+
:documentation_default => 'auto',
|
1617
|
+
:public => true,
|
1618
|
+
:type => String,
|
1619
|
+
:dynamic_name => true,
|
1620
|
+
:allowed_from_server => false,
|
1621
|
+
:description => 'Controls auto-instrumentation of the LogStasher library at start-up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
1622
|
+
},
|
1606
1623
|
:'instrumentation.memcache' => {
|
1607
1624
|
:default => 'auto',
|
1625
|
+
:documentation_default => 'auto',
|
1608
1626
|
:public => true,
|
1609
1627
|
:type => String,
|
1610
1628
|
:dynamic_name => true,
|
@@ -1698,6 +1716,7 @@ module NewRelic
|
|
1698
1716
|
},
|
1699
1717
|
:'instrumentation.rake' => {
|
1700
1718
|
:default => 'auto',
|
1719
|
+
:documentation_default => 'auto',
|
1701
1720
|
:public => true,
|
1702
1721
|
:type => String,
|
1703
1722
|
:dynamic_name => true,
|
@@ -1706,6 +1725,7 @@ module NewRelic
|
|
1706
1725
|
},
|
1707
1726
|
:'instrumentation.redis' => {
|
1708
1727
|
:default => 'auto',
|
1728
|
+
:documentation_default => 'auto',
|
1709
1729
|
:public => true,
|
1710
1730
|
:type => String,
|
1711
1731
|
:dynamic_name => true,
|
@@ -1723,6 +1743,7 @@ module NewRelic
|
|
1723
1743
|
},
|
1724
1744
|
:'instrumentation.roda' => {
|
1725
1745
|
:default => 'auto',
|
1746
|
+
:documentation_default => 'auto',
|
1726
1747
|
:public => true,
|
1727
1748
|
:type => String,
|
1728
1749
|
:dynamic_name => true,
|
@@ -1731,6 +1752,7 @@ module NewRelic
|
|
1731
1752
|
},
|
1732
1753
|
:'instrumentation.sinatra' => {
|
1733
1754
|
:default => 'auto',
|
1755
|
+
:documentation_default => 'auto',
|
1734
1756
|
:public => true,
|
1735
1757
|
:type => String,
|
1736
1758
|
:dynamic_name => true,
|
@@ -1746,6 +1768,7 @@ module NewRelic
|
|
1746
1768
|
},
|
1747
1769
|
:'instrumentation.view_component' => {
|
1748
1770
|
:default => 'auto',
|
1771
|
+
:documentation_default => 'auto',
|
1749
1772
|
:public => true,
|
1750
1773
|
:type => String,
|
1751
1774
|
:dynamic_name => true,
|
@@ -1782,6 +1805,7 @@ module NewRelic
|
|
1782
1805
|
},
|
1783
1806
|
:'instrumentation.thread' => {
|
1784
1807
|
:default => 'auto',
|
1808
|
+
:documentation_default => 'auto',
|
1785
1809
|
:public => true,
|
1786
1810
|
:type => String,
|
1787
1811
|
:dynamic_name => true,
|
@@ -1804,6 +1828,7 @@ module NewRelic
|
|
1804
1828
|
},
|
1805
1829
|
:'instrumentation.tilt' => {
|
1806
1830
|
:default => 'auto',
|
1831
|
+
:documentation_default => 'auto',
|
1807
1832
|
:public => true,
|
1808
1833
|
:type => String,
|
1809
1834
|
:dynamic_name => true,
|
@@ -2514,6 +2539,84 @@ module NewRelic
|
|
2514
2539
|
:type => Integer,
|
2515
2540
|
:allowed_from_server => false,
|
2516
2541
|
:description => 'This value represents the total amount of memory available to the host (not the process), in mebibytes (1024 squared or 1,048,576 bytes).'
|
2542
|
+
},
|
2543
|
+
# security agent
|
2544
|
+
:'security.agent.enabled' => {
|
2545
|
+
:default => false,
|
2546
|
+
:external => true,
|
2547
|
+
:public => true,
|
2548
|
+
:type => Boolean,
|
2549
|
+
:allowed_from_server => false,
|
2550
|
+
:description => "If `true`, the security agent is loaded (a Ruby 'require' is performed)"
|
2551
|
+
},
|
2552
|
+
:'security.enabled' => {
|
2553
|
+
:default => false,
|
2554
|
+
:external => true,
|
2555
|
+
:public => true,
|
2556
|
+
:type => Boolean,
|
2557
|
+
:allowed_from_server => false,
|
2558
|
+
:description => 'If `true`, the security agent is started (the agent runs in its event loop)'
|
2559
|
+
},
|
2560
|
+
:'security.mode' => {
|
2561
|
+
:default => 'IAST',
|
2562
|
+
:external => true,
|
2563
|
+
:public => true,
|
2564
|
+
:type => String,
|
2565
|
+
:allowed_from_server => true,
|
2566
|
+
:allowlist => %w[IAST RASP],
|
2567
|
+
:description => 'Defines the mode for the security agent to operate in. Currently only `IAST` is supported',
|
2568
|
+
:dynamic_name => true
|
2569
|
+
},
|
2570
|
+
:'security.validator_service_url' => {
|
2571
|
+
:default => 'wss://csec.nr-data.net',
|
2572
|
+
:external => true,
|
2573
|
+
:public => true,
|
2574
|
+
:type => String,
|
2575
|
+
:allowed_from_server => true,
|
2576
|
+
:description => 'Defines the endpoint URL for posting security-related data',
|
2577
|
+
:dynamic_name => true
|
2578
|
+
},
|
2579
|
+
:'security.detection.rci.enabled' => {
|
2580
|
+
:default => true,
|
2581
|
+
:external => true,
|
2582
|
+
:public => true,
|
2583
|
+
:type => Boolean,
|
2584
|
+
:allowed_from_server => false,
|
2585
|
+
:description => 'If `true`, enables RCI (remote code injection) detection'
|
2586
|
+
},
|
2587
|
+
:'security.detection.rxss.enabled' => {
|
2588
|
+
:default => true,
|
2589
|
+
:external => true,
|
2590
|
+
:public => true,
|
2591
|
+
:type => Boolean,
|
2592
|
+
:allowed_from_server => false,
|
2593
|
+
:description => 'If `true`, enables RXSS (reflected cross-site scripting) detection'
|
2594
|
+
},
|
2595
|
+
:'security.detection.deserialization.enabled' => {
|
2596
|
+
:default => true,
|
2597
|
+
:external => true,
|
2598
|
+
:public => true,
|
2599
|
+
:type => Boolean,
|
2600
|
+
:allowed_from_server => false,
|
2601
|
+
:description => 'If `true`, enables deserialization detection'
|
2602
|
+
},
|
2603
|
+
:'security.application_info.port' => {
|
2604
|
+
:default => nil,
|
2605
|
+
:allow_nil => true,
|
2606
|
+
:public => true,
|
2607
|
+
:type => Integer,
|
2608
|
+
:external => true,
|
2609
|
+
:allowed_from_server => false,
|
2610
|
+
:description => 'The port the application is listening on. This setting is mandatory for Passenger servers. Other servers should be detected by default.'
|
2611
|
+
},
|
2612
|
+
:'security.request.body_limit' => {
|
2613
|
+
:default => 300,
|
2614
|
+
:allow_nil => true,
|
2615
|
+
:public => true,
|
2616
|
+
:type => Integer,
|
2617
|
+
:external => true,
|
2618
|
+
:allowed_from_server => false,
|
2619
|
+
:description => 'Defines the request body limit to process in security events (in KB). The default value is 300, for 300KB.'
|
2517
2620
|
}
|
2518
2621
|
}.freeze
|
2519
2622
|
# rubocop:enable Metrics/CollectionLiteralLength
|
@@ -48,6 +48,12 @@ module NewRelic
|
|
48
48
|
correlation_id: opts[:correlation_id],
|
49
49
|
exchange_type: type
|
50
50
|
)
|
51
|
+
if segment
|
52
|
+
segment.add_agent_attribute('server.address', channel&.connection&.hostname)
|
53
|
+
segment.add_agent_attribute('server.port', channel&.connection&.port)
|
54
|
+
segment.add_agent_attribute('messaging.destination.name', destination) # for produce, this is exchange name
|
55
|
+
segment.add_agent_attribute('messaging.rabbitmq.destination.routing_key', opts[:routing_key])
|
56
|
+
end
|
51
57
|
rescue => e
|
52
58
|
NewRelic::Agent.logger.error('Error starting message broker segment in Bunny::Exchange#publish', e)
|
53
59
|
yield
|
@@ -94,6 +100,14 @@ module NewRelic
|
|
94
100
|
queue_name: name,
|
95
101
|
start_time: t0
|
96
102
|
)
|
103
|
+
if segment
|
104
|
+
segment.add_agent_attribute('server.address', channel&.connection&.hostname)
|
105
|
+
segment.add_agent_attribute('server.port', channel&.connection&.port)
|
106
|
+
segment.add_agent_attribute('messaging.destination.name', name) # for consume, this is queue name
|
107
|
+
segment.add_agent_attribute('messaging.destination_publish.name', exch_name)
|
108
|
+
segment.add_agent_attribute('message.queueName', name)
|
109
|
+
segment.add_agent_attribute('messaging.rabbitmq.destination.routing_key', delivery_info&.routing_key)
|
110
|
+
end
|
97
111
|
rescue => e
|
98
112
|
NewRelic::Agent.logger.error('Error starting message broker segment in Bunny::Queue#pop', e)
|
99
113
|
else
|
@@ -102,7 +102,7 @@ module NewRelic::Agent::Instrumentation
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def nr_cluster_name
|
105
|
-
return @nr_cluster_name if @nr_cluster_name
|
105
|
+
return @nr_cluster_name if defined?(@nr_cluster_name)
|
106
106
|
return if nr_hosts.empty?
|
107
107
|
|
108
108
|
NewRelic::Agent.disable_all_tracing do
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
module NewRelic::Agent::Instrumentation
|
6
|
+
module LogStasher::Chain
|
7
|
+
def self.instrument!
|
8
|
+
::LogStasher.singleton_class.class_eval do
|
9
|
+
include NewRelic::Agent::Instrumentation::LogStasher
|
10
|
+
|
11
|
+
alias_method(:build_logstash_event_without_new_relic, :build_logstash_event)
|
12
|
+
|
13
|
+
def build_logstash_event(*args)
|
14
|
+
build_logstash_event_with_new_relic(*args) do
|
15
|
+
build_logstash_event_without_new_relic(*args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
module NewRelic::Agent::Instrumentation
|
6
|
+
module LogStasher
|
7
|
+
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
|
8
|
+
|
9
|
+
def self.enabled?
|
10
|
+
NewRelic::Agent.config[:'instrumentation.logstasher'] != 'disabled'
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_logstash_event_with_new_relic(*args)
|
14
|
+
logstasher_event = yield
|
15
|
+
log = logstasher_event.instance_variable_get(:@data)
|
16
|
+
|
17
|
+
::NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
|
18
|
+
::NewRelic::Agent.agent.log_event_aggregator.record_logstasher_event(log)
|
19
|
+
::NewRelic::Agent::LocalLogDecorator.decorate(log)
|
20
|
+
|
21
|
+
logstasher_event
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
module NewRelic::Agent::Instrumentation
|
6
|
+
module LogStasher::Prepend
|
7
|
+
include NewRelic::Agent::Instrumentation::LogStasher
|
8
|
+
|
9
|
+
def build_logstash_event(*args)
|
10
|
+
build_logstash_event_with_new_relic(*args) { super }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require_relative 'logstasher/instrumentation'
|
6
|
+
require_relative 'logstasher/chain'
|
7
|
+
require_relative 'logstasher/prepend'
|
8
|
+
|
9
|
+
DependencyDetection.defer do
|
10
|
+
named :logstasher
|
11
|
+
|
12
|
+
depends_on do
|
13
|
+
defined?(LogStasher) &&
|
14
|
+
Gem::Version.new(LogStasher::VERSION) >= Gem::Version.new('1.0.0') &&
|
15
|
+
NewRelic::Agent.config[:'application_logging.enabled']
|
16
|
+
end
|
17
|
+
|
18
|
+
executes do
|
19
|
+
NewRelic::Agent.logger.info('Installing LogStasher instrumentation')
|
20
|
+
|
21
|
+
if use_prepend?
|
22
|
+
prepend_instrument LogStasher.singleton_class, NewRelic::Agent::Instrumentation::LogStasher::Prepend
|
23
|
+
else
|
24
|
+
chain_instrument NewRelic::Agent::Instrumentation::LogStasher::Chain
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -13,6 +13,7 @@ module NewRelic
|
|
13
13
|
attr_accessor :_nr_deferred_detection_ran
|
14
14
|
end
|
15
15
|
builder_class._nr_deferred_detection_ran = false
|
16
|
+
NewRelic::Control::SecurityInterface.instance.wait = true
|
16
17
|
end
|
17
18
|
|
18
19
|
def deferred_dependency_check
|
@@ -21,6 +22,8 @@ module NewRelic
|
|
21
22
|
NewRelic::Agent.logger.info('Doing deferred dependency-detection before Rack startup')
|
22
23
|
DependencyDetection.detect!
|
23
24
|
self.class._nr_deferred_detection_ran = true
|
25
|
+
NewRelic::Control::SecurityInterface.instance.wait = false
|
26
|
+
NewRelic::Control::SecurityInterface.instance.init_agent
|
24
27
|
end
|
25
28
|
|
26
29
|
def check_for_late_instrumentation(app)
|
@@ -32,15 +32,19 @@ DependencyDetection.defer do
|
|
32
32
|
NewRelic::Agent::Instrumentation::ActionControllerSubscriber \
|
33
33
|
.subscribe(/^process_action.action_controller$/)
|
34
34
|
|
35
|
-
subs = %w[
|
35
|
+
subs = %w[exist_fragment?
|
36
|
+
expire_fragment
|
37
|
+
halted_callback
|
38
|
+
read_fragment
|
39
|
+
redirect_to
|
36
40
|
send_data
|
41
|
+
send_file
|
37
42
|
send_stream
|
38
|
-
|
39
|
-
|
40
|
-
unpermitted_parameters]
|
43
|
+
write_fragment
|
44
|
+
unpermitted_parameters].map { |s| Regexp.escape(s) }
|
41
45
|
|
42
46
|
# have to double escape period because its going from string -> regex
|
43
47
|
NewRelic::Agent::Instrumentation::ActionControllerOtherSubscriber \
|
44
|
-
.subscribe(Regexp.new("^(
|
48
|
+
.subscribe(Regexp.new("^(?:#{subs.join('|')})\\.action_controller$"))
|
45
49
|
end
|
46
50
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
module NewRelic::Agent::Instrumentation
|
6
|
+
module RedisClient
|
7
|
+
module ClusterMiddleware
|
8
|
+
include NewRelic::Agent::Instrumentation::Redis
|
9
|
+
|
10
|
+
# Until we decide to move our Redis instrumentation entirely off patches
|
11
|
+
# keep the middleware instrumentation for the call and connect methods
|
12
|
+
# limited to the redis-clustering instrumentation.
|
13
|
+
#
|
14
|
+
# Redis's middleware option does not capture errors as high in the stack
|
15
|
+
# as our patches. Leaving the patches for call and connect on the main
|
16
|
+
# Redis gem limits the feature disparity our customers experience.
|
17
|
+
def call(*args, &block)
|
18
|
+
call_with_tracing(args[0]) { super }
|
19
|
+
end
|
20
|
+
|
21
|
+
def connect(*args, &block)
|
22
|
+
connect_with_tracing { super }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -9,14 +9,14 @@ module NewRelic::Agent::Instrumentation
|
|
9
9
|
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
|
10
10
|
|
11
11
|
def connect_with_tracing
|
12
|
-
with_tracing(Constants::CONNECT, database:
|
12
|
+
with_tracing(Constants::CONNECT, database: _nr_db) { yield }
|
13
13
|
end
|
14
14
|
|
15
15
|
def call_with_tracing(command, &block)
|
16
16
|
operation = command[0]
|
17
17
|
statement = ::NewRelic::Agent::Datastores::Redis.format_command(command)
|
18
18
|
|
19
|
-
with_tracing(operation, statement: statement, database:
|
19
|
+
with_tracing(operation, statement: statement, database: _nr_db) { yield }
|
20
20
|
end
|
21
21
|
|
22
22
|
# Used for Redis 4.x and 3.x
|
@@ -24,22 +24,15 @@ module NewRelic::Agent::Instrumentation
|
|
24
24
|
operation = pipeline.is_a?(::Redis::Pipeline::Multi) ? Constants::MULTI_OPERATION : Constants::PIPELINE_OPERATION
|
25
25
|
statement = ::NewRelic::Agent::Datastores::Redis.format_pipeline_commands(pipeline.commands)
|
26
26
|
|
27
|
-
with_tracing(operation, statement: statement, database:
|
27
|
+
with_tracing(operation, statement: statement, database: _nr_db) { yield }
|
28
28
|
end
|
29
29
|
|
30
30
|
# Used for Redis 5.x+
|
31
31
|
def call_pipelined_with_tracing(pipeline)
|
32
|
-
db = begin
|
33
|
-
_nr_redis_client_config.db
|
34
|
-
rescue StandardError => e
|
35
|
-
NewRelic::Agent.logger.error("Failed to determine configured Redis db value: #{e.class} - #{e.message}")
|
36
|
-
nil
|
37
|
-
end
|
38
|
-
|
39
32
|
operation = pipeline.flatten.include?('MULTI') ? Constants::MULTI_OPERATION : Constants::PIPELINE_OPERATION
|
40
33
|
statement = ::NewRelic::Agent::Datastores::Redis.format_pipeline_commands(pipeline)
|
41
34
|
|
42
|
-
with_tracing(operation, statement: statement, database:
|
35
|
+
with_tracing(operation, statement: statement, database: _nr_db) { yield }
|
43
36
|
end
|
44
37
|
|
45
38
|
private
|
@@ -94,5 +87,15 @@ module NewRelic::Agent::Instrumentation
|
|
94
87
|
config
|
95
88
|
end
|
96
89
|
end
|
90
|
+
|
91
|
+
def _nr_db
|
92
|
+
# db is a method on the Redis client in versions < 5.x
|
93
|
+
return db if respond_to?(:db)
|
94
|
+
# db is accessible through the RedisClient::Config object in versions > 5.x
|
95
|
+
return _nr_redis_client_config.db if _nr_redis_client_config.respond_to?(:db)
|
96
|
+
rescue StandardError => e
|
97
|
+
NewRelic::Agent.logger.debug("Failed to determine configured Redis db value: #{e.class} - #{e.message}")
|
98
|
+
nil
|
99
|
+
end
|
97
100
|
end
|
98
101
|
end
|
@@ -6,6 +6,9 @@ module NewRelic::Agent::Instrumentation
|
|
6
6
|
module RedisClient
|
7
7
|
module Middleware
|
8
8
|
# This module is used to instrument Redis 5.x+
|
9
|
+
#
|
10
|
+
# It only instruments call_pipelined because connect and call are accessed
|
11
|
+
# too late in the stack to capture all errors
|
9
12
|
include NewRelic::Agent::Instrumentation::Redis
|
10
13
|
|
11
14
|
def call_pipelined(*args, &block)
|
@@ -10,6 +10,7 @@ require_relative 'redis/chain'
|
|
10
10
|
require_relative 'redis/constants'
|
11
11
|
require_relative 'redis/prepend'
|
12
12
|
require_relative 'redis/middleware'
|
13
|
+
require_relative 'redis/cluster_middleware'
|
13
14
|
|
14
15
|
DependencyDetection.defer do
|
15
16
|
# Why not :redis? newrelic-redis used that name, so avoid conflicting
|
@@ -33,6 +34,10 @@ DependencyDetection.defer do
|
|
33
34
|
NewRelic::Agent.logger.info('Installing Redis Instrumentation')
|
34
35
|
if NewRelic::Agent::Instrumentation::Redis::Constants::HAS_REDIS_CLIENT
|
35
36
|
RedisClient.register(NewRelic::Agent::Instrumentation::RedisClient::Middleware)
|
37
|
+
|
38
|
+
if defined?(Redis::Cluster::Client)
|
39
|
+
return RedisClient.register(NewRelic::Agent::Instrumentation::RedisClient::ClusterMiddleware)
|
40
|
+
end
|
36
41
|
end
|
37
42
|
|
38
43
|
if use_prepend?
|