I'm using Serilog.Sinks.Seq in my C# app (see the configuration code below) but I can't figure out how to set the JsonSerializerOptions.DefaultIgnoreCondition to ignore nulls. Any help in this regard would be greatly appreciated...
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddHostedService<Worker>();
})
.UseSerilog((context, config) =>
{
var seqUri = new Uri(context.Configuration["SeqUri"]!);
var seqApiKey = context.Configuration["SeqApiKey"]!;
config.MinimumLevel.Debug()
.WriteTo.Seq(seqUri.AbsoluteUri, apiKey: seqApiKey);
})
.Build();
await host.RunAsync();
WriteTo.Seq does not provide any ways to use JsonSerializerOptions. The Seq server itself is responsible for handling the serialization of the log events. It's designed to work with structured log data so it uses its own serialization format which is built for optimization. I'm not aware of anyways to modify or override it.
You can use other sinks for logging which provide support for custom serialization Serilog.Sinks.File or Serilog.Sinks.Elasticsearch. You can use these sinks to log and then use Log Shipping to consume those logs in Seq.
Related
Dependency injection from the box (Microsoft) has good stuffs, precisely IConfiguration interface, which allows to get stored configuration data using different providers and then to bind it with different classes using Options patterns. It's a really good stuff, but IConfiguration interface has only mechanism to read data and does not have to save data. From the other hand, usually, applications have possibility to change their configuration and to store it some where. Do you have any idea how I can implement this option?
Initially, I've stored some configuration data into the appsettings.json file and when I configure the DI container I get these data and bind their with particular class.
public static IHostBuilder ConfigureHost(this IHostBuilder builder)
{
_ = builder.ConfigureAppConfiguration((context, config) =>
{
_ = config.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings12.json")
.Build();
});
_ = builder.ConfigureServices((context, services) =>
services.Configure<OptionsModel>(context.Configuration.GetSection("Options"))
.AddSingleton<IOptionsService, OptionsService>()
.AddSingleton<MainWindowModelView>()
.AddSingleton<MainWindow>()
);
return builder;
}
This code works fine, but I can't find is there any mechanism in the box to store the changed configuration data back. There is a form to change these configuration data and I want to save their to the file. Could anyone to suggest me how I can save it?
I have a console application that uses the .NET Generic Host for reading settings and for dependeny injection.
How can I configure which library is used for parsing the JSON configuraton files (appsettings.json)? I'd like to use Newtonsoft Json.NET instead of the default (System.Text.Json).
Background: my settings files have BigInteger values that are handled quite well by Newtonsoft, but fail to load with the default.
Note that this is explicitly not about ASP.NET but a plain console application. It is extremely difficult to find something applying to a simple console app use case because everything googleable is about ASP.NET.
The code setting up the host currently looks like this:
Host
.CreateDefaultBuilder()
.ConfigureLogging(...)
.ConfigureServices(...)
.UseConsoleLifetime()
.Build()
.StartAsync();
Somewhere in there surely is the place to hook up the Newtonsoft JSON parser.
(.NET 6)
Configuration works the same in a console app as it does in ASP.NET. The defaults may be different but the concepts are the same.
You need to add the newtonsoft json configuration provider and take out the default json configuration provider.
See the extension methods documentation here:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.configuration.newtonsoftjsonconfigurationextensions?view=dotnet-plat-ext-3.1&viewFallbackFrom=dotnet-plat-ext-6.0
See here for adding and removing configuration providers generally:
https://learn.microsoft.com/en-us/dotnet/core/extensions/configuration-providers
Full Console Example:
appsettings.json
{
"MySection": {
"MyBigValue": 2928298298298292898298292254353453534435353
}
}
program.cs
//this requires adding the Microsoft.Extensions.Configuration.NewtonsoftJson package
using System.Numerics;
using Microsoft.Extensions.Configuration.Json;
using Microsoft.Extensions.Options;
var host = Host
.CreateDefaultBuilder()
.ConfigureAppConfiguration((hostingContext, configuration) =>
{
//note this whole section is probably unneeded because conversion is happening in the ConfigurationBinder class
//and json conversion has nothing to do with it
//remove old JSON source
var jsonSources = configuration.Sources.Where(s => s is JsonConfigurationSource).Cast<JsonConfigurationSource>().ToList();
jsonSources.ForEach(s => configuration.Sources.Remove(s));
//replace them with newtonsoft sources
jsonSources.ForEach(s =>
{
if (File.Exists(s.Path))
configuration.AddNewtonsoftJsonFile(s.Path);
});
//note this will put the JSON sources after the environment variable sources which is not how it is by default
})
.ConfigureServices((hostcontext, services) =>
{
var mySection = hostcontext.Configuration.GetSection("MySection");
services.Configure<MySection>(mySection);
})
.UseConsoleLifetime()
.Build();
host.StartAsync();
var mySection = host.Services.GetRequiredService<IOptions<MySection>>().Value;
Console.WriteLine(mySection.MyBigValueInt);
Console.ReadLine();
class MySection
{
public string MyBigValue { get; set; }
//a more complex alternative to using this property is to register a TypeConverter for BigInteger that does the string conversion
public BigInteger MyBigValueInt => BigInteger.Parse(MyBigValue);
}
I am trying to adapt Application Insights to my liking. And I have some problems. I have it mounted like this.
In the startup.cs class:
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry();
services.AddControllers();
}
In the Program.cs:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddApplicationInsights("73985d32-dc3b-4a7e-915e-aa7ef37fbef8");
logging.AddFilter<ApplicationInsightsLoggerProvider>("", LogLevel.Information);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
So I avoid using the appsettings.json configuration, because the log level will be variable.
My first question is, how can I make the dynamic log level, by querying the database?
Another question, is how can I add a custom parameter, type customer_name?
Finally, how can I make Application Insights register the values that I want, using:
Only record the values that come out of these functions, for example, if there is an exception, you would not have to register it.
_logger.LogInformation("Test info");
_logger.LogError(ex, ex.Message);
About your first question
I think it's impossible,for more details, you can check bowman's answer.
Overriding Log Level for Azure Functions
About second question
Jitendra Patil's code really great, this should be what you need.
Adding custom properties for each request in Application Insights metrics
I have a .net 5 web application that uses Application Insights. I try to log into AI trace by using ILogger<>. However: When analyzing the "traces" - Content in AI on Azure the logs are not shown.
Part of StartUp:
services.AddLogging(loggingbuilder =>
{
loggingbuilder.AddFilter<ApplicationInsightsLoggerProvider>("", LogLevel.Trace);
loggingbuilder.AddApplicationInsights();
});
services.AddApplicationInsightsTelemetry();
The constructor of the class that should do the logging injects ILogger and AppInsights via dependency injection:
public ImportService(ILogger<ImportService> log, TelemetryClient telemetryClient)
{
_log = log;
_telemetryClient = telemetryClient;
}
Inside the method I have the following two logging attempts:
public async Task<Customer> UpdateCustomerByEmail(string email)
{
_telemetryClient.TrackTrace("From Telemetry");
_log.LogWarning("From Log");
[...]
}
While the first one ("from Telemetry") ends up correctly in AI-traces, the second one ("From Log") never shows up there.
The instrumentationkey is stored in the appsettings (and obviously correct because the telemetryClient-Track is working)
Might this documentation be relevant for you? Adding the following code to program.cs worked for me:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddApplicationInsights("<instrumentationKeyHere>");
logging.AddFilter<Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider>("", LogLevel.Information);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
The nuget package Microsoft.Extensions.Logging.ApplicationInsights must also be installed.
In your case it might be sufficient to simply provide the Instrumentation Key as a paramter to the AddApplicationInsights function.
As stated in the documentation "This code is required only when you use a standalone logging provider. For regular Application Insights monitoring, the instrumentation key is loaded automatically from the configuration path ApplicationInsights: Instrumentationkey."
This might explain why regular monitoring works, but not for logging.
I have a. NET core console app that implement IHostedService and a reference to another project with a DbContext definition.
This is the configuration of DbContext in console app:
IHost host = new HostBuilder()
.ConfigureHostConfiguration(configHost =>
{
configHost.SetBasePath(Directory.GetCurrentDirectory());
configHost.AddEnvironmentVariables(prefix: "ASPNETCORE_");
configHost.AddCommandLine(args);
})
.ConfigureAppConfiguration((hostContext, configApp) =>
{
configApp.SetBasePath(Directory.GetCurrentDirectory());
configApp.AddEnvironmentVariables(prefix: "ASPNETCORE_");
configApp.AddJsonFile($"appsettings.json", true);
configApp.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", true);
configApp.AddCommandLine(args);
})
.ConfigureServices((hostContext, services) =>
{
services.AddDbContext<MyAppDbContext>(options => options.UseNpgsql(hostContext.Configuration.GetConnectionString("DefaultConnection")));
services.AddHostedService<ApplicationLifetimeHostedService>();
})
.Build();
Now, in the OnStarted() method of ApplicationLifetimeHostedService I have:
using (var _context = new MyAppDbContext())
{
...
_context.SaveChanges();
}
Why MyAppDbContext take the connection string value from OnConfiguring method of dbcontext definition class (hard-coded, generated from scaffolding), and not from appsettings.{ASPNETCORE_ENVIROMENT}.json ()?
Thank you in advance!
Based on your configuration, currently the IHostBuilder is for non web applications and simulates a generic configuration, eventually this will replace the IWebHostBuilder. However, you do not need those... In your instance you would be better off with CreateDefaultBuilder.
Host Configuration
App Configuration
Both are provided by default, with more granular control. The primary item is the default services provided by the builder and what they compile or build.
To directly answer your issue though, in your top line, you are missing the following:
var host = new HostBuilder()
.ConfigureHostConfiguration(configuration =>
{
// For brevity, removed some.
configuration.AddJsonFile("appsettings.json", false, true);
}
That is why your appsettings.json is not working. The ConfigureHostConfiguration will carry through to the ConfigureAppConfiguration.
Host configuration automatically flows to app configuration
(ConfigureAppConfiguration and the rest of the app).
No providers are included by default. You must explicitly specify
whatever configuration providers the app requires in
ConfigureHostConfiguration, including:
File configuration (for example, from a hostsettings.json file).
Environment variable configuration.
Command-line argument configuration.
Any other required configuration providers.