describe Appsignal::Environment do include EnvironmentMetadataHelper before do start_agent capture_environment_metadata_report_calls end def report(key, &value_block) described_class.report(key, &value_block) end describe ".report" do it "sends environment metadata to the extension" do logs = capture_logs do report("_test_ruby_version") { "1.0.0" } expect_environment_metadata("_test_ruby_version", "1.0.0") end expect(logs).to be_empty end context "when the key is a non String type" do it "does not set the value" do logs = capture_logs do report(:_test_symbol) { "1.0.0" } expect_not_environment_metadata(:_test_symbol) expect_not_environment_metadata("_test_symbol") end expect(logs).to contains_log( :error, "Unable to report on environment metadata: Unsupported value type for :_test_symbol" ) end end context "when the key is nil" do it "does not set the value" do logs = capture_logs do report(nil) { "1" } expect_not_environment_metadata(nil) end expect(logs).to contains_log( :error, "Unable to report on environment metadata: Unsupported value type for nil" ) end end context "when the value is true or false" do it "reports true or false as Strings" do logs = capture_logs do report("_test_true") { true } report("_test_false") { false } expect_environment_metadata("_test_true", "true") expect_environment_metadata("_test_false", "false") end expect(logs).to be_empty end end context "when the value is nil" do it "does not set the value" do logs = capture_logs do report("_test_ruby_version") { nil } expect_not_environment_metadata("_test_ruby_version") end expect(logs).to contains_log( :error, "Unable to report on environment metadata \"_test_ruby_version\": " \ "Unsupported value type for nil" ) end end context "when the value block raises an error" do it "does not re-raise the error and writes it to the log" do logs = capture_logs do report("_test_error") { raise "uh oh" } expect_not_environment_metadata("_test_error") end expect(logs).to contains_log( :error, "Unable to report on environment metadata \"_test_error\":\n" \ "RuntimeError: uh oh" ) end end context "when something unforeseen errors" do it "does not re-raise the error and writes it to the log" do klass = Class.new do def inspect raise "inspect error" end end logs = capture_logs do report(klass.new) { raise "value error" } expect(Appsignal::Extension).to_not have_received(:set_environment_metadata) end expect(logs).to contains_log( :error, "Unable to report on environment metadata:\n" \ "RuntimeError: inspect error" ) end end end describe ".report_supported_gems" do it "reports about all AppSignal supported gems in the bundle using Bundler all_specs" do logs = capture_logs { described_class.report_supported_gems } expect(logs).to be_empty unless Bundler.rubygems.respond_to?(:all_specs) skip "Using new Bundler version without `all_specs` method" end bundle_gem_specs = silence { ::Bundler.rubygems.all_specs } rack_spec = bundle_gem_specs.find { |s| s.name == "rack" } rake_spec = bundle_gem_specs.find { |s| s.name == "rake" } expect_environment_metadata("ruby_rack_version", rack_spec.version.to_s) expect_environment_metadata("ruby_rake_version", rake_spec.version.to_s) expect(rack_spec.version.to_s).to_not be_empty expect(rake_spec.version.to_s).to_not be_empty end it "reports about all AppSignal supported gems in the bundle using bundler installed_specs" do unless Bundler.rubygems.respond_to?(:installed_specs) skip "Using old Bundler version without `installed_specs` method" end logs = capture_logs { described_class.report_supported_gems } expect(logs).to be_empty bundle_gem_specs = ::Bundler.rubygems.installed_specs rack_spec = bundle_gem_specs.find { |s| s.name == "rack" } rake_spec = bundle_gem_specs.find { |s| s.name == "rake" } expect_environment_metadata("ruby_rack_version", rack_spec.version.to_s) expect_environment_metadata("ruby_rake_version", rake_spec.version.to_s) expect(rack_spec.version.to_s).to_not be_empty expect(rake_spec.version.to_s).to_not be_empty end context "when something unforeseen errors" do it "does not re-raise the error and writes it to the log" do expect(Bundler).to receive(:rubygems).and_raise(RuntimeError, "bundler error") logs = capture_logs { described_class.report_supported_gems } expect(logs).to contains_log( :error, "Unable to report supported gems:\nRuntimeError: bundler error" ) end end end describe ".report_enabled" do it "reports a feature being enabled" do logs = capture_logs { described_class.report_enabled("a_test") } expect(logs).to be_empty expect_environment_metadata("ruby_a_test_enabled", "true") end context "when something unforeseen errors" do it "does not re-raise the error and writes it to the log" do klass = Class.new do def to_s raise "to_s error" end end logs = capture_logs { described_class.report_enabled(klass.new) } expect(logs).to contains_log( :error, "Unable to report integration enabled:\nRuntimeError: to_s error" ) end end end end