Skip to content

Commit

Permalink
Merge pull request #553 from MindscapeHQ/ph/ms-logger
Browse files Browse the repository at this point in the history
Add MS Logger support
  • Loading branch information
phillip-haydon authored Dec 10, 2024
2 parents b86f813 + 3213a2a commit ce98721
Show file tree
Hide file tree
Showing 38 changed files with 1,037 additions and 35 deletions.
13 changes: 12 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
[*]
indent_style = space
indent_size = 2
indent_size = 2

[*.cs]
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0290
csharp_style_prefer_primary_constructors = false
dotnet_diagnostic.IDE0290.severity = none

# https://www.jetbrains.com/help/rider/ConvertToPrimaryConstructor.html
resharper_convert_to_primary_constructor_highlighting = none

# Ensure if statements always use braces
csharp_prefer_braces = true:error
5 changes: 5 additions & 0 deletions CHANGE-LOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Full Change Log for Raygun4Net.* packages

### v11.2.0
- Add new `IMessageBuilder` interface to allow for custom message builders
- New `Mindscape.Raygun4Net.Extensions.Logging` package
- See: https://github.com/MindscapeHQ/raygun4net/pull/553

### v11.1.3
- Skip serializing `WinRT.ObjectReferenceWithContext<WinRT.Interop.IUnknownVftbl>` objects attached to the Exception.Data to avoid AccessViolationException.
- See: https://github.com/MindscapeHQ/raygun4net/pull/549
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>10</LangVersion>
<IsPackable>false</IsPackable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Mindscape.Raygun4Net.AspNetCore.Builders;

namespace Mindscape.Raygun4Net.AspNetCore;

Expand Down Expand Up @@ -51,7 +52,8 @@ public static IServiceCollection AddRaygun(this IServiceCollection services, ICo
options?.Invoke(settings);

services.TryAddSingleton(settings);
services.TryAddSingleton(s => new RaygunClient(s.GetService<RaygunSettings>()!, s.GetService<IRaygunUserProvider>()!));
services.TryAddSingleton(s => new RaygunClient(s.GetRequiredService<RaygunSettings>(), s.GetRequiredService<IRaygunUserProvider>(), s.GetServices<IMessageBuilder>()));
services.TryAddSingleton<RaygunClientBase>(provider => provider.GetRequiredService<RaygunClient>());
services.AddHttpContextAccessor();

return services;
Expand All @@ -68,8 +70,10 @@ public static IServiceCollection AddRaygun(this IServiceCollection services, Act
// Override settings with user-provided settings
options?.Invoke(settings);

services.TryAddSingleton<IMessageBuilder, RequestDataBuilder>();
services.TryAddSingleton(settings);
services.TryAddSingleton(s => new RaygunClient(s.GetService<RaygunSettings>()!, s.GetService<IRaygunUserProvider>()!));
services.TryAddSingleton(s => new RaygunClient(s.GetRequiredService<RaygunSettings>(), s.GetRequiredService<IRaygunUserProvider>(), s.GetServices<IMessageBuilder>()));
services.TryAddSingleton<RaygunClientBase>(provider => provider.GetRequiredService<RaygunClient>());
services.AddHttpContextAccessor();

return services;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ public static async Task<RaygunRequestMessage> Build(HttpContext? context, Raygu
QueryString = GetQueryString(request, options),
Cookies = GetCookies(request, options),
RawData = GetRawData(request, options),
Headers = GetHeaders(request, options)
Headers = GetHeaders(request, options),
Form = await GetForm(request, options)
};

message.Form = await GetForm(request, options);


return message;
}

Expand Down Expand Up @@ -156,7 +155,7 @@ private static IList GetCookies(HttpRequest request, IRaygunHttpSettings options
// Filter out sensitive values.
rawData = StripSensitiveValues(rawData, options);

// Early escape if theres no data.
// Early escape if there's no data.
if (string.IsNullOrEmpty(rawData))
{
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#nullable enable

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;

Expand All @@ -8,19 +9,19 @@ namespace Mindscape.Raygun4Net.AspNetCore.Builders
// ReSharper disable once ClassNeverInstantiated.Global
public class RaygunAspNetCoreResponseMessageBuilder
{
public static RaygunResponseMessage Build(HttpContext? context)
public static Task<RaygunResponseMessage> Build(HttpContext? context, RaygunSettings _)
{
if (context == null)
{
return new RaygunResponseMessage();
return Task.FromResult(new RaygunResponseMessage());
}

var httpResponseFeature = context.Features.Get<IHttpResponseFeature>();
return new RaygunResponseMessage
return Task.FromResult(new RaygunResponseMessage
{
StatusCode = context.Response.StatusCode,
StatusDescription = httpResponseFeature?.ReasonPhrase
};
});
}
}
}
27 changes: 27 additions & 0 deletions Mindscape.Raygun4Net.AspNetCore/Builders/RequestDataBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

namespace Mindscape.Raygun4Net.AspNetCore.Builders;

public class RequestDataBuilder : IMessageBuilder
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly RaygunSettings _settings;

public RequestDataBuilder(IHttpContextAccessor httpContextAccessor, RaygunSettings settings)
{
_httpContextAccessor = httpContextAccessor;
_settings = settings;
}

public async Task<RaygunMessage> Apply(RaygunMessage message, Exception exception)
{
var ctx = _httpContextAccessor.HttpContext;

message.Details.Request = await RaygunAspNetCoreRequestMessageBuilder.Build(ctx, _settings);
message.Details.Response = await RaygunAspNetCoreResponseMessageBuilder.Build(ctx, _settings);

return message;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
Expand Down Expand Up @@ -30,8 +30,8 @@
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'netstandard2.1'">
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.2.0" />
</ItemGroup>

<ItemGroup>
Expand All @@ -44,7 +44,7 @@
<ProjectReference Include="..\Mindscape.Raygun4Net.NetCore.Common\Mindscape.Raygun4Net.NetCore.Common.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0' Or '$(TargetFramework)' == 'net7.0' Or '$(TargetFramework)' == 'net8.0'">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

Expand Down
11 changes: 8 additions & 3 deletions Mindscape.Raygun4Net.AspNetCore/RaygunClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ public RaygunClient(RaygunSettings settings, HttpClient httpClient) : base(setti
{
}

public RaygunClient(RaygunSettings settings, IRaygunUserProvider userProvider) : base(settings, userProvider)
public RaygunClient(RaygunSettings settings, IRaygunUserProvider userProvider) : base(settings, userProvider, [])
{
}

public RaygunClient(RaygunSettings settings, IRaygunUserProvider userProvider, IEnumerable<IMessageBuilder> messageBuilders) : base(settings, userProvider, messageBuilders)
{
}

public RaygunClient(RaygunSettings settings, HttpClient httpClient, IRaygunUserProvider userProvider) : base(settings, httpClient, userProvider)
public RaygunClient(RaygunSettings settings, HttpClient httpClient, IRaygunUserProvider userProvider) : base(settings, httpClient, userProvider, [])
{
}
// ReSharper restore MemberCanBeProtected.Global
Expand All @@ -58,6 +62,7 @@ protected override bool CanSend(RaygunMessage? message)

return !settings.ExcludedStatusCodes.Contains(message.Details.Response.StatusCode);
}

/// <summary>
/// Asynchronously transmits an exception to Raygun with optional Http Request data.
/// </summary>
Expand All @@ -72,7 +77,7 @@ public async Task SendInBackground(Exception exception, IList<string> tags, Http
// otherwise it will be disposed while we are using it on the other thread.
// BuildRequestMessage relies on ReadFormAsync, so we need to await it to ensure it's processed before continuing.
var currentRequestMessage = await RaygunAspNetCoreRequestMessageBuilder.Build(context, Settings.Value);
var currentResponseMessage = RaygunAspNetCoreResponseMessageBuilder.Build(context);
var currentResponseMessage = await RaygunAspNetCoreResponseMessageBuilder.Build(context, Settings.Value);

var exceptions = StripWrapperExceptions(exception);

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

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0;net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<AssemblyOriginatorKeyFile>..\Raygun.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<IsPackable>true</IsPackable>
<DebugType>embedded</DebugType>
</PropertyGroup>

<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
<None Include="..\LICENSE" Pack="true" PackagePath="\" />
<None Include="..\128x128-transparent.png" Pack="true" PackagePath="\" />
</ItemGroup>

<PropertyGroup>
<Description>.NET / .NETStandard - library for targeting .NET applications</Description>
<PackageId>Mindscape.Raygun4Net.Extensions.Logging</PackageId>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageIconUrl>https://app.raygun.com/Content/Images/nuget-icon.png</PackageIconUrl>
<PackageIcon>128x128-transparent.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageReleaseNotes>https://github.com/MindscapeHQ/raygun4net/blob/master/CHANGE-LOG.md</PackageReleaseNotes>
<PackageTags>crash;exception-handling;exception-reporting;exception-handler;unhandled-exceptions;debugging;debug;bug;bugs;exceptions;error;errors;crash-reporting;logging;mslogger</PackageTags>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Mindscape.Raygun4Net.NetCore.Common\Mindscape.Raygun4Net.NetCore.Common.csproj" />
</ItemGroup>

</Project>
104 changes: 104 additions & 0 deletions Mindscape.Raygun4Net.Extensions.Logging/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Mindscape.Raygun4Net.Extensions.Logging

This package provides a logging provider for the Raygun service. It allows you to send log messages to Raygun,
where they can be viewed and managed in the Raygun dashboard.

## Installation

Install the **Mindscape.Raygun4Net.Extensions.Logging** NuGet package into your project. You can either use the below dotnet CLI command, or the NuGet management GUI in the IDE you use.

```csharp
dotnet add package Mindscape.Raygun4Net.Extensions.Logging
```

You will need to install the **Mindscape.Raygun4Net** package as well, if you haven't already.

```csharp
// If you're using it in an ASP.NET Core application:
dotnet add package Mindscape.Raygun4Net.AspNetCore

// If you're using it in a .NET Core service application:
dotnet add package Mindscape.Raygun4Net.NetCore
```

## Usage

Add the Raygun provider to the logging configuration in your `Program.cs` or `Startup.cs` file.

### ASP.NET Core Application

```csharp
using Mindscape.Raygun4Net.AspNetCore;
using Mindscape.Raygun4Net.Extensions.Logging;

var builder = WebApplication.CreateBuilder(args);

// Registers the Raygun Client for AspNetCore
builder.Services.AddRaygun(settings =>
{
settings.ApiKey = "*your api key*";
});

// (Optional) Registers the Raygun User Provider
builder.Services.AddRaygunUserProvider();

// Registers the Raygun Logger for use in MS Logger
builder.Logging.AddRaygunLogger();

var app = builder.Build();
```

### .NET Core Service Application

```csharp
using Mindscape.Raygun4Net.Extensions.Logging;
using Mindscape.Raygun4Net.NetCore;

var builder = Host.CreateApplicationBuilder(args);

// Registers the Raygun Client for NetCore
builder.Services.AddRaygun(options =>
{
options.ApiKey = "*your api key*";
});

// Registers the Raygun Logger for use in MS Logger
builder.Logging.AddRaygunLogger();

var host = builder.Build();
```

## Configuration

When registering the Raygun provider, you can configure it with the following options:

* MinimumLogLevel: The minimum log level for messages to be sent to Raygun. Defaults to `LogLevel.Error`.
* OnlyLogExceptions: If false, logs without exceptions will be sent to Raygun. Defaults to `true`.

These can be set in code:

```csharp
builder.Logging.AddRaygunLogger(options: options =>
{
options.MinimumLogLevel = LogLevel.Information;
options.OnlyLogExceptions = false;
});
```

Or in the `appsettings.json` file:

```json
{
"RaygunSettings": {
"MinimumLogLevel": "Information",
"OnlyLogExceptions": false
}
}
```

## Notes

The category/contextSource set as a tag in Raygun.

When logs are sent without an exception, a Custom Data property is added to the Raygun message with the
key `NullException` with the value `Logged without exception` to identify Raygun Logs that have no exception.
Loading

0 comments on commit ce98721

Please sign in to comment.