-
Notifications
You must be signed in to change notification settings - Fork 600
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2267 from newrelic/roda_newrelic_ignore
Add Roda support for newrelic_ignore*
- Loading branch information
Showing
5 changed files
with
273 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# This file is distributed under New Relic's license terms. | ||
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details. | ||
# frozen_string_literal: true | ||
|
||
module NewRelic::Agent::Instrumentation | ||
module Roda | ||
module Ignorer | ||
def self.should_ignore?(app, type) | ||
return false unless app.opts.include?(:newrelic_ignores) | ||
|
||
app.opts[:newrelic_ignores][type].any? do |pattern| | ||
pattern === app.request.path_info | ||
end | ||
end | ||
|
||
def newrelic_ignore(*routes) | ||
set_newrelic_ignore(:routes, *routes) | ||
end | ||
|
||
def newrelic_ignore_apdex(*routes) | ||
set_newrelic_ignore(:apdex, *routes) | ||
end | ||
|
||
def newrelic_ignore_enduser(*routes) | ||
set_newrelic_ignore(:enduser, *routes) | ||
end | ||
|
||
private | ||
|
||
def set_newrelic_ignore(type, *routes) | ||
# Create a newrelic_ignores hash if one doesn't exist | ||
opts[:newrelic_ignores] = Hash.new([]) if !opts.include?(:newrelic_ignores) | ||
|
||
if routes.empty? | ||
opts[:newrelic_ignores][type] += [Regexp.new('.*')] | ||
else | ||
opts[:newrelic_ignores][type] += routes.map do |r| | ||
# Roda adds leading slashes to routes, so we need to do the same | ||
"#{'/' unless r.start_with?('/')}#{r}" | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
# This file is distributed under New Relic's license terms. | ||
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details. | ||
# frozen_string_literal: true | ||
|
||
require_relative '../../../../lib/new_relic/agent/instrumentation/roda/instrumentation' | ||
require_relative '../../../../lib/new_relic/agent/instrumentation/roda/roda_transaction_namer' | ||
require_relative '../../../../lib/new_relic/agent/instrumentation/roda/ignorer' | ||
|
||
JS_AGENT_LOADER = 'JS_AGENT_LOADER' | ||
|
||
class RodaIgnorerTestApp < Roda | ||
newrelic_ignore('/ignore_me', '/ignore_me_too') | ||
newrelic_ignore('no_leading_slash') | ||
newrelic_ignore('/ignored_erroring') | ||
|
||
route do |r| | ||
r.on('/home') { 'home' } | ||
r.on('/ignore_me') { 'this page is ignored' } | ||
r.on('/ignore_me_too') { 'this page is ignored too' } | ||
r.on('/ignore_me_not') { 'our regex should not capture this' } | ||
r.on('no_leading_slash') { 'user does not use leading slash for ignore' } | ||
r.on('/no_apdex') { 'no apex should be recorded' } | ||
r.on('/ignored_erroring') { raise 'boom' } | ||
end | ||
end | ||
|
||
class RodaIgnoreTest < Minitest::Test | ||
include Rack::Test::Methods | ||
include MultiverseHelpers | ||
|
||
setup_and_teardown_agent | ||
|
||
def app | ||
RodaIgnorerTestApp | ||
end | ||
|
||
def test_seen_route | ||
get('/home') | ||
|
||
assert_metrics_recorded('Controller/Roda/RodaIgnorerTestApp/GET home') | ||
end | ||
|
||
def test_ignore_route | ||
get('/ignore_me') | ||
|
||
assert_metrics_not_recorded([ | ||
'Controller/Roda/RodaIgnorerTestApp/GET ignore_me', | ||
'Apdex/Roda/RodaIgnorerTestApp/GET ignore_me' | ||
]) | ||
end | ||
|
||
def test_regex_ignores_intended_route | ||
get('/ignore_me') | ||
get('/ignore_me_not') | ||
|
||
assert_metrics_not_recorded([ | ||
'Controller/Roda/RodaIgnorerTestApp/GET ignore_me', | ||
'Apdex/Roda/RodaIgnorerTestApp/GET ignore_me' | ||
]) | ||
|
||
assert_metrics_recorded([ | ||
'Controller/Roda/RodaIgnorerTestApp/GET ignore_me_not', | ||
'Apdex/Roda/RodaIgnorerTestApp/GET ignore_me_not' | ||
]) | ||
end | ||
|
||
def test_ignores_if_route_does_not_have_leading_slash | ||
get('no_leading_slash') | ||
|
||
assert_metrics_not_recorded([ | ||
'Controller/Roda/RodaIgnorerTestApp/GET no_leading_slash', | ||
'Apdex/Roda/RodaIgnorerTestApp/GET no_leading_slash' | ||
]) | ||
end | ||
|
||
def test_ignore_errors_in_ignored_transactions | ||
get('/ignored_erroring') | ||
|
||
assert_metrics_not_recorded(['Errors/all']) | ||
end | ||
end | ||
|
||
class RodaIgnoreAllRoutesApp < Roda | ||
# newrelic_ignore called without any arguments will ignore the entire app | ||
newrelic_ignore | ||
|
||
route do |r| | ||
r.on('home') { 'home' } | ||
r.on('hello') { 'hello' } | ||
end | ||
end | ||
|
||
class RodaIgnoreAllRoutesAppTest < Minitest::Test | ||
include Rack::Test::Methods | ||
include MultiverseHelpers | ||
|
||
setup_and_teardown_agent | ||
|
||
def app | ||
RodaIgnoreAllRoutesApp | ||
end | ||
|
||
def test_ignores_by_splats | ||
get('/hello') | ||
get('/home') | ||
|
||
assert_metrics_not_recorded([ | ||
'Controller/Roda/RodaIgnoreAllTestApp/GET hello', | ||
'Apdex/Roda/RodaIgnoreAllTestApp/GET hello' | ||
]) | ||
|
||
assert_metrics_not_recorded([ | ||
'Controller/Roda/RodaIgnoreAllTestApp/GET home', | ||
'Apdex/Roda/RodaIgnoreAllTestApp/GET home' | ||
]) | ||
end | ||
end | ||
|
||
class RodaIgnoreApdexApp < Roda | ||
newrelic_ignore_apdex('/no_apdex') | ||
|
||
route do |r| | ||
r.on('home') { 'home' } | ||
r.on('no_apdex') { 'do not record apdex' } | ||
end | ||
end | ||
|
||
class RodaIgnoreApdexAppTest < Minitest::Test | ||
include Rack::Test::Methods | ||
include MultiverseHelpers | ||
|
||
setup_and_teardown_agent | ||
|
||
def app | ||
RodaIgnoreApdexApp | ||
end | ||
|
||
def test_ignores_apdex_by_route | ||
get('/no_apdex') | ||
|
||
assert_metrics_not_recorded('Apdex/Roda/RodaIgnoreApdexApp/GET no_apdex') | ||
end | ||
|
||
def test_ignores_enduser_but_not_route | ||
get('no_apdex') | ||
|
||
assert_metrics_recorded('Controller/Roda/RodaIgnoreApdexApp/GET no_apdex') | ||
assert_metrics_not_recorded('Apdex/Roda/RodaIgnoreApdexApp/GET no_apdex') | ||
end | ||
end | ||
|
||
class RodaIgnoreEndUserApp < Roda | ||
def fake_html_for_browser_timing_header | ||
'<html><head><title></title></head><body></body></html>' | ||
end | ||
|
||
newrelic_ignore_enduser('ignore_enduser') | ||
|
||
route do |r| | ||
r.on('home') { fake_html_for_browser_timing_header } | ||
r.on('ignore_enduser') { fake_html_for_browser_timing_header } | ||
end | ||
end | ||
|
||
class RodaIgnoreEndUserAppTest < Minitest::Test | ||
include Rack::Test::Methods | ||
include MultiverseHelpers | ||
|
||
def assert_enduser_ignored(response) | ||
refute_match(/#{JS_AGENT_LOADER}/o, response.body) | ||
end | ||
|
||
def refute_enduser_ignored(response) | ||
assert_match(/#{JS_AGENT_LOADER}/o, response.body) | ||
end | ||
|
||
setup_and_teardown_agent(:application_id => 'appId', | ||
:beacon => 'beacon', | ||
:browser_key => 'browserKey', | ||
:js_agent_loader => 'JS_AGENT_LOADER') | ||
|
||
def app | ||
RodaIgnoreEndUserApp | ||
end | ||
|
||
def test_ignore_enduser_should_only_apply_to_specified_route | ||
with_config(:application_id => 'appId', | ||
:beacon => 'beacon', | ||
:browser_key => 'browserKey', | ||
:js_agent_loader => 'JS_AGENT_LOADER') do | ||
get('home') | ||
|
||
refute_enduser_ignored(last_response) | ||
assert_metrics_recorded('Controller/Roda/RodaIgnoreEndUserApp/GET home') | ||
end | ||
end | ||
|
||
def test_ignores_enduser | ||
get('ignore_enduser') | ||
|
||
assert_enduser_ignored(last_response) | ||
end | ||
end |