Skip to content

Commit

Permalink
aws-sdk-lambda: improve error handling
Browse files Browse the repository at this point in the history
use separate error handling for errors raised by the gem itself and
errors raised by the agent.

Errors raised by the gem need to be noticed by the agent (sent to New
Relic) and re-raised to the user's app.

Errors raised by the agent need to be logged but not impact the
returning of the successful gem invocation response.

Co-authored-by: Kayla Reopelle <87386821+kaylareopelle@users.noreply.github.com>
  • Loading branch information
fallwith and kaylareopelle committed Nov 2, 2024
1 parent 375db67 commit 0a1527d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ def with_tracing(action, *args)
# prevent additional instrumentation for things like Net::HTTP from
# creating any segments that may appear as redundant / confusing
NewRelic::Agent.disable_all_tracing do
response = NewRelic::Agent::Tracer.capture_segment_error(segment) { yield }
begin
response = yield
process_response(response, segment)
response
rescue => e
NewRelic::Agent.notice_error(e)
raise
NewRelic::Agent.logger.error("Error processing aws-sdk-lambda invocation response (action = #{action}): #{e}")
ensure
response
end
end
ensure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,47 @@ def test_client_call_raises_an_exception
in_transaction do |txn|
client = Aws::Lambda::Client.new(region: REGION)
client.config.account_id = AWS_ACCOUNT_ID
def client.process_response(*_args); raise 'kaboom'; end

assert_raises(RuntimeError) { client.invoke(function_name: 'Invoke-Me-And-Explode') }
# We need the aws-sdk-lambda client's `yield` to raise an exception for
# this test, but that's tricky given that we're monkeypatching the very
# client invocation method under test. So let's trust that
# capture_segment_error is thoroughly tested elsewhere and stub it to
# do its raise-and-notice-an-error thing in a predictable way so that the
# aws-sdk-lambda specific stuff can be tested.
capture_proc = proc do |segment|
error = RuntimeError.new('kaboom')
segment.notice_error(error)
raise error
end

NewRelic::Agent::Tracer.stub(:capture_segment_error,
capture_proc,
[NewRelic::Agent::Transaction::ExternalRequestSegment]) do
assert_raises(RuntimeError) { client.invoke(function_name: 'Invoke-Me-And-Explode') }
end

noticed_error = lambda_segment(txn).noticed_error

assert_equal 'kaboom', noticed_error.message
assert_equal 'RuntimeError', noticed_error.exception_class_name
end
end

def test_errors_in_processing_the_invocation_response_are_logged_but_not_raised_to_the_user_app
in_transaction do |txn|
client = Aws::Lambda::Client.new(region: REGION)
client.config.account_id = AWS_ACCOUNT_ID
def client.process_response(*_args); raise 'kaboom'; end

NewRelic::Agent.stub(:logger, NewRelic::Agent::MemoryLogger.new) do
client.invoke(function_name: 'Invoke-Me-And-Only-The-Agent-Explodes')

assert NewRelic::Agent.logger.messages.any? { |m| m[1][0].match?(/^Error processing aws-sdk-lambda/) },
'Expected to find an error message in the agent logs'
end
end
end

def test_client_response_indicates_an_unhandled_function_error
function_error = 'Unhandled'
message = 'oh no'
Expand Down

0 comments on commit 0a1527d

Please sign in to comment.