I have a Blazor Server-Side app running with .NET 5.0 and I'm trying to switch from ElmahCore to Exceptional.
But I can't get it to log Blazor exceptions.
When I throw an exception in a MVC controller it gets logged, but if I throw one in e.g. OnAfterRenderAsync nothing gets logged.
What do I need to configure to get Blazor exceptions logged with Exceptional?
Also in ElmahCore I could use ElmahExtensions.RiseError(exception); to log an exception I catched/handled in code but still wanted to show up in the error-log. Is there something similar for Exceptional?
I configured Exceptional with the default configuration from HERE.
I downloaded the package first:
Install-Package StackExchange.Exceptional.AspNetCore -Version 2.2.17
Next, add the Exceptional tag configuration to the appsettings.json file, which contains the connection string used to store errors in the database:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"Exceptional": {
"Store": {
"ApplicationName": "Test",
"Type": "SQL",
"ConnectionString": "Your Db"
}
}
}
Registering AddExceptional service in ConfigureServices Method:
services.AddExceptional(Configuration.GetSection("Exceptional"), settings =>
{
settings.UseExceptionalPageOnThrow = HostingEnvironment.IsDevelopment();
});
After adding ConfigureServices next, we are going to add “UseExceptional” middleware in Configure method.
Adding app.UseExceptional(); Middleware in Configure method to handle errors:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseExceptional();
.....
}
Then I wrote a throw exception throw new NotImplementedException();
Then you can see the record:
According to the article you provided, it should be done.Which side did you have a problem with?
Related
I have the following in appsettings.json for Serilog:
"Serilog": {
"Using": [],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft.AspNetCore": "Warning",
"System": "Warning" //Amik ezekből a névterekből jönnek is Informationok lesznek.
}
},
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
"WriteTo": [
{ "Name": "Console" }
]
},
I tried to add Serilog for my bootstrap app, but nothing worked well :(.
It is not logging to the console.
I have the following settings in appsettings.json for Serilog. I tried to add Serilog for my bootstrap app, but nothing worked well
It is not logging into console.
Well, its not quite clear if you have followed all the steps accordingly. Based on your shared appsettings.json it appreared that your configuration is partially correct. If you don't define anything inside using block its better to ommit that. In addition to this, you haven't defined your "Args" parameter where need to log what I mean is the path. Furthermore, whether you have install the required nuget package and included the required code snippet in your program.cs file
Therefore, you can follow the steps below to implement it correctly.
Prerequisite:
Serilog Nuget Package
appsettings.json configuration
1. Serilog Nuget Package
To configure Serilog for asp.net core reagrdless of its version, you need to following package in your application reference.
serilog.aspnetcore, serilog.aspnetcore and serilog.expressions
You can add from your Nuget Package Manager as following:
Once all the required package installed accordingly it should look like below:
In addititon, you even can using nuget package manager console command which are like below:
dotnet add package serilog.aspnetcore
dotnet add package serilog.sinks.seq
dotnet add package serilog.expressions
2. appsettings.json configuration
Please replace your appsettings.json file as following for serilog.
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"path": "./logs/log-.txt",
"rollingInterval": "Day"
}
}
]
},
"AllowedHosts": "*"
}
Program.cs file
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console().CreateBootstrapLogger();
Log.Information("Staring up logging");
try
{
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((context, logConfig) => logConfig
.WriteTo.Console()
.ReadFrom.Configuration(context.Configuration));
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseSerilogRequestLogging();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex,"Unhandled Exception");
}
finally
{
Log.Information("Log Complete");
Log.CloseAndFlush();
}
Output:
Note: If you would like to know more details about logging in asp.net core you could check the official document here
We work in .NET 6 and want to log all incoming requests. We plan to allow this primarily in DEV and TEST environments but potentially and temporarily also in PROD.
The new HttpLogger sounds like a perfect match. But it will output to the standard ILogger which in our case is Elastic. From GDPR reasons we want to avoid that where potentially sensitive data will be exposed in an uncontrolled way.
Does anyone have another solution:
Redirect messages from HttpLogger to other storage
Create custom middleware to be able to sniff requests and output to custom storage
I found this interesting post on reading the body twice but was not able to make it work: https://codetalk.in/posts/2022/01/04/read-request-body-multiple-times-in-asp-dot-net-core
You can do that just by configuration, for example in production app settings, disable HTTP logging for Elastic and enable it for file logger, something like this (really depends on your loggers and configurations):
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
},
"Elastic": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "None"
}
},
"File":
{
"IncludeScopes": true,
"LogLevel": {
"Default": "None",
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
}
}
}
}
To be more restrictive, configure HttpLoggingOptions for production to not log some fields for example.
I created the following function:
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace FunctionApp1
{
public class DINotWorking
{
ILogger _log;
public DINotWorking(ILogger<DINotWorking> log)
{
_log = log;
_log.LogInformation("I can in constructor");
}
[FunctionName("HttpTrg1")]
public IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,ILogger logger1)
{
_log.LogInformation("Contructor injected Log works !");
logger1.LogInformation("Function injected log Work!");
string name = req.Query["name"];
string responseMessage = $"Hello, '{name}'. This HTTP triggered function executed successfully.";
return new OkObjectResult(responseMessage);
}
}
}
host.json
{
"version": "2.0",
"logging": {
"fileLoggingMode": "always",
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
},
"logLevel": {
"FunctionApp1.DINotWorking": "Information",
"FunctionApp1.DINotWorking.User": "Information"
}
}
}
The function has two loggers available in it:
_log is a dependency injected class member with the type ILogger<DINotWorking>.
logger1 is dependency injected function parameter with the type ILogger
I am going to reference them as #1 and #2 going forward.
They behave differently in different environments:
local development - Azure Function tools
In local development environment in azure function tools both #1 and #2 behave identical:
Deployed - Azure Function portal - Application Insight
In Azure Function portal, they both log to Application Insight. Means both #1 and #2 behave identical:
Deployed - Azure Function portal - Filesystem Logs
In Azure Function portal, #1 log entries do not show in the Filesystem logs. Why?
Question: Why #1 log entries do not show in Filesystem logs?
Azure function logging is a black box to me.
Obviously, there is a difference between constructor injected ILogger and Function injected ILogger.
Does this have anything to do with Log Categories explained here
How can I see the difference in my code?
How can I make them behave the same in all environment in the host.json?
Update #1
Per #Hari Krishna suggestion, I've changed the host.json file to the following.
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
},
"fileLoggingMode": "always",
"logLevel": {
"FunctionApp1.HttpTrg1": "Information",
"FunctionApp1.HttpTrg1.User": "Information"
}
}
}
The issue is still persisting (outstanding).
How can I diagnose this issue? Is there anyway the hosting tells me why it is ignoring constructor injected log entries from file system logs?
AFAIK,
In Azure Function portal, #1 log entries do not show in the Filesystem logs. Why?
By default, FileSystem Logs shows the Function execution logs like executing, executed, and error.
We can configure the host.json file to get all the logs (App Insights logs + File System Logs) in File System Logs because everything should be configured whatever the logs you want to push to Application Insights:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
},
"fileLoggingMode": "always",
"logLevel": {
"Function.HttpTrigger1": "Information",
"default": "None"
}
}
}
I have configured the fileLoggingMode in host.json to log both (application & function). Then the output is:
File System Logs:
App Insights Logs:
For more information on fileLoggingMode attributes, refer to this MS Doc and GitHub Open Informative Ticket.
Updated Answer:
Please Check that I have uploaded my code on my GitHub Repository by writing the similar code as yours and shown how to configure the Host.json as well as Function Code.
Results:
Locally I can see both the logs:
After deploying to Azure Function App, App Insights Logs were:
Also, the File System Logs were:
I am investigating the best way to implement logging for my Service Fabric Stateless API and have been somewhat overwhelmed by the varying different solutions for what appears to be a relatively simple requirement.
I have implemented logging using the WebHostBuilder().ConfigureLogging and have successfully logged my trace messages to the Debug window and via Serilog.Extensions.Logging.File I have also managed to dump this log to a file, this all being controlled via a #if DEBUG directive and this I was happy with.
Then I needed to configure what would happen when deployed to a cluster within Azure and this is when I became overwhelmed!!!
I thought that I could register ServiceEventSource type logger in the same manner as I did with AddDebug however it was not this simple.
So I have managed to get my logs to appear within the diagnostic window using the ServiceEventSource.Current.Message but these logs are not integrated within the ASP.NET logging framework :/
My continued investigation has led me to understand that Service Fabric logging should be directed towards Application Insights albeit many, many articles having varying degrees of detail and applicability to the latest framework.
My current thinking is that I need to remove the ASP.NET logging and implement something such as EventFlow to allow my trace messages to be generated and subsequently piped through to Application Insights for interrogation at a later date, is my thinking correct??
Or am I currently going off at a tangent?
UPDATE 15/05/2019
After deploying this to Azure Service Fabric the log files were not populated, this appears to be an incompatibility between the Serilog.Sinks.AzureBlobStorage NUGET package and the .NET Core version 2.2.0 that my project was targeting.
I have posted a ticket on the GitHub page and await a response, in the short term you can download the source code and migrate the project to a Microsoft.NETCore.App 2.2.0 project and directly reference this and everything works perfectly.
ORIGINAL ANSWER
I seem to do this quite a lot, answering my own question but here goes again. It's taken me a day or two to get to the bottom of this so I thought I would share my findings and solution with the community in-case it might help somebody else in the future and/or somebody might have something to add or even contradict me which I'd welcome any input.
My development environment is as follows: -
Microsoft Visual Studio 15.9.11
Windows 10 Professional
SDK: Microsoft.NETCore.App 2.2.0
I created a new Service Fabric Stateless Service the purpose of this service is to provide RESTful endpoints to a Angular 7 front end web application.
My requirement was to provide logging information in both my development environment via the Debug window and to also provide similar logging information whilst my apps are being hosted within a Service Fabric Cluster on Azure.
NUGET Package Installations
Microsoft.Extensions.Logging (2.2.0)
Serilog.AspNetCore (2.1.1)
Serilog.Enrichers.Environment (2.1.3)
Serilog.Settings.Configuration (3.0.1)
Serilog.Sinks.Debug (1.0.1)
Serilog.Sinks.AzureBlobStorage (1.3.0)
Controlling Development & Production Environments
I control the development & production environments using the DEBUG pre-processor directive to include either the appsettings.json or appsettings.Development.json file.
My appSettings.Development.json file is like this: -
{
"AppSettings": {
// My app settings not applicable to this
},
"Serilog": {
"Using": [ "Serilog.Sinks.Debug" ],
"MinimumLevel": {
"Default": "Verbose",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {MachineName} {Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": ["WithMachineName"]
}
}
My appSettings.json file is like this: -
{
"AppSettings": {
// My app settings not applicable to this
},
"Serilog": {
"Using": [ "Serilog.Sinks.AzureBlobStorage" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "AzureBlobStorage",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {MachineName} {Level:u3}] {Message:lj}{NewLine}{Exception}",
"connectionString": "[Connection String]",
"storageContainerName": "app",
"storageFileName": "{yyyy}-{MM}-{dd}.log"
}
}
],
"Enrich": [ "WithMachineName" ]
}
}
As you can see from the above settings files I output to the Debug window when in development and I have chosen to output to Azure Blob Storage when deployed to a Service Fabric Cluster in Azure.
To implement the Serilog logging simple review my Stateless Service class implementation below, which shows how to toggle the two different appSettings.json files dependent upon the environment and also how the Serilog logger is inserted into the dependency injection system via the use of the UseSerilog extension method.
using System.Collections.Generic;
using System.Fabric;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ServiceFabric.Services.Communication.AspNetCore;
using Microsoft.ServiceFabric.Services.Communication.Runtime;
using Microsoft.ServiceFabric.Services.Runtime;
using Serilog;
namespace Caboodal.Manatee.ServiceFabric.Api.Identity
{
internal sealed class Identity : StatelessService
{
public Identity(StatelessServiceContext context)
: base(context)
{
}
private string AppSettingsFilename
{
get
{
#if DEBUG
return "appsettings.Development.json";
#else
return "appsettings.json";
#endif
}
}
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
var appSettings = GetAppSettings();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(appSettings)
.CreateLogger();
return new[]
{
new ServiceInstanceListener(
serviceContext =>
new KestrelCommunicationListener(
serviceContext,
"ServiceEndpoint",
(url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder()
.UseKestrel()
.ConfigureAppConfiguration(
(builderContext, config) =>
{
config.AddJsonFile(AppSettingsFilename, false, true);
})
.ConfigureServices(
services => services
.AddSingleton(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseSerilog()
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
}))
};
}
private IConfigurationRoot GetAppSettings()
{
return new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(AppSettingsFilename)
.Build();
}
}
}
Using the Logger within a controller
Because the ILogger instance is configured as a Dependency Injected instance it can simply be accessed within your Controller classes like any other dependency e.g.
[Authorize]
[ApiController]
[Route("[controller]")]
public class UserController : ApiController
{
private readonly IUserService _userService;
private readonly ILogger<UserController> _logger;
public UserController(IUserService userService, ILogger<UserController> logger)
{
_userService = userService;
_logger = logger;
}
[AllowAnonymous]
[HttpPost("authenticate")]
public IActionResult Authenticate([FromBody] DtoAuthenticateRequest request)
{
// Adding log entries
_logger.Log(LogLevel.Debug, "Here is a log entry");
// Some code in here
return Ok(response);
}
}
I got very sidetracked with the ServiceEventSource.cs class but with the usage of Serilog I have now ignored this aspect of the project template.
If you wish to output your logs to other data consumers or simply into different formats then just review the Serilog website here for a complete list of the Sinks available, with Application Insights being one of the many.
I created a very simple Console app which is supposed to log the messages to the AWS Logs but although the app runs I can't find any log on AWS.
I think publishing the app code does not make sense: I presume it's ok and it does not throw any exception.
I think the problem is located in the AWS settings. This is what I did in AWS:
created some role , not sure why but did it almost close to what aws poor and messy documentation says. So the role is created, not exactly as it was supposed in the "documentation" but it contains the required permissions for the logs. Why I created it? - I don't have a clue - my app does not use it!
Created the Log Group - ok, this parameter is what I put into the config of my app
Not sure I need t create the log stream, but ok, I created it, but when I click on it it says "No events found." and "It appears you have not installed a CloudWatch Logs agent .."
Why do I need some agent? what is it? how to install? - absolutely not clear and pointing to the poor aws "documentation" is useless.
I guess these are the major things done in the AWS but..still no result - nothing works, I cant see the logs.
Searched for the answer in google, youtube, etc - no result.
Found some code which is similar to mine but it's no enought - it seems there are some settings required to be done on AWS.
What's wrong?
You have two options:
Write log files to disk and use CloudWatch Agent to submit these logs to CloudWatch: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/QuickStartWindows2016.html
With this option you don't need to configure anything related to AWS in the program, but you have to install and configure the Agent.
Use AWS.Logger NuGet package and configure it to send the logs to CloudWatch, in this case you don't need to use the Agent: https://github.com/aws/aws-logging-dotnet/tree/master/samples/AspNetCore
With this option you must create AWS API user with CloudWatch Log writing permission and put this user credentials into AWS.Logger configuration. Show the configuring code you used if you need an advice on this.
I had a similar problem, which turned out to be more config-related.
Firstly, make sure that you have AWS Toolkit for Visual Studio installed and set up with the appropriate user. I use an IAM User with the correct policy permissions to read and write Cloudwatch logs.
Here's a copy of my basic console test that works correctly:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace Runner
{
class Program
{
public static async Task Main(string[] args)
{
var services = ConfigureServices(new ServiceCollection())
.BuildServiceProvider();
await services.GetService<App>().RunAsync();
}
private static IServiceCollection ConfigureServices(IServiceCollection services)
{
var configuration = ConfigurationFactory.GetConfiguration();
services
.AddSingleton(configuration)
.AddLogging(builder =>
{
var config = configuration.GetSection("Logging");
builder
.AddConfiguration(configuration.GetSection("Logging"))
.AddConsole()
.AddDebug()
.AddAWSProvider(configuration.GetAWSLoggingConfigSection().Config);
})
// add app
services.AddTransient<App>();
return services;
}
}
public class App
{
private ILogger<App> Logger;
public App(ILogger<App> logger)
{
Logger = logger;
}
public async Task RunAsync()
{
try
{
Logger.LogTrace("LogTrace", "{\"Test\":1}");
Logger.LogInformation("LogInformation", "{\"Test\":2}");
Logger.LogWarning("LogWarning", "{\"Test\":3}");
Logger.LogDebug("LogDebug", "{\"Test\":4}");
Logger.LogError("LogError", "{\"Test\":5}");
Logger.LogCritical("LogCritical", "{\"Test\":6}");
Thread.Sleep(3000);
Debugger.Break();
}
catch (Exception ex)
{
throw;
}
}
}
}
And my appsettings.json file is:
{
"Logging": {
"Region": "eu-west-1",
"LogGroup": "/dev/runner",
"IncludeLogLevel": true,
"IncludeCategory": true,
"IncludeNewline": true,
"IncludeException": true,
"IncludeEventId": false,
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
},
"Console": {
"LogLevel": {
"Default": "Error",
"System": "Information",
"Microsoft": "Information"
}
},
"Debug": {
"LogLevel": {
"Default": "Trace",
"System": "Information",
"Microsoft": "Information"
}
}
}
}
The Thread.Sleep is to allow the console logger to catch up with itself - if you just break you often don't see anything.
Similarly, if you quit the program executing at the breakpoint the AWS logger won't flush its buffers to Cloudwatch (it will just create the logstream and leave it empty), so let the program run to completion to populate the logstream itself.