DevSource.Observability
1.0.0
dotnet add package DevSource.Observability --version 1.0.0
NuGet\Install-Package DevSource.Observability -Version 1.0.0
<PackageReference Include="DevSource.Observability" Version="1.0.0" />
<PackageVersion Include="DevSource.Observability" Version="1.0.0" />
<PackageReference Include="DevSource.Observability" />
paket add DevSource.Observability --version 1.0.0
#r "nuget: DevSource.Observability, 1.0.0"
#:package DevSource.Observability@1.0.0
#addin nuget:?package=DevSource.Observability&version=1.0.0
#tool nuget:?package=DevSource.Observability&version=1.0.0
DevSource.Observability
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)ObservabilityOptionsand nested option classes underDevSource.Observability.OptionsIObservabilityContextAccessorandObservabilityContextlogger.BeginObservabilityScope(...)SensitiveDataRedactorDevSourceLogLineFormatterObservabilityScopeKeys
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.
CorrelationIdis accepted only when it matches the package safety policy- invalid
CorrelationIdvalues are discarded and replaced with a safe fallback TenantIdis observational only and must not be used as an authorization source- invalid
TenantIdvalues are ignored instead of being propagated
Recommended Production Defaults
- keep
Logging.IncludePayload=falseby default in production - enable payload capture only for controlled scenarios with a reviewed redaction list
- keep
Logging.MaxPayloadLengthbounded - prefer OTLP through OpenTelemetry Collector for production routing
- keep
CorrelationIdandTenantIdshort, stable, and machine-friendly
Default sensitive fields redacted by the package:
passwordcpfcnpjdocumentssntokenapiKeyrefreshTokensecretauthorization
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
CorrelationIdlength:64 - maximum
TenantIdlength:128 - accepted characters:
A-Z,a-z,0-9,-,_,.,: - invalid
CorrelationIdvalues are replaced with a generated fallback - invalid
TenantIdvalues 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:
RequestIdfromHttpContext.TraceIdentifierTraceIdfromActivity.CurrentCorrelationIdfrom the configured correlation header or a generated fallbackTenantIdfrom 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
actionNameexplicitly when a stable business action name is required
Production Guidance
- treat inbound correlation and tenant headers as untrusted input
- use
TenantIdfrom 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 metricsOpenTelemetry Collector: recommended production gateway and fan-out layerJaeger: validated for traces through OpenTelemetry pipelinesSeq: validated for logs through OTLP or Collector-based routingGrafanaandLoki: validated through OTLP plus CollectorElasticsearchandKibana: validated through Collector-compatible ingestion; for traces with OTEL mapping mode, use8.16+as the practical minimum recommended baselinePrometheus: 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 | Versions 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. |
-
net10.0
- DevSource.Foundation (>= 1.0.1)
- OpenTelemetry (>= 1.15.3)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.15.3)
- OpenTelemetry.Extensions.Hosting (>= 1.15.3)
- OpenTelemetry.Instrumentation.AspNetCore (>= 1.15.2)
- OpenTelemetry.Instrumentation.Http (>= 1.15.1)
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 |