Cloudstrap.Observability.AzureMonitor
0.2.0-preview.83
Prefix Reserved
dotnet add package Cloudstrap.Observability.AzureMonitor --version 0.2.0-preview.83
NuGet\Install-Package Cloudstrap.Observability.AzureMonitor -Version 0.2.0-preview.83
<PackageReference Include="Cloudstrap.Observability.AzureMonitor" Version="0.2.0-preview.83" />
<PackageVersion Include="Cloudstrap.Observability.AzureMonitor" Version="0.2.0-preview.83" />
<PackageReference Include="Cloudstrap.Observability.AzureMonitor" />
paket add Cloudstrap.Observability.AzureMonitor --version 0.2.0-preview.83
#r "nuget: Cloudstrap.Observability.AzureMonitor, 0.2.0-preview.83"
#:package Cloudstrap.Observability.AzureMonitor@0.2.0-preview.83
#addin nuget:?package=Cloudstrap.Observability.AzureMonitor&version=0.2.0-preview.83&prerelease
#tool nuget:?package=Cloudstrap.Observability.AzureMonitor&version=0.2.0-preview.83&prerelease
Cloudstrap.Observability.AzureMonitor
Application Insights export for the Cloudstrap observability pipeline. Flip one setting, add one chained call, and traces, metrics and logs land in Application Insights — correlated by operation ID.
Part of the Cloudstrap suite. MIT licensed.
Quick start
builder.UseCloudstrapObservability()
.AddAzureMonitor();
{
"Cloudstrap": {
"Application": {
"SystemName": "Contoso",
"SubsystemName": "Orders",
"SubsystemType": "Api"
},
"OpenTelemetry": {
"Mode": "AzureMonitor"
},
"AzureMonitor": {
"ConnectionString": "InstrumentationKey=...;IngestionEndpoint=https://...;LiveEndpoint=https://..."
}
}
}
Leave the call in place permanently. In any mode other than AzureMonitor it contributes no exporter and
changes no pipeline behavior, so the same binary moves between environments on configuration alone. It is
also idempotent — calling it twice registers one set of exporters. (A configure callback passed only to a
second call is discarded: the first call wins.)
Settings — Cloudstrap:AzureMonitor
| Setting | Type | Default | Purpose |
|---|---|---|---|
ConnectionString |
string | (none) | The Application Insights connection string. Falls back to the standard APPLICATIONINSIGHTS_CONNECTION_STRING variable. |
SamplingRatio |
float | (none) | Fraction of traces sampled, 0.0–1.0. Mutually exclusive with TracesPerSecond. |
TracesPerSecond |
double | (none) | Rate-limited sampling. Mutually exclusive with SamplingRatio. |
UseDefaultAzureCredential |
bool | false |
Authenticate ingestion with Entra ID instead of the connection string key. |
The section is bound and validated in every mode, not just AzureMonitor — a ratio outside 0.0–1.0,
or SamplingRatio and TracesPerSecond set together, fails startup naming the offending keys rather than
surfacing the day you flip the mode. The connection-string requirement is the one rule scoped to
AzureMonitor mode.
Sampling: the default is not 100%
When you configure neither SamplingRatio nor TracesPerSecond, the exporter's own platform default
applies: rate-limited sampling at 5 traces per second. This is Azure's current default, chosen for cost
protection, and Cloudstrap deliberately inherits it rather than overriding it.
Coming from Otlp or Console mode — which sample everything — this is the one behavior change that will
surprise you. To raise the volume:
"SamplingRatio": 1.0— export every trace."SamplingRatio": 0.25— export a quarter of them."TracesPerSecond": 20— raise the rate limit instead."Cloudstrap:OpenTelemetry:AlwaysOnSampler": true— record everything regardless of the settings above. Intended for development and diagnosis, not production volume.
Counts stay accurate either way: the Application Insights sampler stamps the rate it sampled at, and the portal renormalizes from it.
Connection string resolution
Cloudstrap:AzureMonitor:ConnectionString, when set to a non-blank value.- Otherwise the SDK resolves the standard
APPLICATIONINSIGHTS_CONNECTION_STRINGenvironment variable. - Otherwise host startup fails, naming both sources.
The fallback must be a real environment variable. Cloudstrap's validator also accepts that key from any
configuration source, but the SDK itself reads only the process environment — so supplying it through
appsettings.json alone would pass validation and then export nothing.
Sovereign and regional clouds need no extra setting: the connection string carries its own
IngestionEndpoint.
Entra ID ingestion authentication
For workspaces with local (key) authentication disabled:
{ "Cloudstrap": { "AzureMonitor": { "UseDefaultAzureCredential": true } } }
This attaches a DefaultAzureCredential, which behaves identically on Azure Web Apps, containers and
developer machines. One credential is shared by all three signals. To supply your own:
.AddAzureMonitor(exporter => exporter.Credential = new ManagedIdentityCredential("<client-id>"));
A credential supplied in code always wins over the flag.
The configure escape hatch
The callback runs after Cloudstrap's own configuration, so it always has the final say, and it reaches every exporter setting Cloudstrap does not surface:
.AddAzureMonitor(exporter =>
{
exporter.DisableOfflineStorage = true; // no telemetry spool on disk
exporter.StorageDirectory = "/var/tmp/ai"; // or put the spool somewhere writable
exporter.EnableStandardMetrics = false; // opt out of pre-aggregated metrics
});
Standard (pre-aggregated) metrics are enabled by the exporter by default; Cloudstrap does not touch them.
Blazor Server
Cloudstrap:OpenTelemetry:EnableBlazorHubTracing is honored in this mode too, but through export-time
suppression rather than sampling, because the exporter owns the sampler. Three things follow:
- Under a rate limit the hub spans still consume sampling budget before being scrubbed, so prefer
SamplingRatiooverTracesPerSecondon Blazor Server. - Only the hub span itself is suppressed — work started inside a hub invocation is still exported, parented
to the scrubbed span. In
ConsoleandOtlpmode the parent-based sampler drops those descendants too. - Suppression is owner-mode only. In
Contributemode the host owns the pipeline: Cloudstrap adds no scrub, and this package's exporter replaces whatever sampler the host installed, so hub suppression is the host's to arrange.
Aspire and other pipeline owners
Wire the Application Insights exporter either in Aspire's ServiceDefaults or through Cloudstrap — never both, or every span is exported twice.
This package works in Contribute pipeline mode, which is the real pairing for an Aspire app: the host owns
the pipeline and Cloudstrap adds the Azure Monitor exporters and its enrichment to it.
Live Metrics
Live Metrics is not available in this version. It requires an exporter entry point that takes ownership
of all three signals and overrides the sampler, which would break two contracts Cloudstrap consumers rely on:
the per-signal EnableTracing/EnableMetrics/EnableLogs flags, and the "consumer hooks run last" rule.
If you need it, either wire UseAzureMonitorExporter yourself in Contribute mode, or use the
Azure.Monitor.OpenTelemetry.AspNetCore distro instead of this package. This will be revisited if Azure
decouples Live Metrics from the distro entry point.
Failure isolation
Export failures never crash the application — the exporter retries in the background and spools to disk. The
OpenTelemetry-AzureMonitor-Exporter EventSource is the diagnostic channel when telemetry does not arrive.
Verifying against a real Application Insights resource
Automated tests never contact Azure. Verify a real backend once, manually:
- Create an Application Insights resource in the Azure portal and copy its connection string.
- Set
Cloudstrap:AzureMonitor:ConnectionStringto it andCloudstrap:OpenTelemetry:ModetoAzureMonitor. SetCloudstrap:AzureMonitor:SamplingRatioto1.0so nothing is sampled away while you are looking. - Run the application and issue one request that calls a downstream dependency and writes a log entry.
- Wait two to three minutes for ingestion, then in the portal check:
- Transaction search — the request appears, with
cloudstrap.system.name,cloudstrap.subsystem.nameandcloudstrap.subsystem.typeamong its custom dimensions. - End-to-end transaction details — the dependency call and the log entry hang off the same request,
sharing one
operation_Id. - Metrics —
performanceCountersand the .NET runtime metrics are arriving.
- Transaction search — the request appears, with
- Set the sampling back to production values.
| 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
- Azure.Identity (>= 1.21.0)
- Azure.Monitor.OpenTelemetry.Exporter (>= 1.8.3)
- Cloudstrap.Observability (>= 0.2.0-preview.83)
- Microsoft.Extensions.Configuration (>= 10.0.10)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Options (>= 10.0.10)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.10)
- OpenTelemetry.Exporter.Console (>= 1.17.0)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.17.0)
- OpenTelemetry.Extensions.Hosting (>= 1.17.0)
- OpenTelemetry.Instrumentation.AspNetCore (>= 1.17.0)
- OpenTelemetry.Instrumentation.Http (>= 1.17.0)
- OpenTelemetry.Instrumentation.Runtime (>= 1.17.0)
- OpenTelemetry.Instrumentation.SqlClient (>= 1.17.0)
- Serilog (>= 4.4.0)
- Serilog.Extensions.Hosting (>= 10.0.0)
- Serilog.Sinks.Console (>= 6.1.1)
- Serilog.Sinks.File (>= 7.0.0)
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.2.0-preview.83 | 35 | 9/3/2026 |
| 0.2.0-preview.2 | 72 | 8/27/2026 |