diff --git a/CHANGELOG.md b/CHANGELOG.md index 722acd11..c9df6695 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ Airbrake Ruby Changelog ### master +* Started sending information about notifier name & version, operating system & + language with every remote config GET request + ([#594](https://github.com/airbrake/airbrake-ruby/pull/594)) + ### [v5.0.0.rc.1][v5.0.0.rc.1] (July 13, 2020) * Added the `error_notifications` option (enabled by default). This option diff --git a/lib/airbrake-ruby/notice.rb b/lib/airbrake-ruby/notice.rb index c5529d31..f10ea793 100644 --- a/lib/airbrake-ruby/notice.rb +++ b/lib/airbrake-ruby/notice.rb @@ -4,19 +4,12 @@ module Airbrake # # @since v1.0.0 class Notice - # @return [Hash{Symbol=>String}] the information about the notifier library - NOTIFIER = { - name: 'airbrake-ruby'.freeze, - version: Airbrake::AIRBRAKE_RUBY_VERSION, - url: 'https://github.com/airbrake/airbrake-ruby'.freeze, - }.freeze - # @return [Hash{Symbol=>String,Hash}] the information to be displayed in the # Context tab in the dashboard CONTEXT = { os: RUBY_PLATFORM, language: "#{RUBY_ENGINE}/#{RUBY_VERSION}".freeze, - notifier: NOTIFIER, + notifier: Airbrake::NOTIFIER_INFO, }.freeze # @return [Integer] the maxium size of the JSON payload in bytes diff --git a/lib/airbrake-ruby/remote_settings.rb b/lib/airbrake-ruby/remote_settings.rb index 8a04efee..d712af2d 100644 --- a/lib/airbrake-ruby/remote_settings.rb +++ b/lib/airbrake-ruby/remote_settings.rb @@ -24,6 +24,15 @@ class RemoteSettings '../../config/config.json', ).freeze + # @return [Hash{Symbol=>String}] metadata to be attached to every GET + # request + QUERY_PARAMS = URI.encode_www_form( + notifier_name: Airbrake::NOTIFIER_INFO[:name], + notifier_version: Airbrake::NOTIFIER_INFO[:version], + os: RUBY_PLATFORM, + language: "#{RUBY_ENGINE}/#{RUBY_VERSION}".freeze, + ).freeze + # Polls remote config of the given project. # # @param [Integer] project_id @@ -84,7 +93,7 @@ def stop_polling def fetch_config response = nil begin - response = Net::HTTP.get(URI(@data.config_route)) + response = Net::HTTP.get(build_config_uri) rescue StandardError => ex logger.error(ex) return {} @@ -108,6 +117,12 @@ def fetch_config json end + def build_config_uri + uri = URI(@data.config_route) + uri.query = QUERY_PARAMS + uri + end + def load_config config_dir = File.dirname(CONFIG_DUMP_PATH) Dir.mkdir(config_dir) unless File.directory?(config_dir) diff --git a/lib/airbrake-ruby/sync_sender.rb b/lib/airbrake-ruby/sync_sender.rb index c8c78b83..bf3df05f 100644 --- a/lib/airbrake-ruby/sync_sender.rb +++ b/lib/airbrake-ruby/sync_sender.rb @@ -79,7 +79,7 @@ def build_request_body(req, data) req['Authorization'] = "Bearer #{@config.project_key}" req['Content-Type'] = CONTENT_TYPE req['User-Agent'] = - "#{Airbrake::Notice::NOTIFIER[:name]}/#{Airbrake::AIRBRAKE_RUBY_VERSION}" \ + "#{Airbrake::NOTIFIER_INFO[:name]}/#{Airbrake::AIRBRAKE_RUBY_VERSION}" \ " Ruby/#{RUBY_VERSION}" req diff --git a/lib/airbrake-ruby/version.rb b/lib/airbrake-ruby/version.rb index 617ed6e9..67b02db6 100644 --- a/lib/airbrake-ruby/version.rb +++ b/lib/airbrake-ruby/version.rb @@ -2,5 +2,15 @@ # More information: http://semver.org/ module Airbrake # @return [String] the library version + # @api public AIRBRAKE_RUBY_VERSION = '5.0.0.rc.1'.freeze + + # @return [Hash{Symbol=>String}] the information about the notifier library + # @since ?.?.? + # @api public + NOTIFIER_INFO = { + name: 'airbrake-ruby'.freeze, + version: Airbrake::AIRBRAKE_RUBY_VERSION, + url: 'https://github.com/airbrake/airbrake-ruby'.freeze, + }.freeze end diff --git a/spec/remote_settings_spec.rb b/spec/remote_settings_spec.rb index 7aed2ef1..5e405c93 100644 --- a/spec/remote_settings_spec.rb +++ b/spec/remote_settings_spec.rb @@ -25,9 +25,12 @@ let(:config_path) { described_class::CONFIG_DUMP_PATH } let(:config_dir) { File.dirname(config_path) } - before do - stub_request(:get, endpoint).to_return(status: 200, body: body.to_json) + let!(:stub) do + stub_request(:get, Regexp.new(endpoint)) + .to_return(status: 200, body: body.to_json) + end + before do # Do not create config dumps on disk. allow(Dir).to receive(:mkdir).with(config_dir) allow(File).to receive(:write).with(config_path, anything) @@ -52,7 +55,7 @@ sleep(0.2) remote_settings.stop_polling - expect(a_request(:get, endpoint)).to have_been_made.once + expect(stub).to have_been_requested.once end it "yields the config to the block twice" do @@ -63,7 +66,7 @@ sleep(0.2) remote_settings.stop_polling - expect(a_request(:get, endpoint)).to have_been_made.once + expect(stub).to have_been_requested.once end context "when config loading fails" do @@ -77,7 +80,7 @@ sleep(0.2) remote_settings.stop_polling - expect(a_request(:get, endpoint)).to have_been_made.once + expect(stub).to have_been_requested.once end end end @@ -88,7 +91,18 @@ sleep(0.1) remote_settings.stop_polling - expect(a_request(:get, endpoint)).to have_been_made.at_least_once + expect(stub).to have_been_requested.at_least_once + end + + it "sends params about the environment with the request" do + remote_settings = described_class.poll(project_id) {} + sleep(0.1) + remote_settings.stop_polling + + stub_with_query_params = stub.with( + query: URI.decode_www_form(described_class::QUERY_PARAMS).to_h, + ) + expect(stub_with_query_params).to have_been_requested.at_least_once end it "fetches remote settings" do @@ -118,7 +132,7 @@ sleep(0.1) remote_settings.stop_polling - expect(a_request(:get, endpoint)).not_to have_been_made + expect(stub).not_to have_been_requested expect(settings.interval).to eq(600) end end @@ -136,14 +150,15 @@ sleep(0.1) remote_settings.stop_polling - expect(a_request(:get, endpoint)).to have_been_made.once + expect(stub).to have_been_requested.once expect(settings.interval).to eq(600) end end context "when API returns an XML response" do - before do - stub_request(:get, endpoint).to_return(status: 200, body: ' new_endpoint, 'poll_sec' => 0.1 } end - before do - stub_request(:get, new_endpoint).to_return(status: 200, body: body.to_json) + let!(:new_stub) do + stub_request(:get, Regexp.new(new_endpoint)) + .to_return(status: 200, body: body.to_json) end it "makes the next request to the specified config route" do @@ -176,8 +194,8 @@ remote_settings.stop_polling - expect(a_request(:get, endpoint)).to have_been_made.once - expect(a_request(:get, new_endpoint)).to have_been_made.once + expect(stub).to have_been_requested.once + expect(new_stub).to have_been_requested.once end end end @@ -191,7 +209,7 @@ sleep(0.2) remote_settings.stop_polling - expect(a_request(:get, endpoint)).to have_been_made.once + expect(stub).to have_been_requested.once end context "when config dumping fails" do @@ -205,7 +223,7 @@ sleep(0.2) remote_settings.stop_polling - expect(a_request(:get, endpoint)).to have_been_made.once + expect(stub).to have_been_requested.once end end end