Aller au contenu

Asp.net core 9

De Banane Atomic

Links

Changes

Log

By default, an app is logging into Console, Debug, EventSource, EventLog (only when running on Windows).
This include the linux journal for production and the VS code DEBUG CONSOLE for development.
public class MyClass(ILogger<MyClass> logger)
{
    public void MyMethod()
    {
        // to optimize the performances, test if the log level is enabled
        if (logger.IsEnabled(LogLevel.Debug)) logger.LogDebug("Debug");
        logger.LogTrace("Trace");
        logger.LogInformation("Info");
        logger.LogWarning("Warn");
        logger.LogError("Error");
        logger.LogCritical("Fatal");
    }
}
appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",       // log level par défaut
      "Microsoft": "Warning",         // pour les loggers commençant par Microsoft
      "MyNamespace.MyClass": "Debug"  // pour les loggers de MyClass
    }
  }
Program.cs
builder.Logging.ClearProviders();  // remove all the providers: no more logs
The Log methods are synchronous.
There is no file log provider.

Log in Program.cs

Program.cs
app.Logger.LogInformation("message");

Built-in logging providers

Console
  • VS code "DEBUG CONSOLE" tab
  • In the console window when the app is run with dotnet run
Debug Debug window when debugging in Visual Studio
On Linux journal or /var/log/message or /var/log/syslog
EventSource Event Tracing for Windows (ETW)
EventLog Windows Event Log
TraceSource System.Diagnostics.TraceSource libraries and providers ()
Azure App Service text files in an Azure App Service app's file system and to blob storage in an Azure Storage account

Console

appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Error"  // default log level
    }
  },
  "Console": {
    "LogLevel": {
      "Default": "Information"  // overwrite log level
    },
    "FormatterName": "json"  // log in JSON format
  }
}

journal

mar 19 17:53:10 hostname logtest[29321]: fail: LogTest.Controllers.ItemController[0]
mar 19 17:53:10 hostname logtest[29321]:       Log message

mar 19 17:58:27 hostname logtest[29321]: fail: Microsoft.AspNetCore.Server.Kestrel[13]
mar 19 17:58:27 hostname logtest[29321]:       Connection id "...", Request id "...": An unhandled exception was thrown by the application.
mar 19 17:58:27 hostname logtest[29321]: System.Exception: exception message
mar 19 17:58:27 hostname logtest[29321]:    at LogTest.Controllers.ItemController.ThrowException() in /dev-path/LogTest/Controllers/ItemController.cs:line 41

apache log

  • access.log is well filled by each query
  • error.log is never filled

LoggerMessage

Use LoggerMessage over Logger extension methods to improve performances.

logger.LogInformation("Message: {Message}", message);

static partial class Log
{
    [LoggerMessage(Level = LogLevel.Information, Message = "Message: {Message}")]
    public static partial void LogRequest(ILogger logger, string Message);
}

Log.LogRequest(logger, message);

Configuration

Sources des settings par défaut dans l'ordre de lecture:

  1. appsettings.json
  2. appsettings.<EnvironmentName>.json
  3. UserSecrets in Development environment
  4. Environment variables
  5. Command-line arguments
Les settings de la source suivante écrasent ceux déjà chargés.
ItemsController.cs
public class ItemsController(IConfiguration configuration) : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        // recherche Key, si Key n'a pas été trouvé affecte default value à la variable value
        var value = Configuration.GetValue<string>("Key", "default value");
        var value = Configuration["Key"];

       // pour les connection strings
       configuration.GetConnectionString("SqlServer1")

       // dotnet add package System.Data.SqlClient
       var builder = new SqlConnectionStringBuilder(Configuration.GetConnectionString("SqlServer4")); // from appsettings.json
       builder.Password = configuration["DbPassword"]; // from secrets storage in Dev and appsettings.json in Prod 
       var connectionString = builder.ConnectionString;

appsettings.json

appsettings.json
{
  "Key": "Value",
  "ConnectionStrings": {
    "SqlServer1": "Server=(localdb)\\MSSQLLocalDB;Database=MyDb;Integrated Security=True;MultipleActiveResultSets=True",
    "SqlServer2": "Server=(localdb)\\mssqllocaldb;Database=MyDb;Trusted_Connection=True;",
    "SqlServer3": "Server=localhost;Database=MyDb;User=sa;Password=pwd;",
    "SqlServer4": "server=localhost;database=MyDb;user=sa;",
    "MySql": "Server=localhost;Database=MyDb;User=root;Password=pwd;",
    "Sqlite": "Data Source=MyDb.db"
  },
  "DbPassword": "****"
}

Safe storage of app secrets in development in ASP.NET Core

Useful in dev environment to not store password in source code.

# aller dans le dossier contenant le *.csproj
cd MyProject

# adds a UserSecretsId element within a PropertyGroup of the .csproj file
dotnet user-secrets init

# set a secret
# put a space as first character so the command line is not saved in the history
 dotnet user-secrets set "key" "secret"
# the whole connection string
 dotnet user-secrets set "ConnectionStrings:SqlServer" "server=localhost;database=test;user=test;password=****"
# only the connection string password
 dotnet user-secrets set "DbPassword" "****"

# the secrets are stored in a JSON configuration file in a system-protected user profile folder on the local machine
# Windows: %APPDATA%\microsoft\UserSecrets\<userSecretsId>\secrets.json
# Linux:   ~/.microsoft/usersecrets/<userSecretsId>/secrets.json


# list all secrets of the current project
dotnet user-secrets list

# remove a secret in the current project
dotnet user-secrets remove "key"

# remove all secrets of the current project
dotnet user-secrets clear
The user secrets configuration source is automatically added in development mode for Web API project when WebApplication.CreateBuilder(args) is called.
CreateBuilder calls AddUserSecrets when the EnvironmentName is Development
Console/Program.cs
public static IConfigurationRoot Configuration { get; set; }

private static void Main()
{
    var builder = new ConfigurationBuilder();
    // dotnet add package Microsoft.Extensions.Configuration.UserSecrets
    builder.AddUserSecrets<Program>();
    Configuration = builder.Build();

Non-prefixed environment variables

/etc/systemd/system/kestrel-myapp.service
Environment=ConnectionStrings__MyApp=server\x3dlocalhost\x3bdatabase\x3dMyDb\x3buser\x3dMyUser\x3bpassword\x3dMyPwd
Environment=SqlServerVersion=10.10.5-MariaDB

Command-line

dotnet MyApp MyKey="value"