Skip to content

Commit c0dad86

Browse files
Fix TypeLoadException exception error (#8157)
## Summary of changes Fixes `TypeLoadException`[ being logged as an error](https://app.datadoghq.com/error-tracking?query=service%3Ainstrumentation-telemetry-data%20%40lib_language%3Adotnet%20version%3A3.3%2A&et-side=activity&fromUser=false&issue_states=open&order=total_count&refresh_mode=sliding&source=all&sp=%5B%7B%22p%22%3A%7B%22issueId%22%3A%224cdd44b0-aea9-11f0-940c-da7ad0900002%22%7D%2C%22i%22%3A%22error-tracking-issue%22%7D%5D&from_ts=1769594245972&to_ts=1770199045972&live=true) during tracer initialization on .NET Framework when `System.Web.Hosting.HostingEnvironment` is unavailable. ## Reason for change On .NET Framework 4.x, users were seeing this error during startup: ``` Error: Unable to get application name through ASP.NET settings System.TypeLoadException at Datadog.Trace.PlatformHelpers.ApplicationNameHelpers.TryLoadAspNetSiteName(String& siteName) at Datadog.Trace.PlatformHelpers.ApplicationNameHelpers.GetApplicationName(TracerSettings settings) ``` ## Root Cause The existing code had a `try-catch` block inside `TryLoadAspNetSiteName` to catch `TypeLoadException`, but the exception was thrown **during JIT compilation** of the method, not during execution. When the JIT compiler encountered `System.Web.Hosting.HostingEnvironment` references, it threw `TypeLoadException` before any code in the method could execute - so the inner catch block was never reached. ## Implementation details Extracted the `System.Web`-dependent code into a separate method marked with `[MethodImpl(MethodImplOptions.NoInlining)]`. This: 1. Defers JIT compilation of the System.Web-dependent code until the method is actually called 2. Allows the `TypeLoadException` to be caught at the call site 3. Logs a **Warning** (expected behavior) instead of an **Error** A similar pattern is already used in `SecurityCoordinator.Framework.cs:243-244`. ## Test coverage ## Other details <!-- Fixes #{issue} --> <!-- ⚠️ Note: Where possible, please obtain 2 approvals prior to merging. Unless CODEOWNERS specifies otherwise, for external teams it is typically best to have one review from a team member, and one review from apm-dotnet. Trivial changes do not require 2 reviews. MergeQueue is NOT enabled in this repository. If you have write access to the repo, the PR has 1-2 approvals (see above), and all of the required checks have passed, you can use the Squash and Merge button to merge the PR. If you don't have write access, or you need help, reach out in the #apm-dotnet channel in Slack. -->
1 parent 57f90c1 commit c0dad86

1 file changed

Lines changed: 29 additions & 8 deletions

File tree

tracer/src/Datadog.Trace/PlatformHelpers/ApplicationNameHelpers.cs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System;
99
using System.Diagnostics.CodeAnalysis;
1010
using System.Reflection;
11+
using System.Runtime.CompilerServices;
1112
using Datadog.Trace.Configuration;
1213
using Datadog.Trace.Logging;
1314
using Datadog.Trace.Util;
@@ -70,14 +71,10 @@ private static bool TryLoadAspNetSiteName([NotNullWhen(true)] out string? siteNa
7071
#if NETFRAMEWORK
7172
try
7273
{
73-
// System.Web.dll is only available on .NET Framework
74-
if (System.Web.Hosting.HostingEnvironment.IsHosted)
75-
{
76-
// if this app is an ASP.NET application, return "SiteName/ApplicationVirtualPath".
77-
// note that ApplicationVirtualPath includes a leading slash.
78-
siteName = (System.Web.Hosting.HostingEnvironment.SiteName + System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath).TrimEnd('/');
79-
return true;
80-
}
74+
// Call into a separate method to avoid TypeLoadException being thrown
75+
// during JIT compilation of this method when System.Web types are unavailable.
76+
// The NoInlining attribute ensures the JIT defers compilation until the call site.
77+
return TryGetHostingEnvironmentSiteName(out siteName);
8178
}
8279
catch (TypeLoadException ex)
8380
{
@@ -87,4 +84,28 @@ private static bool TryLoadAspNetSiteName([NotNullWhen(true)] out string? siteNa
8784
siteName = null;
8885
return false;
8986
}
87+
88+
#if NETFRAMEWORK
89+
/// <summary>
90+
/// This method must be called from within a try-catch block.
91+
/// The TypeLoadException will be thrown at the CALLSITE when System.Web types are unavailable,
92+
/// not inside this method, due to JIT compilation behavior.
93+
/// The NoInlining attribute is critical to ensure this behavior.
94+
/// </summary>
95+
[MethodImpl(MethodImplOptions.NoInlining)]
96+
private static bool TryGetHostingEnvironmentSiteName([NotNullWhen(true)] out string? siteName)
97+
{
98+
// System.Web.dll is only available on .NET Framework
99+
if (System.Web.Hosting.HostingEnvironment.IsHosted)
100+
{
101+
// if this app is an ASP.NET application, return "SiteName/ApplicationVirtualPath".
102+
// note that ApplicationVirtualPath includes a leading slash.
103+
siteName = (System.Web.Hosting.HostingEnvironment.SiteName + System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath).TrimEnd('/');
104+
return true;
105+
}
106+
107+
siteName = null;
108+
return false;
109+
}
110+
#endif
90111
}

0 commit comments

Comments
 (0)