Serilog LoggerConfiguration equivalent of AddFilter with log level - serilog

My current code is like this:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) {
return WebHost.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) => {
logging.AddFilter("Microsoft.AspNetCore.SignalR", LogLevel.Debug);
logging.AddFilter("Microsoft.AspNetCore.Http.Connections", LogLevel.Debug);
})
.UseSerilog(Log.Logger)
I now get deprication error:
warning CS0618: 'SerilogWebHostBuilderExtensions.UseSerilog(IWebHostBuilder, ILogger, bool, LoggerProviderCollection)' is obsolete: 'Prefer UseSerilog() on IHostBuilder'
My understanding is I need to now create the logger like this:
public static void Main(string[] args) {
Log.Logger = new LoggerConfiguration()
// set filters ???
.CreateLogger();
and then just have UseSerilog() in CreateWebHostBuilder
But how do I set equivalent filters in LoggerConfiguration ? I can't seem to find relevant examples.

That error is telling you to move away from Microsoft.AspNetCore.Hosting.IWebHostBuilder to Microsoft.Extensions.Hosting.IHostBuilder.
IWebHostBuilder is for .NET Core 2, see the documentation.
Your code would look like below.
(Also renamed that method.)
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) => {
logging.AddFilter("Microsoft.AspNetCore.SignalR", LogLevel.Debug);
logging.AddFilter("Microsoft.AspNetCore.Http.Connections", LogLevel.Debug);
})
.UseSerilog(Log.Logger);
}
If you can't migrate, you'll have to pick an older version of Serilog.

Related

C# .NET Core 3.1 Serilog usage in BackgroundService

Following a tutorial on how to use Serilog I read the settings from an appsettings.json file - and all below works well, when things are simple:
Main program (in simple MVP version):
public static void Main(string[] args)
{
//Read Configuration from appSettings
var config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
//Initialize Logger
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(config).CreateLogger();
try
{
Log.Information("Starting up the service");
CreateHostBuilder(args).Build().Run();
....
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
})
.UseSerilog();
Then the class with the BackgroundService:
....
using Microsoft.Extensions.Logging;//and not Serilog!!
public class Worker : BackgroundService
{
private readonly ILogger _logger;
....
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
---------------------SIMPLE THINGS FOR ME ENDS HERE :-) ----------------------------------
Now, I want to build it up to a "real" program from this first MVP - placing function in seperate classes according to SOLID principles.For instance my first class is a ConfigurationCollector collecting all relevant paramters from the appsettings.json file that I place in a seperat class. The class works and does it jobs - but I want logging to work - and I try to use the allready configured Serilog logger used accross class (just as I did with ILogger, so that the Worker object creates a new ConfigurationCollector class like
public Worker(ILogger<Worker> logger)
{
_logger = logger;
_configCollector = new ConfigCollector(logger);
}
I know that logger is now a type of
ILogger<ConfigCollector>
which is not
ILogger<Worker>
But how do I inject the original Serilog from the initiation of the service into each class used, such that the objects are shown properly in the logs?
public class ConfigCollector
{
private readonly ILogger<ConfigCollector> _logger;
....
public ConfigCollector(ILogger<ConfigCollector> logger)
{
_logger = logger;
}
.NET 6 Background service
.UseSerilog((builder, loggerConfig) =>
loggerConfig.ReadFrom.Configuration(builder.Configuration))
.Build();

Read Environment Variables in generic host without prefix (.NET)

I want to read my custom environment variables in .NET 5 or .NET 6. I have some problems. I can only read environment variables with the DOTNET_ and ASPNETCORE_ prefixes:
For example, I can't read that MyKey=MyValue:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostContext,configuration) =>
{
string myKey = hostContext.Configuration["MyKey"];
configuration.AddJsonFile($"Airlines/{myKey}.json");
})
.ConfigureServices((hostContext, services) =>
{
services.AddRabbitMQ();
services.AddSingleton<NiraAvailableFlightsConsumer>();
services.AddOptions<AirlineOptions>()
.Bind(hostContext.Configuration);
});
The documentation for the default builder says:
Loads host configuration from:
Environment variables prefixed with DOTNET_.
So your variable is not read as part of the host context configuration. You can tell the builder to load all environment variables by adding the ConfigureHostConfiguration call to your startup:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureHostConfiguration(config =>
{
config.AddEnvironmentVariables();
})
.ConfigureAppConfiguration((hostContext, configuration) =>
{
string myKey = hostContext.Configuration["MyKey"];
configuration.AddJsonFile($"Airlines/{myKey}.json");
})
.ConfigureServices((hostContext, services) =>
{
....
});

How to inject and use Serilog (Ilogger) when web-api startup

I'm developing a .NET core 3.1 Console application (web-api).
I use a Serilog service (it is basically using the Microsoft.Extensions.Logging).
The Serilog is injected and can be used in the FW Controllers methods.
Now - I need something a little bit different - Whenever the system is starting up (after being down) I need to make an http post request - you can see it when executing the ConnectionInitiator.Initiate(), in the startup method. In that same scope (method\class) - I need to use the logger, in order to log some data. Now - If the request would be through the controller - the logger, would be available (by the DI).
To make a long story short - I need somehow to inject the Ilogger to the class or to make it available in some other way. I've tried use the logger in the startUp, but this seems to be impossible (since .net core 3.0 - if I understand correctly)
See my code:
Program.cs:
public class Program
{
public static void Main(string[] args)
{
var loggerConfig = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
//Reading the appconfig.json
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(loggerConfig).CreateLogger();
try
{
Log.Information("System Started up");
CreateWebHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "THE APPLICATION FAILED TO START UP");
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args).ConfigureLogging((context, logging) =>
{
logging.ClearProviders();
}).UseSerilog().UseStartup<Startup>();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
StartUp.cs
public class Startup
{
public Startup(IConfiguration configuration/*, Microsoft.Extensions.Logging.ILogger logger*/)
{
Configuration = configuration;
ConnectionInitiator.Initiate(configuration/*, logger*/);
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddControllers();
services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(dispose: true));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().SetIsOriginAllowed((host) => true).AllowCredentials());
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
ConnectionInitiator.cs:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
namespace AAA.BL
{
public static class ConnectionInitiator
{
private static readonly object threadlock = new object();
private static MyConfig myConfig;
private static ILogger ilogger;
/*
public ConnectionInitiator(ILogger _logger)
{
ilogger = _logger;
}
*/
public static void/*async Task*/ Initiate(IConfiguration configuration/*, ILogger ilogger*/)
{
HttpRequester httpRequester = new HttpRequester();
if (myConfig == null)
{
myConfig = new myConfig(configuration);
}
IssueOTPResponse response = /*await*/ httpRequester.PostSomething(myConfig, ilogger).Result; //Double check thread safe singleton implementation
if (response.ststuacode != 200)
{
ilogger.logcritical($"critical error when initiate connection (connectioninitiator): {response.statusdescription}");
}
}
}
}
It seems like the answer is much simpler that I expected - By using the Serilog and was added as a service in the Configure method - It can be reached globally (in every place of the namepsace) by using the static class Log and its static method Logger, for example:
Log.Logger.Information("XXXXX");

.net core 3 access database in startup - services.buildserviceprovider warning

i am using the following code in configureservices in startup.cs in netcore 3
Can someone show how i can do this a better way, how do i inject it into configure method? I need to access the database before dependency injection has resolved it but buildservices isnt recommended.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<bookingsstrathContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MyEntities2")));
services.AddScoped<IMyAccountService, MyAccountService>();
var sp = services.BuildServiceProvider();
// Resolve the services from the service provider
var _myAccountService = sp.GetService<IMyAccountService>();
//get the local role from the local database
if (_myAccountService.IsUserInRole(context.Principal.GetUserGraphSamAccountName(), "Administrator"))
{
//myIdentity.AddClaim(new Claim(ClaimTypes.Role, "Administrator"));
context.Principal.AddUserSystemRole("Administrator");
}
}
You can add your account service in program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(serviceCollection =>
serviceCollection.AddScoped<IMyAccountService, MyAccountService>())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
and then you can use it in startup.cs
private readonly IMyAccountService _myAccountService;
public Startup(IConfiguration configuration, IMyAccountService AccountService)
{
Configuration = configuration;
_myAccountService = AccountService
}

Hangfire with Ninject using InRequestScope

I have installed the Hangfire.Ninject package to an ASP MVC 5 application so that I can run some background jobs.
I've read through the documentation but I'm baffled as to how to implement it.
My existing configuration uses InRequestScope for my IUnitOfwork class to ensure only a single instance is instantiated per HTTP request as follows:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
}
To use ninject with hangfire having followed the documentation I have updated the configuration as follows in my ninjectwebcommon.cs class:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
GlobalConfiguration.Configuration.UseNinjectActivator(kernel);
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>()
.ToSelf()
.InNamedOrBackgroundJobScope(context => context.Kernel.Components.GetAll<INinjectHttpApplicationPlugin>()
.Select(c => c.GetRequestScope(context))
.FirstOrDefault(s => s != null));
}
But now I get the following error:
Error activating IUnitOfWork using self-binding of IUnitOfWork
No constructor was available to create an instance of the implementation type.
I have a class I would like to use to process my background job using hangfire is as follows:
public class EmailJob
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMailer _mailer;
public EmailJob(IUnitOfWork unitOfWork, IMailer mailer)
{
_unitOfWork = unitOfWork;
_notificationMailer = notificationMailer;
}
public void Execute()
{
// DO Stuff
}
}
Any one know what I'm doing wrong? The documentation also states:
Services registered with InRequestScope() directive will be unavailable during job activation, you should re-register these services without this hint.
What does this mean? I still want to ensure that only one IUnitOfwork class which implement dbContext is used per http request. How is this now going to affect the rest of the application if I remove the InRequestScope?
I think the issue is that you are binding IUnitOfWork to itself.
Niject would need a concrete class to activate something like UnitOfWork.
kernel.Bind<IUnitOfWork>()
.To<UnitOfWork()
.InNamedOrBackgroundJobScope(context => context.Kernel.Components.GetAll<INinjectHttpApplicationPlugin>()
.Select(c => c.GetRequestScope(context))
.FirstOrDefault(s => s != null));

Resources