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
Related
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.
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'm getting this message in the console when running a server-side Blazor app:
Error: There was an unhandled exception on the current circuit, so
this circuit will be terminated. For more details turn on detailed
exceptions in 'CircuitOptions.DetailedErrors'
I've had a look at the Blazor error handling documentation, but I can't work out how to actually turn on the detailed errors mentioned in that message?
More digging on this revealed that there are both non-Blazor specific .NET Core ways to turn on Detailed Errors, and also a Blazor specific approach:
The general .NET Core way to turn on Detailed Errors:
There are a number of ways to get the detailed errors as discussed in the .NET Core documentation, but I ended up using the Detailed Errors setting:
WebHost.CreateDefaultBuilder(args).UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
And the Development Environment setting:
WebHost.CreateDefaultBuilder(args).UseEnvironment(Environments.Development)
Both of those are used in Program.cs:
If you are using the older (and eventually to be deprecated IWebHostBuilder approach) that looks like this:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
//.UseEnvironment(EnvironmentName.Development)
.UseStartup<Startup>();
And if you're using the newer IHostBuilder approach that was introduced with Core 2.1 that looks like this:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseStartup<Startup>()
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
//.UseEnvironment(EnvironmentName.Development);
});
Once I set that I got more details about my misfiring Blazor code.
A Blazor specific approach:
An alternative approach for turning on detailed errors can also be found in this answer, which includes this code:
services.AddServerSideBlazor().AddCircuitOptions(options => { options.DetailedErrors = true; });
This approach can then be expanded to include a check for whether the code is being run in the development environment
services.AddServerSideBlazor().AddCircuitOptions(o =>
{
//only add details when debugging
o.DetailedErrors = _env.IsDevelopment();
});
as highlighted by #Eonasdan's answer below
A better way to add detailed errors is to check your environment first. In Startup.cs add IWebHostEnvironment env to your constructor.
Then you can do this:
services.AddServerSideBlazor().AddCircuitOptions(o =>
{
if (_env.IsDevelopment()) //only add details when debugging
{
o.DetailedErrors = true;
}
});
NO CODE : EASIER & More SECURE
Best Practice
This is easier than most of the proposed solutions and it does not introduce a possible security issue into the code. It is also considered a coding best practice.
Microsoft recommends adding the following to the appsettings.development.json file as it does not add code to the application that can become a security risk. Do not put this in your appsettings.json unless absolutely necessary (and then only temporarily in a staging or dev environment).
You can also use this approach to provide detailed error logging for SignalR.
src: Handle errors in ASP.NET Core Blazor apps: Detailed circuit errors
{
"DetailedErrors": true, // turns on CircuitOptions.DetailedErrors
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.AspNetCore.SignalR": "Debug" // turns on SignalR debugging
}
}
}
For .NET Core 6 you can use WebApplicationBuilder.
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
builder.Services.AddServerSideBlazor().AddCircuitOptions(x => x.DetailedErrors = true);
}
else
{
builder.Services.AddServerSideBlazor();
}
For me it was slightly different
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseSetting(WebHostDefaults.DetailedErrorsKey, "true");
webBuilder.UseStartup<Startup>();
});
I don't want to type the key of application insight in the Program.cs, Can I type it in some file of configurations or in another place? It's a ASP .Net Core
I want to include a register in application insights of my logs but with modifications. Now I have a register, but I am typing the key in the Program.cs and I have "a problem" when I change of environment. Do you know any way to type this key dynamicly on the Program.cs or can I do this declaration in another place of the program.
This is the Program.cs. It started with the Main and after it starts the BuildWebHost where I load the key of applications insights and it's what I want to change:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.AddApplicationInsights("db0fe38d-c208-8ed7-23e4ef4479bb");
// Optional: Apply filters to configure LogLevel Trace or above is sent to
// ApplicationInsights for all categories.
logging.AddFilter<ApplicationInsightsLoggerProvider>("", LogLevel.Trace);
// Additional filtering For category starting in "Microsoft",
// only Warning or above will be sent to Application Insights.
logging.AddFilter<ApplicationInsightsLoggerProvider>("Microsoft", LogLevel.Warning);
}).Build();
How I said, I would avoid to type key on the Program and I would like take this param from a config file or type this declaration in another place
Since it is an ASP.NET Core application, you can use the ConfigureLogging extension method that injects the WebHostBuilderContext to retrieve your configuration:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) =>
{
var appInsightKey = hostingContext.Configuration["MyAppInsight"];
logging.AddApplicationInsights(appInsightKey);
// Optional: Apply filters to configure LogLevel Trace or above is sent to
// ApplicationInsights for all categories.
logging.AddFilter<ApplicationInsightsLoggerProvider>("", LogLevel.Trace);
// Additional filtering For category starting in "Microsoft",
// only Warning or above will be sent to Application Insights.
logging.AddFilter<ApplicationInsightsLoggerProvider>("Microsoft", LogLevel.Warning);
}).Build();
Just add UseApplicationInsights(), then remove the instrumentation key(assume the instrumentation key set in the appsettings.json).
Sample code as below, and works well at my side:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseApplicationInsights() // add this line of code, and it will auto-read ikey from appsettings.json.
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
//then you can remove instrumentation key from here.
logging.AddApplicationInsights();
logging.AddFilter<ApplicationInsightsLoggerProvider>("", LogLevel.Trace);
logging.AddFilter<ApplicationInsightsLoggerProvider>("Microsoft", LogLevel.Warning);
}).Build();
I am starting to work on an ASP.NET Core 2.0 Web Api. I added 2 secrets to the secrets.json file and am trying to read them in through the Configuration property in my Startup file. Each time I called I try to get the value from the Configuration variable, it returns null. An example of how I am reading this from the secrets.json is shown below.
public void ConfigureServices(IServiceCollection services)
{
var secret = Configuration["TestSecret"];
My secrets.json file looks like:
{
"TestSecret": "SecretValue"
}
I have also tried to retrieve the value by using:
public void ConfigureServices(IServiceCollection services)
{
IConfigurationSection secret = Configuration.GetSection("TestSecret");
var value = secret.Value;
This returns a section that corresponds to the TestSecret section, but the value in the IConfigurationSection is also null.
I have tried to install the Microsoft.Extensions.Configuration.UserSecrets NuGet package, but this hasn't helped. Am I missing a package I need to install or is there an alternate way to retrieve this value?
If I need to provide any more information to help solve this issue, please ask in the comments. I will try to provide as much information as possible to help solve this issue.
In general you use a file called "appSettings.json" file for storing all json values like that. This file doesn't need to be manually added in 2.0. Unless there is a specific reason for having multiple json files I would recommend doing this as it allows you to have all your application specific settings in the one place
it is possible to manually add a .json file though.
for asp.net Core 2.0 in your Program.cs in the BuildWebHost method
you add in the following
.ConfigureAppConfiguration((WebHostBuilderContext, ConfigurationBuilder) =>
{
ConfigurationBuilder
.AddJsonFile("Secrets.json", optional: true);
ConfigurationBuilder.AddEnvironmentVariables();
})
depending on the setup the entire method should look like
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((WebHostBuilderContext, ConfigurationBuilder) =>
{
ConfigurationBuilder
.AddJsonFile("Secrets.json", optional: true);
ConfigurationBuilder.AddEnvironmentVariables();
})
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
To get a value from in your ConfigureServices method you use
var testSecret = Configuration.GetSection("Secrets")["TestSecret"];
this is how the Secrets.Json file should look
{
"Secrets":
{
"TestSecret": "SecretValue"
}
}
Did you configure to use secrets in the Startup method?
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder();
if (env.IsDevelopment())
{
builder.AddUserSecrets<Startup>();
}
Configuration = builder.Build();
}
Read more here
For me it was null because I was playing around with other ASPNETCORE_ENVIRONMENT values and the default logic is apparently dependent on this being "Development"... which makes basic sense given that secrets.json is entirely local dev scenario.
As a related aside, for us there's mild heartburn that "Development" could mean either cloud runtime dev or raw local dev so we're forced to create yet another key/value to represent local dev because ASPNETCORE_ENVIRONMENT = Development drives specific logic we don't want to lose.