Skip to content

Commit

Permalink
chore: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Joshua Searles committed Dec 25, 2023
1 parent e6adb21 commit cd9da68
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 64 deletions.
88 changes: 56 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,58 +1,82 @@
This project is licensed under the terms of the Apache license 2.0.
# Elmah.AspNetCore

# Using ElmahCore
ELMAH for Net.Standard and Net.Core (3.1, 5, 6)
ELMAH (Error Logging Middleware and Handlers) for ASP.NET Core. (dotnet 6, 7, 8)

Features include:

- Logging of unhandled exceptions
- Hooks to include handled exceptions and other contextual information
- Captures of logs

This is a fork of [ElmahCore](https://github.com/ElmahCore/ElmahCore). Credit goes to the owners and contributors of that library. This fork attempts to catch up the library with ongoing changes in the dotnet releases and follow established conventions and practices for integegration.

![alt text](https://github.com/ElmahCore/ElmahCore/raw/master/images/elmah-new-ui.png)

Add nuget package **elmahcore**
Add Nuget package **Elmah.AspNetCore**

## Simple usage
Startup.cs
```csharp
1) services.AddElmah() in ConfigureServices
2) app.UseElmah(); in Configure

*First*, install the _Elmah.AspNetCore_ [Nuget package](https://www.nuget.org/packages/Elmah.AspNetCore) into your app.

```shell
dotnet add package Elmah.AspNetCore
```
`app.UseElmah()` must be after initializing other exception handling middleware, such as (UseExceptionHandler, UseDeveloperExceptionPage, etc.)

Default elmah path `~/elmah`.
Program.cs

## Change URL path
```csharp
services.AddElmah(options => options.Path = "you_path_here")
var builder = WebApplication.CreateBuilder(args);

// This call wires up services needed by Elmah
builder.Services.AddElmah();

var app = builder.Build();

app.UseElmah();

app.MapElmah();
```

`app.UseElmah()` registers the Elmah middleware which will capture any uncaught errors in subsequent middleware. It is recommended that this is included before most other middleware. For best results, call after the built-in `UseExceptionHandler`.

`app.MapElmah()` registers the routes used to serve content for the Elmah UI. By default these will be under `/elmah`, but the method includes an overload which allows overriding the root path.

## Restrict access to the Elmah url

The `MapElmah()` registers the Elmah endpoints as regular endpoints in the application. As such, it will pick up the default authorization & authentication policies used by the application. Metadata can be applied to the returned endpoint builder to customize this.

```csharp
services.AddElmah(options =>
{
options.OnPermissionCheck = context => context.User.Identity.IsAuthenticated;
});
```
**Note:** `app.UseElmah();` needs to be after
```
app.UseAuthentication();
app.UseAuthorization();
app.UseElmah();
// allow all users to access UI
app.MapElmah().AllowAnonymous();

// require authenticated user
app.MapElmah().RequireAuthorization();
```
or the user will be redirected to the sign in screen even if he is authenticated.

> See dotnet documentation for [Authorization](https://learn.microsoft.com/en-us/aspnet/core/security/authorization/introduction?view=aspnetcore-8.0) for additional details.
## Change Error Log type
You can create your own error log, which will store errors anywhere.

```csharp
class MyErrorLog: ErrorLog
class MyErrorLog : ErrorLog
//implement ErrorLog
```
This ErrorLogs available in board:
- MemoryErrorLogstore errors in memory (by default)
- XmlFileErrorLogstore errors in XML files
- SqlErrorLog - store errors in MS SQL (add reference to [ElmahCore.Sql](https://www.nuget.org/packages/ElmahCore.Sql))
- MysqlErrorLog - store errors in MySQL (add reference to [ElmahCore.MySql](https://www.nuget.org/packages/ElmahCore.MySql))
- PgsqlErrorLog - store errors in PostgreSQL (add reference to [ElmahCore.Postgresql](https://www.nuget.org/packages/ElmahCore.Postgresql))

This ErrorLogs available in board:
- MemoryErrorLogstore errors in memory (by default)
- XmlFileErrorLogstore errors in XML files
- SqlErrorLog - store errors in MS SQL (add reference to [ElmahCore.Sql](https://www.nuget.org/packages/ElmahCore.Sql))
- MysqlErrorLog - store errors in MySQL (add reference to [ElmahCore.MySql](https://www.nuget.org/packages/ElmahCore.MySql))
- PgsqlErrorLog - store errors in PostgreSQL (add reference to [ElmahCore.Postgresql](https://www.nuget.org/packages/ElmahCore.Postgresql))

```csharp
services.AddElmah<XmlFileErrorLog>(options =>
services.AddElmah(elmah =>
{
options.LogPath = "~/log"; // OR options.LogPath = "с:\errors";
elmah.PersistToFile("~/log"; /* OR "с:\errors" */);
});
```

```csharp
services.AddElmah<SqlErrorLog>(options =>
{
Expand Down
4 changes: 2 additions & 2 deletions demos/ElmahCore.DemoCore6/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
builder.Services.AddRazorPages();

// Register and configure the services used by Elmah.
builder.Services.AddElmah(elmah =>
builder.Host.UseElmah((_, elmah) =>
{
elmah.Configure(options =>
{
Expand Down Expand Up @@ -44,7 +44,7 @@
// Adds elmah middleware - the placement of this call is important.
// All middleware after this has context captured and available to
// elmah.
app.UseElmah();
app.UseElmahMiddleware();

app.UseRouting();

Expand Down
4 changes: 2 additions & 2 deletions demos/ElmahCore.DemoCore7/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ private static void Main(string[] args)

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddElmah(elmah =>
builder.Host.UseElmah((_, elmah) =>
{
elmah.UseElmahExceptionPage();
});
Expand All @@ -22,7 +22,7 @@ private static void Main(string[] args)
}
app.UseStaticFiles();

app.UseElmah();
app.UseElmahMiddleware();
app.UseRouting();

app.UseAuthorization();
Expand Down
4 changes: 2 additions & 2 deletions demos/ElmahCore.DemoCore8/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ private static void Main(string[] args)
builder.Services.AddRazorPages();

// Default implementation - will keep an in-memory error log
builder.Services.AddElmah();
builder.Host.UseElmah();

var app = builder.Build();

app.UseExceptionHandler("/Error");
app.UseElmah();
app.UseElmahMiddleware();

app.UseHttpsRedirection();
app.UseStaticFiles();
Expand Down
28 changes: 26 additions & 2 deletions src/ElmahCore.Mvc/Configuration/ApplicationBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using ElmahCore.Mvc;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace ElmahCore;

public static class ApplicationBuilderExtensions
{
public static IApplicationBuilder UseElmah(this IApplicationBuilder app)
public static IApplicationBuilder UseElmahMiddleware(this IApplicationBuilder app)
{
var observer = app.ApplicationServices.GetService<ElmahDiagnosticObserver>();
if (observer is not null)
Expand All @@ -18,4 +20,26 @@ public static IApplicationBuilder UseElmah(this IApplicationBuilder app)
app.UseMiddleware<ErrorLogMiddleware>();
return app;
}

public static IHostBuilder UseElmah(this IHostBuilder host)
{
return host.UseElmah(null);
}

public static IHostBuilder UseElmah(this IHostBuilder host, Action<HostBuilderContext, ElmahBuilder>? configureElmah)
{
host.ConfigureServices((builderContext, services) =>
{
services.AddElmahCoreServices();

var elmah = new ElmahBuilder(services);

// Set as default because it is required - consumer can replace in configure delegate
elmah.PersistToMemory();

configureElmah?.Invoke(builderContext, elmah);
});

return host;
}
}
24 changes: 0 additions & 24 deletions src/ElmahCore.Mvc/Configuration/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,6 @@ namespace ElmahCore;

public static class ServiceCollectionExtensions
{
/// <summary>
/// Registers Elmah services and in-memory error logging.
/// </summary>
/// <param name="services">The service collection</param>
/// <returns></returns>
public static IServiceCollection AddElmah(this IServiceCollection services)
{
return services.AddElmah(builder => builder.PersistToMemory());
}

public static IServiceCollection AddElmah(this IServiceCollection services, Action<ElmahBuilder> configureElmah)
{
services.AddElmahCoreServices();

var elmah = new ElmahBuilder(services);

// Set as default because it is required - consumer can replace in configure delegate
elmah.PersistToMemory();

configureElmah(elmah);

return services;
}

public static IServiceCollection AddElmahCoreServices(this IServiceCollection services)
{
ArgumentNullException.ThrowIfNull(services);
Expand Down

0 comments on commit cd9da68

Please sign in to comment.