Skip to content

Commit 3fde00a

Browse files
Automatically capture heap dumps (#3667)
1 parent ed36c19 commit 3fde00a

36 files changed

+1256
-10
lines changed

Diff for: .generated.NoMobile.sln

+7
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "root", "root", "{233D34AB-9
178178
EndProject
179179
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.AspNetCore.Blazor.WebAssembly", "src\Sentry.AspNetCore.Blazor.WebAssembly\Sentry.AspNetCore.Blazor.WebAssembly.csproj", "{8298202C-9983-4D0A-851D-805539EE481A}"
180180
EndProject
181+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.Samples.Console.HeapDump", "samples\Sentry.Samples.Console.HeapDump\Sentry.Samples.Console.HeapDump.csproj", "{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821}"
182+
EndProject
181183
Global
182184
GlobalSection(SolutionConfigurationPlatforms) = preSolution
183185
Debug|Any CPU = Debug|Any CPU
@@ -493,6 +495,10 @@ Global
493495
{A5B26C14-7313-4EDC-91E3-287F9374AB75}.Debug|Any CPU.Build.0 = Debug|Any CPU
494496
{A5B26C14-7313-4EDC-91E3-287F9374AB75}.Release|Any CPU.ActiveCfg = Release|Any CPU
495497
{A5B26C14-7313-4EDC-91E3-287F9374AB75}.Release|Any CPU.Build.0 = Release|Any CPU
498+
{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
499+
{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821}.Debug|Any CPU.Build.0 = Debug|Any CPU
500+
{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821}.Release|Any CPU.ActiveCfg = Release|Any CPU
501+
{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821}.Release|Any CPU.Build.0 = Release|Any CPU
496502
EndGlobalSection
497503
GlobalSection(SolutionProperties) = preSolution
498504
HideSolutionNode = FALSE
@@ -575,5 +581,6 @@ Global
575581
{46E40BE8-1AB0-4846-B0A2-A40AD0272C64} = {6987A1CC-608E-4868-A02C-09D30C8B7B2D}
576582
{8298202C-9983-4D0A-851D-805539EE481A} = {230B9384-90FD-4551-A5DE-1A5C197F25B6}
577583
{A5B26C14-7313-4EDC-91E3-287F9374AB75} = {21B42F60-5802-404E-90F0-AEBCC56760C0}
584+
{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821} = {21B42F60-5802-404E-90F0-AEBCC56760C0}
578585
EndGlobalSection
579586
EndGlobal

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- `SentryOptions.EnableTracing` has been removed. Instead, tracing should be enabled or disabled by setting the `SentryOptions.TracesSampleRate` or by using `SentryOptions.TracesSampler` to configure a sampling function ([#3569](https://github.com/getsentry/sentry-dotnet/pull/3569))
1212
- The `FailedRequestTargets`, `TagFilters` and `TracePropagationTargets` options have all been changed from `SubstringOrRegexPattern` to `IList<StringOrRegex>` ([#3566](https://github.com/getsentry/sentry-dotnet/pull/3566))
1313
- `Scope.Transaction` is now always stored as an `AsyncLocal` also in [Global Mode](https://docs.sentry.io/platforms/dotnet/configuration/options/#is-global-mode-enabled), to prevent auto-instrumented spans from the UI ending up parented to transactions from a background task (or vice versa). ([#3596](https://github.com/getsentry/sentry-dotnet/pull/3596))
14+
- Heap dumps can be captured automatically when memory usage exceeds a configurable threshold ([#3667](https://github.com/getsentry/sentry-dotnet/pull/3667))
1415
- Sentry's Experimental Metrics feature has been deprecated and removed from the SDK. ([#3718](https://github.com/getsentry/sentry-dotnet/pull/3718))
1516

1617
### Features

Diff for: Directory.Build.props

+9
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@
8484
<SentryCLIDirectory>$(MSBuildThisFileDirectory)tools\sentry-cli\$(SentryCLIVersion)\</SentryCLIDirectory>
8585
</PropertyGroup>
8686

87+
<!-- dotnet-gcdump needs net6+ and won't work on mobile. -->
88+
<PropertyGroup>
89+
<PlatformIsLegacy Condition="$(TargetFramework.StartsWith('net4')) or $(TargetFramework.StartsWith('netstandard'))">true</PlatformIsLegacy>
90+
<PlatformIsMobile Condition="$(TargetFramework.EndsWith('android')) or $(TargetFramework.EndsWith('ios')) or $(TargetFramework.EndsWith('maccatalyst'))">true</PlatformIsMobile>
91+
<MemoryDumpSupported Condition="!($(PlatformIsLegacy) == 'true' or $(PlatformIsMobile) == 'true')">true</MemoryDumpSupported>
92+
93+
<DefineConstants Condition="'$(MemoryDumpSupported)' == 'true'">$(DefineConstants);MEMORY_DUMP_SUPPORTED</DefineConstants>
94+
</PropertyGroup>
95+
8796
<!-- Public key of .assets/Sentry.snk - not a secret. Used by other InternalsVisibleTo entries throughout the solution. -->
8897
<PropertyGroup>
8998
<SentryPublicKey>002400000480000094000000060200000024000052534131000400000100010059964a931488bcdbd14657f1ee0df32df61b57b3d14d7290c262c2cc9ddaad6ec984044f761f778e1823049d2cb996a4f58c8ea5b46c37891414cb34b4036b1c178d7b582289d2eef3c0f1e9b692c229a306831ee3d371d9e883f0eb0f74aeac6c6ab8c85fd1ec04b267e15a31532c4b4e2191f5980459db4dce0081f1050fb8</SentryPublicKey>

Diff for: Sentry-CI-Build-Linux.slnf

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"samples\\Sentry.Samples.Azure.Functions.Worker\\Sentry.Samples.Azure.Functions.Worker.csproj",
1616
"samples\\Sentry.Samples.Console.Basic\\Sentry.Samples.Console.Basic.csproj",
1717
"samples\\Sentry.Samples.Console.Customized\\Sentry.Samples.Console.Customized.csproj",
18+
"samples\\Sentry.Samples.Console.HeapDump\\Sentry.Samples.Console.HeapDump.csproj",
1819
"samples\\Sentry.Samples.Console.Native\\Sentry.Samples.Console.Native.csproj",
1920
"samples\\Sentry.Samples.Console.Profiling\\Sentry.Samples.Console.Profiling.csproj",
2021
"samples\\Sentry.Samples.EntityFramework\\Sentry.Samples.EntityFramework.csproj",

Diff for: Sentry-CI-Build-Windows.slnf

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"samples\\Sentry.Samples.Azure.Functions.Worker\\Sentry.Samples.Azure.Functions.Worker.csproj",
1717
"samples\\Sentry.Samples.Console.Basic\\Sentry.Samples.Console.Basic.csproj",
1818
"samples\\Sentry.Samples.Console.Customized\\Sentry.Samples.Console.Customized.csproj",
19+
"samples\\Sentry.Samples.Console.HeapDump\\Sentry.Samples.Console.HeapDump.csproj",
1920
"samples\\Sentry.Samples.Console.Native\\Sentry.Samples.Console.Native.csproj",
2021
"samples\\Sentry.Samples.Console.Profiling\\Sentry.Samples.Console.Profiling.csproj",
2122
"samples\\Sentry.Samples.EntityFramework\\Sentry.Samples.EntityFramework.csproj",

Diff for: Sentry-CI-Build-macOS.slnf

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"samples\\Sentry.Samples.Azure.Functions.Worker\\Sentry.Samples.Azure.Functions.Worker.csproj",
1717
"samples\\Sentry.Samples.Console.Basic\\Sentry.Samples.Console.Basic.csproj",
1818
"samples\\Sentry.Samples.Console.Customized\\Sentry.Samples.Console.Customized.csproj",
19+
"samples\\Sentry.Samples.Console.HeapDump\\Sentry.Samples.Console.HeapDump.csproj",
1920
"samples\\Sentry.Samples.Console.Native\\Sentry.Samples.Console.Native.csproj",
2021
"samples\\Sentry.Samples.Console.Profiling\\Sentry.Samples.Console.Profiling.csproj",
2122
"samples\\Sentry.Samples.EntityFramework\\Sentry.Samples.EntityFramework.csproj",

Diff for: Sentry.sln

+7
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "root", "root", "{233D34AB-9
187187
EndProject
188188
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.AspNetCore.Blazor.WebAssembly", "src\Sentry.AspNetCore.Blazor.WebAssembly\Sentry.AspNetCore.Blazor.WebAssembly.csproj", "{8298202C-9983-4D0A-851D-805539EE481A}"
189189
EndProject
190+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.Samples.Console.HeapDump", "samples\Sentry.Samples.Console.HeapDump\Sentry.Samples.Console.HeapDump.csproj", "{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821}"
191+
EndProject
190192
Global
191193
GlobalSection(SolutionConfigurationPlatforms) = preSolution
192194
Debug|Any CPU = Debug|Any CPU
@@ -502,6 +504,10 @@ Global
502504
{A5B26C14-7313-4EDC-91E3-287F9374AB75}.Debug|Any CPU.Build.0 = Debug|Any CPU
503505
{A5B26C14-7313-4EDC-91E3-287F9374AB75}.Release|Any CPU.ActiveCfg = Release|Any CPU
504506
{A5B26C14-7313-4EDC-91E3-287F9374AB75}.Release|Any CPU.Build.0 = Release|Any CPU
507+
{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
508+
{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821}.Debug|Any CPU.Build.0 = Debug|Any CPU
509+
{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821}.Release|Any CPU.ActiveCfg = Release|Any CPU
510+
{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821}.Release|Any CPU.Build.0 = Release|Any CPU
505511
EndGlobalSection
506512
GlobalSection(SolutionProperties) = preSolution
507513
HideSolutionNode = FALSE
@@ -584,5 +590,6 @@ Global
584590
{46E40BE8-1AB0-4846-B0A2-A40AD0272C64} = {6987A1CC-608E-4868-A02C-09D30C8B7B2D}
585591
{8298202C-9983-4D0A-851D-805539EE481A} = {230B9384-90FD-4551-A5DE-1A5C197F25B6}
586592
{A5B26C14-7313-4EDC-91E3-287F9374AB75} = {21B42F60-5802-404E-90F0-AEBCC56760C0}
593+
{D7DF0B26-AD43-4F8B-9BFE-C4471CCC9821} = {21B42F60-5802-404E-90F0-AEBCC56760C0}
587594
EndGlobalSection
588595
EndGlobal

Diff for: Sentry.sln.DotSettings

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OS/@EntryIndexedValue">OS</s:String>
55
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QL/@EntryIndexedValue">QL</s:String>
66
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
7+
<s:Boolean x:Key="/Default/UserDictionary/Words/=debouncer/@EntryIndexedValue">True</s:Boolean>
78
<s:Boolean x:Key="/Default/UserDictionary/Words/=Enricher/@EntryIndexedValue">True</s:Boolean>
89
<s:Boolean x:Key="/Default/UserDictionary/Words/=enrichers/@EntryIndexedValue">True</s:Boolean>
910
<s:Boolean x:Key="/Default/UserDictionary/Words/=instrumenter/@EntryIndexedValue">True</s:Boolean>

Diff for: SentryNoMobile.slnf

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"samples\\Sentry.Samples.Azure.Functions.Worker\\Sentry.Samples.Azure.Functions.Worker.csproj",
1515
"samples\\Sentry.Samples.Console.Basic\\Sentry.Samples.Console.Basic.csproj",
1616
"samples\\Sentry.Samples.Console.Customized\\Sentry.Samples.Console.Customized.csproj",
17+
"samples\\Sentry.Samples.Console.HeapDump\\Sentry.Samples.Console.HeapDump.csproj",
1718
"samples\\Sentry.Samples.Console.Native\\Sentry.Samples.Console.Native.csproj",
1819
"samples\\Sentry.Samples.Console.Profiling\\Sentry.Samples.Console.Profiling.csproj",
1920
"samples\\Sentry.Samples.EntityFramework\\Sentry.Samples.EntityFramework.csproj",

Diff for: samples/Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</PropertyGroup>
88

99
<!-- Workaround for hang on compile issue. See https://github.com/xamarin/xamarin-macios/issues/17825#issuecomment-1478568270. -->
10-
<PropertyGroup Condition="'$(Configuration)' == 'Release' And '$(TargetFramework)' == 'net7.0-ios' And '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)' == 'Arm64'">
10+
<PropertyGroup Condition="'$(Configuration)' == 'Release' And $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
1111
<MtouchUseLlvm>false</MtouchUseLlvm>
1212
</PropertyGroup>
1313
</Project>

Diff for: samples/Sentry.Samples.Console.Basic/Program.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
* For more advanced features of the SDK, see Sentry.Samples.Console.Customized.
99
*/
1010

11-
// Initialize the Sentry SDK. (It is not necessary to dispose it.)
12-
1311
using System.Net.Http;
12+
using static System.Console;
1413

14+
// Initialize the Sentry SDK. (It is not necessary to dispose it.)
1515
SentrySdk.Init(options =>
1616
{
1717
// You can set here in code, or you can set it in the SENTRY_DSN environment variable.
@@ -55,7 +55,7 @@ async Task FirstFunction()
5555
var messageHandler = new SentryHttpMessageHandler();
5656
var httpClient = new HttpClient(messageHandler, true);
5757
var html = await httpClient.GetStringAsync("https://example.com/");
58-
Console.WriteLine(html);
58+
WriteLine(html);
5959
}
6060

6161
async Task SecondFunction()

Diff for: samples/Sentry.Samples.Console.HeapDump/Program.cs

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* This sample demonstrates how you can configure Sentry to automatically capture heap dumps based on certain memory
3+
* triggers (e.g. if memory consumption exceeds a certain percentage threshold).
4+
*
5+
* Note that this functionality is only available when targeting net6.0 or above and is not available on iOS, Android
6+
* or Mac Catalyst.
7+
*/
8+
9+
using System.Reflection;
10+
using static System.Console;
11+
12+
var cts = new CancellationTokenSource();
13+
14+
// Initialize the Sentry SDK. (It is not necessary to dispose it.)
15+
SentrySdk.Init(options =>
16+
{
17+
// You can set here in code, or you can set it in the SENTRY_DSN environment variable.
18+
// See https://docs.sentry.io/product/sentry-basics/dsn-explainer/
19+
options.Dsn = "https://[email protected]/5428537";
20+
21+
// When debug is enabled, the Sentry client will emit detailed debugging information to the console.
22+
// This might be helpful, or might interfere with the normal operation of your application.
23+
// We enable it here for demonstration purposes.
24+
// You should not do this in your applications unless you are troubleshooting issues with Sentry.
25+
options.Debug = true;
26+
27+
// Set TracesSampleRate = 0 to disable tracing for this demo
28+
options.TracesSampleRate = 0;
29+
30+
// This option tells Sentry to capture a heap dump and send these as a file attachment in a Sentry event
31+
options.EnableHeapDumps(
32+
// Triggers a heap dump if the process uses more than 5% of the total memory. We could use any threshold or even
33+
// provide a custom trigger function here instead.
34+
5,
35+
// Limit the frequency of heap dumps to a maximum of 3 events per day and at least 1 hour between each event.
36+
Debouncer.PerDay(3, TimeSpan.FromHours(1)),
37+
// Set the level for heap dump events to Info
38+
SentryLevel.Info
39+
);
40+
41+
// This is an example of intercepting events before they get sent to Sentry. Typically, you might use this to
42+
// filter events that you didn't want to send but in this case we're using it to detect when a heap dump has
43+
// been captured, so we know when to stop allocating memory in the heap dump demo.
44+
options.SetBeforeSend((evt, hint) =>
45+
{
46+
if (hint.Attachments.Any(a => a.FileName.EndsWith("gcdump")))
47+
{
48+
cts.Cancel();
49+
}
50+
return evt; // If we returned null here, that would stop the event from being sent
51+
});
52+
});
53+
54+
// In Debug mode there will be a bit of stuff logged out during initialization... wait for that to play out
55+
await Task.Delay(1000);
56+
57+
var memoryHog = new List<object>();
58+
WriteLine();
59+
60+
WriteLine("Hogging memory...");
61+
62+
// Sentry checks memory usage every time a full garbage collection occurs. It might take a while to trigger this,
63+
// although we've configured some ridiculously aggressive settings in the runtimeconfig.template.json file to make
64+
// this happen more quickly, for the purposes of this demo... definitely don't do this in production!
65+
while (cts.Token.IsCancellationRequested == false)
66+
{
67+
var array = new byte[2_000_000_000];
68+
array.Initialize();
69+
memoryHog.Add(array);
70+
}
71+
72+
GC.KeepAlive(memoryHog);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<InvariantGlobalization>true</InvariantGlobalization>
9+
</PropertyGroup>
10+
<PropertyGroup>
11+
<!--
12+
Note, these options do nothing if you are not authenticated.
13+
See https://docs.sentry.io/platforms/dotnet/configuration/msbuild/#authentication
14+
-->
15+
<!--
16+
<SentryUrl>...your Sentry URL if self-hosted, or omit this line if using sentry.io...</SentryUrl>
17+
-->
18+
<SentryOrg>sentry-sdks</SentryOrg>
19+
<SentryProject>sentry-dotnet</SentryProject>
20+
21+
<!--
22+
After the above properties are configured, you can use the following features.
23+
Uploading symbols to Sentry will enable server-side symbolication (i.e. when the PDB is not present at runtime, or for AOT published programs).
24+
Uploading sources to Sentry during the build will enable Source Context in the Sentry issue details page.
25+
-->
26+
<SentryUploadSymbols>true</SentryUploadSymbols>
27+
<SentryUploadSources>true</SentryUploadSources>
28+
29+
<!--
30+
You can automatically create releases via sentry-cli and control their creation via these properties
31+
See https://docs.sentry.io/cli/releases/#creating-releases
32+
-->
33+
<SentryCreateRelease>true</SentryCreateRelease>
34+
35+
<!--
36+
To associate commits with releases
37+
See https://docs.sentry.io/cli/releases/#commit-integration
38+
-->
39+
<SentrySetCommits>true</SentrySetCommits>
40+
<SentrySetCommitOptions>--local</SentrySetCommitOptions>
41+
42+
<!--
43+
To associate commits with releases
44+
See https://docs.sentry.io/cli/releases/#commit-integration
45+
-->
46+
<!-- <SentrySetCommits>true</SentrySetCommits>-->
47+
<!-- <SentrySetCommitOptions>&#45;&#45;local</SentrySetCommitOptions>-->
48+
</PropertyGroup>
49+
50+
<!-- In your own project, this would be a PackageReference to the latest version of Sentry. -->
51+
<ItemGroup>
52+
<ProjectReference Include="..\..\src\Sentry\Sentry.csproj" />
53+
</ItemGroup>
54+
55+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"configProperties": {
3+
"System.GC.ConserveMemory": 9,
4+
"System.GC.HighMemoryPercent": 20
5+
}
6+
}

0 commit comments

Comments
 (0)