-
Notifications
You must be signed in to change notification settings - Fork 600
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RuboCop: address some AbcSize issues #1849
Changes from all commits
ffd61c5
a6d1cec
56f45fe
3666602
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,36 +60,13 @@ def interval_for(event_type) | |
end | ||
|
||
def create_and_run_event_loop | ||
data_harvest = :"#{Agent.config[:data_report_period]}_second_harvest" | ||
event_harvest = :"#{Agent.config[:event_report_period]}_second_harvest" | ||
|
||
@event_loop = create_event_loop | ||
data_harvest = :"#{Agent.config[:data_report_period]}_second_harvest" | ||
@event_loop.on(data_harvest) do | ||
transmit_data | ||
end | ||
|
||
@event_loop.on(interval_for(TRANSACTION_EVENT_DATA)) do | ||
transmit_analytic_event_data | ||
end | ||
@event_loop.on(interval_for(CUSTOM_EVENT_DATA)) do | ||
transmit_custom_event_data | ||
end | ||
@event_loop.on(interval_for(ERROR_EVENT_DATA)) do | ||
transmit_error_event_data | ||
end | ||
@event_loop.on(interval_for(SPAN_EVENT_DATA)) do | ||
transmit_span_event_data | ||
end | ||
@event_loop.on(interval_for(LOG_EVENT_DATA)) do | ||
transmit_log_event_data | ||
end | ||
|
||
@event_loop.on(:reset_log_once_keys) do | ||
::NewRelic::Agent.logger.clear_already_logged | ||
end | ||
@event_loop.fire_every(Agent.config[:data_report_period], data_harvest) | ||
@event_loop.fire_every(Agent.config[:event_report_period], event_harvest) | ||
@event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys) | ||
establish_interval_transmissions | ||
establish_fire_everies(data_harvest) | ||
|
||
@event_loop.run | ||
end | ||
|
@@ -161,6 +138,37 @@ def deferred_work!(connection_options) | |
end | ||
end | ||
end | ||
|
||
private | ||
|
||
def establish_interval_transmissions | ||
@event_loop.on(interval_for(TRANSACTION_EVENT_DATA)) do | ||
transmit_analytic_event_data | ||
end | ||
@event_loop.on(interval_for(CUSTOM_EVENT_DATA)) do | ||
transmit_custom_event_data | ||
end | ||
@event_loop.on(interval_for(ERROR_EVENT_DATA)) do | ||
transmit_error_event_data | ||
end | ||
@event_loop.on(interval_for(SPAN_EVENT_DATA)) do | ||
transmit_span_event_data | ||
end | ||
@event_loop.on(interval_for(LOG_EVENT_DATA)) do | ||
transmit_log_event_data | ||
end | ||
end | ||
|
||
def establish_fire_everies(data_harvest) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fun method name lol |
||
@event_loop.on(:reset_log_once_keys) do | ||
::NewRelic::Agent.logger.clear_already_logged | ||
end | ||
|
||
event_harvest = :"#{Agent.config[:event_report_period]}_second_harvest" | ||
@event_loop.fire_every(Agent.config[:data_report_period], data_harvest) | ||
@event_loop.fire_every(Agent.config[:event_report_period], event_harvest) | ||
@event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys) | ||
end | ||
end | ||
end | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -163,24 +163,24 @@ def set_params_v2(request) | |
def options | ||
OptionParser.new(%Q(Usage: #{$0} #{self.class.command} [OPTIONS] ["description"] ), 40) do |o| | ||
o.separator("OPTIONS:") | ||
o.on("-a", "--appname=NAME", String, | ||
"Set the application name.", | ||
"Default is app_name setting in newrelic.yml. Available only when using API v1.") { |e| @appname = e } | ||
o.on("-i", "--appid=ID", String, | ||
"Set the application ID", | ||
"If not provided, will connect to the New Relic collector to get it") { |i| @application_id = i } | ||
o.on("-e", "--environment=name", String, | ||
"Override the (RAILS|RUBY|RACK)_ENV setting", | ||
o.on('-a', '--appname=NAME', String, | ||
'Set the application name.', | ||
'Default is app_name setting in newrelic.yml. Available only when using API v1.') { |e| @appname = e } | ||
o.on('-i', '--appid=ID', String, | ||
'Set the application ID', | ||
'If not provided, will connect to the New Relic collector to get it') { |i| @application_id = i } | ||
o.on('-e', '--environment=name', String, | ||
'Override the (RAILS|RUBY|RACK)_ENV setting', | ||
"currently: #{control.env}") { |e| @environment = e } | ||
o.on("-u", "--user=USER", String, | ||
"Specify the user deploying, for information only", | ||
o.on('-u', '--user=USER', String, | ||
'Specify the user deploying, for information only', | ||
"Default: #{@user || '<none>'}") { |u| @user = u } | ||
o.on("-r", "--revision=REV", String, | ||
"Specify the revision being deployed. Required when using New Relic REST API v2") { |r| @revision = r } | ||
o.on("-l", "--license-key=KEY", String, | ||
"Specify the license key of the account for the app being deployed") { |l| @license_key = l } | ||
o.on("-c", "--changes", | ||
"Read in a change log from the standard input") { @changelog = STDIN.read } | ||
o.on('-r', '--revision=REV', String, | ||
'Specify the revision being deployed. Required when using New Relic REST API v2') { |r| @revision = r } | ||
o.on('-l', '--license-key=KEY', String, | ||
'Specify the license key of the account for the app being deployed') { |l| @license_key = l } | ||
o.on('-c', '--changes', | ||
'Read in a change log from the standard input') { @changelog = STDIN.read } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I love seeing these single quotes. Isn't there a built-in linter for changing double quotes to singles for areas without interpolation? I wonder if that might be worth turning on? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can tell RuboCop to insist on the use of single quotes for strings without interpolation or you can tell RuboCop to insist on double quotes everywhere. I believe RuboCop currently defaults to the first one of those, but there has been well reasoned arguments for the second approach as well. I believe we are currently disabling that cop and allowing any kind of quotes at any time regardless of interpolation. If the devs decide on a standard, we can update the RuboCop config accordingly. Until then, I've been operating with my personal preference of RuboCop defaults. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the record! I prefer single quotes. Double quotes alert me to interpolation, so I'd love to see this single quote cop enabled. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My preference is also single quotes unless in interpolation, though it can get hairy if we have apostrophes in our strings. |
||
yield(o) if block_given? | ||
end | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,26 +44,38 @@ def rails_config | |
# find a config and use that. | ||
def init_config(options = {}) | ||
@config = options[:config] | ||
# Install the dependency detection, | ||
if rails_config && ::Rails.configuration.respond_to?(:after_initialize) | ||
rails_config.after_initialize do | ||
# This will insure we load all the instrumentation as late as possible. If the agent | ||
# is not enabled, it will load a limited amount of instrumentation. | ||
DependencyDetection.detect! | ||
end | ||
install_dependency_detection | ||
install_browser_monitoring_and_agent_hooks | ||
rescue => e | ||
::NewRelic::Agent.logger.error('Failure during init_config for Rails. Is Rails required in a non-Rails ' \ | ||
'app? Set NEW_RELIC_FRAMEWORK=ruby to avoid this message. The Ruby agent ' \ | ||
'will continue running, but Rails-specific features may be missing. ' \ | ||
"#{e.class} - #{e.message}") | ||
end | ||
|
||
def install_dependency_detection | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Love turning that comment into a method! |
||
return unless rails_config && ::Rails.configuration.respond_to?(:after_initialize) | ||
|
||
rails_config.after_initialize do | ||
# This will insure we load all the instrumentation as late as | ||
# possible. If the agent is not enabled, it will load a limited | ||
# amount of instrumentation. | ||
DependencyDetection.detect! | ||
end | ||
end | ||
|
||
def install_browser_monitoring_and_agent_hooks | ||
return unless rails_config | ||
|
||
if !Agent.config[:agent_enabled] | ||
# Might not be running if it does not think mongrel, thin, passenger, etc | ||
# is running, if it thinks it's a rake task, or if the agent_enabled is false. | ||
::NewRelic::Agent.logger.info("New Relic Agent not running.") | ||
# Might not be running if it does not think mongrel, thin, | ||
# passenger, etc. is running, if it thinks it's a rake task, or | ||
# if the agent_enabled is false. | ||
::NewRelic::Agent.logger.info('New Relic Agent not running. Skipping browser monitoring and agent hooks.') | ||
else | ||
install_browser_monitoring(rails_config) | ||
install_agent_hooks(rails_config) | ||
end | ||
rescue => e | ||
::NewRelic::Agent.logger.error("Failure during init_config for Rails. Is Rails required in a non-Rails app? Set NEW_RELIC_FRAMEWORK=ruby to avoid this message.", | ||
"The Ruby agent will continue running, but Rails-specific features may be missing.", | ||
e) | ||
end | ||
|
||
def install_agent_hooks(config) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,7 +40,7 @@ def traced_call(env) | |
|
||
js_to_inject = NewRelic::Agent.browser_timing_header | ||
if (js_to_inject != NewRelic::EMPTY_STR) && should_instrument?(env, status, headers) | ||
response_string = autoinstrument_source(response, headers, js_to_inject) | ||
response_string = autoinstrument_source(response, js_to_inject) | ||
if headers.key?(CONTENT_LENGTH) | ||
content_length = response_string ? response_string.bytesize : 0 | ||
headers[CONTENT_LENGTH] = content_length.to_s | ||
|
@@ -69,30 +69,33 @@ def should_instrument?(env, status, headers) | |
|
||
private | ||
|
||
def autoinstrument_source(response, headers, js_to_inject) | ||
def autoinstrument_source(response, js_to_inject) | ||
source = gather_source(response) | ||
close_old_response(response) | ||
return nil unless source | ||
return unless source | ||
|
||
modify_source(source, js_to_inject) | ||
rescue => e | ||
NewRelic::Agent.logger.debug("Skipping RUM instrumentation on exception: #{e.class} - #{e.message}") | ||
end | ||
|
||
def modify_source(source, js_to_inject) | ||
# Only scan the first 50k (roughly) then give up. | ||
beginning_of_source = source[0..SCAN_LIMIT] | ||
meta_tag_positions = find_meta_tag_positions(beginning_of_source) | ||
if body_start = find_body_start(beginning_of_source) | ||
if insertion_index = find_insertion_index(meta_tag_positions, beginning_of_source, body_start) | ||
source = source_injection(source, insertion_index, js_to_inject) | ||
else | ||
NewRelic::Agent.logger.debug("Skipping RUM instrumentation. Could not properly determine location to inject script.") | ||
NewRelic::Agent.logger.debug('Skipping RUM instrumentation. Could not properly determine location to ' \ | ||
'inject script.') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, so while I was fixing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh just a length thing! Cool thank you |
||
end | ||
else | ||
msg = "Skipping RUM instrumentation. Unable to find <body> tag in first #{SCAN_LIMIT} bytes of document." | ||
NewRelic::Agent.logger.log_once(:warn, :rum_insertion_failure, msg) | ||
NewRelic::Agent.logger.debug(msg) | ||
end | ||
|
||
source | ||
rescue => e | ||
NewRelic::Agent.logger.debug("Skipping RUM instrumentation on exception.", e) | ||
nil | ||
end | ||
|
||
def html?(headers) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still feels like a decent amount of duplication. Would it work to put tbe *_EVENT_DATA constants into an array and loop through them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The short answer for why I didn't do so is that I'm trying to very tightly scope this PR's changes to RuboCop related things. I brought in changes in line length and quotes because there are cops for those things, but I didn't want to do any refactoring to the code beyond that.
For a summary of a longer answer, that thought did come to mind in this section of the code but each constant is mapped to a different method call and the names don't all follow a common convention. For example:
TRANSACTION_EVENT_DATA
maps totransmit_analytic_event_data
which breaks the pattern oftransmit_<CONSTANT.downcase>. I also did not want to dive into a deep understanding of the requirements of what needs to take place in the context of an event loops
doblock. It's possible that something like
send(methodize(CONSTANT)` wouldn't work the same way. So I stuck to just satisfying the cop.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that makes sense to me. One thought I had is that in the future if we want to further refactor this we could put the constants into a hash that has the methods in it, that way we don't have to try to guess or interpolate what the method name is supposed to be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I totally agree with making tightly scoped changes. This is great as-is.