diff --git a/apps/opentelemetry_api/lib/open_telemetry/span.ex b/apps/opentelemetry_api/lib/open_telemetry/span.ex index ce8328199..c1cba850f 100644 --- a/apps/opentelemetry_api/lib/open_telemetry/span.ex +++ b/apps/opentelemetry_api/lib/open_telemetry/span.ex @@ -179,6 +179,19 @@ defmodule OpenTelemetry.Span do add_event(span_ctx, :exception, exception_attributes ++ attributes) end + def record_exception(span_ctx, kind, reason, stacktrace) + when is_atom(kind) and not is_nil(reason) and is_list(stacktrace) do + add_event( + span_ctx, + :exception, + [ + {:"exception.type", to_string(kind)}, + {:"exception.message", inspect(reason)}, + {:"exception.stacktrace", Exception.format_stacktrace(stacktrace)} + ] + ) + end + def record_exception(_, _, _, _), do: false @doc """ diff --git a/test/otel_tests.exs b/test/otel_tests.exs index 677bda517..722f67d28 100644 --- a/test/otel_tests.exs +++ b/test/otel_tests.exs @@ -266,6 +266,82 @@ defmodule OtelTests do end end + test "Span.record_exception/4 should add a throw event to the span" do + s = Tracer.start_span("span-1") + + try do + throw("value") + catch + kind, reason -> + assert Span.record_exception(s, kind, reason, __STACKTRACE__) + assert Span.end_span(s) + + attributes = + :otel_attributes.new( + [ + {:"exception.type", "throw"}, + {:"exception.message", "\"value\""}, + {:"exception.stacktrace", Exception.format_stacktrace(__STACKTRACE__)} + ], + 128, + :infinity + ) + + assert_receive {:span, + span( + name: "span-1", + events: { + :events, + 128, + 128, + :infinity, + 0, + [ + {:event, _, :exception, ^attributes} + ] + } + )} + end + end + + test "Span.record_exception/4 should add an abnormal exit event to the span" do + s = Tracer.start_span("span-1") + + try do + exit(:abnormal) + catch + kind, reason -> + assert Span.record_exception(s, kind, reason, __STACKTRACE__) + assert Span.end_span(s) + + attributes = + :otel_attributes.new( + [ + {:"exception.type", "exit"}, + {:"exception.message", ":abnormal"}, + {:"exception.stacktrace", Exception.format_stacktrace(__STACKTRACE__)} + ], + 128, + :infinity + ) + + assert_receive {:span, + span( + name: "span-1", + events: { + :events, + 128, + 128, + :infinity, + 0, + [ + {:event, _, :exception, ^attributes} + ] + } + )} + end + end + test "Custom Sampler that checks attributes" do name = "span-prob-sampled" trace_id = 120_647_249_294_066_572_380_176_333_851_662_846_319