diff --git a/integration-test/common.ps1 b/integration-test/common.ps1 index d09721ce15..779b942156 100644 --- a/integration-test/common.ps1 +++ b/integration-test/common.ps1 @@ -196,6 +196,7 @@ BeforeAll { Pop-Location } } + function DotnetNew([string] $type, [string] $name, [string] $framework) { Remove-Item -Path $name -Recurse -Force -ErrorAction SilentlyContinue @@ -231,4 +232,22 @@ BeforeAll { "@ | Out-File $name/Directory.Build.props } } + + function DotnetRun([string] $projectPath, [string] $tfm, [string[]] $applicationArguments) + { + $executable = "dotnet run --project $projectPath --configuration Release --framework $tfm -- $($applicationArguments -join ' ')" + + Write-Host "::group::Executing $executable" + try + { + Invoke-Expression "$executable 2>&1" | ForEach-Object { + Write-Host " $_" + $_ + } + } + finally + { + Write-Host '::endgroup::' + } + } } diff --git a/integration-test/runtime.Tests.ps1 b/integration-test/runtime.Tests.ps1 index 0fa357c3fa..0061214255 100644 --- a/integration-test/runtime.Tests.ps1 +++ b/integration-test/runtime.Tests.ps1 @@ -183,6 +183,74 @@ internal class FakeTransport : ITransport } } +# Integration Tests for Sentry.Profiling +Describe 'Console app with Profiling on ' -ForEach @( + foreach ($fw in $currentFrameworks) { @{ framework = $fw } } +) { + BeforeAll { + ResetLocalPackages + RegisterLocalPackage 'Sentry.Profiling' + + $path = "./console-app-with-profiling-on-$framework" + DotnetNew 'console' $path $framework + AddPackageReference $path 'Sentry.Profiling' + + @' +using Sentry; +using Sentry.Extensibility; +using Sentry.Protocol.Envelopes; + +SentrySdk.Init(options => +{ + options.Dsn = args[0]; + options.Debug = true; + options.Transport = new FakeTransport(); + + options.TracesSampleRate = 1.0; + options.ProfilesSampleRate = 1.0; + options.AddProfilingIntegration(TimeSpan.FromMilliseconds(1_000)); +}); + +InvokeMethod(); + +Console.WriteLine("Application completed successfully."); + +static void InvokeMethod() +{ + var transaction = SentrySdk.StartTransaction("app", "run"); + Console.WriteLine("Hello World!"); + transaction.Finish(); +} + +internal class FakeTransport : ITransport +{ + public virtual Task SendEnvelopeAsync(Envelope envelope, CancellationToken cancellationToken = default) + { + envelope.Serialize(Console.OpenStandardOutput(), null); + return Task.CompletedTask; + } +} +'@ | Out-File $path/Program.cs + } + + AfterAll { + Remove-Item -Recurse -Force -Path $path -ErrorAction SilentlyContinue + } + + # see https://github.com/getsentry/sentry-dotnet/issues/4815 + It 'Profiling integration does not cause ReflectionTypeLoadException on startup' { + $dsn = 'http://key@127.0.0.1:9999/123' + + $output = DotnetRun $path $framework $dsn + + $output | Should -Not -AnyElementMatch 'ReflectionTypeLoadException' + $output | Should -Not -AnyElementMatch 'Dia2Lib' + $output | Should -Not -AnyElementMatch 'TraceReloggerLib' + $output | Should -AnyElementMatch 'Profiling stopped on transaction finish.' + $output | Should -AnyElementMatch 'Application completed successfully.' + } +} + # This ensures we don't have a regression for https://github.com/getsentry/sentry-dotnet/issues/2825 Describe 'Console app regression (missing System.Reflection.Metadata)' { BeforeAll { diff --git a/src/Sentry.Profiling/SamplingTransactionProfilerFactory.cs b/src/Sentry.Profiling/SamplingTransactionProfilerFactory.cs index 1d3d03c5f3..3884524807 100644 --- a/src/Sentry.Profiling/SamplingTransactionProfilerFactory.cs +++ b/src/Sentry.Profiling/SamplingTransactionProfilerFactory.cs @@ -38,7 +38,7 @@ public SamplingTransactionProfilerFactory(SentryOptions options, TimeSpan startu Debug.Assert(TimeSpan.FromSeconds(0) == TimeSpan.Zero); if (startupTimeout != TimeSpan.Zero && !_sessionTask.Wait(startupTimeout)) { - options.LogWarning("Profiler session startup took longer then the given timeout {0:c}. Profilling will start once the first event is received.", startupTimeout); + options.LogWarning("Profiler session startup took longer then the given timeout {0:c}. Profiling will start once the first event is received.", startupTimeout); StartupTimedOut = true; } }