Elven.Observability.NotaCarioca.Logging.NLog
0.1.0-alpha.4
dotnet add package Elven.Observability.NotaCarioca.Logging.NLog --version 0.1.0-alpha.4
NuGet\Install-Package Elven.Observability.NotaCarioca.Logging.NLog -Version 0.1.0-alpha.4
<PackageReference Include="Elven.Observability.NotaCarioca.Logging.NLog" Version="0.1.0-alpha.4" />
<PackageVersion Include="Elven.Observability.NotaCarioca.Logging.NLog" Version="0.1.0-alpha.4" />
<PackageReference Include="Elven.Observability.NotaCarioca.Logging.NLog" />
paket add Elven.Observability.NotaCarioca.Logging.NLog --version 0.1.0-alpha.4
#r "nuget: Elven.Observability.NotaCarioca.Logging.NLog, 0.1.0-alpha.4"
#:package Elven.Observability.NotaCarioca.Logging.NLog@0.1.0-alpha.4
#addin nuget:?package=Elven.Observability.NotaCarioca.Logging.NLog&version=0.1.0-alpha.4&prerelease
#tool nuget:?package=Elven.Observability.NotaCarioca.Logging.NLog&version=0.1.0-alpha.4&prerelease
Elven Observability Nota Carioca .NET Framework 4.7.2/4.8
Elven Observability Nota Carioca is a safe-default OpenTelemetry distribution for critical .NET Framework 4.7.2 and 4.8 applications.
It is designed for legacy enterprise systems where low risk, easy rollback, and predictable behavior matter more than magic.
The library exports telemetry to a customer-side OpenTelemetry Collector. Application code should not contain Elven backend credentials. Keep backend tokens and tenant routing in the Collector.
What You Get
- Traces, metrics, and logs for .NET Framework 4.7.2 and 4.8.
- W3C trace context where possible.
- WCF client/server instrumentation through Elven behaviors and message inspectors.
- ASP.NET classic HTTP module support, including ASMX/SOAP operation naming.
- Outbound HTTP and SQL instrumentation through stable OpenTelemetry packages.
- Oracle datastore spans through an explicit low-risk ADO.NET helper.
- EF6 support through an explicit
DbCommandInterceptor. - Manual business spans and business/product metrics.
- log4net, NLog, Serilog, and System.Diagnostics bridges.
- Redaction and masking before export.
- Kill switches through
app.config,web.config, or environment variables.
Supported Runtime
- .NET Framework 4.7.2 and 4.8.
- Windows Server, IIS, IIS Express, Windows Services, and console apps.
- ASP.NET classic, ASP.NET MVC/Web API on .NET Framework, WCF, EF6, ADO.NET, and legacy logging frameworks.
This package is not for ASP.NET Core or modern .NET. Use the modern Elven .NET package for those applications.
Quick Start
Use this order for a first installation in a legacy app.
- Make sure an OpenTelemetry Collector is reachable from the application.
- Install the package or packages needed by the app.
- Configure
appSettingsor environment variables. - Initialize Elven Observability once during application startup.
- Add WCF, ASP.NET, EF6, or logging bridge wiring only where needed.
- Add business metrics and spans for critical journeys.
- Run locally or in staging with the Collector offline and online.
- Keep rollback ready with
ELVEN_ENABLED=false.
Packages
The meta-package is intentionally conservative. It includes the safe default surface for core bootstrap, ASP.NET classic/ASMX, HTTP, SQL, Oracle helper APIs, and business APIs. WCF, EF6, and logging bridges are installed explicitly so critical legacy apps do not pull unnecessary dependencies.
dotnet add package Elven.Observability.NotaCarioca
For older non-SDK-style .NET Framework projects, Visual Studio Package Manager Console is usually easier:
Install-Package Elven.Observability.NotaCarioca
You can also use the Visual Studio NuGet Package Manager UI. The important part is that the installed packages appear in the application project that owns the final app.config or web.config.
Install extra packages based on what the application actually uses:
| Scenario | Package |
|---|---|
| WCF client/server behaviors | Elven.Observability.NotaCarioca.Wcf |
| Oracle ADO.NET helper | Elven.Observability.NotaCarioca.Oracle |
| EF6 command interceptor | Elven.Observability.NotaCarioca.EF6 |
| log4net bridge | Elven.Observability.NotaCarioca.Logging.Log4Net |
| NLog bridge | Elven.Observability.NotaCarioca.Logging.NLog |
| Serilog bridge | Elven.Observability.NotaCarioca.Logging.Serilog |
| System.Diagnostics Trace bridge | Elven.Observability.NotaCarioca.Logging.SystemDiagnostics |
| Core-only custom integration | Elven.Observability.NotaCarioca.Core |
| Business-only API reference | Elven.Observability.NotaCarioca.Business |
Typical WCF service:
dotnet add package Elven.Observability.NotaCarioca
dotnet add package Elven.Observability.NotaCarioca.Wcf
dotnet add package Elven.Observability.NotaCarioca.Logging.Log4Net
Typical ASP.NET MVC/Web API application:
dotnet add package Elven.Observability.NotaCarioca
dotnet add package Elven.Observability.NotaCarioca.EF6
dotnet add package Elven.Observability.NotaCarioca.Logging.NLog
Typical ASP.NET WebForms/ASMX application with Oracle:
Install-Package Elven.Observability.NotaCarioca -Version 0.1.0-alpha.4 -Prerelease
Install-Package Elven.Observability.NotaCarioca.Oracle -Version 0.1.0-alpha.4 -Prerelease
Install-Package Elven.Observability.NotaCarioca.Logging.SystemDiagnostics -Version 0.1.0-alpha.4 -Prerelease
Collector First
Configure the application to send OTLP to a local or customer-side Collector:
<appSettings>
<add key="ELVEN_SERVICE_NAME" value="nota-carioca-nfse" />
<add key="ELVEN_ENVIRONMENT" value="production" />
<add key="OTEL_EXPORTER_OTLP_ENDPOINT" value="http://otel-collector.local:4318" />
<add key="OTEL_EXPORTER_OTLP_PROTOCOL" value="http/protobuf" />
</appSettings>
The default protocol is http/protobuf on port 4318. This is the recommended default for legacy .NET Framework applications. gRPC is available only when explicitly configured and validated in the customer's runtime.
Collector reference config:
Initialization
Initialize once per AppDomain.
Do this before the first ElvenMetrics, ElvenTrace, EF6 registration, or logging bridge call. The manual facades have a lazy safety net, but production apps should initialize explicitly during startup so service name, environment, collector endpoint, and kill switches are resolved before telemetry begins.
For config-first applications, use Initialize() and keep values in app.config, web.config, or environment variables:
using Elven.Observability.NotaCarioca;
var observability = ElvenObservability.Initialize();
For config plus a small code override, use the callback overload. This reads app settings and env vars first, then applies the callback:
using Elven.Observability.NotaCarioca;
var observability = ElvenObservability.Initialize(options =>
{
options.ServiceVersion = typeof(Program).Assembly.GetName().Version?.ToString();
options.EnableWcfInstrumentation = true;
});
For full programmatic configuration, pass ElvenLegacyOptions directly:
using Elven.Observability.NotaCarioca;
var observability = ElvenObservability.Initialize(new ElvenLegacyOptions
{
ServiceName = "nota-carioca-nfse",
Environment = "production",
CollectorEndpoint = new Uri("http://otel-collector.local:4318"),
EnableWcfInstrumentation = true,
EnableSqlInstrumentation = true,
EnableLog4NetBridge = true
});
Important: external false kill switches in env vars or appSettings still win over programmatic true.
Dispose the handle during controlled shutdown. Dispose() already performs a timeout-bounded flush, so do not call ForceFlushAsync() immediately before it:
observability.Dispose();
Configuration Reference
Common keys:
| Key | Default | Purpose |
|---|---|---|
ELVEN_ENABLED |
true |
Global kill switch. Set false for emergency rollback. |
ELVEN_SERVICE_NAME |
unknown-legacy-service |
Logical service name. Set this in every app. |
ELVEN_SERVICE_NAMESPACE |
legacy |
Optional namespace for grouping services. |
ELVEN_SERVICE_VERSION |
empty | App version. Useful for release correlation. |
ELVEN_ENVIRONMENT |
empty | production, staging, qa, etc. |
OTEL_EXPORTER_OTLP_ENDPOINT |
http://localhost:4318 |
Collector base endpoint. With http/protobuf, the library sends traces to /v1/traces, metrics to /v1/metrics, and logs to /v1/logs. |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT |
empty | Optional traces-only endpoint. Use the full OTLP/HTTP path, for example http://localhost:4318/v1/traces. |
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT |
empty | Optional metrics-only endpoint. Use the full OTLP/HTTP path, for example http://localhost:4318/v1/metrics. |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT |
empty | Optional logs-only endpoint. Use the full OTLP/HTTP path, for example http://localhost:4318/v1/logs. |
OTEL_EXPORTER_OTLP_PROTOCOL |
http/protobuf |
Use http/protobuf unless gRPC is validated. |
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL |
empty | Optional traces-only protocol override. |
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL |
empty | Optional metrics-only protocol override. |
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL |
empty | Optional logs-only protocol override. |
OTEL_EXPORTER_OTLP_TIMEOUT |
30000 |
Export timeout in milliseconds. |
OTEL_EXPORTER_OTLP_TRACES_TIMEOUT |
empty | Optional traces-only timeout in milliseconds. |
OTEL_EXPORTER_OTLP_METRICS_TIMEOUT |
empty | Optional metrics-only timeout in milliseconds. |
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT |
empty | Optional logs-only timeout in milliseconds. |
OTEL_METRIC_EXPORT_INTERVAL |
60000 |
Metric export interval in milliseconds. |
OTEL_TRACES_EXPORTER |
otlp |
Set none to disable trace export. |
OTEL_METRICS_EXPORTER |
otlp |
Set none to disable metric export. |
OTEL_LOGS_EXPORTER |
otlp |
Set none to disable log export. |
OTEL_TRACES_SAMPLER |
always_on equivalent |
Supports always_on, always_off, and ratio through OTEL_TRACES_SAMPLER_ARG. |
ELVEN_REDACTION_MODE |
default |
Use default or strict. off/none is only for controlled non-production tests. Hard secrets still stay redacted. |
ELVEN_LOG_BODY_MODE |
redacted |
Controls log body handling independently from trace/log correlation. Values: redacted, metadata, off, passthrough. |
ELVEN_ALLOWED_RAW_ATTRIBUTES |
empty | Exact allowlist for raw attributes. Use sparingly. It never bypasses hard-secret redaction. |
ELVEN_MARK_ACTIVE_SPAN_ON_ERROR_LOG |
false |
Opt-in: when a legacy log bridge emits Error or higher and an Activity is active, mark that span as error and add a sanitized log.error event. |
ELVEN_MAX_METRIC_TAG_COUNT |
12 |
Maximum tags per metric datapoint. |
ELVEN_MAX_TAG_VALUE_LENGTH |
256 |
Maximum tag value length. |
ELVEN_MAX_STATEMENT_LENGTH |
8192 |
Maximum exported db.statement / db.query.text length after redaction. Truncated statements end with [TRUNCATED]. |
ELVEN_MAX_LOG_BODY_LENGTH |
65536 |
Maximum log body length emitted by Elven log bridges after redaction. Truncated bodies end with [TRUNCATED]. |
Module kill switches:
| Key | Default | Purpose |
|---|---|---|
ELVEN_ENABLE_ASPNET |
true |
ASP.NET classic HTTP module. |
ELVEN_ENABLE_ASMX |
true |
ASMX/SOAP naming and metadata when the ASP.NET module sees .asmx requests. |
ELVEN_ENABLE_HTTP |
true |
Outbound HTTP instrumentation. |
ELVEN_ENABLE_SQL |
true |
SqlClient instrumentation. |
ELVEN_ENABLE_ORACLE |
true |
Manual Oracle ADO.NET helper spans and metrics. Safe no-op unless the helper is called. |
ELVEN_ENABLE_EF6 |
false |
EF6 interceptor support. Requires explicit registration. |
ELVEN_ENABLE_WCF |
false |
WCF behavior/message inspector support. |
ELVEN_ENABLE_RUNTIME_METRICS |
true |
Runtime metrics. |
ELVEN_ENABLE_PROCESS_METRICS |
false |
Process gauges. Opt-in. |
ELVEN_ENABLE_LOG4NET |
false |
log4net bridge. |
ELVEN_ENABLE_NLOG |
false |
NLog bridge. |
ELVEN_ENABLE_SERILOG |
false |
Serilog bridge. |
ELVEN_ENABLE_SYSTEM_DIAGNOSTICS |
false |
System.Diagnostics TraceListener bridge. |
Emergency rollback:
<appSettings>
<add key="ELVEN_ENABLED" value="false" />
</appSettings>
Signal-specific rollback:
<appSettings>
<add key="OTEL_TRACES_EXPORTER" value="none" />
<add key="OTEL_METRICS_EXPORTER" value="none" />
<add key="OTEL_LOGS_EXPORTER" value="none" />
</appSettings>
ASP.NET Classic
Install:
dotnet add package Elven.Observability.NotaCarioca
Add the module to web.config:
<configuration>
<appSettings>
<add key="ELVEN_SERVICE_NAME" value="legacy-web" />
<add key="ELVEN_ENVIRONMENT" value="production" />
<add key="OTEL_EXPORTER_OTLP_ENDPOINT" value="http://otel-collector.local:4318" />
<add key="OTEL_EXPORTER_OTLP_PROTOCOL" value="http/protobuf" />
<add key="ELVEN_ENABLE_ASPNET" value="true" />
<add key="ELVEN_ENABLE_ASMX" value="true" />
</appSettings>
<system.web>
<compilation targetFramework="4.7.2" />
<httpRuntime targetFramework="4.7.2" />
<httpModules>
<add name="ElvenObservability"
type="Elven.Observability.NotaCarioca.AspNet.ElvenAspNetHttpModule, Elven.Observability.NotaCarioca.AspNet" />
</httpModules>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<add name="ElvenObservability"
type="Elven.Observability.NotaCarioca.AspNet.ElvenAspNetHttpModule, Elven.Observability.NotaCarioca.AspNet" />
</modules>
</system.webServer>
</configuration>
The module creates inbound HTTP server spans, records status codes, records sanitized exceptions, and sets correlation_id from x-correlation-id or x-request-id when present.
ASMX/SOAP
ASMX instrumentation is part of the ASP.NET classic module. It does not read SOAP bodies. It uses the request path, PathInfo, and SOAPAction header to produce useful low-cardinality server span names.
For a request like:
POST /WSNacional/nfse.asmx
SOAPAction: "http://notacarioca.rio.gov.br/GerarNfse"
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
baggage: client=prefeitura-rio,journey=nfse
The server span is named:
ASMX nfse/GerarNfse
Common tags:
| Attribute | Example |
|---|---|
rpc.system |
asmx |
rpc.service |
nfse |
rpc.method |
GerarNfse |
soap.action |
http://notacarioca.rio.gov.br/GerarNfse |
http.route |
/WSNacional/nfse.asmx/GerarNfse |
http.response.status_code |
200 |
correlation_id |
existing or generated correlation id |
Inbound W3C traceparent, tracestate, and baggage are preserved so upstream services can continue the same distributed trace through the legacy ASMX app.
Manual Propagation For Legacy Threads And Web References
The ASP.NET module and supported HTTP instrumentation handle the common path. Some legacy code uses raw Thread, Timer, generated Web References, or custom HttpWebRequest creation where Activity.Current can be lost before the outbound call. In those cases, capture context before crossing the boundary and inject it explicitly.
Capture and restore context around background work:
var context = ElvenTrace.CaptureContext();
ThreadPool.QueueUserWorkItem(_ =>
{
using (ElvenTrace.StartBusinessSpan("NotaNacional Worker", new
{
journey = "nota_nacional",
phase = "api_fetch"
}, context))
{
// legacy worker code
}
});
VB.NET:
Dim context = ElvenTrace.CaptureContext()
Dim thread = New Threading.Thread(
Sub()
Using ElvenTrace.StartBusinessSpan(
"NotaNacional Worker",
New With {.journey = "nota_nacional", .phase = "api_fetch"},
context)
' legacy worker code
End Using
End Sub)
thread.Start()
Inject W3C headers manually when a legacy outbound client bypasses automatic instrumentation:
var request = (HttpWebRequest)WebRequest.Create(url);
ElvenPropagation.InjectHttpHeaders(request.Headers);
This writes traceparent, tracestate, baggage, x-correlation-id, and x-request-id when values are available. Header injection is fail-open: if a legacy transport rejects a header, the application call still continues.
WCF
WCF is first-class, but opt-in by design. The main package does not install WCF behaviors automatically.
Install both packages in the WCF application project:
Install-Package Elven.Observability.NotaCarioca -Version 0.1.0-alpha.4 -Prerelease
Install-Package Elven.Observability.NotaCarioca.Wcf -Version 0.1.0-alpha.4 -Prerelease
For SDK-style projects:
dotnet add package Elven.Observability.NotaCarioca --version 0.1.0-alpha.4
dotnet add package Elven.Observability.NotaCarioca.Wcf --version 0.1.0-alpha.4
WCF Setup Checklist
- Install
Elven.Observability.NotaCarioca. - Install
Elven.Observability.NotaCarioca.Wcf. - Set service name, environment, Collector endpoint, and
ELVEN_ENABLE_WCF=true. - Initialize Elven Observability once during app startup.
- Register the WCF behavior extension.
- Attach the service behavior to WCF services and the endpoint behavior to WCF clients.
- Run a staging call and verify one WCF client span and one WCF server span.
WCF App Settings
Use this in web.config or app.config:
<appSettings>
<add key="ELVEN_SERVICE_NAME" value="nota-carioca-nfse" />
<add key="ELVEN_ENVIRONMENT" value="production" />
<add key="OTEL_EXPORTER_OTLP_ENDPOINT" value="http://otel-collector.local:4318" />
<add key="OTEL_EXPORTER_OTLP_PROTOCOL" value="http/protobuf" />
<add key="ELVEN_ENABLE_WCF" value="true" />
</appSettings>
Emergency rollback:
<appSettings>
<add key="ELVEN_ENABLED" value="false" />
</appSettings>
WCF-only rollback:
<appSettings>
<add key="ELVEN_ENABLE_WCF" value="false" />
</appSettings>
WCF Startup Code
Initialize once before the first WCF call or before opening a ServiceHost.
ASP.NET/IIS-hosted .svc service, for example in Global.asax:
using System;
using System.Web;
using Elven.Observability.NotaCarioca;
public class Global : HttpApplication
{
private static IElvenObservabilityHandle observability;
protected void Application_Start(object sender, EventArgs e)
{
observability = ElvenObservability.Initialize();
}
protected void Application_End(object sender, EventArgs e)
{
if (observability != null)
{
observability.Dispose();
}
}
}
Windows Service or console-hosted WCF:
using System;
using System.ServiceModel;
using Elven.Observability.NotaCarioca;
public static class Program
{
public static void Main()
{
var observability = ElvenObservability.Initialize();
try
{
using (var host = new ServiceHost(typeof(NfseService)))
{
host.Open();
Console.WriteLine("WCF service is running. Press ENTER to stop.");
Console.ReadLine();
}
}
finally
{
observability.Dispose();
}
}
}
The WCF inspectors also have a lazy safety net, but explicit startup initialization is the recommended production path.
Register The WCF Behavior Extension
Add this once under system.serviceModel:
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="elvenObservability"
type="Elven.Observability.NotaCarioca.Wcf.ElvenWcfBehaviorExtensionElement, Elven.Observability.NotaCarioca.Wcf" />
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="observedEndpoint">
<elvenObservability serviceName="nota-carioca-nfse" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="observedService">
<elvenObservability serviceName="nota-carioca-nfse" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
serviceName is optional, but recommended. Use the same logical service name that the client expects to see in dashboards, for example nota-carioca-nfse, nfse-web, or nota-carioca-worker.
WCF Server Service
For WCF services, attach behaviorConfiguration="observedService" to the service. The service behavior observes all endpoints hosted by that service:
<system.serviceModel>
<services>
<service name="GovRio.Nfse.NfseService"
behaviorConfiguration="observedService">
<endpoint address=""
binding="basicHttpBinding"
contract="GovRio.Nfse.INfseService" />
</service>
</services>
</system.serviceModel>
For services with multiple endpoints, keep the service behavior on the service and list the endpoints normally:
<endpoint address="basic"
binding="basicHttpBinding"
contract="GovRio.Nfse.INfseService" />
<endpoint address="tcp"
binding="netTcpBinding"
contract="GovRio.Nfse.INfseService" />
Avoid attaching both observedService and observedEndpoint to the same server endpoint. The library has a defensive duplicate-inspector guard, but the clean configuration is service behavior for servers and endpoint behavior for clients.
WCF Client Endpoint
Attach behaviorConfiguration="observedEndpoint" to the generated or hand-written WCF client endpoint:
<system.serviceModel>
<client>
<endpoint name="NfseService"
address="http://nfse.local/NfseService.svc"
binding="basicHttpBinding"
contract="GovRio.Nfse.INfseService"
behaviorConfiguration="observedEndpoint" />
</client>
</system.serviceModel>
If the application has several external service endpoints, configure each one explicitly:
<client>
<endpoint name="Amadeus"
address="http://nfse-provider.local/NfseService.svc"
binding="basicHttpBinding"
contract="GovRio.Nfse.INfseService"
behaviorConfiguration="observedEndpoint" />
<endpoint name="Gol"
address="net.tcp://prefeitura.local:808/NfseService"
binding="netTcpBinding"
contract="GovRio.Nfse.INfseService"
behaviorConfiguration="observedEndpoint" />
</client>
What WCF Telemetry Includes
The WCF behavior records:
- client spans for outbound WCF calls;
- server spans for inbound WCF operations;
rpc.system=wcf;- service/contract information when available;
- operation/action name;
- binding name, such as
BasicHttpBindingorNetTcpBinding; - endpoint/remote address when available;
- SOAP Fault detection;
- WCF duration metrics through
rpc.server.duration,rpc.client.duration, and HTTP-compatiblehttp.server.request.duration/http.client.request.duration; - WCF error category for SOAP Faults and abandoned calls;
- exception type and sanitized message when the exception is recorded by a manual span, logging bridge, ASP.NET module, or surrounding application catch block;
correlation_idfor cross-signal dashboards.
What WCF Telemetry Does Not Collect By Default
The library does not collect giant SOAP/XML bodies by default.
By default it does not export:
- SOAP envelope body;
- raw request XML;
- raw response XML;
- WS-Security credentials;
- tokens, passwords, session ids, cookies, cards, CPF/CNPJ, e-mail, or phone values;
- arbitrary application headers. Header allowlists are reserved for a future implementation and do not enable capture in this release.
This is intentional for legacy enterprise systems. It gives observability for calls, dependencies, faults, latency, and correlation without moving sensitive payloads into telemetry.
WCF Context Propagation
Outbound WCF clients inject:
traceparenttracestatebaggagex-correlation-id
Inbound WCF services extract:
traceparenttracestatebaggagex-correlation-idx-request-id
Propagation is written to SOAP headers and to HTTP headers when the binding exposes HTTP transport headers. netTcpBinding still carries SOAP headers.
If a caller sends W3C context, Elven continues that trace. If no W3C context exists, Elven creates a trace and uses correlation_id as the fallback business/operations correlation key.
WCF Business Metrics Example
Automatic WCF spans show the technical call. Add business metrics around the operation to power journey dashboards:
using Elven.Observability.NotaCarioca;
public NfseResponse ConsultarNfse(NfseRequest request)
{
var started = DateTimeOffset.UtcNow;
using (var span = ElvenTrace.StartBusinessSpan("ConsultarNfse", new
{
journey = "consulta_nfse",
provider = request.Provider,
source = "nota-carioca",
client_id = request.ClientId
}))
{
try
{
var response = providerClient.ConsultarNfse(request);
ElvenMetrics.Counter("nfse.consulta.requested")
.Add(1, new
{
journey = "consulta_nfse",
provider = request.Provider,
status = "success"
});
span.SetAttribute("result", "success");
return response;
}
catch (TimeoutException ex)
{
span.RecordException(ex);
ElvenMetrics.Counter("nfse.consulta.failed")
.Add(1, new
{
journey = "consulta_nfse",
provider = request.Provider,
error_category = "provider_error"
});
throw;
}
finally
{
ElvenMetrics.Duration("external_service.latency")
.Record(DateTimeOffset.UtcNow - started, new
{
journey = "consulta_nfse",
provider = request.Provider,
operation = "consulta_nfse"
});
}
}
}
client_id is hashed by default before export. Sensitive values inside tags are redacted before they leave the process.
Manual WCF Fallback
If the automatic behavior does not fit a legacy binding, keep the package installed and use manual spans around critical operations:
using System;
using Elven.Observability.NotaCarioca.Wcf;
using (ElvenWcfManual.StartOperation("ConsultarNfse", new
{
journey = "consulta_nfse",
provider = "nota-carioca"
}))
{
try
{
// WCF operation code
}
catch (Exception ex)
{
ElvenWcfManual.RecordException(ex);
throw;
}
}
WCF Validation Checklist
After installation, validate these items in staging:
- the app starts with
ELVEN_ENABLE_WCF=true; - the same app starts with
ELVEN_ENABLE_WCF=false; - one successful WCF call produces a client span;
- the server side produces a server span when the service is also instrumented;
traceparentis propagated between client and server;correlation_idis present in traces and logs;- SOAP Faults are marked as errors;
- no SOAP body or large XML payload appears in telemetry;
- app pool recycle or service stop flushes telemetry when possible.
Common fixes:
- If there are no WCF spans, confirm
Elven.Observability.NotaCarioca.Wcfis installed in the executable/web app project. - Confirm
ELVEN_ENABLE_WCF=true. - Confirm the behavior extension is registered under
system.serviceModel/extensions/behaviorExtensions. - For server-side spans, confirm
behaviorConfiguration="observedService"is attached to the<service>. - For client-side spans, confirm
behaviorConfiguration="observedEndpoint"is attached to the exact<client>endpoint used by the application. - For generated service references, edit the generated client endpoint in
app.configorweb.config, not only the service contract. - For HTTPS, WS-Security, custom bindings, and certificate-heavy scenarios, validate in staging with customer-like bindings before broad rollout.
Complete Minimal WCF Example
This is the smallest complete shape most WCF applications need. Keep the services section for a WCF server, keep the client section for a WCF client, or keep both when the same process acts as both.
<configuration>
<appSettings>
<add key="ELVEN_SERVICE_NAME" value="nota-carioca-nfse" />
<add key="ELVEN_ENVIRONMENT" value="production" />
<add key="OTEL_EXPORTER_OTLP_ENDPOINT" value="http://otel-collector.local:4318" />
<add key="OTEL_EXPORTER_OTLP_PROTOCOL" value="http/protobuf" />
<add key="ELVEN_ENABLE_WCF" value="true" />
</appSettings>
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="elvenObservability"
type="Elven.Observability.NotaCarioca.Wcf.ElvenWcfBehaviorExtensionElement, Elven.Observability.NotaCarioca.Wcf" />
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="observedEndpoint">
<elvenObservability serviceName="nota-carioca-nfse" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="observedService">
<elvenObservability serviceName="nota-carioca-nfse" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="GovRio.Nfse.NfseService"
behaviorConfiguration="observedService">
<endpoint address=""
binding="basicHttpBinding"
contract="GovRio.Nfse.INfseService" />
</service>
</services>
<client>
<endpoint name="NfseService"
address="http://nfse.local/NfseService.svc"
binding="basicHttpBinding"
contract="GovRio.Nfse.INfseService"
behaviorConfiguration="observedEndpoint" />
</client>
</system.serviceModel>
</configuration>
Programmatic startup:
using Elven.Observability.NotaCarioca;
ElvenObservability.Initialize();
Validated WCF Coverage
The CI release gate validates WCF coverage for:
basicHttpBinding;netTcpBinding;- W3C propagation;
correlation_idpropagation;- client and server spans;
- SOAP Fault error marking, exception classification, and metadata-only exception events in the isolated Windows GA smoke;
- duplicate-inspector protection when service and endpoint behaviors are accidentally configured together;
- abandoned client activity timeout protection.
SOAP Fault validation runs in a bounded isolated process because some .NET Framework test-host combinations do not terminate cleanly after a self-hosted fault channel. This does not change the production WCF lifecycle: the library does not install an IErrorHandler, inspect the SOAP payload, defer the customer's fault, or participate in fault construction.
HTTPS, WS-Security, custom bindings, and customer-specific certificate chains should still be validated in the customer's staging environment before fleet-wide rollout.
SQL And EF6
SqlClient instrumentation is enabled by default through ELVEN_ENABLE_SQL=true.
SQL statements and SQL parameters are redacted by default before export. The library keeps the operation shape while protecting values.
EF6 requires explicit registration:
dotnet add package Elven.Observability.NotaCarioca.EF6
using Elven.Observability.NotaCarioca;
using Elven.Observability.NotaCarioca.EF6;
ElvenObservability.Initialize();
ElvenEf6Instrumentation.Register();
Call ElvenEf6Instrumentation.Register() once during startup before EF6 queries start.
Dapper is usually covered through the underlying ADO.NET/SqlClient calls when SQL instrumentation is enabled.
Oracle ADO.NET
Oracle support is intentionally implemented as an explicit helper instead of a driver/profiler hook. This avoids forcing an Oracle.ManagedDataAccess upgrade in critical legacy apps.
Install:
Install-Package Elven.Observability.NotaCarioca.Oracle -Version 0.1.0-alpha.4 -Prerelease
Enable it:
<appSettings>
<add key="ELVEN_ENABLE_ORACLE" value="true" />
</appSettings>
Wrap the central ADO.NET execution point, not every repository method. In most legacy systems there is one DBCommand, DataAccess, or OracleHelper class where commands are executed:
using Elven.Observability.NotaCarioca.Oracle;
var result = ElvenOracleInstrumentation.ExecuteScalar(
command,
() => command.ExecuteScalar(),
new
{
business_operation = "GerarNfse",
journey = "nfse",
datastore = "oracle"
});
For VB.NET:
Imports Elven.Observability.NotaCarioca.Oracle
Dim result = ElvenOracleInstrumentation.ExecuteScalar(
command,
Function() command.ExecuteScalar(),
New With {
.business_operation = "GerarNfse",
.journey = "nfse",
.datastore = "oracle"
})
The helper records a client span and a duration histogram named db.client.operation.duration.
Common tags:
| Attribute | Example |
|---|---|
db.system.name |
oracle |
db.operation.name |
SELECT, UPDATE, BEGIN |
db.namespace |
database/schema name when available |
server.address |
Oracle data source when exposed by the provider |
db.statement / db.query.text |
statement shape with literals redacted |
db.query.parameter.count |
number of parameters |
status |
ok or error |
error.category |
classifier output |
By default the SQL/PLSQL statement shape is kept but literals, CPF/CNPJ, e-mail, tokens, GUIDs, binary values, and parameter values are redacted before export. ELVEN_MAX_STATEMENT_LENGTH bounds the exported statement after redaction, and truncated statements end with [TRUNCATED]. Do not add raw SQL parameters to ELVEN_ALLOWED_RAW_ATTRIBUTES.
Logging Bridges
Logs are exported through OpenTelemetry logs and are enriched with:
trace_idspan_idcorrelation_id- service name
- environment
- service version when configured
- host name
- process id
Each bridge has its own kill switch. Installing an appender/target/sink is not enough; the corresponding ELVEN_ENABLE_* flag must also be true.
Log bodies can be controlled separately from the bridge and from trace correlation:
| Mode | What is exported |
|---|---|
redacted |
Default. Keeps the log message/XML readable, redacts sensitive values, preserves trace/span/correlation fields. |
metadata |
Emits the log record with attributes and correlation, but replaces the body with [LOG_BODY_SUPPRESSED]. Useful when XML bodies are too large or too sensitive. |
off |
Drops log records emitted by Elven legacy bridges. Use the bridge kill switches when you want per-logger-family control. |
passthrough / raw |
Keeps non-sensitive body content as-is but still applies hard redaction for credentials, tokens, documents, cards, cookies, sessions, and SOAP security values. Use only for controlled debugging. |
ELVEN_MAX_LOG_BODY_LENGTH bounds the body emitted by Elven bridges after redaction. Increase it only for controlled troubleshooting windows; very large XML log bodies can dominate exporter, Collector, and Loki costs.
Example:
<appSettings>
<add key="ELVEN_ENABLE_LOG4NET" value="true" />
<add key="ELVEN_LOG_BODY_MODE" value="redacted" />
</appSettings>
log4net
Install:
dotnet add package Elven.Observability.NotaCarioca.Logging.Log4Net
Config:
<appSettings>
<add key="ELVEN_ENABLE_LOG4NET" value="true" />
</appSettings>
<log4net>
<appender name="Elven"
type="Elven.Observability.NotaCarioca.Logging.Log4Net.ElvenLog4NetAppender, Elven.Observability.NotaCarioca.Logging.Log4Net" />
<root>
<level value="INFO" />
<appender-ref ref="Elven" />
</root>
</log4net>
NLog
Install:
dotnet add package Elven.Observability.NotaCarioca.Logging.NLog
Config:
<appSettings>
<add key="ELVEN_ENABLE_NLOG" value="true" />
</appSettings>
<nlog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<extensions>
<add assembly="Elven.Observability.NotaCarioca.Logging.NLog" />
</extensions>
<targets>
<target xsi:type="ElvenObservability"
name="elven"
layout="${longdate}|${level}|${logger}|${message}" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="elven" />
</rules>
</nlog>
Serilog
Install:
dotnet add package Elven.Observability.NotaCarioca.Logging.Serilog
Code:
using Elven.Observability.NotaCarioca.Logging.Serilog;
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.ElvenObservability()
.CreateLogger();
Config:
<appSettings>
<add key="ELVEN_ENABLE_SERILOG" value="true" />
</appSettings>
System.Diagnostics.Trace
Install:
dotnet add package Elven.Observability.NotaCarioca.Logging.SystemDiagnostics
Code:
using Elven.Observability.NotaCarioca.Logging.SystemDiagnostics;
ElvenSystemDiagnosticsBridge.Install();
Config:
<appSettings>
<add key="ELVEN_ENABLE_SYSTEM_DIAGNOSTICS" value="true" />
</appSettings>
EventLog has a reserved config flag in this release, but no concrete EventLog bridge is shipped yet. Do not rely on EventLog ingestion until a dedicated bridge is added and tested.
Business Metrics
Business metrics are for product and journey dashboards, not just infrastructure dashboards.
Good examples:
- nfses created
- payment approvals
- payment denials
- external service latency
- fraud analysis decisions
- retries by provider
- queue depth
- active sessions
Bad examples:
- metric names containing a user id
- tags containing raw CPF, card, token, e-mail, phone, or session id
- tags with thousands of possible values
- creating a new metric name per provider, customer, or nfse
Mental Model
Use metric names for stable business facts.
Use tags for low-cardinality dimensions.
Good:
ElvenMetrics.Counter("nfse.document.created")
.Add(1, new { provider = "nota-carioca", journey = "emissao", status = "success" });
Avoid:
ElvenMetrics.Counter("nfse.document.created." + nfseId).Add(1);
Naming Conventions
Use lowercase dot-separated names:
nfse.session.openednfse.consulta.requestednfse.consulta.completednfse.document.createdpayment.authorizedpayment.deniedexternal_service.latencyexternal_service.retry.countfraud.analysis.completed
Use stable tag names:
journeybusiness.operationproviderchannelsourcestatusresulterror.categorypayment.gatewaypayment.statuscorrelation_id
Identifiers such as client_id, nfse.id, session.id, user.id, CPF/CNPJ, e-mail, phone, card, token, password, cookie, and API keys are protected by default. Ordinary correlation_id values are preserved because they are needed for cross-signal correlation, but sensitive-looking values are still sanitized.
C# anonymous objects cannot use dotted property names. In simple examples, use CLR-friendly aliases such as payment_gateway or error_category. If a dashboard or collector rule requires the exact dotted attribute name, pass a dictionary or annotate a DTO property with ElvenBusinessAttribute:
ElvenMetrics.Counter("payment.authorized")
.Add(1, new Dictionary<string, object>
{
["payment.gateway"] = "rede",
["payment.status"] = "approved",
["journey"] = "pagamento"
});
Counter
Use a counter for events that only go up.
ElvenMetrics.Counter("nfse.document.created", "NFS-e documents created")
.Add(1, new
{
journey = "emissao",
provider = "nota-carioca",
status = "success"
});
Use counters for:
- created NFS-e documents
- opened sessions
- failed payments
- provider errors
- retries
- validation failures
- business rule denials
Duration
Use duration for latency or elapsed time. Values are exported in milliseconds.
var started = DateTimeOffset.UtcNow;
try
{
// external service call
}
finally
{
var elapsed = DateTimeOffset.UtcNow - started;
ElvenMetrics.Duration("external_service.latency", "External service call latency")
.Record(elapsed, new
{
provider = "prefeitura",
operation = "consulta",
status = "success"
});
}
You can also record milliseconds directly:
ElvenMetrics.Duration("external_service.latency")
.Record(123.4, new { provider = "nota-carioca", operation = "consulta_nfse" });
Use duration for:
- external service call latency
- payment gateway latency
- fraud analysis latency
- nfse workflow elapsed time
- cache lookup latency
- database dependency latency when business-specific context matters
UpDownCounter
Use an up/down counter for values that can increase and decrease.
ElvenMetrics.UpDownCounter("nfse.sessions.active", "Active nfse sessions")
.Add(1, new { journey = "login" });
try
{
// active session work
}
finally
{
ElvenMetrics.UpDownCounter("nfse.sessions.active")
.Add(-1, new { journey = "login" });
}
Use up/down counters for:
- active sessions
- in-flight external service calls
- queue depth deltas
- active payment attempts
Full Journey Example
This pattern creates one business span and several metrics for the same user journey.
using Elven.Observability.NotaCarioca;
public NfseResponse EmitirNfse(NfseRequest request)
{
using (var span = ElvenTrace.StartBusinessSpan("EmitirNfse", new
{
journey = "emissao",
provider = request.Provider,
source = "nota-carioca",
client_id = request.ClientId
}))
{
var started = DateTimeOffset.UtcNow;
try
{
ElvenMetrics.Counter("nfse.document.attempted")
.Add(1, new
{
journey = "emissao",
provider = request.Provider
});
var response = providerClient.EmitirNfse(request);
ElvenMetrics.Counter("nfse.document.created")
.Add(1, new
{
journey = "emissao",
provider = request.Provider,
status = "success"
});
span.SetAttribute("result", "success");
return response;
}
catch (TimeoutException ex)
{
span.RecordException(ex);
span.SetAttribute("error.category", "provider_error");
ElvenMetrics.Counter("nfse.document.failed")
.Add(1, new
{
journey = "emissao",
provider = request.Provider,
error_category = "provider_error"
});
throw;
}
finally
{
ElvenMetrics.Duration("nfse.document.duration")
.Record(DateTimeOffset.UtcNow - started, new
{
journey = "emissao",
provider = request.Provider
});
}
}
}
Recommended Helper Class
For a large legacy system, centralize names in one class. This keeps dashboards stable.
public static class NfseTelemetry
{
public static void NfseCreated(string provider, string journey)
{
ElvenMetrics.Counter("nfse.document.created")
.Add(1, new
{
provider = provider,
journey = journey,
status = "success"
});
}
public static void ProviderLatency(string provider, string operation, TimeSpan elapsed)
{
ElvenMetrics.Duration("external_service.latency")
.Record(elapsed, new
{
provider = provider,
operation = operation
});
}
}
Then call:
NfseTelemetry.NfseCreated("nota-carioca", "emissao");
NfseTelemetry.ProviderLatency("prefeitura", "consulta", elapsed);
Tag Safety
Metric tags are sanitized before export.
The library:
- redacts sensitive keys such as
password,token,api_key,authorization,cookie,cpf,cnpj,card, anddocument; - redacts sensitive-looking values such as e-mails, CPF/CNPJ, card numbers, bearer/basic tokens, and phones;
- hashes known identifiers such as
client_id,user.id,nfse.id, andsession.id; - preserves ordinary
correlation_idvalues for correlation; - limits tag count through
ELVEN_MAX_METRIC_TAG_COUNT; - limits tag value length through
ELVEN_MAX_TAG_VALUE_LENGTH.
You can rename DTO properties with ElvenBusinessAttribute and force redaction with ElvenSensitive:
public sealed class NfseMetricTags
{
[ElvenBusinessAttribute("provider")]
public string Provider { get; set; }
[ElvenBusinessAttribute("journey")]
public string Journey { get; set; }
[ElvenSensitive]
public string RawDocument { get; set; }
}
Usage:
ElvenMetrics.Counter("nfse.document.created")
.Add(1, new NfseMetricTags
{
Provider = "nota-carioca",
Journey = "emissao",
RawDocument = request.Cpf
});
RawDocument will be exported as [REDACTED].
Business Spans
Use business spans around important operations. They create trace spans with business attributes and connect manual telemetry to automatic WCF, HTTP, and SQL spans.
using (ElvenTrace.StartBusinessSpan("AbrirSessao", new
{
client_id = clientId,
journey = "login",
provider = "nota-carioca"
}))
{
// customer code
}
For exception handling:
using (var span = ElvenTrace.StartBusinessSpan("Pagamento", new { journey = "pagamento" }))
{
try
{
gateway.Pay(request);
span.SetAttribute("payment.status", "approved");
}
catch (Exception ex)
{
span.RecordException(ex);
span.SetAttribute("payment.status", "failed");
throw;
}
}
For simple wrappers:
var result = ElvenTrace.Run("Antifraude", () =>
{
return fraudClient.Analyze(request);
}, new
{
journey = "pagamento",
provider = "fraud-provider"
});
Async:
var result = await ElvenTrace.RunAsync("Gateway", async () =>
{
return await gateway.AuthorizeAsync(request).ConfigureAwait(false);
}, new
{
journey = "pagamento",
payment_gateway = "rede"
}).ConfigureAwait(false);
You can add context later:
ElvenTrace.SetAttribute("provider", "nota-carioca");
ElvenTrace.SetBusinessContext(new { journey = "emissao", result = "success" });
Privacy Defaults
Default behavior:
- SQL statement shape is preserved, but literals, comments, GUIDs, binary values, comparison values, and
IN (...)lists are redacted. SQL parameters are fully redacted. - SOAP/XML shape is preserved, but sensitive element and attribute values are redacted.
- Authorization, cookie, session, password, token, API key, SOAP security, card, CPF/CNPJ, e-mail, and phone values are redacted.
- Known identifiers such as
client_id,user.id,nfse.id, andsession.idare hashed. - HTTP and SOAP payloads are not collected by default.
- Exception stack traces are not exported by default.
- Metric tag count and tag value length are bounded.
Raw attributes require an exact allowlist:
<appSettings>
<add key="ELVEN_ALLOWED_RAW_ATTRIBUTES" value="db.query.summary" />
</appSettings>
Do not allowlist secrets, tokens, documents, card data, cookies, raw SQL parameters, or raw payload fields.
ELVEN_REDACTION_MODE=none disables soft redaction for controlled tests, but hard secrets are still blocked. If you need to keep XML logs usable while protecting credentials, prefer the default ELVEN_LOG_BODY_MODE=redacted instead of disabling redaction globally.
To include exception stack traces in a controlled environment:
<appSettings>
<add key="ELVEN_CAPTURE_EXCEPTION_STACKTRACE" value="true" />
</appSettings>
Production Rollout Checklist
Before enabling in production:
- Confirm
ELVEN_SERVICE_NAME,ELVEN_ENVIRONMENT, and Collector endpoint. - Confirm Collector can receive traces, metrics, and logs on
4318. - Enable one app first, not the whole fleet.
- Start with default redaction.
- Keep payload capture off.
- Keep WCF and EF6 opt-in.
- Add business metrics only with low-cardinality tags.
- Verify dashboards and traces in staging.
- Test rollback with
ELVEN_ENABLED=false. - Confirm app shutdown or recycle flush behavior where possible.
Troubleshooting
No telemetry:
- Check
ELVEN_ENABLEDis notfalse. - Check
OTEL_TRACES_EXPORTER,OTEL_METRICS_EXPORTER, andOTEL_LOGS_EXPORTERare notnone. - Check
OTEL_EXPORTER_OTLP_ENDPOINTpoints to the Collector, not directly to Elven. - Check firewall and DNS from the app server to the Collector.
- Check Collector logs for rejected data.
No WCF spans:
- Check
Elven.Observability.NotaCarioca.Wcfis installed. - Check
ELVEN_ENABLE_WCF=true. - Check the behavior extension is registered.
- Check server services use
behaviorConfiguration="observedService". - Check client endpoints use
behaviorConfiguration="observedEndpoint". - Check the binding actually uses the service or client entry that has the behavior configuration.
No ASP.NET spans:
- Check the HTTP module is in
system.web/httpModulesorsystem.webServer/modules. - Check the application pool is running .NET Framework 4.7.2 or 4.8.
- Recycle the app pool after changing
web.config.
No ASMX operation names:
- Check
ELVEN_ENABLE_ASMX=true. - Check the ASP.NET module is active for
.asmxrequests. - Check the client sends a useful
SOAPActionheader, or that the request path includes methodPathInfo.
No EF6 spans:
- Check
Elven.Observability.NotaCarioca.EF6is installed. - Check
ELVEN_ENABLE_EF6=true. - Check
ElvenEf6Instrumentation.Register()runs before EF6 commands execute.
No logs:
- Check
ELVEN_ENABLE_LOG4NET,ELVEN_ENABLE_NLOG,ELVEN_ENABLE_SERILOG, orELVEN_ENABLE_SYSTEM_DIAGNOSTICS. - Check the appender, target, sink, or listener is actually registered in the app logging framework.
- Check
OTEL_LOGS_EXPORTERis notnone.
Assembly binding issues:
- Legacy apps may need binding redirects after installing NuGet packages.
- For executable projects, enable automatic binding redirects where possible.
- For web apps, review generated binding redirects in
web.config.
Startup diagnostics:
foreach (var message in ElvenStartupDiagnostics.Snapshot())
{
System.Diagnostics.Trace.WriteLine(message);
}
Build, Test, Pack
Run on Windows for full .NET Framework 4.7.2/4.8 coverage:
dotnet restore Elven.Observability.NotaCarioca.sln
dotnet build Elven.Observability.NotaCarioca.sln -c Release --no-restore
dotnet test tests/Elven.Observability.NotaCarioca.UnitTests/Elven.Observability.NotaCarioca.UnitTests.csproj -c Release --no-build
dotnet test tests/Elven.Observability.NotaCarioca.WcfIntegrationTests/Elven.Observability.NotaCarioca.WcfIntegrationTests.csproj -c Release --no-build
./samples/GaSmoke/bin/Release/net48/GaSmoke.exe
dotnet pack Elven.Observability.NotaCarioca.sln -c Release --no-build -o artifacts/packages
The package build produces both net472 and net48 assets. The GA smoke currently runs as a net48 executable because it exercises WCF and SQL Server LocalDB on Windows. CI also runs scripts/ci/run-aspnet-classic-smoke.ps1 to load the ASP.NET classic HTTP module under IIS Express.
Signing And Publishing
NuGet publication has two supported paths:
nuget-release: publishes unsigned author packages after all gates pass. NuGet.org applies repository signing after acceptance.signed-release: signs packages with an Elven code-signing certificate before publishing. Use this path when Elven author signing is available.
Manual signing and publish:
./scripts/nuget/sign-packages.ps1
./scripts/nuget/publish-signed-packages.ps1 -PublishSymbols
Manual unsigned publish:
dotnet pack Elven.Observability.NotaCarioca.sln -c Release --no-build -o artifacts/packages
./scripts/nuget/publish-unsigned-packages.ps1 -PublishSymbols
Do not publish from regular CI artifacts. Use either the manual nuget-release workflow for unsigned publication or the manual signed-release workflow when author signing is configured.
See docs/signing-and-publishing.md for both release paths, NuGet.org certificate registration, and GitHub secret setup.
Samples
Known Limitations
- EventLog ingestion is reserved but not implemented as a concrete bridge in this release.
- WCF HTTPS and message security should be validated with customer-like certificates and bindings before broad rollout.
CaptureSoapPayload,CaptureSoapHeaders,AllowedRequestHeaders, andAllowedResponseHeadersare reserved compatibility options and are intentionally no-op in this release. Setting them emits a bounded startup diagnostic; it never captures payloads or application headers.- Local
dotnet testfor .NET Framework may not run on non-Windows or arm64 machines. Windows CI is the authoritative test host.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET Framework | net472 is compatible. net48 is compatible. net481 was computed. |
-
.NETFramework 4.7.2
- Elven.Observability.NotaCarioca.Core (>= 0.1.0-alpha.4)
- NLog (>= 6.1.3)
-
.NETFramework 4.8
- Elven.Observability.NotaCarioca.Core (>= 0.1.0-alpha.4)
- NLog (>= 6.1.3)
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 |
|---|---|---|
| 0.1.0-alpha.4 | 41 | 7/15/2026 |
| 0.1.0-alpha.3 | 53 | 7/6/2026 |
| 0.1.0-alpha.2 | 53 | 7/6/2026 |