diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2512b89 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +0.10.0 (2018-01-22) +------------------- +* Bugfix - Fixed an issue where subsegment captures could break even if `context_missing` is set to `LOG_ERROR`. +* Bugfix - Fixed gemspec to have the correct Ruby version requirement. diff --git a/aws-xray-sdk.gemspec b/aws-xray-sdk.gemspec index 885c36e..8928acd 100644 --- a/aws-xray-sdk.gemspec +++ b/aws-xray-sdk.gemspec @@ -7,9 +7,13 @@ Gem::Specification.new do |spec| spec.version = XRay::VERSION spec.author = 'Amazon Web Services' spec.email = 'aws-xray-ruby@amazon.com' + spec.summary = 'AWS X-Ray SDK for Ruby' spec.description = 'The AWS X-Ray SDK for Ruby enables Ruby developers to record and emit information from within their applications to the AWS X-Ray service.' spec.homepage = 'https://github.com/aws/aws-xray-sdk-ruby' + + spec.required_ruby_version = '>= 2.3.6' + spec.license = 'Apache-2.0' spec.files = Dir.glob('lib/**/*') diff --git a/lib/aws-xray-sdk/facets/aws_sdk.rb b/lib/aws-xray-sdk/facets/aws_sdk.rb index 0a7237a..568e57a 100644 --- a/lib/aws-xray-sdk/facets/aws_sdk.rb +++ b/lib/aws-xray-sdk/facets/aws_sdk.rb @@ -18,6 +18,10 @@ class Handler < Seahorse::Client::Handler def call(context) recorder = Aws.config[:xray_recorder] + if recorder.current_entity.nil? + super + end + operation = context.operation_name service_name = context.client.class.api.metadata['serviceAbbreviation'] || context.client.class.to_s.split('::')[1] diff --git a/lib/aws-xray-sdk/facets/rails/active_record.rb b/lib/aws-xray-sdk/facets/rails/active_record.rb index e9b4fd6..e598ad6 100644 --- a/lib/aws-xray-sdk/facets/rails/active_record.rb +++ b/lib/aws-xray-sdk/facets/rails/active_record.rb @@ -20,6 +20,8 @@ def record(transaction) db_config = pool.spec.config name, sql = build_name_sql_meta config: db_config, conn: conn subsegment = XRay.recorder.begin_subsegment name, namespace: 'remote' + # subsegment is nil in case of context missing + return if subsegment.nil? subsegment.start_time = transaction.time.to_f subsegment.sql = sql XRay.recorder.end_subsegment end_time: transaction.end.to_f diff --git a/lib/aws-xray-sdk/recorder.rb b/lib/aws-xray-sdk/recorder.rb index de5e24d..6e97723 100644 --- a/lib/aws-xray-sdk/recorder.rb +++ b/lib/aws-xray-sdk/recorder.rb @@ -57,7 +57,8 @@ def end_segment(end_time: nil) # Begin a new subsegment and add it to be the child of the current active # subsegment or segment. Also tie the new created subsegment to the current context. # Its sampling decision will follow its parent. - # @return [Subsegment] the newly created subsegment. + # @return [Subsegment] the newly created subsegment. It could be `nil` if no active entity + # can be found and `context_missing` is set to `LOG_ERROR`. def begin_subsegment(name, namespace: nil, segment: nil) entity = segment || current_entity return unless entity @@ -104,8 +105,16 @@ def end_subsegment(end_time: nil) end # Record the passed block as a subsegment. + # If `context_missing` is set to `LOG_ERROR` and no active entity can be found, + # the passed block will be executed as normal but it will not be recorded. def capture(name, namespace: nil, segment: nil) subsegment = begin_subsegment name, namespace: namespace, segment: segment + # prevent passed block from failing in case of context missing with log error + if subsegment.nil? + segment = DummySegment.new name: name + subsegment = DummySubsegment.new name: name, segment: segment + end + begin yield subsegment rescue Exception => e diff --git a/lib/aws-xray-sdk/version.rb b/lib/aws-xray-sdk/version.rb index cab21bb..cfe3b54 100644 --- a/lib/aws-xray-sdk/version.rb +++ b/lib/aws-xray-sdk/version.rb @@ -1,3 +1,3 @@ module XRay - VERSION = '0.9.0' + VERSION = '0.10.0' end diff --git a/test/aws-xray-sdk/tc_aws_sdk.rb b/test/aws-xray-sdk/tc_aws_sdk.rb index 7fcbc67..801659b 100644 --- a/test/aws-xray-sdk/tc_aws_sdk.rb +++ b/test/aws-xray-sdk/tc_aws_sdk.rb @@ -110,4 +110,26 @@ def test_capiture_client_error assert_equal 'Timeout::Error', ex_h[:message] assert_equal 'Timeout::Error', ex_h[:type] end + + def test_log_error_pass_through + recorder = XRay::Recorder.new + config = { + sampling: false, + emitter: XRay::TestHelper::StubbedEmitter.new, + patch: %I[aws_sdk], + context_missing: 'LOG_ERROR' + } + recorder.configure(config) + Aws.config.update xray_recorder: recorder + + s3 = Aws::S3::Client.new(stub_responses: true) + bucket_data = s3.stub_data(:list_buckets, buckets: [{ name: '1' }]) + s3.stub_responses(:list_buckets, bucket_data) + resp = s3.list_buckets + + # nothing should be sent + assert_nil recorder.emitter.entities + # s3 call is executed + assert_equal '1', resp.buckets[0].name + end end diff --git a/test/aws-xray-sdk/tc_recorder.rb b/test/aws-xray-sdk/tc_recorder.rb index e0b5a59..443ea73 100644 --- a/test/aws-xray-sdk/tc_recorder.rb +++ b/test/aws-xray-sdk/tc_recorder.rb @@ -132,12 +132,26 @@ def test_thread_infection def test_context_missing_passthrough recorder = XRay::Recorder.new - recorder.config.context_missing = 'LOG_ERROR' + config = { + sampling: false, + context_missing: 'LOG_ERROR', + emitter: XRay::TestHelper::StubbedEmitter.new + } + recorder.configure(config) + recorder.annotations[:k] = 1 recorder.sampled? do recorder.annotations.update k2: 2 recorder.metadata.update k3: 3 end recorder.metadata[:foo] = 'bar' + + v = recorder.capture(name) do |subsegment| + subsegment.annotations[:k] = '1' + 1 + end + + assert_equal 1, v + assert_nil recorder.emitter.entities end end