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

Raygun4Blazor - Preview 1 #1

Merged
merged 5 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ jobs:
run: dotnet build --no-restore
- name: Test
working-directory: ./src
run: dotnet test --no-build --verbosity normal
run: dotnet test
83 changes: 82 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,82 @@
# Raygun for Blazor, coming soon!
# Raygun for Blazor

## Usage

### Installation

- [ ] TODO: Package installation instructions. e.g.

```
dotnet add package <something>
```

### Setup

#### Using `WebAssemblyHostBuilder` to create the client

Use `UseRaygunBlazor` extension to configure the `RaygunBlazorClient` and related services for use in a Blazor WebAssembly application.

```cs
var builder = WebAssemblyHostBuilder.CreateDefault(args);

builder.UseRaygunBlazor();
```

The `RaygunSettings` will be obtained from the `appsettings.json` under the configuration section name `Raygun`.

For all configuration values, check the `RaygunSettings` class under `src/Raygun.NetCore.Blazor/RaygunSettings.cs`.

#### Initalize the client

Inject the `RaygunBlazorClient` in your code:

```cs
@inject RaygunBlazorClient raygunClient;
```

And call to `raygunClient.InitializeAsync()` at least once.

- [ ] TODO: Add more info. See `src/Raygun.NetCore.Blazor/RaygunBlazorClient.cs` for more information.

### Recording an error

Call to `raygunClient.RecordExceptionAsync(...)`

- [ ] TODO: Add more info. See `src/Raygun.NetCore.Blazor/RaygunBlazorClient.cs` for more information.

### Recording a breadcrumb

Call to `raygunClient.RecordBreadcrumb(...);`

- [ ] TODO: Add more info. See `src/Raygun.NetCore.Blazor/RaygunBlazorClient.cs` for more information.

### `RaygunErrorBoundary`

- [ ] TODO: Document when to use the `RaygunErrorBoundary`.

Currently used in `src/Raygun.NetCore.Samples.Blazor.WebAssembly/App.razor`

## Example Project

Example project is located in `src/Raygun.NetCore.Samples.Blazor.WebAssembly`

To run the example:

1. Install `dotnet-sdk` minimum version supported in `8.0.300`.
2. Add the `ApiKey` property to in `src/Raygun.NetCore.Samples.Blazor.WebAssembly/wwwroot/appsettings.json`

```
{
"Raygun": {
"ApiKey": "YOUR_API_KEY"
}
}
```

3. Run `dotnet watch` from the example folder.

A browser window to `http://localhost:5010/` should automatically open.

## Publishing

- [ ] TODO: Packagre publishing instructions, e.g. NuGet publish instructions
129 changes: 129 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<Project>
<!-- Folder layout -->
<PropertyGroup>
<IsBenchmarkProject Condition="$(MSBuildProjectName.ToLower().Contains('.benchmarks.'))">true</IsBenchmarkProject>
<IsTestAssetProject Condition="$(MSBuildProjectName.ToLower().Contains('tests.shared.'))">true</IsTestAssetProject>
<IsTestProject Condition="$(MSBuildProjectName.ToLower().Contains('.tests.')) == 'true' AND $(IsTestAssetProject) != 'true'">true</IsTestProject>
<IsSampleProject Condition="$(MSBuildProjectName.ToLower().Contains('.samples.'))">true</IsSampleProject>
<IsNetCore Condition=" '$(TargetFramework)' == 'net6.0' OR '$(TargetFramework)' == 'net7.0' OR '$(TargetFramework)' == 'net8.0' ">true</IsNetCore>
<IsPrimaryProject Condition=" '$(IsBenchmarkProject)' != 'true' AND '$(IsTestProject)' != 'true' AND '$(IsTestAssetProject)' != 'true' AND '$(IsSampleProject)' != 'true' ">true</IsPrimaryProject>

<IncludeSource>false</IncludeSource>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>

<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)Raygun.snk</AssemblyOriginatorKeyFile>
<StrongNamePublicKey>PublicKey=0024000004800000940000000602000000240000525341310004000001000100499b604a09b4538bcd0e626ae13f86083c9ab5950e3d7f8465d18fb93fd5e445b8fa2a46c42187b02aaeea0b8f738f238b9e1975384adf036cca1545619980c3fbfaf0fe47b9b9e88986f02cdbdeea9d69876e4fbba06b1a9dfc79eb829e258a12d1e751042384655719e3dd58552c18a978f953d110ea0209535682d64ec5bf</StrongNamePublicKey>

<LangVersion>12</LangVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DefineConstants>TRACE;RELEASE</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>

<PropertyGroup>
<Product>Raygun</Product>
<Authors>Robert McLaws</Authors>
<Company>Raygun Limited</Company>
<RpmPackageVendor>Raygun</RpmPackageVendor>
<Copyright>Copyright © 2024-2025 Raygun Limited. All rights reserved.</Copyright>
<NeutralLanguage>en-US</NeutralLanguage>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<!--
Suppress a warning about upcoming deprecation of PackageLicenseUrl. When embedding licenses are supported,
replace PackageLicenseUrl with PackageLicenseExpression.
-->
<NoWarn>$(NoWarn);NU5125</NoWarn>
<!-- Suppress warnings about using SemVer 2.0. -->
<NoWarn>$(NoWarn);NU5105</NoWarn>

<!-- Contact email address for NuGet packages and Linux installers. -->
<!--<MaintainerEmail>[email protected]</MaintainerEmail>-->

<PackageIcon>raygun.png</PackageIcon>
<PackageProjectUrl>https://github.com/MindscapeHQ/raygun4blazor</PackageProjectUrl>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageTags>raygun;blazor</PackageTags>
<Serviceable>true</Serviceable>

<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
<RepositoryUrl>https://github.com/MindscapeHQ/raygun4blazor/raygun4blazor.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
</PropertyGroup>

<!-- Compilation options -->
<PropertyGroup>
<!--<TreatWarningsAsErrors>true</TreatWarningsAsErrors>-->
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>

<!-- Instructs the compiler to use SHA256 instead of SHA1 when adding file hashes to PDBs. -->
<ChecksumAlgorithm>SHA256</ChecksumAlgorithm>

<!-- Fixes a common error in targets implementing a NoBuild mode. -->
<BuildProjectReferences Condition=" '$(NoBuild)' == 'true' ">false</BuildProjectReferences>

<!-- Suppress warnings about uninstantiated classes. -->
<NoWarn>$(NoWarn);CA1812;CS1570</NoWarn>

<!-- Suppress warnings about pre-release packages -->
<NoWarn>$(NoWarn);NU5104</NoWarn>

</PropertyGroup>

<PropertyGroup Condition=" $(IsTestProject) == 'true' ">
<NoWarn>$(NoWarn);CA1001;CA1031;CA1062;CA1301;CA1303;AC1307;CA1707;CA1716;CA1801;CA1806;CA1819;CA1822;CA1825;CA2000;CA2007;CA2227;CA2234</NoWarn>
</PropertyGroup>

<PropertyGroup Condition=" $(IsSampleProject) == 'true' ">
<NoWarn>$(NoWarn);CA1001;CA1707;CA1716;CA1801;CA1822</NoWarn>
</PropertyGroup>

<PropertyGroup Condition=" '$(IsPrimaryProject)' == 'true' ">
<IsPackable>true</IsPackable>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)</DocumentationFile>
</PropertyGroup>

<PropertyGroup Condition=" '$(IsPrimaryProject)' != 'true' ">
<IsPackable>false</IsPackable>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>

<PropertyGroup>
<StandardTestTfms>net8.0</StandardTestTfms>
</PropertyGroup>

<ItemGroup Condition=" $(IsTestProject) != 'true' and $(IsSampleProject) != 'true'">
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.*" PrivateAssets="All" />

<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>$(AssemblyName.Replace("Raygun.NetCore.", "Raygun.NetCore.Tests.")), $(StrongNamePublicKey)</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

<ItemGroup Condition=" $(IsTestProject) == 'true' ">
<PackageReference Include="FluentAssertions" Version="6.*" PrivateAssets="All" />
<PackageReference Include="FluentAssertions.Analyzers" Version="0.*" PrivateAssets="All" />
<PackageReference Include="MSTest" Version="3.*" />

<!-- @robertmclaws: Temporary workaround for 8.0 bug: https://github.com/microsoft/vstest/pull/4792 -->
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.*-*" />
<PackageReference Include="Microsoft.TestPlatform" Version="17.*-*" />
</ItemGroup>

<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)raygun.png" Pack="true" PackagePath="\" Condition="'$(IsTestProject)' != 'true'" />
</ItemGroup>

</Project>
7 changes: 7 additions & 0 deletions src/Raygun.NetCore.Blazor.Server/Class1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Raygun.NetCore.Blazor.Server
{
public class Class1

Check warning on line 3 in src/Raygun.NetCore.Blazor.Server/Class1.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'Class1'
{

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.AspNetCore.Builder
{

public static class HostBuilderExtensions

Check warning on line 10 in src/Raygun.NetCore.Blazor.Server/Extensions/HostBuilderExtensions.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'HostBuilderExtensions'
{
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<DocumentationFile>$(DocumentationFile)\$(AssemblyName).xml</DocumentationFile>
</PropertyGroup>

</Project>
110 changes: 110 additions & 0 deletions src/Raygun.NetCore.Blazor.WebAssembly/Controls/RaygunErrorBoundary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.Options;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Raygun.NetCore.Blazor.WebAssembly.Controls
{

/// <summary>
/// An extension of the Blazor <see cref="ErrorBoundary" /> control that automatically sends exceptions to Raygun.
/// </summary>
public class RaygunErrorBoundary : ErrorBoundary
{

#region Internal Parameters

/// <summary>
///
/// </summary>
[Inject]
internal IJSRuntime JSRuntime { get; set; }

/// <summary>
///
/// </summary>
[Inject]
internal RaygunBlazorClient RaygunClient { get; set; }

/// <summary>
///
/// </summary>
[Inject]
internal IOptions<RaygunSettings> RaygunSettings { get; set; }

#endregion

#region Public Parameters

/// <summary>
///
/// </summary>
[Parameter]
public bool ShowExceptionUI { get; set; }

#endregion

#region Internal Methods

/// <summary>
/// When an error occurs, send it to Raygun.
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
protected override async Task OnErrorAsync(Exception exception)
{
if (!RaygunSettings.Value.CatchUnhandledExceptions) return;

await RaygunClient.RecordExceptionAsync(exception, ["UnhandledException", "Blazor", ".NET"]);
}

/// <inheritdoc />
/// <remarks>
/// We are rendering differently than the ErrorBoundary base control because Raygun's ethos is to first not
/// mess with anything about the app. So if the developer wants to display UI, they have to specifically opt-in.
/// </remarks>
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
if (CurrentException is not null && ShowExceptionUI)
{
if (ErrorContent is not null)
{
builder.AddContent(1, ErrorContent(CurrentException));
}
else
{
// RWM: We may need to consider invoking JavaScript to set the "blazor-error-ui" visible instead.
// The code sets the style to display-block;


// The default error UI doesn't include any content, because:
// [1] We don't know whether or not you'd be happy to show the stack trace. It depends both on
// whether DetailedErrors is enabled and whether you're in production, because even on WebAssembly
// you likely don't want to put technical data like that in the UI for end users. A reasonable way
// to toggle this is via something like "#if DEBUG" but that can only be done in user code.
// [2] We can't have any other human-readable content by default, because it would need to be valid
// for all languages.
// Instead, the default project template provides locale-specific default content via CSS. This provides
// a quick form of customization even without having to subclass this component.
builder.OpenElement(2, "div");
builder.AddAttribute(3, "class", "blazor-error-boundary");
builder.CloseElement();
}
}
else
{
builder.AddContent(0, ChildContent);
}
}

#endregion

}

}
Loading
Loading