FeatureFlags.AdaptiveLogging 1.0.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package FeatureFlags.AdaptiveLogging --version 1.0.2
                    
NuGet\Install-Package FeatureFlags.AdaptiveLogging -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FeatureFlags.AdaptiveLogging" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FeatureFlags.AdaptiveLogging" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="FeatureFlags.AdaptiveLogging" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FeatureFlags.AdaptiveLogging --version 1.0.2
                    
#r "nuget: FeatureFlags.AdaptiveLogging, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FeatureFlags.AdaptiveLogging@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FeatureFlags.AdaptiveLogging&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=FeatureFlags.AdaptiveLogging&version=1.0.2
                    
Install as a Cake Tool

FeatureFlags.AdaptiveLogging

A lightweight helper for feature‑flag–driven, adaptive logging powered by Azure App Configuration. It:

  • Wires Feature Flags from configuration via AddFeatureFlagsFromConfiguration().
  • Registers services via AddFeatureFlagDrivenLogging().
  • Uses a single refresh knob AppConfig:RefreshInSeconds for both the Feature Flags SDK refresh window ( UseFeatureFlags().SetRefreshInterval(...)) and a local non‑blocking TryRefreshAsync throttle—keeping evaluation cadence consistent.
  • When the flag is ON, ensures Debug/Trace diagnostics are visible. If the provider would drop them, the helper * elevates* them to Information and prefixes "[FORCED-<LEVEL>]" so you can spot them in production.
  • Provides automatic correlation: if you don’t pass a requestId, a GUID (format N) is generated and all messages from that FeatureLogger instance are prefixed with the same id.

1) Required settings

{
  "AppConfig": {
    "ConnectionString": "Endpoint=...;Id=...;Secret=...",
    "Label": "dev|ProjectX",
    "RefreshInSeconds": 5
  },
  "Logging": { "LogLevel": { "Default": "Information" } }
}

2) Create flags and labels

  • Create your flag (e.g., LogEndpointA) in App Configuration Feature Manager.
  • Use Label for environment and/or project scoping (e.g., dev|WebApi, stg|WorkerA).

3) Cost & performance

  • Lower AI costs via host.json levels and sampling; Debug appears only when the flag is ON.
  • Unified refresh avoids drift and excessive calls.

4) Install & wire

dotnet add package FeatureFlags.AdaptiveLogging
builder.Configuration.AddFeatureFlagsFromConfiguration();
builder.Services.AddFeatureFlagDrivenLogging();

5) From zero in App Configuration

  1. Create the App Configuration resource.
  2. Add LogEndpointA (and label variants if needed).
  3. Set AppConfig:* in your app settings.

6) Quick recipes (pseudo‑code only)

6.1 .NET 8 Console

var cfg = new ConfigurationBuilder()
  .AddJsonFile("appsettings.json", false, true)
  .AddEnvironmentVariables()
  .Build();

cfg.AddFeatureFlagsFromConfiguration();

var services = new ServiceCollection();
services.AddLogging(b => b.AddConsole().SetMinimumLevel(LogLevel.Information));
services.AddFeatureFlagDrivenLogging();
services.AddSingleton<IConfiguration>(cfg);

var sp = services.BuildServiceProvider();
var logger = sp.GetRequiredService<ILoggerFactory>().CreateLogger("Console");

var flogger = await logger.EnableDebugAsync("LogEndpointA");
flogger.LogInformation("Console says hi");
flogger.LogDebug("More details (visible when flag is ON)");

6.2 .NET 8 Minimal API

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddFeatureFlagsFromConfiguration();
builder.Services.AddFeatureFlagDrivenLogging();
builder.Services.AddControllers();

var app = builder.Build();

public class WeatherController : ControllerBase
{
    private readonly ILogger<WeatherController> _logger;
    public WeatherController(ILogger<WeatherController> logger) => _logger = logger;

    [HttpGet("/api/weather")]
    public async Task<IActionResult> Get()
    {
        var flogger = await _logger.EnableDebugAsync("LogEndpointA");
        flogger.LogInformation("Weather endpoint hit");
        flogger.LogDebug("Debug when flag is ON");
        return Ok(new { ok = true });
    }
}

6.3 .NET 10 Minimal API

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddFeatureFlagsFromConfiguration();
builder.Services.AddFeatureFlagDrivenLogging();
builder.Services.AddControllers();

var app = builder.Build();

app.MapGet("/api/info", async (ILogger<Program> logger) =>
{
    var flogger = await logger.EnableDebugAsync("LogEndpointA");
    flogger.LogInformation(".NET 10 endpoint");
    flogger.LogDebug("Debug when flag is ON");
    return Results.Ok(new { ok = true });
});

6.4 Azure Functions v4 – in‑process (.NET 8)

public override void ConfigureAppConfiguration(b)
  => b.ConfigurationBuilder.AddFeatureFlagsFromConfiguration();

public override void Configure(h)
  => h.Services.AddFeatureFlagDrivenLogging();

public class Function1
{
    private readonly ILogger<Function1> _logger;
    public Function1(ILogger<Function1> logger) => _logger = logger;

    [FunctionName("Function1")]
    public async Task Run([QueueTrigger("demo-queue")] string msg)
    {
        var flogger = await _logger.EnableDebugAsync("LogEndpointA");
        flogger.LogInformation("Processing {Msg}", msg);
        flogger.LogDebug("Debug when flag is ON");
    }
}

6.5 Azure Functions v4 – isolated (.NET 8)

var host = new HostBuilder()
  .ConfigureAppConfiguration((ctx, cfg) => cfg.AddFeatureFlagsFromConfiguration())
  .ConfigureFunctionsWorkerDefaults()
  .ConfigureServices(s => s.AddFeatureFlagDrivenLogging())
  .Build();

public class QueueProcessor
{
    private readonly ILogger<QueueProcessor> _logger;
    public QueueProcessor(ILogger<QueueProcessor> logger) => _logger = logger;

    [Function("QueueProcessor")]
    public async Task Run([QueueTrigger("demo-queue")] string msg)
    {
        var flogger = await _logger.EnableDebugAsync("LogEndpointA");
        flogger.LogInformation("[Isolated] Processing {Msg}", msg);
        flogger.LogDebug("[Isolated] Debug when flag is ON");
    }
}

6.6 .NET Framework 4.7.2 (OWIN)

var cfg = new ConfigurationBuilder()
  .AddJsonFile("appsettings.json", false, true)
  .AddEnvironmentVariables()
  .Build();

cfg.AddFeatureFlagsFromConfiguration();

var services = new ServiceCollection();
services.AddLogging(b => b.AddConsole().SetMinimumLevel(LogLevel.Information));
services.AddFeatureFlagDrivenLogging();
services.AddSingleton<IConfiguration>(cfg);

var sp = services.BuildServiceProvider();

public class SampleController : ApiController
{
    private readonly ILogger _logger = Program.Services
        .GetRequiredService<ILoggerFactory>()
        .CreateLogger("Sample");

    [HttpGet, Route("api/sample")]
    public async Task<IHttpActionResult> Get()
    {
        var flogger = await _logger.EnableDebugAsync("LogEndpointA");
        flogger.LogInformation("Framework endpoint");
        flogger.LogDebug("Debug when flag is ON");
        return Ok(new { ok = true });
    }
}

6.7 Azure Functions – Queue trigger (Service Bus)

// In-process startup wiring (once at startup)
public override void ConfigureAppConfiguration(builder)
    => builder.ConfigurationBuilder.AddFeatureFlagsFromConfiguration();

public override void Configure(services)
    => services.Services.AddFeatureFlagDrivenLogging();

// Function class (Service Bus trigger)
public class QueueProcessor
{
    private readonly ILogger<QueueProcessor> _logger;
    public QueueProcessor(ILogger<QueueProcessor> logger) => _logger = logger;

    [FunctionName("QueueProcessor")]
    public async Task Run(
        [ServiceBusTrigger("your-queue-name", Connection = "ServiceBus:Connection")] string message,
        int deliveryCount)
    {
        var flogger = await _logger.EnableDebugAsync("LogEndpointA");
        flogger.LogInformation("SB message received. DeliveryCount={DeliveryCount}", deliveryCount);
        flogger.LogDebug("Raw payload: {Message}", message);
        // ... business logic ...
        flogger.LogInformation("SB message processed at {UtcNow}", DateTime.UtcNow);
    }
}
// appsettings.json (pseudo-config)
{
  "ServiceBus": {
    "Connection": "Endpoint=sb://<namespace>.servicebus.windows.net/;SharedAccessKeyName=...;SharedAccessKey=..."
  },
  "AppConfig": {
    "ConnectionString": "Endpoint=...;Id=...;Secret=...",
    "Label": "dev|ProjectX",
    "RefreshInSeconds": 5
  },
  "Logging": { "LogLevel": { "Default": "Information" } }
}

7) Application Insights Kusto (KQL) cheat‑sheet

  • Latest logs:
traces | where timestamp > ago(30m) | order by timestamp desc
  • Elevated debug lines:
traces | where timestamp > ago(2h) | where message has "[FORCED-DEBUG]" or message has "[FORCED-Trace]"
  • Filter by your request/correlation id:
let rid = "a3f2e6d9f81e4e9e9f6b2d3f4c5a6b7c";
traces | where timestamp > ago(1d) | where message startswith strcat("[", rid, "] ")
  • Volume/severity distribution:
traces | where timestamp > ago(24h) | summarize count() by severityLevel | order by severityLevel asc

8) Changelog (high‑level)

  • Automatic correlation id when not provided.
  • Unified refresh interval for SDK and local throttle.
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.