Skip to content

Commit 280a82f

Browse files
committed
Added support for capturing top most failing span + improved no_capture_reason communication
1 parent 235f296 commit 280a82f

File tree

6 files changed

+67
-9
lines changed

6 files changed

+67
-9
lines changed

tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.Debugger.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ internal static class Debugger
143143
/// Configuration key for the maximum number of frames in a call stack we would like to capture values for.
144144
/// </summary>
145145
/// <seealso cref="ExceptionReplaySettings.MaximumFramesToCapture"/>
146-
public const string ExceptionReplayMaxFramesToCapture = "DD_EXCEPTION_REPLAY_MAX_FRAMES_TO_CAPTURE";
146+
public const string ExceptionReplayCaptureMaxFrames = "DD_EXCEPTION_REPLAY_CAPTURE_MAX_FRAMES";
147147

148148
/// <summary>
149149
/// Configuration key to enable capturing the variables of all the frames in exception call stack.

tracer/src/Datadog.Trace/Debugger/ExceptionAutoInstrumentation/ExceptionReplayDiagnosticTagNames.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ internal static class ExceptionReplayDiagnosticTagNames
2020
public const string Eligible = nameof(Eligible);
2121
public const string NotEligible = nameof(NotEligible);
2222
public const string ExceptionTrackManagerNotInitialized = nameof(ExceptionTrackManagerNotInitialized);
23-
public const string NotRootSpan = nameof(NotRootSpan);
2423
public const string ExceptionObjectIsNull = nameof(ExceptionObjectIsNull);
2524
public const string NonSupportedExceptionType = nameof(NonSupportedExceptionType);
2625
public const string CachedDoneExceptionCase = nameof(CachedDoneExceptionCase);

tracer/src/Datadog.Trace/Debugger/ExceptionAutoInstrumentation/ExceptionReplaySettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public ExceptionReplaySettings(IConfigurationSource? source, IConfigurationTelem
3333
CaptureFullCallStack = config.WithKeys(ConfigurationKeys.Debugger.ExceptionReplayCaptureFullCallStackEnabled).AsBool(false);
3434

3535
var maximumFramesToCapture = config
36-
.WithKeys(ConfigurationKeys.Debugger.ExceptionReplayMaxFramesToCapture)
36+
.WithKeys(ConfigurationKeys.Debugger.ExceptionReplayCaptureMaxFrames)
3737
.AsInt32(DefaultMaxFramesToCapture, maxDepth => maxDepth > 0)
3838
.Value;
3939

tracer/src/Datadog.Trace/Debugger/ExceptionAutoInstrumentation/ExceptionTrackManager.cs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,11 @@ public static void Report(Span span, Exception? exception)
7979
return;
8080
}
8181

82-
// For V1 of Exception Debugging, we only care about exceptions propagating up the stack
83-
// and marked as error by the service entry/root span.
84-
if (span.IsRootSpan == false || exception == null || !IsSupportedExceptionType(exception))
82+
if (exception == null || !IsSupportedExceptionType(exception))
8583
{
8684
Log.Information(exception, "Skipping the processing of the exception. Exception = {Exception}, Span = {Span}", exception?.ToString(), span.ToString());
8785

88-
var failureReason =
89-
span.IsRootSpan == false ? ExceptionReplayDiagnosticTagNames.NotRootSpan :
90-
exception == null ? ExceptionReplayDiagnosticTagNames.ExceptionObjectIsNull : ExceptionReplayDiagnosticTagNames.NonSupportedExceptionType;
86+
var failureReason = exception == null ? ExceptionReplayDiagnosticTagNames.ExceptionObjectIsNull : ExceptionReplayDiagnosticTagNames.NonSupportedExceptionType;
9187
SetDiagnosticTag(span, failureReason, 0);
9288
return;
9389
}
@@ -323,6 +319,8 @@ private static void ProcessException(Exception exception, int normalizedExHash,
323319
}
324320
else
325321
{
322+
EvaluateWithRootSpanCases.Add(normalizedExHash);
323+
326324
if (rootSpan != null)
327325
{
328326
SetDiagnosticTag(rootSpan, ExceptionReplayDiagnosticTagNames.EmptyCallStackTreeWhileCollecting, normalizedExHash);
@@ -759,6 +757,40 @@ private static bool ShouldSkip(MethodBase method)
759757

760758
private static void SetDiagnosticTag(Span span, string exceptionPhase, int exceptionHash)
761759
{
760+
if (exceptionPhase is ExceptionReplayDiagnosticTagNames.CachedInvalidatedExceptionCase or ExceptionReplayDiagnosticTagNames.CachedDoneExceptionCase or ExceptionReplayDiagnosticTagNames.NonCachedDoneExceptionCase)
761+
{
762+
return;
763+
}
764+
765+
var noCaptureReason = string.Empty;
766+
767+
switch (exceptionPhase)
768+
{
769+
case ExceptionReplayDiagnosticTagNames.Eligible:
770+
break;
771+
case ExceptionReplayDiagnosticTagNames.NoCustomerFrames or ExceptionReplayDiagnosticTagNames.NoFramesToInstrument:
772+
noCaptureReason = NoCaptureReason.OnlyThirdPartyCode;
773+
break;
774+
case ExceptionReplayDiagnosticTagNames.InvalidatedCase or ExceptionReplayDiagnosticTagNames.InvalidatedExceptionCase:
775+
noCaptureReason = NoCaptureReason.InstrumentationFailure;
776+
break;
777+
case ExceptionReplayDiagnosticTagNames.NonSupportedExceptionType:
778+
noCaptureReason = NoCaptureReason.NonSupportedExceptionType;
779+
break;
780+
case ExceptionReplayDiagnosticTagNames.NotEligible or ExceptionReplayDiagnosticTagNames.NewCase:
781+
noCaptureReason = NoCaptureReason.FirstOccurrence;
782+
break;
783+
default:
784+
noCaptureReason = NoCaptureReason.GeneralError;
785+
break;
786+
}
787+
788+
if (noCaptureReason != string.Empty)
789+
{
790+
span.Tags.SetTag("error.debug_info_captured", "true");
791+
span.Tags.SetTag("_dd.debug.error.no_capture_reason", noCaptureReason);
792+
}
793+
762794
span.Tags.SetTag("_dd.di._er", exceptionPhase);
763795
span.Tags.SetTag("_dd.di._eh", exceptionHash.ToString());
764796
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// <copyright file="NoCaptureReason.cs" company="Datadog">
2+
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
3+
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
4+
// </copyright>
5+
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Linq;
9+
using System.Text;
10+
using System.Threading.Tasks;
11+
12+
#nullable enable
13+
namespace Datadog.Trace.Debugger.ExceptionAutoInstrumentation
14+
{
15+
/// <summary>
16+
/// Assigned as a tag on incoming spans by <see cref="ExceptionTrackManager"/> to designate why certain errors were not captured
17+
/// </summary>
18+
internal static class NoCaptureReason
19+
{
20+
public const string OnlyThirdPartyCode = nameof(OnlyThirdPartyCode);
21+
public const string InstrumentationFailure = nameof(InstrumentationFailure);
22+
public const string NonSupportedExceptionType = nameof(NonSupportedExceptionType);
23+
public const string FirstOccurrence = nameof(FirstOccurrence);
24+
public const string GeneralError = nameof(GeneralError);
25+
}
26+
}

tracer/test/Datadog.Trace.Tests/Telemetry/config_norm_rules.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@
423423
"DD_TRACE_COMPUTE_STATS": "dd_trace_compute_stats",
424424
"DD_EXCEPTION_DEBUGGING_ENABLED": "dd_exception_debugging_enabled",
425425
"DD_EXCEPTION_DEBUGGING_MAX_FRAMES_TO_CAPTURE": "dd_exception_debugging_max_frames_to_capture",
426+
"DD_EXCEPTION_REPLAY_CAPTURE_MAX_FRAMES": "dd_exception_replay_capture_max_frames",
426427
"DD_EXCEPTION_DEBUGGING_CAPTURE_FULL_CALLSTACK_ENABLED": "dd_exception_debugging_capture_full_callstack_enabled",
427428
"DD_EXCEPTION_DEBUGGING_RATE_LIMIT_SECONDS": "dd_exception_debugging_rate_limit_seconds",
428429
"DD_EXCEPTION_DEBUGGING_MAX_EXCEPTION_ANALYSIS_LIMIT": "dd_exception_debugging_max_exception_analysis_limit",

0 commit comments

Comments
 (0)