AnnotatedDiagrams.Runtime
0.1.22
dotnet add package AnnotatedDiagrams.Runtime --version 0.1.22
NuGet\Install-Package AnnotatedDiagrams.Runtime -Version 0.1.22
<PackageReference Include="AnnotatedDiagrams.Runtime" Version="0.1.22" />
<PackageVersion Include="AnnotatedDiagrams.Runtime" Version="0.1.22" />
<PackageReference Include="AnnotatedDiagrams.Runtime" />
paket add AnnotatedDiagrams.Runtime --version 0.1.22
#r "nuget: AnnotatedDiagrams.Runtime, 0.1.22"
#:package AnnotatedDiagrams.Runtime@0.1.22
#addin nuget:?package=AnnotatedDiagrams.Runtime&version=0.1.22
#tool nuget:?package=AnnotatedDiagrams.Runtime&version=0.1.22
AnnotatedDiagrams.Runtime
ASP.NET Core runtime for AnnotatedDiagrams. Scans loaded assemblies, builds a DiagramGraph, and exposes HTTP endpoints — similar to the OpenAPI middleware pattern.
Installation
dotnet add package AnnotatedDiagrams.Runtime
ASP.NET Core setup
Register services and map endpoints in Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAnnotatedDiagramsRuntime(options =>
{
options.SourceCommit = Environment.GetEnvironmentVariable("GIT_COMMIT");
// options.CacheDuration = TimeSpan.FromMinutes(1); // default
// options.IncludeClientManifests = true; // merge Blazor WASM manifests (default)
// options.ExcludeFromOpenApi = true; // hide from Swagger/NSwag (default)
});
var app = builder.Build();
app.UseAnnotatedDiagramsTraffic(); // traffic middleware — call after app.UseRouting()
app.MapAnnotatedDiagrams(); // mounts endpoints under /diagrams (default prefix)
app.Run();
MapAnnotatedDiagrams accepts an optional patternPrefix argument (default: "/diagrams").
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/diagrams/graph |
Full DiagramGraph JSON |
GET |
/diagrams/filter-options |
Distinct tags, systems, boundaries and kinds available for filtering |
GET |
/diagrams/metrics |
Live traffic metrics (DiagramMetricsResponse), or 204 No Content if none |
Traffic middleware
UseAnnotatedDiagramsTraffic() adds AnnotatedDiagramsTrafficMiddleware to the pipeline. It records HTTP request latency per route template (e.g. POST /api/orders/{id}) and makes it available via GET /diagrams/metrics for live traffic visualization in the dashboard.
Call it after app.UseRouting() so that route templates are resolved by the time the middleware runs.
Linking HTTP routes to diagram edges
Add a route: tag to the [DiagramRelation] or [DiagramRelationToExternal] annotation matching the format METHOD /path:
[DiagramRelation(typeof(OrdersService),
Kind = RelationKind.Calls,
Label = "Place order",
Tags = new[] { "route:POST /api/orders/{id}" })]
The middleware records POST /api/orders/{id} automatically; the tag tells the metrics collector which diagram edge to associate that traffic with.
Non-HTTP traffic recording
For channels not covered by the HTTP middleware — message queues, databases, file shares, FTP, email, SMS — inject DiagramTrafficRecorder and record each operation manually.
The simplest pattern: use the external node ID
The channelKey you pass to Record / RecordAsync is automatically matched against the target ID of [DiagramRelationToExternal("id", ...)]. No route: tag is required on the annotation:
// Annotation — no route: tag needed:
[DiagramRelationToExternal("production-orders-placed",
Kind = RelationKind.Publishes, Label = "Publishes order event")]
// Recording — just use the same ID:
await recorder.RecordAsync(_queue.SendAsync(order), "production-orders-placed");
RecordAsync / Record overloads
// Async — pass the already-started Task; timing wraps the await
await recorder.RecordAsync(_queue.SendAsync(order), "production-orders-placed");
var msg = await recorder.RecordAsync(_queue.ReceiveAsync(), "production-orders-placed");
// Sync — pass a lambda; timing wraps the call
recorder.Record(() => _bus.Publish(evt), "event-bus");
var id = recorder.Record(() => _repo.Save(entity), "access-manager-db");
// Manual timing — when you need to control the span yourself
recorder.Record("production-orders-placed"); // count-only
recorder.Record("production-orders-placed", elapsedMs); // explicit ms
recorder.Record("production-orders-placed", stopwatch); // from Stopwatch
Explicit key override
If the channel key needs to differ from the external node ID, add a route: tag and pass the same value:
[DiagramRelationToExternal("event-bus",
Kind = RelationKind.Publishes,
Tags = new[] { "route:queue:orders-placed" })]
recorder.Record(() => _bus.Publish(evt), "queue:orders-placed");
Metrics matching strategy
DiagramMetricsCollector matches recorded metrics to diagram edges using three strategies in priority order:
| Priority | Strategy | When to use |
|---|---|---|
| 1 | Explicit route: tag |
HTTP edges (auto-tracked) and non-HTTP overrides |
| 2 | External node ID | Default for DiagramRelationToExternal — no tag required |
| 3 | Edge label fallback | Legacy or simple annotations without a tag |
OpenAPI / Swagger / NSwag
Diagram endpoints are excluded from OpenAPI document generation by default. Set ExcludeFromOpenApi = false to include them:
builder.Services.AddAnnotatedDiagramsRuntime(options =>
{
options.ExcludeFromOpenApi = false;
});
Blazor WebAssembly client manifest merge
When a hosted Blazor WASM client references AnnotatedDiagrams.Client, it generates a .graph.json manifest at build time. The runtime discovers and merges these manifests automatically.
IncludeClientManifests(defaulttrue) — set tofalseto disableClientManifestDiscoveryMode—Auto(default),Disabled, orCustomPathsOnlyClientManifestSearchPaths— additional search directories when usingCustomPathsOnly
Custom metrics provider
Replace the built-in HTTP traffic metrics with your own by registering IDiagramMetricsProvider:
builder.Services.AddSingleton<IDiagramMetricsProvider, MyMetricsProvider>();
public class MyMetricsProvider : IDiagramMetricsProvider
{
public DiagramMetrics? GetMetrics(DiagramGraph graph, View? view)
{
// Return null to produce 204 No Content on the metrics endpoint.
return new DiagramMetrics("last_5m", myEdgeMetrics);
}
}
| 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 was computed. 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 was computed. 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. |
-
net8.0
- AnnotatedDiagrams (>= 0.1.22)
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.22 | 111 | 4/27/2026 |
| 0.1.21 | 104 | 4/24/2026 |
| 0.1.20 | 97 | 4/24/2026 |
| 0.1.19 | 98 | 4/24/2026 |
| 0.1.18 | 101 | 4/23/2026 |
| 0.1.17 | 122 | 4/1/2026 |
| 0.1.16 | 109 | 3/31/2026 |
| 0.1.15 | 104 | 3/30/2026 |
| 0.1.14 | 110 | 3/15/2026 |
| 0.1.13 | 109 | 3/13/2026 |
| 0.1.12 | 131 | 3/9/2026 |
| 0.1.11 | 101 | 3/9/2026 |
| 0.1.10 | 101 | 3/9/2026 |
| 0.1.9 | 102 | 3/4/2026 |
| 0.1.7 | 98 | 3/4/2026 |
| 0.1.6 | 117 | 2/17/2026 |