dotnet-diagnostics-core
0.32.1
dotnet add package dotnet-diagnostics-core --version 0.32.1
NuGet\Install-Package dotnet-diagnostics-core -Version 0.32.1
<PackageReference Include="dotnet-diagnostics-core" Version="0.32.1" />
<PackageVersion Include="dotnet-diagnostics-core" Version="0.32.1" />
<PackageReference Include="dotnet-diagnostics-core" />
paket add dotnet-diagnostics-core --version 0.32.1
#r "nuget: dotnet-diagnostics-core, 0.32.1"
#:package dotnet-diagnostics-core@0.32.1
#addin nuget:?package=dotnet-diagnostics-core&version=0.32.1
#tool nuget:?package=dotnet-diagnostics-core&version=0.32.1
dotnet-diagnostics-core
The transport-agnostic .NET diagnostics engine behind the
dotnet-diagnostics-mcp MCP server and
the dotnet-diagnostics-cli. It attaches to a live .NET process over the runtime diagnostic IPC
socket and turns raw EventPipe / ClrMD / TraceEvent streams into structured results. Those normal
paths require no target code changes or prior instrumentation. The explicit exception is
MethodParameterCaptureUseCases: it performs a privileged dynamic attach of vendored
dotnet-monitor profilers plus a startup hook and temporarily ReJIT-instruments an allowlist of
methods; hosts must expose that sensitive capability only behind an explicit authorization policy.
This package exists so other hosts can call the same engine in-process, without shelling out to
a tool. The first such consumer is the BenchmarkDotNet diagnoser
(dotnet-diagnostics-benchmarkdotnet).
dotnet add package dotnet-diagnostics-core
Consumer target frameworks:
net8.0,net9.0,net10.0. Platform: the engine attaches over the diagnostic IPC socket; live ClrMD memory readers (heap/thread snapshots, method bytes, module bytes) additionally needCAP_SYS_PTRACEon Linux and the same UID as the target. Process dumps write through diagnostic IPC and do not require that kernel capability. See the repo docs for the deployment matrix.
Supported public surface (Pattern B — curated facade)
⚠️ Pre-1.0 / unstable. While this package is versioned
0.xit carries no SemVer API stability guarantee. Only the entry points listed below are intended for external use; every other public type is an implementation detail that will be internalized incrementally and may change or disappear without a major-version bump. Depend on the facade, not on the plumbing.
The supported entry points are the static use-case classes; each method returns a
DiagnosticResult<T> envelope (success payload, DiagnosticError, and NextActionHints):
| Use-case class | What it does |
|---|---|
ProcessInspectionUseCases |
Discover .NET processes; process / capability / container / runtime-config / triage views. |
EventCollectionUseCases |
EventPipe collection: counters, exceptions, GC, GC DATAS, logs, JIT, threadpool, contention, db, activities, event-source, event catalog. |
HeapInspectionUseCases |
Live or dump heap walk + drilldown handles. |
ProcessDumpUseCases |
Write a process dump (Mini / Triage / WithHeap / Full). |
ByteMaterializationUseCases |
Stream module (PE/PDB) or dump bytes. |
MethodParameterCaptureUseCases |
Explicit dynamic-profiler capture of allowlisted method parameters on supported CoreCLR targets. |
IDiagnosticSession / ICounterSessionFactory |
Attach typed callbacks, start, cancel, and stop a bounded live EventCounter session; terminal status reports EventPipe loss and dropped observations. |
ComposedDiagnosticSession |
Combine live sessions with finite captures behind one bounded, typed callback dispatcher. |
Supporting types that are part of the facade because the use-cases return or accept them:
DiagnosticResult/DiagnosticResult<T>,DiagnosticError,NextActionHint— the result envelope.- The per-collector snapshot/result records returned by the use-cases (e.g.
CounterSnapshot,GcSummary,ContentionSnapshot, …).
Live counter sessions are separate from finite EventCollectionUseCases snapshots. Attach one or
more typed handlers before starting; the Core dispatcher invokes matching callbacks serially in
registration order. Event sequence numbers are assigned before bounded queue insertion, so gaps
reveal drops; the queue (maximum capacity 16,384) drops new observations when full and reports the
total in DiagnosticSessionCompletion. Session options validate positive process IDs and intervals,
cap provider lists at 64 names of at most 256 characters each, and reject queue capacities outside
the documented bound before opening EventPipe. The live
CounterSession.DroppedObservations property exposes the running count. Use StopAsync,
DisposeAsync, or the cancellation token passed to StartAsync to stop and drain the session.
await using var session = counterSessions.CreateSession(processId);
using var subscription = session.Attach<CounterObservation>((observation, cancellationToken) =>
{
Console.WriteLine($"{observation.Sequence}: {observation.Counter.Name}={observation.Counter.Value}");
return ValueTask.CompletedTask;
});
await session.StartAsync(cancellationToken);
var completion = await session.Completion;
IDiagnosticSession is the common lifecycle and typed event attachment contract. Event-specific
session factories can publish additional DiagnosticSessionEvent record types without changing
existing finite collector APIs. Live counters and the IStreaming*Collector interfaces for
exceptions, activities, monitor contention, GC, logs, JIT, ThreadPool, startup, database activity,
networking, Kestrel, crash-guard exceptions, generic EventSource events, EventSource catalog metadata,
in-flight request lifecycle events, memory trend samples, and process-resource samples publish typed
observations incrementally. GC DATAS post-processing, CPU/allocation samplers, point-in-time readers,
and other offline aggregations remain finite operations; add them with AddCapture to publish their
typed terminal result rather than implying live observations their collectors do not expose. Stopping
cancels capture producers; callbacks continue draining the bounded queue. The callback cancellation
token is canceled if handler delivery exceeds the shutdown wait budget.
Use ComposedDiagnosticSession when one consumer needs multiple capture families in one lifecycle.
Add live sessions with AddSession; add existing finite collector/use-case calls with
AddCapture. Each finite operation publishes exactly one
DiagnosticSessionCaptureResult<TCapture> event containing its statically typed result. For
windowed collectors that expose observations, use AddStreamingCapture: it publishes each typed
observation as a DiagnosticSessionObservation<TObservation> and then the same typed terminal
result. Point-in-time operations remain a single result event. Capture operations run concurrently,
and all events share the composed session's bounded queue and monotonic sequence. Collectors with
multiple observation types can use AddEventCapture and publish each type as its own
DiagnosticSessionEvent.
For example, attach a CounterObservation handler and a
DiagnosticSessionObservation<ManagedExceptionEvent> handler, add the live counter session with
AddSession, and add IStreamingExceptionCollector.CollectStreamingAsync with AddStreamingCapture. Both
capture families then share one start/stop lifecycle and callback queue; the exception snapshot is
also delivered as a DiagnosticSessionCaptureResult<ExceptionSnapshot>.
Finite operations and evidence recording
AddCapture<T> accepts any existing asynchronous collector result without a family-specific adapter.
Use it for GC DATAS post-processing, CPU/allocation/off-CPU/native samplers, CPU-efficiency sampling,
method-parameter capture, dump/heap/thread inspection, requests-now, and other point-in-time operations.
The callback gets the original result, including handles and partial/error/cancellation information
when the capture returns a DiagnosticResult<T>. A completed session means its producers and callback
delivery finished; it does not turn a failed diagnostic envelope into a successful diagnostic result.
await using var session = new ComposedDiagnosticSession(pid);
using var subscription =
session.Attach<DiagnosticSessionCaptureResult<DiagnosticResult<GcDatasSnapshot>>>((item, token) =>
{
Console.WriteLine(item.Result.Summary);
return ValueTask.CompletedTask;
});
session.AddDiagnosticCapture("datas", "GC tuning", token =>
EventCollectionUseCases.CollectGcDatas(datasCollector, processResolver, handleStore,
processId: pid, durationSeconds: 10, cancellationToken: token));
await session.StartAsync(cancellationToken);
var completion = await session.Completion;
Named AddCapture(kind, name, ...), AddStreamingCapture(kind, name, ...), and
AddEventCapture(kind, name, ...) sources enter separate child routes when started inside an existing
evidence-recording scope. Use AddDiagnosticCapture for use-case envelopes: it records the structured
error, cancellation flag, and typed payload without persisting the envelope as an arbitrary object.
The raw named overloads expect snapshot/artifact results, not DiagnosticResult<T> envelopes.
Without an active recording scope, named sources remain ephemeral and never open SQLite themselves.
For durable composition, execute StartAsync and await Completion inside a
DurableCaptureUseCases.CaptureAsync operation using the existing batch parent kind. Capture kinds
and retained artifact types must be supported by the durable codec; a session does not make unsupported
operations persistable. Collectors continue using their existing bounded, redacted observation
projections. Final typed child results are retained independently of callback delivery, so a full
session queue can drop even a terminal callback without losing that producer's recorded snapshot.
DiagnosticSessionCompletion.DroppedObservations measures callback-queue loss, not SQLite record loss;
the durable capture's quality metadata reports recording/source loss separately.
Plain unnamed sources and AddSession do not establish child recording routes. A child live counter
session does not currently record its callbacks through this bridge; use a named finite counter
capture for durable counter evidence. No generic callback-to-JSON or callback-to-SQLite serializer is
introduced.
Example
using DotnetDiagnostics.Core.UseCases;
// Snapshot EventCounters for ~5s from a target PID.
DiagnosticResult<CounterSnapshot> result =
await EventCollectionUseCases.SnapshotCounters(processId: pid, durationSeconds: 5);
if (result.IsSuccess)
{
foreach (var hint in result.Hints)
Console.WriteLine(hint.Message);
}
Not in scope for this package
- The MCP tool surface, HTTP transport and bearer auth live in
dotnet-diagnostics-mcp. - The one-shot / REPL command line lives in
dotnet-diagnostics-cli.
License
MIT — see the repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 is compatible. 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. |
-
net10.0
- Azure.Identity (>= 1.21.0)
- Microsoft.Data.Sqlite (>= 10.0.5)
- Microsoft.Diagnostics.NETCore.Client (>= 0.2.661903)
- Microsoft.Diagnostics.Runtime (>= 4.1.745802)
- Microsoft.Diagnostics.Tracing.TraceEvent (>= 3.2.2)
- Microsoft.Extensions.DependencyInjection (>= 10.0.5)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Logging (>= 10.0.5)
- SQLitePCLRaw.lib.e_sqlite3 (>= 3.53.3)
-
net8.0
- Azure.Identity (>= 1.21.0)
- Microsoft.Data.Sqlite (>= 10.0.5)
- Microsoft.Diagnostics.NETCore.Client (>= 0.2.661903)
- Microsoft.Diagnostics.Runtime (>= 4.1.745802)
- Microsoft.Diagnostics.Tracing.TraceEvent (>= 3.2.2)
- Microsoft.Extensions.DependencyInjection (>= 10.0.5)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Logging (>= 10.0.5)
- SQLitePCLRaw.lib.e_sqlite3 (>= 3.53.3)
-
net9.0
- Azure.Identity (>= 1.21.0)
- Microsoft.Data.Sqlite (>= 10.0.5)
- Microsoft.Diagnostics.NETCore.Client (>= 0.2.661903)
- Microsoft.Diagnostics.Runtime (>= 4.1.745802)
- Microsoft.Diagnostics.Tracing.TraceEvent (>= 3.2.2)
- Microsoft.Extensions.DependencyInjection (>= 10.0.5)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Logging (>= 10.0.5)
- SQLitePCLRaw.lib.e_sqlite3 (>= 3.53.3)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on dotnet-diagnostics-core:
| Package | Downloads |
|---|---|
|
dotnet-diagnostics-benchmarkdotnet
A BenchmarkDotNet IDiagnoser for net8.0/net9.0/net10.0 benchmark projects that attaches the dotnet-diagnostics engine in-process to a benchmark's child process and captures EventPipe perf indicators (GC, contention, thread pool, exceptions, JIT, counters, …) as JSON artifacts plus a per-run "biggest offenders" report. Tag benchmark methods with [DiagnosticKind] and add [DotnetDiagnosticsDiagnoser] to the benchmark class. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.32.1 | 52 | 10/22/2026 |
| 0.31.0 | 109 | 10/16/2026 |
| 0.30.0 | 123 | 10/15/2026 |
| 0.29.0 | 128 | 10/13/2026 |
| 0.28.0 | 292 | 9/30/2026 |
| 0.27.0 | 158 | 9/18/2026 |
| 0.26.0 | 142 | 9/17/2026 |
| 0.25.0 | 737 | 8/28/2026 |
| 0.24.0 | 1,213 | 8/19/2026 |
| 0.23.0 | 156 | 8/13/2026 |
| 0.22.0 | 151 | 8/1/2026 |
| 0.21.0 | 151 | 7/30/2026 |
| 0.20.0 | 144 | 7/29/2026 |
| 0.19.0 | 146 | 7/21/2026 |
| 0.18.0 | 143 | 7/20/2026 |
| 0.17.0 | 153 | 7/7/2026 |
| 0.16.0 | 148 | 7/2/2026 |
| 0.15.0 | 156 | 7/2/2026 |
| 0.14.0 | 183 | 6/11/2026 |
| 0.13.0 | 150 | 6/10/2026 |