asp.net-coreazure-web-app-serviceazure-monitoring

How to gather custom logs from Azure web app to Log analytics?


I have a .net core app which is deployed to Azure web app based on the Windows platform. In my app, I'm using Serilog for logs and I have these settings to send the specific log format to this location: ../../LogFiles/Application/diagnostics-.txt. I have set the diagnostics settings. Why I can not see any data from the table AppServiceAppLogs?

This is my serilog's setting

"WriteTo": [
      {
        "Name": "Async",
        "Args": {
          "configure": [
            {
              "Name": "File",
              "Args": {
                "path": "../../LogFiles/Application/diagnostics-.txt",
                "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{ApplicationName}] [{Version}] [{Environment}] [{ClientAgent}] [{CorrelationId}] [{Level}] [{SourceContext}] {Message}{NewLine}{Exception}",
                "rollingInterval": "Day",
                "retainedFileCountLimit": 100
              }
            }
          ]
        }
      },

Here is an example log: [2023-10-10 10:10:25.788 +00:00] [supportMs] [0] [Uat2] [Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36] [00000000-0000-0000-0000-0000000000] [Error] [CacheManager.RedisCacheManager] xxxxxxxxxxxxxx

I want to collect custom logs from Azure web app and show logs in log analytics workspace


Solution

  • In Azure Log analytics workspace we need to create DCR with our Windows or Linux Agent and only the below Resource Types are directly supported for creating DCR where Azure App service is not present:-

    enter image description here

    I have implemented serilog logic in my Asp.net core app the simplest way to retrieve the serilog logs in Log analytics is to write them in Console like below:-

    Added below code in my Program.cs file:-

    builder.Host.UseSerilog((context, config) =>
    {
        config.WriteTo.Console(); 
    });
    

    Local the Logs are visible in the local console:-

    enter image description here

    Added a Diagnostic Setting to send the logs to Azure Log analytics workspace and the same logs were visible like below:-

    enter image description here

    enter image description here

    In order to meet your requirement, You can add serilog to a file like below:-

    builder.Host.UseSerilog((context, config) =>
    {
        config.WriteTo.File(".log"); // Replace 'path-to-log-file.log' with your desired file path.
    });
    

    .log file is created while deploying my Azure web app like below:-

    enter image description here

    Now, implement the logic from this SO thread answer in your .net app to send this custom logs file data. But the API in the Answer is going to get deprecated. Instead use Azure Log Ingestion API here and Add it in your .Net app.

    For more clarity on Azure Log Ingestion API you can refer the steps here for Azure Portal.

    Additionally, After implementing the above Log ingestion code in your .net app, you can also create a custom table in your log analytics workspace with the sample data from your log file like below:-

    enter image description here

    Convert your Log file into json and then upload it as a sample like below so Log analytics understands the schema:-

    enter image description here

    Now, Click Next and Create the Custom Table.

    Use the same DCR, DCE and custom table in your Azure Log Ingestion code refer below:-

    var endpoint = new Uri("<data_collection_endpoint>");
    var ruleId = "<data_collection_rule_id>";
    var streamName = "<stream_name>";
    
    var credential = new DefaultAzureCredential();
    LogsIngestionClient client = new(endpoint, credential);
    DateTimeOffset currentTime = DateTimeOffset.UtcNow;
    
    //custom log code binary data
    BinaryData data = BinaryData.FromObjectAsJson(
    // custom log code
    
    // Upload our logs
    Response response = await client.UploadAsync(
        ruleId,
        streamName,
        RequestContent.Create(data)).ConfigureAwait(false);