DevSource.Observability 1.0.0

dotnet add package DevSource.Observability --version 1.0.0
                    
NuGet\Install-Package DevSource.Observability -Version 1.0.0
                    
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="DevSource.Observability" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DevSource.Observability" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="DevSource.Observability" />
                    
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 DevSource.Observability --version 1.0.0
                    
#r "nuget: DevSource.Observability, 1.0.0"
                    
#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 DevSource.Observability@1.0.0
                    
#: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=DevSource.Observability&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=DevSource.Observability&version=1.0.0
                    
Install as a Cake Tool

DevSource.Observability

.NET C%23 NuGet Tests

DevSource Observability native .NET observability package for structured logging, HTTP context enrichment, and OpenTelemetry bootstrapping.

Target

  • net10.0

Installation

dotnet add package DevSource.Observability

Stable v1 Contract

The following public surface is part of the stable 1.x contract:

  • services.AddObservability()
  • services.AddObservability(configuration)
  • ObservabilityOptions and nested option classes under DevSource.Observability.Options
  • IObservabilityContextAccessor and ObservabilityContext
  • logger.BeginObservabilityScope(...)
  • SensitiveDataRedactor
  • DevSourceLogLineFormatter
  • ObservabilityScopeKeys

Compatibility policy for 1.x:

  • existing public members in the stable contract will not be removed or have breaking signature changes in minor or patch releases
  • new optional members may be added in minor releases
  • behavior fixes that correct bugs or tighten security redaction may ship in patch releases

Trusted Boundary

CorrelationId and TenantId received from HTTP headers are treated as untrusted input.

  • CorrelationId is accepted only when it matches the package safety policy
  • invalid CorrelationId values are discarded and replaced with a safe fallback
  • TenantId is observational only and must not be used as an authorization source
  • invalid TenantId values are ignored instead of being propagated
  • keep Logging.IncludePayload=false by default in production
  • enable payload capture only for controlled scenarios with a reviewed redaction list
  • keep Logging.MaxPayloadLength bounded
  • prefer OTLP through OpenTelemetry Collector for production routing
  • keep CorrelationId and TenantId short, stable, and machine-friendly

Default sensitive fields redacted by the package:

  • password
  • cpf
  • cnpj
  • document
  • ssn
  • token
  • apiKey
  • refreshToken
  • secret
  • authorization

Payload handling rules:

  • object payloads are serialized to JSON and redacted recursively
  • JSON strings are parsed and redacted when TryRedactJsonStrings=true
  • non-JSON strings and binary-like content are treated as opaque text and only length-limited, not deeply redacted by structure

Why IncludePayload=false is the production default:

  • traces and metrics are usually better tools for latency and bottleneck analysis
  • structured business fields are usually better than full payload capture for searchable logs
  • full payload capture increases privacy risk, cardinality, indexing cost, and CPU usage
  • enable payload capture selectively for diagnostic flows, controlled environments, or specific categories of operations

Configuration

{
  "Observability": {
    "ApplicationName": "Catalog.Api",
    "Environment": "Production",
    "Logging": {
      "Enabled": true,
      "Console": true,
      "FormattedConsole": true,
      "IncludePayload": false,
      "MaxPayloadLength": 2048,
      "TryRedactJsonStrings": true,
      "RedactFields": [
        "password",
        "cpf",
        "cnpj",
        "document",
        "ssn",
        "token",
        "apiKey",
        "refreshToken",
        "secret",
        "authorization"
      ]
    },
    "Tracing": {
      "Enabled": true
    },
    "Metrics": {
      "Enabled": true
    },
    "Exporters": {
      "UseOtlp": true,
      "OtlpEndpoint": "http://localhost:4317"
    },
    "Http": {
      "Enabled": true,
      "CorrelationIdHeaderName": "X-Correlation-Id",
      "TenantIdHeaderName": "X-Tenant-Id",
      "MaxCorrelationIdLength": 64,
      "MaxTenantIdLength": 128
    }
  }
}

HTTP header safety policy used by default:

  • maximum CorrelationId length: 64
  • maximum TenantId length: 128
  • accepted characters: A-Z, a-z, 0-9, -, _, ., :
  • invalid CorrelationId values are replaced with a generated fallback
  • invalid TenantId values are ignored

ASP.NET Core Usage

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddObservability(builder.Configuration);
builder.Services.AddHttpClient();

var app = builder.Build();

app.MapGet("/customers/{id}", (string id, ILoggerFactory loggerFactory) =>
{
    var logger = loggerFactory.CreateLogger("Customers");

    using var scope = logger.BeginObservabilityScope(
        actionName: "GetCustomer",
        tenantId: "tenant-01",
        correlationId: "corr-123");

    logger.LogInformation("Customer {CustomerId} retrieved", id);
    return Results.Ok(new { id });
});

app.Run();

For ASP.NET Core applications the HTTP context middleware is registered automatically through a startup filter.

HttpClientFactory Correlation Propagation

Every HttpClient created through IHttpClientFactory automatically receives the current correlation header when a correlation id is available in IObservabilityContextAccessor.

builder.Services.AddObservability(builder.Configuration);
builder.Services.AddHttpClient("billing");

If you customize Observability:Http:CorrelationIdHeaderName, the same header name is used both on inbound and outbound HTTP flows.

If you customize the max lengths, keep them conservative unless you fully control every upstream client and downstream observability tool.

Optional Logging Scope

using DevSource.Observability.Logging;

using var scope = logger.BeginObservabilityScope(
    actionName: "CreateCustomer",
    tenantId: "tenant-01",
    correlationId: "corr-123",
    payload: new { name = "John Doe", password = "123456" });

logger.LogInformation("Customer created");

Payloads attached to the scope are redacted when they contain configured sensitive field names.

HTTP Context Enrichment

For web applications the package automatically captures:

  • RequestId from HttpContext.TraceIdentifier
  • TraceId from Activity.Current
  • CorrelationId from the configured correlation header or a generated fallback
  • TenantId from the configured tenant header

The resolved CorrelationId is also written back to the response header.

ActionName Behavior

ActionName resolution follows this order:

  • route pattern from the resolved endpoint, when available
  • request path as fallback
  • explicit override when you open a manual logging scope with BeginObservabilityScope(...)

Known limitations:

  • if routing has not selected an endpoint yet, route-template-based names are not available
  • minimal APIs and MVC routes produce template-based names only after endpoint resolution
  • non-HTTP background work must set actionName explicitly when a stable business action name is required

Production Guidance

  • treat inbound correlation and tenant headers as untrusted input
  • use TenantId from headers only for observability context, never for authorization or tenancy enforcement
  • prefer logging key business fields explicitly instead of enabling payload capture globally
  • if auditing is required, model audit events intentionally instead of relying on raw payload logging alone

OTLP + Collector Guidance

Production recommendation:

  • application exports OTLP to Collector
  • Collector fans out to Jaeger, Loki, Seq, Elasticsearch, Prometheus, or other destinations

Minimal Collector endpoint example:

receivers:
  otlp:
    protocols:
      grpc:
      http:

exporters:
  debug: {}

service:
  pipelines:
    logs:
      receivers: [otlp]
      exporters: [debug]
    traces:
      receivers: [otlp]
      exporters: [debug]
    metrics:
      receivers: [otlp]
      exporters: [debug]

Console Output

[2026-06-04 21:30:12][INF][CreateCustomer][Customer created][tenant-01][-][trace-abc][corr-123]

Structured fields remain the canonical representation for OpenTelemetry and downstream tools.

Destination Guidance

  • OTLP: preferred path for logs, traces, and metrics
  • OpenTelemetry Collector: recommended production gateway and fan-out layer
  • Jaeger: validated for traces through OpenTelemetry pipelines
  • Seq: validated for logs through OTLP or Collector-based routing
  • Grafana and Loki: validated through OTLP plus Collector
  • Elasticsearch and Kibana: validated through Collector-compatible ingestion; for traces with OTEL mapping mode, use 8.16+ as the practical minimum recommended baseline
  • Prometheus: recommended through OpenTelemetry Collector or another OTLP-compatible metrics pipeline

Release Notes

Current stable release: 1.0.0.

See CHANGELOG.md for the package changelog.

Product Compatible and additional computed target framework versions.
.NET 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. 
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.

Version Downloads Last Updated
1.0.0 92 6/6/2026