.Net application development specialists
asp.net, c#, vb.net, html, javascript, jquery, html, xhtml, css, oop, design patterns, sql server, mvc and much more
contact: admin@paxium.co.uk

Paxium is the company owned by myself, Dave Amour and used for providing IT contract development services including


  • Application development - Desktop, Web, Services - with Classic ASP, Asp.net WebForms, Asp.net MVC, Asp.net Core
  • Html, Css, JavaScript, jQuery, React, C#, SQL Server, Ado.net, Entity Framework, NHibernate, TDD, WebApi, GIT, IIS
  • Database schema design, implementation & ETL activities
  • Website design and hosting including email hosting
  • Training - typically one to one sessions
  • Reverse Engineering and documentation of undocumented systems
  • Code Reviews
  • Performance Tuning
  • Located in Cannock, Staffordshire
Rugeley Chess Club Buying Butler Cuckooland Katmaid Pet Sitting Services Roland Garros 60 60 Golf cement Technical Conformity Goofy MaggieBears Vacc Track Find Your Smart Phone eBate Taylors Poultry Services Lafarge Rebates System Codemasters Grid Game eBate DOFF

.NET Logging Providers in Azure Functions (Isolated)

Latest update - you can set the AppInsights log level in local.settings.json as below. Note it uses colon object notation. See end of this article why.

    
            {
                "IsEncrypted": false,
                "Values": {
                    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
                    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
                    "APPLICATIONINSIGHTS_CONNECTION_STRING": "YourConnectionHere",
                    "Logging:LogLevel:Default": "Information",
                    "Logging:ApplicationInsights:LogLevel:Default": "Information",
                    "ApplicationInsights:EnableAdaptiveSampling": "false"
                }
            }
        
    

In the isolated worker model, ILogger<T> is a façade that fans out each log to one or more providers. Each provider has its own minimum log level and filtering rules. Common providers you’ll see:

1) DebugLoggerProvider

Writes to the Visual Studio Debug/Output window when a debugger is attached. Great for local development.

2) EventSourceLoggerProvider

Emits ETW (Event Tracing for Windows) events for system-level tracing and diagnostics tooling. Generally infrastructure-oriented.

3) EventLogLoggerProvider

Writes to the Windows Event Log (relevant on Windows hosts). Not active on Linux.

4) WorkerLoggerProvider (Azure Functions)

The Azure Functions host logger. Drives what you see in the local console and in the Azure Portal’s log stream for the Function App.

5) ApplicationInsightsLoggerProvider

Sends logs to Azure Application Insights. By default in many templates/environments, this provider is set to Warning to control telemetry volume and cost.


Setting Application Insights to Information (Isolated worker)

In the isolated worker model, host.json does not control the Application Insights provider’s level. Use appsettings.json (plus a small bootstrapping line in Program.cs) or Azure App Settings.

A) appsettings.json

Add an appsettings.json file to your Function project and include the following. This sets AI to Information and disables adaptive sampling so you see every log during dev/test.

    
        {
            "Logging": {
                "LogLevel": {
                    "Default": "Information",
                    "EventLog": "Information"
                },
                "ApplicationInsights": {
                    "LogLevel": {
                        "Default": "Information"
                    }
                },
                "EventLog": {
                    "LogLevel": {
                        "Default": "Information"
                    }
                }
            }
        }
        
    

Note - ApplicationInsights has to be this exact case here. It is typical to have the whole file as camelCase but this one piece has to be PascalCase otherwise it won't work. I think it matches the Warning rule that Application Insights uses by default and overrides it but only matches if the casing is correct.

So if you don't have the above casing spot on, you can remove the App Insights default warning rule that it adds by doing so in Program.cs as below

    
        builder.Logging.Services.Configure<LoggerFilterOptions>(options =>
        {
            // The Application Insights SDK adds a default logging filter that instructs ILogger 
            // to capture only Warning and more severe logs.
            // Application Insights requires an explicit override.
            // Log levels can also be configured using appsettings.json. 
            // For more information, see:
            // https://learn.microsoft.com/azure/azure-monitor/app/worker-service#ilogger-logs

            var defaultRule = options.Rules
                .FirstOrDefault(rule => 
                    rule.ProviderName == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");

            if (defaultRule is not null)
            {
                options.Rules.Remove(defaultRule);
            }
        });
        
    

Program.cs (ensure the file is loaded)

Make sure the host loads appsettings.json. You can also add an explicit filter on the AI provider (belt-and-braces).

Program.cs — Loading appsettings.json and Configuring Application Insights

This example shows how to load appsettings.json in a .NET 8 isolated Azure Function and configure Application Insights for full telemetry visibility.

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = FunctionsApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddEnvironmentVariables();

builder.ConfigureFunctionsWebApplication();

builder.Services
    .AddApplicationInsightsTelemetryWorkerService()
    .ConfigureFunctionsApplicationInsights();

builder.Build().Run();

This setup allows appsettings.json (and Azure App Settings) to define Application Insights log levels and sampling behaviour, ensuring consistent configuration across local and cloud environments.

B) Azure App Settings (production-friendly override)

In the Azure Portal → your Function App → Configuration → Application settings, add:

Logging__ApplicationInsights__LogLevel__Default = Information
ApplicationInsights__EnableAdaptiveSampling              = false

These environment variables override appsettings.json without code changes.


Why raise AI to Information?

Pros: parity between local console (WorkerLogger) and App Insights, easier debugging, and complete traces for investigations and correlation across requests/dependencies.

Cons: more telemetry volume → higher ingestion/storage cost and noisier dashboards.

Guidance: Use Information during development and targeted troubleshooting. For steady-state production, consider restoring AI to Warning (and enable sampling) to control cost and noise.


FAQ & Gotchas

  • “I changed host.json but AI is still Warning”: host.json doesn’t govern AI level in isolated worker.
  • “I see logs in WorkerLogger but not in AI”: Providers are independent; AI may be set to Warning or sampling may drop events.
  • “Do I need both file and env settings?”: No. Pick one. In Azure, App Settings typically override file config.
  • “How to revert in prod?”: Set Logging__ApplicationInsights__LogLevel__Default=Warning and re-enable sampling.

Checking Logs In Azure

Log to Azure Application Insights when running locally (VS)

To send your local dotnet-isolated Function logs to the Azure Application Insights instance, add the connection string to local.settings.json. This file is for local development only and is not uploaded on publish or stored in source control.

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",

    // — Add this line (copy from your AI resource: Overview → Connection string)
    "APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=<key>;IngestionEndpoint=<endpoint>"
  }
}

Important: local.settings.json should not be committed to source control (it contains secrets). The Azure Functions tooling creates it locally and the default template includes it in .gitignore. If needed, ensure your repo ignores it explicitly:

# .gitignore
local.settings.json

How to verify logs in Azure (as shown in the screenshots)

  1. In the Azure Portal, open your Function App (e.g., AppInsightsTestFunction).
  2. Go to Monitoring → Logs (Application Insights query window).
  3. Run a simple KQL query to find your messages:

    traces
    | where message contains "This is an error"
    or message contains "This is a warn"
    or message contains "DaveFucntion - C# HTTP trigger function processed a request."
    | order by timestamp desc

You should see entries with severityLevel 1 (Information), 2 (Warning), and 3 (Error) for your local runs. If nothing appears, double-check that your app ran locally with the connection string present and that your AI resource is in a reachable region.

Final observation. If you create a new function and make no changes it will log warnings and errors to Application Insights by default. But if you add an environment variable of Logging__ApplicationInsights__LogLevel__Default Information then it will log Information level logs as well.

This corresponds to the appsettings values (not event log as that is local windows only)

    
        {
            "Logging": {
                "LogLevel": {
                    "Default": "Information",
                    "EventLog": "Information"
                },
                "ApplicationInsights": {
                    "LogLevel": {
                        "Default": "Information"
                    }
                },
                "EventLog": {
                    "LogLevel": {
                        "Default": "Information"
                    }
                }
            }
        }
        
    

Note - ApplicationInsights has to be this exact case here. It is typical to have the whole file as camelCase but this one piece has to be PascalCase otherwise it won't work. I think it matches the Warning rule that Application Insights uses by default and overrides it but only matches if the casing is correct.

    
        builder.Logging.Services.Configure<LoggerFilterOptions>(options =>
        {
            // The Application Insights SDK adds a default logging filter that instructs ILogger 
            // to capture only Warning and more severe logs.
            // Application Insights requires an explicit override.
            // Log levels can also be configured using appsettings.json. 
            // For more information, see:
            // https://learn.microsoft.com/azure/azure-monitor/app/worker-service#ilogger-logs

            var defaultRule = options.Rules
                .FirstOrDefault(rule => 
                    rule.ProviderName == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");

            if (defaultRule is not null)
            {
                options.Rules.Remove(defaultRule);
            }
        });
        
    

Further Empirical Evidence

Create an Azure Http Function in the cloud. Then create a standard Http Function in Azure and some extra logging such as

    
            logger.LogInformation("Information from Marisa");
            logger.LogWarning("Warning from Marisa");
            logger.LogError("Error from Marisa");
        
    

Other than that make no other changes and then publish to Azure

Run the function a few times and then view the logs. This shows the 6 from 3:50 as I hit the endpoint 3 times, and it only shows Warnings and errors

Marisa Logs

The ones from 3:55 now show Information as well. This can be achieved in Azure by simply adding 3 environment variables as below. Note the App Insights one has to be that case! See other mentions of casing in this article.

Marisa Vars

Running Locally

Now to achieve the same thing when running locally we need to do 3 things

  • Edit the hosts.json file to set Application Insights is enabled to false (so it doesn't drop anything)
  • Add an Application Insights connection string to local.settings.json with the key "APPLICATIONINSIGHTS_CONNECTION_STRING"
  • Create a brand new appsettings.json file with the following contents (The Azure project maay have not created one)
    
        {
            "Logging": {
                "LogLevel": {
                    "Default": "Information",
                    "EventLog": "Information"
                },
                "ApplicationInsights": {
                    "LogLevel": {
                        "Default": "Information"
                    }
                },
                "EventLog": {
                    "LogLevel": {
                        "Default": "Information"
                    }
                }
            }
        }
        
    

Note - ApplicationInsights has to be this exact case here. It is typical to have the whole file as camelCase but this one piece has to be PascalCase otherwise it won't work. I think it matches the Warning rule that Application Insights uses by default and overrides it but only matches if the casing is correct.

This will set the logging level of both ApplicationInsights and EventLog to Information

Note the event log one only works locally in Windows and not in Azure

Also make sure you set the appsettings.json to copy to output directory with a build action of Content and Copy if newer

You can find the connection string in the Azure Portal under your Application Insights resource via the Configure menu and then Properties

Also rather than doing this in host.json

    
        {
            "version": "2.0",
            "logging": {
                "applicationInsights": {
                    "samplingSettings": {
                        "isEnabled": false,
                        "excludedTypes": "Request"
                    },
                    "enableLiveMetricsFilters": true
                }
            }
        }
        
    

You can do this

    
        {
            "version": "2.0",
            "logging": {
                "applicationInsights": {
                    "samplingSettings": {
                        "isEnabled": true,
                        "excludedTypes": "Request;Trace"
                    },
                    "enableLiveMetricsFilters": true
                }
            }
        }
        
    

Understanding excludedTypes in host.json

The excludedTypes setting tells Azure Functions’ Application Insights integration which telemetry types should not be sampled. This means telemetry of those types will always be sent, even if sampling is enabled.

Example configuration

{
    "version": "2.0",
    "logging": {
        "applicationInsights": {
            "samplingSettings": {
                "isEnabled": true,
                "excludedTypes": "Request;Trace"
            },
            "enableLiveMetricsFilters": true
        }
    }
}
  

Explanation

  • Request — Every HTTP-triggered Function invocation is logged. Sampling never drops request telemetry, ensuring all incoming calls are visible.
  • Trace — All log messages generated by your code (e.g. _logger.LogInformation(), _logger.LogError()) are always sent, not sampled.

Combined effect

With "isEnabled": true and "excludedTypes": "Request;Trace":

  • ✅ All requests and trace logs are sent in full.
  • ⚖️ Other telemetry (dependencies, exceptions, custom events) may still be sampled.

Usage guidance

  • Ideal for development or low-traffic environments where full visibility is needed.
  • For high-volume production apps, consider enabling sampling for some telemetry types to reduce data ingestion and cost.

Understanding enableLiveMetricsFilters in host.json

The enableLiveMetricsFilters setting controls how Azure Functions filters telemetry sent to the Application Insights Live Metrics Stream. Live Metrics Stream (also known as Live View) shows real-time data such as requests per second, failures, and log traces, updating every few seconds.

Example configuration

{
    "version": "2.0",
    "logging": {
        "applicationInsights": {
            "samplingSettings": {
                "isEnabled": true,
                "excludedTypes": "Request;Trace"
            },
            "enableLiveMetricsFilters": true
        }
    }
}
  

What it does

  • ✅ When set to true, Azure Functions applies runtime filters that remove low-level system and host logs from the Live Metrics stream.
  • This ensures only meaningful telemetry such as requests, warnings, errors, and custom log messages are shown in real time.
  • It reduces noise and keeps resource usage lower, which is particularly useful for consumption-based Function Apps.

When set to false

  • All telemetry, including internal runtime messages and system-level logs, is sent to the Live Metrics stream.
  • This increases verbosity and telemetry overhead, making the view noisier.

Best practice

  • Keep enableLiveMetricsFilters set to true for most Function Apps to maintain a clean and efficient Live Metrics view.

Summary

Setting Behaviour
"enableLiveMetricsFilters": true Filters out host/internal noise. Shows useful real-time metrics efficiently ✅
"enableLiveMetricsFilters": false Shows everything including background system logs. Noisy and heavier telemetry ⚠️

Do Logging Providers Only Have One Default Rule?

Short answer: No — a logging provider can have multiple default rules, but in most cases (such as Application Insights, Console, Debug, or EventLog) it adds only one by default.

How It Works

Each logging provider defines its own default LoggerFilterRule entries when it is registered. A rule defines the provider name, category, and minimum log level. The framework supports multiple rules per provider so that specific categories (like namespaces or class names) can have different levels.

Example: Application Insights

When you add Application Insights with:


builder.Services.AddApplicationInsightsTelemetryWorkerService();
  

It inserts one default rule similar to:

ProviderName = "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider"
CategoryName = null
LogLevel = Warning

This is why only Warning and higher logs appear in Application Insights by default. The override below removes that rule, allowing configuration to control logging levels:


builder.Logging.Services.Configure<LoggerFilterOptions>(options =>
{
    var defaultRule = options.Rules
        .FirstOrDefault(rule =>
            rule.ProviderName == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");

    if (defaultRule is not null)
    {
        options.Rules.Remove(defaultRule);
    }
});
  

Example: Console Provider

The Console provider may add multiple rules — for example, one for all categories and one specifically for Microsoft logs:

ProviderName = "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider"
CategoryName = "Microsoft"
LogLevel = Warning

ProviderName = "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider"
CategoryName = null
LogLevel = Information
  

Rule Matching Behaviour

  • The most specific matching rule wins (matching both provider and category).
  • If no match is found, the global default level (Logging:LogLevel:Default) applies.

Typical Defaults by Provider

Provider Default Rules Added Notes
Application Insights 1 Captures Warning and above
Console 1–2 General and Microsoft/system log levels
Debug 1 Captures Information and above
EventLog 1 Captures Warning and above
Azure / Blob / EventSource 1 Provider-specific defaults

Summary

Although most providers define only one default rule, the system supports multiple per provider. Each log event is filtered through the most specific matching rule, giving fine-grained control over logging behaviour.


builder.Logging.Services.Configure<LoggerFilterOptions>(options =>
{
    // The Application Insights SDK adds a default logging filter that restricts ILogger 
    // to capture only Warning and more severe logs.
    // This removes that specific rule while keeping any custom Application Insights filters intact.
    // Log levels can also be configured via appsettings.json.
    // Docs: https://learn.microsoft.com/azure/azure-monitor/app/worker-service#ilogger-logs

    var aiRule = options.Rules.FirstOrDefault(rule =>
        rule.ProviderName == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider"
        && rule.LogLevel.HasValue   // Only remove if it explicitly defines a log level
        && rule.LogLevel.Value >= LogLevel.Warning
        && string.IsNullOrEmpty(rule.CategoryName)); // Skip category-specific rules

    if (aiRule is not null)
    {
        options.Rules.Remove(aiRule);
    }
});

Making the Application Insights Rule Removal More Specific

You can refine the logic so that it only removes the default Application Insights logging rule if it explicitly sets a log level filter (for example, restricting logs to Warning and above). This prevents removal of any custom or category-specific rules that you might have defined elsewhere.

Updated C# Code

    
  builder.Logging.Services.Configure<LoggerFilterOptions>(options =>
  {
      // The Application Insights SDK adds a default logging filter that restricts ILogger 
      // to capture only Warning and more severe logs.
      // This removes that specific rule while keeping any custom Application Insights filters intact.
      // Log levels can also be configured via appsettings.json.
      // Docs: https://learn.microsoft.com/azure/azure-monitor/app/worker-service#ilogger-logs

      var aiRule = options.Rules.FirstOrDefault(rule =>
          rule.ProviderName == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider"
          && rule.LogLevel.HasValue   // Only remove if it explicitly defines a log level
          && rule.LogLevel.Value >= LogLevel.Warning
          && string.IsNullOrEmpty(rule.CategoryName)); // Skip category-specific rules

      if (aiRule is not null)
      {
          options.Rules.Remove(aiRule);
      }
  });
  
  

Explanation of the Filter Logic

Condition Description
rule.ProviderName == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider" Targets only Application Insights’ logger provider.
rule.LogLevel.HasValue Ensures the rule is explicitly defining a log level (not null).
rule.LogLevel.Value >= LogLevel.Warning Matches the SDK’s default rule that filters out anything below Warning.
string.IsNullOrEmpty(rule.CategoryName) Ensures you don’t remove category-specific rules that you may have configured.

Result

  • ✅ Removes only the default "Warning and above" Application Insights rule added by the SDK.
  • ✅ Keeps all other logging rules, including custom or category-specific ones.
  • ✅ Allows appsettings.json to correctly control your Application Insights log levels.

Why appsettings.json and host.json use { } notation but local.settings.json uses colon notation

In Azure Functions and .NET applications, configuration files behave differently depending on whether they are read directly by the runtime or simulate environment variables. Here's the breakdown:

🧩 The short answer

  • appsettings.json and host.json are true hierarchical JSON configuration files. They describe structured data, so they use standard curly-brace { } notation.
  • local.settings.json is not a real configuration file — it’s a wrapper around environment variables for the local Azure Functions host. Environment variables are flat key-value pairs, so it uses : to simulate hierarchy.

🧩 Example comparison

appsettings.json

    
{
  "Logging": {
    "LogLevel": {
      "Default": "Information"
    }
  },
  "ApplicationInsights": {
    "EnableAdaptiveSampling": false
  }
}
    
  

local.settings.json

    
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "Logging:LogLevel:Default": "Information",
    "ApplicationInsights:EnableAdaptiveSampling": "false"
  }
}
    
  

Environment variables in Azure

    
Logging__LogLevel__Default=Information
ApplicationInsights__EnableAdaptiveSampling=false
    
  

🧩 Summary

File Used By Syntax Purpose
appsettings.json Your .NET app Curly braces { } Hierarchical configuration
host.json Azure Functions runtime Curly braces { } Runtime and host-level settings
local.settings.json Local Azure Functions host Colon-separated keys : Simulates environment variables
Azure portal App Settings Deployed Function App Double underscores __ Environment variables (colons not allowed)

In short: appsettings.json and host.json are true JSON configs, while local.settings.json is a local environment variable simulator using colon-separated keys.