Skip to content
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

Capture event when unoptimized asm #365

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 15 additions & 1 deletion samples/Sentry.Samples.Console.Customized/Program.cs
@@ -1,6 +1,7 @@
using System;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Sentry;
using Sentry.Extensibility;
Expand Down Expand Up @@ -47,6 +48,9 @@ private static async Task Main(string[] args)
// Before excluding all prefixed 'LibraryX.', any stack trace from a type namespaced 'LibraryX.Core' will be considered InApp.
o.AddInAppInclude("LibraryX.Core");

// Send events whe unoptimized assemblies are detected
o.NotifyUnoptimizedAssembly = true;

// Send personal identifiable information like the username logged on to the computer and machine name
o.SendDefaultPii = true;

Expand Down Expand Up @@ -108,6 +112,10 @@ private static async Task Main(string[] args)
SentrySdk.AddBreadcrumb(
"A 'bad breadcrumb' that will be rejected because of 'BeforeBreadcrumb callback above.'");

// Because 'NotifyUnoptimizedAssembly' is enabled, calling this method will raise an event to alert
// that an Assembly that is compiled for Debug was loaded.
LoadUnoptimizedAssembly();

// Data added to the root scope (no PushScope called up to this point)
// The modifications done here will affect all events sent and will propagate to child scopes.
await SentrySdk.ConfigureScopeAsync(async scope =>
Expand Down Expand Up @@ -147,7 +155,6 @@ private static async Task Main(string[] args)
SentrySdk.CaptureException(error);
}


var count = 10;
for (var i = 0; i < count; i++)
{
Expand Down Expand Up @@ -196,6 +203,13 @@ private static async Task Main(string[] args)
} // On Dispose: SDK closed, events queued are flushed/sent to Sentry
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void LoadUnoptimizedAssembly()
{
// https://twitter.com/jeremydmiller/status/777571510919630848
Console.WriteLine(typeof(StructureMap.Container).Assembly.GetName().Version);
}

private class AdminPartMiddleware
{
private readonly ISentryClient _adminClient;
Expand Down
Expand Up @@ -5,6 +5,8 @@
<TargetFrameworks>netcoreapp2.1;net472</TargetFrameworks>
<!--Set explicitly to demonstrate one way of defining the Sentry Release-->
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
<!-- To be able to load structuremap 4.4.0 which is unsigned-->
<SignAssembly>false</SignAssembly>
</PropertyGroup>

<ItemGroup>
Expand All @@ -14,5 +16,8 @@
<Reference Include="System.Net.Http" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="structuremap" Version="4.4.0" />
</ItemGroup>

</Project>
68 changes: 68 additions & 0 deletions src/Sentry/Integrations/UnoptimizedAssemblyIntegration.cs
@@ -0,0 +1,68 @@
using System;
using System.Linq;
using Sentry.Extensibility;
using Sentry.Protocol;
using Sentry.Reflection;

namespace Sentry.Integrations
{
/// <summary>
/// An integration that emits events when detects assemblies compiled for debug.
/// </summary>
public class UnoptimizedAssemblyIntegration : ISdkIntegration
{
/// <summary>
/// Registers the integration with the hub and options.
/// </summary>
/// <param name="hub">The hub to use to send events.</param>
/// <param name="options">The options to configure the integration.</param>
public void Register(IHub hub, SentryOptions options)
{
if (options.NotifyUnoptimizedAssembly)
{
options.DiagnosticLogger?.LogDebug("Subscribing to AssemblyLoad to detect unoptimized assemblies.");
// TODO: .NET Core equivalent
AppDomain.CurrentDomain.AssemblyLoad += (sender, args) =>
{
if (!args.LoadedAssembly.IsOptimized())
{
CaptureEvent(hub, options, args.LoadedAssembly.FullName);
hub.FlushAsync(TimeSpan.FromSeconds(10)).GetAwaiter().GetResult();
}
};

var unoptimizedAssemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsOptimized())
.Select(a => a.FullName)
.ToArray();

if (unoptimizedAssemblies.Any())
{
CaptureEvent(hub, options, unoptimizedAssemblies);
}
}
}

private static void CaptureEvent(IHub hub, SentryOptions options, params string[] assemblies)
{
if (assemblies.Length > 0)
{
options.DiagnosticLogger?.LogInfo("Unoptimized Assembly found. Raising event for {count} assemblies", assemblies.Length);
using (hub.PushScope())
{
hub.ConfigureScope(s =>
{
s.SetFingerprint(new[] {"UnoptimizedAssemblyIntegration"});
foreach (var asm in assemblies)
{
options.DiagnosticLogger?.LogInfo("Unoptimized Assembly: {asm}", asm);
s.SetExtra("unoptimized-assembly", asm);
}
s.Level = SentryLevel.Warning;
});
hub.CaptureMessage("Unoptimized assembly detected.");
}
}
}
}
}
16 changes: 16 additions & 0 deletions src/Sentry/Reflection/AssemblyExtensions.cs
@@ -1,4 +1,5 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using Sentry.Protocol;

Expand Down Expand Up @@ -29,5 +30,20 @@ public static SdkVersion GetNameAndVersion(this Assembly asm)

return new SdkVersion { Name = name, Version = version };
}

/// <summary>
/// Whether the assembly was compiled with the optimize+ flag
/// </summary>
/// <param name="asm">The assembly to verify the optimization flag</param>
/// <returns>
/// true if no <see cref="DebuggableAttribute"/> exists or
/// <see cref="DebuggableAttribute.IsJITOptimizerDisabled"/> is false,
/// otherwise, false.
/// </returns>
public static bool IsOptimized(this Assembly asm)
{
var att = asm.GetCustomAttribute<DebuggableAttribute>();
return att == null || att.IsJITOptimizerDisabled == false;
}
}
}
8 changes: 7 additions & 1 deletion src/Sentry/SentryOptions.cs
Expand Up @@ -349,6 +349,11 @@ public IDiagnosticLogger DiagnosticLogger
/// </summary>
public bool ReportAssemblies { get; set; } = true;

/// <summary>
/// Whether the SDK should raise events if unoptimized assemblies are loaded.
/// </summary>
public bool NotifyUnoptimizedAssembly { get; set; }

/// <summary>
/// What modes to use for event automatic deduplication
/// </summary>
Expand Down Expand Up @@ -411,7 +416,8 @@ public SentryOptions()
Integrations
= ImmutableList.Create<ISdkIntegration>(
new AppDomainUnhandledExceptionIntegration(),
new AppDomainProcessExitIntegration());
new AppDomainProcessExitIntegration(),
new UnoptimizedAssemblyIntegration());

InAppExclude
= ImmutableList.Create(
Expand Down