diff --git a/Directory.Build.props b/Directory.Build.props index 56d320a..14ca76e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,5 +4,6 @@ Tudor Stanciu STA NDB + STA NDB \ No newline at end of file diff --git a/NDB.Logging.Api/NDB.Logging.Api.csproj b/NDB.Logging.Api/NDB.Logging.Api.csproj new file mode 100644 index 0000000..dc2ee36 --- /dev/null +++ b/NDB.Logging.Api/NDB.Logging.Api.csproj @@ -0,0 +1,16 @@ + + + + netstandard2.0 + https://dev.azure.com/tstanciu94/NDB + .NET standard library for logging stuff in an API. + https://dev.azure.com/tstanciu94/_git/NDB + .NET standard library for logging stuff in an API. + NDB NDB.Logging + + + + + + + diff --git a/NDB.Logging.Api/RequestLoggingAttribute.cs b/NDB.Logging.Api/RequestLoggingAttribute.cs new file mode 100644 index 0000000..435ec16 --- /dev/null +++ b/NDB.Logging.Api/RequestLoggingAttribute.cs @@ -0,0 +1,66 @@ +using Microsoft.AspNetCore.Http.Internal; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Logging; +using System; +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Threading.Tasks; + +namespace NDB.Logging.Api +{ + public class RequestLoggingAttribute : ActionFilterAttribute + { + private readonly ILogger _logger; + + public RequestLoggingAttribute(ILogger logger) + { + _logger = logger; + } + + public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + var stopWatch = new Stopwatch(); + stopWatch.Start(); + + var uid = Guid.NewGuid(); + var request = ((DefaultHttpRequest)((ControllerBase)context.Controller).Request); + var requestUrl = request.Path; + + if (request.QueryString != null && request.QueryString.HasValue) + requestUrl += request.QueryString.ToString(); + + var logContent = $"Start request {uid} for method {requestUrl}"; + + if (request.Method == WebRequestMethods.Http.Post) + { + var requestBody = await GetRequestBody(request); + logContent += $" with body {requestBody}"; + } + + _logger.LogInformation(logContent); + + var resultContext = await next(); + stopWatch.Stop(); + + if (resultContext.Exception != null) + _logger.LogError(resultContext.Exception, $"Request {uid} for method {requestUrl} failed - {resultContext.Exception.Message}"); + + _logger.LogInformation($"End request {uid} for method {requestUrl}"); + _logger.LogDebug($"Request {uid} duration: {stopWatch.ElapsedMilliseconds:N0} ms"); + } + + private async Task GetRequestBody(DefaultHttpRequest request) + { + if (request.ContentLength == 0) + return "-"; + + var body = new StreamReader(request.Body); + body.BaseStream.Seek(0, SeekOrigin.Begin); + var bodyStr = await body.ReadToEndAsync(); + + return bodyStr; + } + } +} \ No newline at end of file diff --git a/NDB.sln b/NDB.sln index 7a9db12..efdc679 100644 --- a/NDB.sln +++ b/NDB.sln @@ -15,7 +15,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NDB.Infrastructure.PublicIP", "NDB.Infrastructure.PublicIP\NDB.Infrastructure.PublicIP.csproj", "{FCB29735-E36A-442A-9307-F124782B8BB8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NDB.Testing.App", "NDB.Testing.App\NDB.Testing.App.csproj", "{656CCE38-90C3-4D19-9D07-EF1F0410CFDC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NDB.Testing.App", "NDB.Testing.App\NDB.Testing.App.csproj", "{656CCE38-90C3-4D19-9D07-EF1F0410CFDC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NDB.Logging.Api", "NDB.Logging.Api\NDB.Logging.Api.csproj", "{74E221BE-C097-468B-93E4-AAE1B2173C49}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -35,6 +37,10 @@ Global {656CCE38-90C3-4D19-9D07-EF1F0410CFDC}.Debug|Any CPU.Build.0 = Debug|Any CPU {656CCE38-90C3-4D19-9D07-EF1F0410CFDC}.Release|Any CPU.ActiveCfg = Release|Any CPU {656CCE38-90C3-4D19-9D07-EF1F0410CFDC}.Release|Any CPU.Build.0 = Release|Any CPU + {74E221BE-C097-468B-93E4-AAE1B2173C49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74E221BE-C097-468B-93E4-AAE1B2173C49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74E221BE-C097-468B-93E4-AAE1B2173C49}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74E221BE-C097-468B-93E4-AAE1B2173C49}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE