Skip to content

feat: add record_exception in the datadog api #4567

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

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

dubloom
Copy link
Contributor

@dubloom dubloom commented Apr 8, 2025

What does this PR do?
This PR adds a record_exception call in the tracer API. It mimics the behavior of the OTEL one for which you can find the documentation here: https://opentelemetry.io/docs/specs/otel/trace/exceptions/

Motivation:
Some customers using Sentry complained they were not capable of recording an exception. It appears that if they are using the OTEL api from our tracer, they can. However, as we want to be a competitor to Sentry, I found that it is not a good solution as it is simpler to use this capability directly from our tracer. In addition the feature is easy to emplement

Change log entry
Yes. Record an exception through span events with the record_exceptioncall.

How to test the change?

  • Tests we added in the span_operation spec

@dubloom dubloom requested review from a team as code owners April 8, 2025 07:36
@codecov-commenter
Copy link

codecov-commenter commented Apr 8, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.76%. Comparing base (6a04b2f) to head (38be961).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4567   +/-   ##
=======================================
  Coverage   97.76%   97.76%           
=======================================
  Files        1404     1404           
  Lines       86173    86220   +47     
  Branches     4354     4356    +2     
=======================================
+ Hits        84247    84295   +48     
+ Misses       1926     1925    -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@datadog-datadog-prod-us1
Copy link
Contributor

datadog-datadog-prod-us1 bot commented Apr 8, 2025

Datadog Report

Branch report: dubloom/record-exception
Commit report: a58f267
Test service: dd-trace-rb

❌ 4 Failed (0 Known Flaky), 20386 Passed, 1366 Skipped, 3m 41.29s Total Time

❌ Failed Tests (4)

  • Datadog::OpenTelemetry with Datadog TraceProvider #record_exception attributes is nil sets records an exception event and sets span error tags using the Exception object - rspec - Details

    Expand for error
     no implicit conversion of nil into Hash
     
     Failure/Error: event_attributes.merge!(attributes)
     
     TypeError:
       no implicit conversion of nil into Hash
     ./lib/datadog/tracing/span_operation.rb:300:in \`merge!'
     ./lib/datadog/tracing/span_operation.rb:300:in \`record_exception'
     ./lib/datadog/opentelemetry/sdk/trace/span.rb:31:in \`record_exception'
     ./spec/datadog/opentelemetry_spec.rb:611:in \`block (4 levels) in <top (required)>'
     ...
    
  • Datadog::OpenTelemetry with Datadog TraceProvider #record_exception attributes is {} sets records an exception event and sets span error tags using the Exception object - rspec - Details

    Expand for error
     expected Span with error message nil to have error message "Error"
     
     Failure/Error: expect(span).to have_error_message('Error')
       expected Span with error message nil to have error message "Error"
     ./spec/datadog/opentelemetry_spec.rb:637:in \`block (6 levels) in <top (required)>'
     ./spec/spec_helper.rb:261:in \`block (2 levels) in <top (required)>'
     ./spec/spec_helper.rb:146:in \`block (2 levels) in <top (required)>'
     /usr/local/bundle/gems/webmock-3.13.0/lib/webmock/rspec.rb:37:in \`block (2 levels) in <top (required)>'
     /usr/local/bundle/gems/rspec-wait-0.0.9/lib/rspec/wait.rb:46:in \`block (2 levels) in <top (required)>'
    
  • Datadog::OpenTelemetry with Datadog TraceProvider #record_exception with attributes containing exception stacktrace, type and message sets records an exception event and sets span error tags using the attributes hash - rspec - Details

    Expand for error
     expected Span with error message nil to have error message "NewError"
     
     Failure/Error: expect(span).to have_error_message('NewError')
       expected Span with error message nil to have error message "NewError"
     ./spec/datadog/opentelemetry_spec.rb:684:in \`block (5 levels) in <top (required)>'
     ./spec/spec_helper.rb:261:in \`block (2 levels) in <top (required)>'
     ./spec/spec_helper.rb:146:in \`block (2 levels) in <top (required)>'
     /usr/local/bundle/gems/webmock-3.13.0/lib/webmock/rspec.rb:37:in \`block (2 levels) in <top (required)>'
     /usr/local/bundle/gems/rspec-wait-0.0.9/lib/rspec/wait.rb:46:in \`block (2 levels) in <top (required)>'
    
  • Datadog::OpenTelemetry with Datadog TraceProvider #record_exception with attributes containing nil values sets records an exception event and sets span error tags using the Exception object - rspec - Details

    Expand for error
     expected Span with error message nil to have error message "Error"
     
     Failure/Error: expect(span).to have_error_message('Error')
       expected Span with error message nil to have error message "Error"
     ./spec/datadog/opentelemetry_spec.rb:652:in \`block (5 levels) in <top (required)>'
     ./spec/spec_helper.rb:261:in \`block (2 levels) in <top (required)>'
     ./spec/spec_helper.rb:146:in \`block (2 levels) in <top (required)>'
     /usr/local/bundle/gems/webmock-3.13.0/lib/webmock/rspec.rb:37:in \`block (2 levels) in <top (required)>'
     /usr/local/bundle/gems/rspec-wait-0.0.9/lib/rspec/wait.rb:46:in \`block (2 levels) in <top (required)>'
    

@pr-commenter
Copy link

pr-commenter bot commented Apr 8, 2025

Benchmarks

Benchmark execution time: 2025-04-10 15:15:32

Comparing candidate commit a58f267 in PR branch dubloom/record-exception with baseline commit ed68392 in branch master.

Found 0 performance improvements and 1 performance regressions! Performance is the same for 30 metrics, 2 unstable metrics.

scenario:profiler - gvl benchmark samples

  • 🟥 throughput [-772.394op/s; -763.606op/s] or [-6.627%; -6.552%]

Copy link
Contributor

@buraizu buraizu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving with a couple of minor doc updates requested

@dubloom dubloom requested review from TonyCTHsu and p-datadog April 10, 2025 12:55
@github-actions github-actions bot added the otel OpenTelemetry-related changes label Apr 10, 2025
# type.
#
# @return [void]
def record_exception(exception, attributes: {})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are calling this from opentelemetry SDK where attributes is defaulted to nil, therefore either there or here you must handle the case of attributes being nil and change it to an empty hash.

I'm thinking this would have been caught by type checking if the types were defined for both methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, thank you.

'exception.type' => exc.type,
'exception.message' => exc.message,
'exception.stacktrace' => exc.backtrace,
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the response to my comment about the type of keys here being strings and not symbols?

Copy link
Contributor Author

@dubloom dubloom Apr 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I applied it in my first review commit but it made the linter job fails: https://github.com/DataDog/dd-trace-rb/actions/runs/14382559325/job/40329857628

Therefore I reverted the change

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, span_event.rbs defines the attribute types:

      type attributes = Hash[String,attributeValue]
      type attributeValue = String | Integer | Float | bool | Array[String] | Array[Integer] | Array[Float] | Array[bool]

The record_exception method should be added to the type definition for SpanOperation referencing these types for attributes.

# take precedence over the type, message and stacktrace inferred from the exception object
type = attributes&.[]('exception.type') || exception.class.to_s
message = attributes&.[]('exception.message') || exception.message
stacktrace = attributes&.[]('exception.stacktrace') || exception.full_message(highlight: false, order: :top)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This defaulting to full_message seems to me to have vanished?

@dubloom dubloom marked this pull request as draft May 5, 2025 07:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
otel OpenTelemetry-related changes tracing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants