Skip to content
Open
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
66 changes: 43 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@

[![WatchDog](https://img.shields.io/badge/WatchDog-blueviolet)](https://github.com/IzyPro/WatchDog)
[![Version](https://img.shields.io/nuget/vpre/WatchDog.NET?color=orange)](https://www.nuget.org/packages/WatchDog.NET#versions-tab)
[![Downloads](https://img.shields.io/nuget/dt/WatchDog.NET?color=red)](https://www.nuget.org/packages/WatchDog.NET#versions-tab)
[![MIT License](https://img.shields.io/github/license/IzyPro/WatchDog?color=Green)](https://github.com/IzyPro/WatchDog/blob/main/LICENSE)
[![WatchDog](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Fgithub.com%2FIzyPro%2FWatchDog)](https://twitter.com/intent/tweet?hashtags=WatchDog&original_referer=https%3A%2F%2Fdeveloper.twitter.com%2F&ref_src=twsrc%5Etfw%7Ctwcamp%5Ebuttonembed%7Ctwterm%5Eshare%7Ctwgr%5E&related=twitterapi%2Ctwitter&text=Hello%2C%20world!%0DCheck%20out%20this%20awesome%20developer%20tool&url=https%3A%2F%2Fgithub.com%2FIzyPro%2FWatchDog&via=WatchDog)
[![WatchDog](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Fgithub.com%2FIzyPro%2FWatchDog)](https://twitter.com/intent/tweet?hashtags=WatchDog&original_referer=https%3A%2F%2Fdeveloper.twitter.com%2F&ref_src=twsrc%5Etfw%7Ctwcamp%5Ebuttonembed%7Ctwterm%5Eshare%7Ctwgr%5E&related=twitterapi%2Ctwitter&text=Hello%2C%20world!%0DCheck%20out%20this%20awesome%20developer%20tool&url=https%3A%2F%2Fgithub.com%2FIzyPro%2FWatchDog&via=HQWatchdog)

## Introduction

WatchDog is a Realtime Message, Event, HTTP (Request & Response) and Exception logger and viewer for ASP.Net Core Web Apps and APIs. It allows developers log and view messages, events, http requests made to their web application and also exception caught during runtime in their web applications, all in Realtime.
It leverages `SignalR` for real-time monitoring and `LiteDb` a Serverless MongoDB-like database with no configuration with the option of using your external MSSQL, MySQl or Postgres databases.
It leverages `SignalR` for real-time monitoring and `LiteDb` a Serverless MongoDB-like database with no configuration with the option of using your external databases (MSSQL, MySQl, Postgres, MongoDB).

# ![Request & Response Viewer](https://github.com/IzyPro/WatchDog/blob/main/watchlog.png)

## General Features

- RealTime HTTP Request and Response Logger
- RealTime Exception Logger
- RealTime HTTP Request, Response, and Exception Logger
- In-code message and event logging
- User Friendly Logger Views
- Search Option for HTTP and Exception Logs
Expand All @@ -26,17 +26,13 @@ It leverages `SignalR` for real-time monitoring and `LiteDb` a Serverless MongoD

## What's New

- Log Level (Info, Error, Warning)
- Extra AutoClear Durations (Hourly, Every6Hours, Every12Hours)
- Optimized Queries
- Cors Support
- Global Json Serializer Support
- Security Optimization
- Query Filters Fixes and Optimizations
- Package Assembly as DB Name Fix(MongoDB)

## Fixes
### Breaking Changes

- Postgres byte error
- OutOfRangeException
- Embedded DB Memory Release on Clear Logs
- SqlDriverOption is now DbDriverOption (>= 1.4.0)


## Support
Expand All @@ -47,12 +43,12 @@ It leverages `SignalR` for real-time monitoring and `LiteDb` a Serverless MongoD
Install via .NET CLI

```bash
dotnet add package WatchDog.NET --version 1.3.3
dotnet add package WatchDog.NET --version 1.4.10
```
Install via Package Manager

```bash
Install-Package WatchDog.NET --version 1.3.3
Install-Package WatchDog.NET --version 1.4.10
```


Expand Down Expand Up @@ -91,15 +87,15 @@ services.AddWatchDogServices(opt =>
});
```

### Setup Logging to External Db (MSSQL, MySQL & PostgreSQL) `Optional`
Add Database Connection String and Choose SqlDriver Option
### Setup Logging to External Db (MSSQL, MySQL, PostgreSQL & MongoDb) `Optional`
Add Database Connection String and Choose DbDriver Option

```c#
services.AddWatchDogServices(opt =>
{
opt.IsAutoClear = false;
opt.SetExternalDbConnString = "Server=localhost;Database=testDb;User Id=postgres;Password=root;";
opt.SqlDriverOption = WatchDogSqlDriverEnum.PostgreSql;
opt.DbDriverOption = WatchDogSqlDriverEnum.PostgreSql;
});
```

Expand All @@ -123,14 +119,14 @@ app.UseWatchDog(opt =>


>**NOTE**
> If your project uses authentication, then `app.UseWatchDog();` should come before app.UseRouting(), app.UseAuthentication(), app.UseAuthorization(), in that order
> If your project uses authentication, then `app.UseWatchDog();` should come after app.UseRouting(), app.UseAuthentication(), app.UseAuthorization(), in that order
<!--- >If your projects startup or program class contains app.UseMvc() or app.UseRouting() then app.UseWatchDog() should come after `Important`
>If your projects startup or program class contains app.UseEndpoints() then app.UseWatchDog() should come before `Important` -->

# ![Request and Response Sample Details](https://github.com/IzyPro/WatchDog/blob/main/requestLog.png)

#### Optional Configurations: `Optional`
- Blacklist: List of routes, paths or specific strings to be ignored (should be a comma separated string like below).
- Blacklist: List of routes, paths or endpoints to be ignored (should be a comma separated string like below).
- Serializer: If not default, specify the type of global json serializer/converter used
- CorsPolicy: Policy Name if project uses CORS

Expand All @@ -140,7 +136,7 @@ app.UseWatchDog(opt =>
opt.WatchPageUsername = "admin";
opt.WatchPagePassword = "Qwerty@123";
//Optional
opt.Blacklist = "Test/testPost, weatherforecast"; //Prevent logging for specified endpoints
opt.Blacklist = "Test/testPost, api/auth/login"; //Prevent logging for specified endpoints
opt.Serializer = WatchDogSerializerEnum.Newtonsoft; //If your project use a global json converter
opt.CorsPolicy = "MyCorsPolicy"
});
Expand Down Expand Up @@ -168,12 +164,32 @@ app.UseWatchDog(opt =>
```
### Log Messages/Events
```
WatchLogger.Log("...TestGet Started...");
WatchLogger.Log("...Test Log...");
WatchLogger.LogWarning(JsonConvert.Serialize(model));
WatchLogger.LogError(res.Content);
WatchLogger.LogError(res.Content, eventId: reference);
```

# ![In-code log messages](https://github.com/IzyPro/WatchDog/blob/main/in-code.png)

#### Sink Logs from ILogger
You can also sink logs from the .NET ILogger into WatchDog

For .NET 6 and above
```
builder.Logging.AddWatchDogLogger();
```
For .NET Core 3.1, configure logging and add `.AddWatchDogLogger()` to the `CreateHostBuilder` method of the `Program.cs` class
```
Host.CreateDefaultBuilder(args)
.ConfigureLogging( logging =>
{
logging.AddWatchDogLogger();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
```

### View Logs and Exception
Start your server and head to `/watchdog` to view the logs.
Expand All @@ -192,3 +208,7 @@ Alternatively, open an issue and we'll get to it as soon as we can.
Kelechi Onyekwere - [Github](https://github.com/Khelechy) [Twitter](https://twitter.com/khelechy1337)

Israel Ulelu - [Github](https://github.com/IzyPro) [Twitter](https://twitter.com/IzyPro_)



### [Official Documentation](https://watchdog-3.gitbook.io/watchdog)
8 changes: 7 additions & 1 deletion WatchDog.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WatchDogCompleteTestAPI", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WatchDogCompleteApiNet6", "WatchDogCompleteApiNet6\WatchDogCompleteApiNet6.csproj", "{B0EA2031-4C36-442F-BC82-618AB0A5DA16}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchDogCompleteMVCTest", "WatchDogCompleteMVCTest\WatchDogCompleteMVCTest.csproj", "{0DCCA957-8A36-405D-8092-233A3759732D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WatchDogCompleteMVCTest", "WatchDogCompleteMVCTest\WatchDogCompleteMVCTest.csproj", "{0DCCA957-8A36-405D-8092-233A3759732D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WatchDogCompleteApiNet7", "WatchDogCompleteApiNet7\WatchDogCompleteApiNet7.csproj", "{C0139FA9-FFAC-4E8B-B545-4F3761F91094}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -33,6 +35,10 @@ Global
{0DCCA957-8A36-405D-8092-233A3759732D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DCCA957-8A36-405D-8092-233A3759732D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DCCA957-8A36-405D-8092-233A3759732D}.Release|Any CPU.Build.0 = Release|Any CPU
{C0139FA9-FFAC-4E8B-B545-4F3761F91094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C0139FA9-FFAC-4E8B-B545-4F3761F91094}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C0139FA9-FFAC-4E8B-B545-4F3761F91094}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C0139FA9-FFAC-4E8B-B545-4F3761F91094}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
36 changes: 26 additions & 10 deletions WatchDog/WatchDog.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net6.0</TargetFrameworks>
<Description>WatchDog is a Realtime Message, Event, HTTP (Request &amp; Response) and Exception logger and viewer for ASP.Net Core Web Apps and APIs. It allows developers log and view messages, events, http requests made to their web application and also exception caught during runtime in their web applications, all in Realtime. It leverages SignalR for real-time monitoring and LiteDb a Serverless MongoDB-like database with no configuration with the option of using your external MSSQL, MySQl or Postgres databases.</Description>
<TargetFrameworks>netcoreapp3.1;net6.0;net7.0</TargetFrameworks>
<Description>WatchDog is a Realtime Message, Event, HTTP (Request &amp; Response) and Exception logger and viewer for ASP.Net Core Web Apps and APIs. It allows developers log and view messages, events, http requests made to their web application and also exception caught during runtime in their web applications, all in Realtime. It leverages SignalR for real-time monitoring and LiteDb a Serverless MongoDB-like database with no configuration with the option of using your external databases.</Description>
<PackageProjectUrl>https://github.com/IzyPro/WatchDog</PackageProjectUrl>
<PackageIcon>favicon.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
Expand All @@ -12,9 +12,13 @@
<Authors>Israel Ulelu, Kelechi Onyekwere</Authors>
<PackageId>WatchDog.NET</PackageId>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Version>1.3.3-rc</Version>
<PackageReleaseNotes>- Query Optimization, Log Level (Info, Error, Warning), [Fix] Postgres Byte error</PackageReleaseNotes>
<Version>1.4.10</Version>
<PackageReleaseNotes>- Security Optimization
- Query Filters Fixes and Optimizations
- Package Assembly as DB Name Fix(MongoDB)</PackageReleaseNotes>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<IncludeSymbols>True</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>

<ItemGroup>
Expand All @@ -38,24 +42,36 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.123" />
<PackageReference Include="LiteDB" Version="5.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.2.0" />
<PackageReference Include="MongoDB.Driver" Version="2.24.0" />
<PackageReference Include="MySql.Data" Version="8.3.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="LiteDB" Version="5.0.19" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' != 'net7.0'">
<PackageReference Include="Microsoft.Extensions.FileProviders.Abstractions" Version="3.1.22" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.22" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="3.1.22" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.22" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.2.0" />
<PackageReference Include="MySql.Data" Version="8.0.29" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Npgsql" Version="[5.0.0,5.0.10]" Condition="'$(TargetFramework)' == 'netcoreapp3.1'" />
<PackageReference Include="Npgsql" Version="6.0.4" Condition="'$(TargetFramework)' == 'net6.0'" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
<PackageReference Include="MongoDB.Driver" Version="2.18.0" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
<PackageReference Include="Microsoft.Extensions.FileProviders.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="7.0.14" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
<PackageReference Include="Npgsql" Version="7.0.6" />
</ItemGroup>
</Project>
34 changes: 27 additions & 7 deletions WatchDog/WatchDogExtension.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using System;
Expand Down Expand Up @@ -32,26 +33,44 @@ public static IServiceCollection AddWatchDogServices(this IServiceCollection ser
AutoClearModel.IsAutoClear = options.IsAutoClear;
AutoClearModel.ClearTimeSchedule = options.ClearTimeSchedule;
WatchDogExternalDbConfig.ConnectionString = options.SetExternalDbConnString;
WatchDogSqlDriverOption.SqlDriverOption = options.SqlDriverOption;
WatchDogDatabaseDriverOption.DatabaseDriverOption = options.DbDriverOption;
WatchDogExternalDbConfig.MongoDbName = string.IsNullOrEmpty(options.MongoDbName) ? Assembly.GetCallingAssembly().GetName().Name?.Replace('.', '_') + "_WatchDogDB" : options.MongoDbName;

if (!string.IsNullOrEmpty(WatchDogExternalDbConfig.ConnectionString) && WatchDogSqlDriverOption.SqlDriverOption == 0)
throw new WatchDogDBDriverException("Missing DB Driver Option: SQLDriverOption is required at .AddWatchDogServices()");
if (WatchDogSqlDriverOption.SqlDriverOption != 0 && string.IsNullOrEmpty(WatchDogExternalDbConfig.ConnectionString))
if (!string.IsNullOrEmpty(WatchDogExternalDbConfig.ConnectionString) && WatchDogDatabaseDriverOption.DatabaseDriverOption == 0)
throw new WatchDogDBDriverException("Missing DB Driver Option: DbDriverOption is required at .AddWatchDogServices()");
if (WatchDogDatabaseDriverOption.DatabaseDriverOption != 0 && string.IsNullOrEmpty(WatchDogExternalDbConfig.ConnectionString))
throw new WatchDogDatabaseException("Missing connection string.");

services.AddDistributedMemoryCache();

services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(5);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});

services.AddSignalR();
services.AddMvcCore(x =>
{
x.EnableEndpointRouting = false;
}).AddApplicationPart(typeof(WatchDogExtension).Assembly);

services.AddSingleton<IBroadcastHelper, BroadcastHelper>();
services.AddSingleton<IMemoryCache, MemoryCache>();

if (!string.IsNullOrEmpty(WatchDogExternalDbConfig.ConnectionString))
{
ExternalDbContext.Migrate();
if (WatchDogDatabaseDriverOption.DatabaseDriverOption == src.Enums.WatchDogDbDriverEnum.Mongo)
{
ExternalDbContext.MigrateNoSql();
}
else
{
ExternalDbContext.Migrate();
}
}


if (AutoClearModel.IsAutoClear)
services.AddHostedService<AutoLogClearerBackgroundService>();

Expand All @@ -60,7 +79,6 @@ public static IServiceCollection AddWatchDogServices(this IServiceCollection ser

public static IApplicationBuilder UseWatchDogExceptionLogger(this IApplicationBuilder builder)
{

return builder.UseMiddleware<src.WatchDogExceptionLogger>();
}

Expand Down Expand Up @@ -95,6 +113,8 @@ public static IApplicationBuilder UseWatchDog(this IApplicationBuilder app, Acti

app.UseAuthorization();

app.UseSession();

if (!string.IsNullOrEmpty(options.CorsPolicy))
app.UseCors(options.CorsPolicy);

Expand Down
17 changes: 17 additions & 0 deletions WatchDog/WatchDogLoggerExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace WatchDog
{
public static class WatchDogLoggerExtension
{
//
// Summary:
// Uses built in ILogger. Note: caller info has an overhead of about <= 4ms
public static ILoggingBuilder AddWatchDogLogger(this ILoggingBuilder builder, bool logCallerInfo = true, bool log = true)
{
builder.Services.AddSingleton<ILoggerProvider, WatchDogLoggerProvider>(_ => new WatchDogLoggerProvider(log, logCallerInfo));
return builder;
}
}
}
Loading