diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7ee6440..3fbba96 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,8 +26,8 @@ jobs: - '7.2.0' # - '7.1.0' # - '7.0.0' - - '6.2.0' - - '6.1.0' + # - '6.2.0' + # - '6.1.0' # - '6.0.0' # And test all built-in PowerShell/Windows Powershell versions on latest CI runner images include: diff --git a/dependencies/System.Buffers.properties b/dependencies/System.Buffers.properties new file mode 100644 index 0000000..5ec138c --- /dev/null +++ b/dependencies/System.Buffers.properties @@ -0,0 +1,3 @@ +version = 4.5.1 +assemblyVersion = 4.0.3.0 +licenseFile = LICENSE.TXT diff --git a/dependencies/System.Collections.Immutable.properties b/dependencies/System.Collections.Immutable.properties new file mode 100644 index 0000000..944f556 --- /dev/null +++ b/dependencies/System.Collections.Immutable.properties @@ -0,0 +1,2 @@ +version = 5.0.0 +licenseFile = LICENSE.TXT diff --git a/dependencies/System.Memory.properties b/dependencies/System.Memory.properties new file mode 100644 index 0000000..c61f89b --- /dev/null +++ b/dependencies/System.Memory.properties @@ -0,0 +1,3 @@ +version = 4.5.4 +assemblyVersion = 4.0.1.1 +licenseFile = LICENSE.TXT diff --git a/dependencies/System.Numerics.Vectors.properties b/dependencies/System.Numerics.Vectors.properties new file mode 100644 index 0000000..72c9621 --- /dev/null +++ b/dependencies/System.Numerics.Vectors.properties @@ -0,0 +1,3 @@ +version = 4.5.0 +assemblyVersion = 4.1.4.0 +licenseFile = LICENSE.TXT diff --git a/dependencies/System.Reflection.Metadata.properties b/dependencies/System.Reflection.Metadata.properties new file mode 100644 index 0000000..944f556 --- /dev/null +++ b/dependencies/System.Reflection.Metadata.properties @@ -0,0 +1,2 @@ +version = 5.0.0 +licenseFile = LICENSE.TXT diff --git a/dependencies/System.Runtime.CompilerServices.Unsafe.properties b/dependencies/System.Runtime.CompilerServices.Unsafe.properties new file mode 100644 index 0000000..c55567d --- /dev/null +++ b/dependencies/System.Runtime.CompilerServices.Unsafe.properties @@ -0,0 +1,3 @@ +version = 4.5.3 +assemblyVersion = 4.0.4.1 +licenseFile = LICENSE.TXT diff --git a/dependencies/System.Text.Encodings.Web.properties b/dependencies/System.Text.Encodings.Web.properties new file mode 100644 index 0000000..9f77425 --- /dev/null +++ b/dependencies/System.Text.Encodings.Web.properties @@ -0,0 +1,3 @@ +version = 6.0.0 +assemblyVersion = 6.0.0.0 +licenseFile = LICENSE.TXT diff --git a/dependencies/System.ValueTuple.properties b/dependencies/System.ValueTuple.properties new file mode 100644 index 0000000..f6806ab --- /dev/null +++ b/dependencies/System.ValueTuple.properties @@ -0,0 +1,3 @@ +version = 4.5.0 +assemblyVersion = 4.0.3.0 +licenseFile = LICENSE.TXT diff --git a/dependencies/download.ps1 b/dependencies/download.ps1 index adec923..2b53f79 100644 --- a/dependencies/download.ps1 +++ b/dependencies/download.ps1 @@ -113,10 +113,27 @@ Download -Dependency 'Sentry' -TFM 'net6.0' Download -Dependency 'Sentry' -TFM 'netstandard2.0' Download -Dependency 'Sentry' -TFM 'net462' -Download -Dependency 'System.Text.Json' -TFM 'net461' -TargetTFM 'net462' -Download -Dependency 'Microsoft.Bcl.AsyncInterfaces' -TFM 'net461' -TargetTFM 'net462' -Download -Dependency 'System.Threading.Tasks.Extensions' -TFM 'net461' -TargetTFM 'net462' - -Download -Dependency 'System.Text.Json' -TFM 'netstandard2.0' -assemblyVersion '6.0.0.0' -Download -Dependency 'Microsoft.Bcl.AsyncInterfaces' -TFM 'netstandard2.0' -Download -Dependency 'System.Threading.Tasks.Extensions' -TFM 'netstandard2.0' +# You can see the list of dependencies that are actually used in sentry-dotnet/src/Sentry/bin/Debug/net462 +# As for the versions in use, check the sentry package on nuget.org. +Download -TFM 'net461' -TargetTFM 'net462' -Dependency 'Microsoft.Bcl.AsyncInterfaces' +Download -TFM 'net461' -TargetTFM 'net462' -Dependency 'System.Buffers' +Download -TFM 'net461' -TargetTFM 'net462' -Dependency 'System.Collections.Immutable' +Download -TFM 'net461' -TargetTFM 'net462' -Dependency 'System.Memory' +Download -TFM 'net46' -TargetTFM 'net462' -Dependency 'System.Numerics.Vectors' +Download -TFM 'net461' -TargetTFM 'net462' -Dependency 'System.Reflection.Metadata' +Download -TFM 'net461' -TargetTFM 'net462' -Dependency 'System.Runtime.CompilerServices.Unsafe' +Download -TFM 'net461' -TargetTFM 'net462' -Dependency 'System.Text.Encodings.Web' +Download -TFM 'net461' -TargetTFM 'net462' -Dependency 'System.Text.Json' +Download -TFM 'net461' -TargetTFM 'net462' -Dependency 'System.Threading.Tasks.Extensions' +Download -TFM 'net461' -TargetTFM 'net462' -Dependency 'System.ValueTuple' + +Download -TFM 'netstandard2.0' -Dependency 'Microsoft.Bcl.AsyncInterfaces' +Download -TFM 'netstandard2.0' -Dependency 'System.Buffers' +Download -TFM 'netstandard2.0' -Dependency 'System.Collections.Immutable' +Download -TFM 'netstandard2.0' -Dependency 'System.Memory' +Download -TFM 'netstandard2.0' -Dependency 'System.Numerics.Vectors' +Download -TFM 'netstandard2.0' -Dependency 'System.Reflection.Metadata' +Download -TFM 'netstandard2.0' -Dependency 'System.Runtime.CompilerServices.Unsafe' +Download -TFM 'netstandard2.0' -Dependency 'System.Text.Encodings.Web' +Download -TFM 'netstandard2.0' -Dependency 'System.Text.Json' -assemblyVersion '6.0.0.0' +Download -TFM 'netstandard2.0' -Dependency 'System.Threading.Tasks.Extensions' diff --git a/module/Sentry.psd1 b/module/Sentry.psd1 index 1d5f0d9..171f6f5 100644 --- a/module/Sentry.psd1 +++ b/module/Sentry.psd1 @@ -1,7 +1,7 @@ # https://learn.microsoft.com/en-us/powershell/scripting/developer/module/how-to-write-a-powershell-module-manifest @{ # Script module or binary module file associated with this manifest. - # RootModule = '' + RootModule = 'Sentry.psm1' # Version number of this module. ModuleVersion = '0.0.1' @@ -31,13 +31,13 @@ ScriptsToProcess = @('assemblies-loader.ps1') # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. - FunctionsToExport = @() + FunctionsToExport = @('Out-Sentry', 'Invoke-WithSentry') # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() # Variables to export from this module - VariablesToExport = '*' + VariablesToExport = @() # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. AliasesToExport = @() diff --git a/module/Sentry.psm1 b/module/Sentry.psm1 new file mode 100644 index 0000000..c6c0eab --- /dev/null +++ b/module/Sentry.psm1 @@ -0,0 +1,53 @@ +function Out-Sentry +{ + param( + [Parameter(ValueFromPipeline = $true)] + [System.Management.Automation.ErrorRecord] + $ErrorRecord, + + [Parameter(ValueFromPipeline = $true)] + [System.Exception] + $Exception, + + [Parameter(ValueFromPipeline = $true)] + [string] + $Message + ) + + begin {} + process + { + if ($ErrorRecord -ne $null) + { + # TODO details + [Sentry.SentrySdk]::CaptureException($ErrorRecord.Exception) + } + if ($Exception -ne $null -and ($Message -eq $null -or "$Exception" -eq "$Message")) + { + [Sentry.SentrySdk]::CaptureException($Exception) + } + if ($Message -ne $null -and $Message -ne $ErrorRecord -and $Message -ne $Exception) + { + [Sentry.SentrySdk]::CaptureMessage($Message) + } + } + end {} +} + +function Invoke-WithSentry +{ + param( + [scriptblock] + $ScriptBlock + ) + + try + { + & $ScriptBlock + } + catch + { + $_ | Out-Sentry + throw + } +} diff --git a/tests/capture.tests.ps1 b/tests/capture.tests.ps1 new file mode 100644 index 0000000..364ad5e --- /dev/null +++ b/tests/capture.tests.ps1 @@ -0,0 +1,80 @@ +BeforeAll { + $events = [System.Collections.Generic.List[Sentry.SentryEvent]]::new(); + $options = [Sentry.SentryOptions]::new() + $options.Debug = $true + $options.Dsn = 'https://key@127.0.0.1/1' + $options.AutoSessionTracking = $false + $options.SetBeforeSend([System.Func[Sentry.SentryEvent, Sentry.SentryEvent]] { + param([Sentry.SentryEvent]$e) + $events.Add($e) + return $null # Prevent sending + }); + [Sentry.SentrySdk]::init($options) +} + +AfterAll { + [Sentry.SentrySdk]::Close() +} + + +Describe 'Out-Sentry' { + AfterEach { + $events.Clear() + } + + It 'captures message' { + 'message' | Out-Sentry + $events.Count | Should -Be 1 + [Sentry.SentryEvent]$event = $events.ToArray()[0] + $event.Exception | Should -Be $null + $event.Message.Message | Should -Be 'message' + } + + It 'captures error record' { + try + { + throw 'error' + } + catch + { + $_ | Out-Sentry + } + $events.Count | Should -Be 1 + [Sentry.SentryEvent]$event = $events.ToArray()[0] + $event.Exception | Should -BeOfType [System.Management.Automation.RuntimeException] + $event.Exception.Message | Should -Be 'error' + } + + It 'captures exception' { + try + { + throw 'exception' + } + catch + { + $_.Exception | Out-Sentry + } + $events.Count | Should -Be 1 + [Sentry.SentryEvent]$event = $events.ToArray()[0] + $event.Exception | Should -BeOfType [System.Management.Automation.RuntimeException] + $event.Exception.Message | Should -Be 'exception' + } +} + +Describe 'Invoke-WithSentry' { + AfterEach { + $events.Clear() + } + + It 'captures error record' { + try + { + Invoke-WithSentry { throw 'inside invoke' } + } + catch {} + $events.Count | Should -Be 1 + [Sentry.SentryEvent]$event = $events.ToArray()[0] + $event.Exception | Should -BeOfType [System.Management.Automation.RuntimeException] + $event.Exception.Message | Should -Be 'inside invoke' + } +} diff --git a/tests/init.tests.ps1 b/tests/init.tests.ps1 index 92b7f3c..cfebb9c 100644 --- a/tests/init.tests.ps1 +++ b/tests/init.tests.ps1 @@ -1,3 +1,7 @@ +BeforeAll { + . $PSScriptRoot/utils.ps1 +} + Describe 'SentrySdk' { AfterEach { [Sentry.SentrySdk]::close() @@ -23,15 +27,6 @@ Describe 'SentrySdk' { # Currently breaks tests, see 'https://github.com/getsentry/sentry-dotnet/issues/3141' # It 'init respects options' { - # class TestLogger:Sentry.Infrastructure.DiagnosticLogger - # { - # TestLogger([Sentry.SentryLevel]$level) : base($level) {} - - # $entries = [System.Collections.Concurrent.ConcurrentQueue[string]]::new(); - - # [void]LogMessage([string] $message) { $this.entries.Enqueue($message); } - # } - # $logger = [TestLogger]::new([Sentry.SentryLevel]::Debug) # $options = [Sentry.SentryOptions]::new() diff --git a/tests/utils.ps1 b/tests/utils.ps1 new file mode 100644 index 0000000..2c23faa --- /dev/null +++ b/tests/utils.ps1 @@ -0,0 +1,19 @@ +class RecordingTransport:Sentry.Extensibility.ITransport +{ + $envelopes = [System.Collections.Concurrent.ConcurrentQueue[Sentry.Protocol.Envelopes.Envelope]]::new(); + + [System.Threading.Tasks.Task]SendEnvelopeAsync([Sentry.Protocol.Envelopes.Envelope] $envelope, [System.Threading.CancellationToken] $cancellationToken) + { + $this.envelopes.Enqueue($envelope); + return [System.Threading.Tasks.Task]::CompletedTask; + } +} + +class TestLogger:Sentry.Infrastructure.DiagnosticLogger +{ + TestLogger([Sentry.SentryLevel]$level) : base($level) {} + + $entries = [System.Collections.Concurrent.ConcurrentQueue[string]]::new(); + + [void]LogMessage([string] $message) { $this.entries.Enqueue($message); } +}