Schema-driven event logging for OpenTelemetry .NET — define events in YAML, get type-safe C# code with metrics, causal linking, and AI-optimized JSON export.
otel-events extends the standard OpenTelemetry pipeline with:
- Schema-driven events — Define events in YAML, get type-safe C# methods via code generation
- AI-optimized JSON export — Compact, single-line JSONL output optimized for machine investigation
- Causal event linking — Track cause-and-effect relationships between events via
eventId/parentEventId - Compile-time enforcement — Roslyn analyzers catch
Console.Write, untypedILoggerusage, and schema violations - Integration packs — Zero-code instrumentation for ASP.NET Core, gRPC, Azure CosmosDB, and Azure Storage
- Event subscriptions — In-process event bus for reactive handlers (circuit breakers, token refresh, alerting)
- Health intelligence — Event-driven health state machine with YAML-defined components, K8s probes, and quorum evaluation
Install from NuGet:
# Core — schema-driven custom events
dotnet add package OtelEvents.Schema # YAML parser + C# code generator
dotnet add package OtelEvents.Exporter.Json # AI-optimized JSONL exporter
dotnet add package OtelEvents.Causality # Causal event linking (eventId/parentEventId)
# Integration packs — zero-code instrumentation (pick what you use)
dotnet add package OtelEvents.AspNetCore # HTTP request/auth/throttle events
dotnet add package OtelEvents.HttpClient # Outbound HTTP call events
dotnet add package OtelEvents.Grpc # gRPC call/auth/throttle events
dotnet add package OtelEvents.Azure.CosmosDb # CosmosDB query/auth/throttle events
dotnet add package OtelEvents.Azure.Storage # Blob/Queue operation events
# Optional
dotnet add package OtelEvents.Analyzers # Roslyn analyzers for logging hygiene
dotnet add package OtelEvents.Testing # In-memory exporter + assertions for tests
dotnet add package OtelEvents.Subscriptions # In-process event bus for reactive handlers
# Health intelligence — event-driven health state machine
dotnet add package OtelEvents.Health # Core state machine + signal analysis
dotnet add package OtelEvents.Health.AspNetCore # K8s health probe endpoints (/healthz/*)
dotnet add package OtelEvents.Health.Grpc # gRPC subchannel quorum evaluation| Package | What it does | When to use |
|---|---|---|
| OtelEvents.Schema | Parses .otel.yaml schema files and generates type-safe C# code ([LoggerMessage] methods + Meter/Counter/Histogram instruments) |
You want to define custom business events (e.g., OrderPlaced, PaymentProcessed) |
| OtelEvents.Exporter.Json | OTEL BaseExporter<LogRecord> that writes compact, single-line JSONL to stdout — optimized for AI/ML log analysis |
You want structured JSON output instead of plain-text logs |
| OtelEvents.Causality | OTEL BaseProcessor<LogRecord> that auto-generates UUID v7 eventId and links events via parentEventId using AsyncLocal scopes |
You want to trace cause-and-effect between events (e.g., all events from one HTTP request) |
These packages auto-emit structured events by hooking into framework pipelines. No YAML schemas needed — just install, register in DI, and events flow automatically:
| Package | Events emitted | What it instruments |
|---|---|---|
| OtelEvents.AspNetCore | http.request.received/completed/failed + http.connection.failed + http.auth.failed + http.throttled |
ASP.NET Core middleware — every HTTP request |
| OtelEvents.HttpClient | http.outbound.started/completed/failed |
Outbound HTTP calls via DelegatingHandler — every IHttpClientFactory call |
| OtelEvents.Grpc | grpc.call.started/completed/failed + connection/auth/throttle events |
gRPC server + client interceptors |
| OtelEvents.Azure.CosmosDb | cosmosdb.query.executed/failed + cosmosdb.point.read/write + connection/auth/throttle events |
Azure CosmosDB SDK via DiagnosticListener |
| OtelEvents.Azure.Storage | storage.blob.uploaded/downloaded/deleted + storage.queue.sent/received + connection/auth/throttle events |
Azure Storage SDK via HttpPipelinePolicy |
| Package | What it does |
|---|---|
| OtelEvents.Analyzers | Roslyn analyzers: warns on Console.Write, direct ILogger.Log*, string interpolation, reserved prefix usage, PII without redaction |
| OtelEvents.Testing | InMemoryLogExporter, OtelEventsTestHost.Create(), LogAssertions — test your events without infrastructure |
| OtelEvents.Subscriptions | In-process event bus — subscribe to events with lambda or DI handlers (e.g., trip circuit breaker on cosmosdb.throttled) |
| OtelEvents.Cli | CLI tool (dotnet otel-events validate/generate/diff/docs) for schema validation, code generation, version comparison |
| Package | What it does | When to use |
|---|---|---|
| OtelEvents.Health | Event-driven health state machine — sliding-window signal analysis, three-state model (Healthy → Degraded → CircuitOpen), multi-tenant tracking | You want health derived from real traffic, not synthetic probes |
| OtelEvents.Health.AspNetCore | K8s probe endpoints — /healthz/live, /healthz/ready, /healthz/startup |
ASP.NET Core apps running in Kubernetes |
| OtelEvents.Health.Grpc | gRPC subchannel health adapter for quorum evaluation | Services with gRPC backend pools that need quorum-based health |
// Program.cs — get structured events for free
builder.Services.AddOpenTelemetry()
.WithLogging(logging =>
{
logging.AddOtelEventsJsonExporter(); // JSONL to stdout
logging.AddProcessor<OtelEventsCausalityProcessor>(); // Causal linking
});
builder.Services.AddOtelEventsAspNetCore(); // Auto-emit HTTP events
builder.Services.AddOtelEventsCosmosDb(); // Auto-emit CosmosDB eventsEvery HTTP request and CosmosDB query now emits structured events — including connection failures, auth failures, and throttling. No custom code needed.
- Define your events in
orders.otel.yaml:
schema:
name: Orders
version: "1.0.0"
namespace: MyApp.Events
meterName: myapp.events
prefix: ORDER # Event codes become ORDER-1000, ORDER-2000, etc.
events:
OrderPlaced:
id: 1000
type: start # Creates a transaction scope
severity: INFO
message: "Order {orderId} placed by {customerId} for ${amount}"
fields:
- orderId
- customerId: { sensitivity: pii }
- amount
metrics:
order.placed.count:
type: counter
labels: [customerId]
OrderFailed:
id: 2000
type: failure # Closes parent scope as failed
parent: OrderPlaced
severity: ERROR
message: "Order {orderId} failed: {reason}"
exception: true
fields:
- orderId
- reason- Generate code and use it:
dotnet otel-events generate orders.otel.yaml -o Generated/// Type-safe, schema-enforced — log + metrics in one call
using var scope = logger.BeginOrderPlaced(orderId, customerId, amount);
// ... do work ...
scope.TryComplete(logger, orderId, carrier, trackingNumber);
// or on failure:
scope.TryFail(logger, orderId, reason, exception);📖 See the full User Guide for detailed tutorials.
// Program.cs — event-driven health from real traffic
builder.Services.AddOtelEventsAspNetCore(); // HTTP events
builder.Services.AddOtelEventsHealth("schemas/health.otel.yaml"); // Health state machine
app.MapHealthEndpoints(); // K8s probesDefine your dependencies in YAML — the health system subscribes to matching events automatically:
components:
orders-db:
window: 300s
healthyAbove: 0.95
degradedAbove: 0.7
signals:
- event: "http.request.completed"
match: { httpRoute: "/orders/*" }
- event: "http.request.failed"
match: { httpRoute: "/orders/*" }📖 See Chapter 14 — OtelEvents.Health for the full guide.
- .NET 8 SDK (builds both net8.0 and net10.0 targets)
| Package | Targets |
|---|---|
Library packages (OtelEvents.*) |
net8.0 |
OtelEvents.Analyzers |
netstandard2.0 (Roslyn requirement) |
OtelEvents.Cli |
net8.0 |
| Test projects | net8.0 |
otel-events-dotnet/
├── src/
│ ├── OtelEvents.Schema/ # YAML schema parser & code generator
│ ├── OtelEvents.Exporter.Json/ # JSON log exporter + severity filter + rate limiter + sampler
│ ├── OtelEvents.Causality/ # Causal event linking processor
│ ├── OtelEvents.Analyzers/ # Roslyn analyzers
│ ├── OtelEvents.Testing/ # Test utilities
│ ├── OtelEvents.Subscriptions/ # In-process event bus
│ ├── OtelEvents.AspNetCore/ # ASP.NET Core integration pack
│ ├── OtelEvents.HttpClient/ # Outbound HTTP client integration pack
│ ├── OtelEvents.Grpc/ # gRPC integration pack
│ ├── OtelEvents.Azure.CosmosDb/ # Azure CosmosDB integration pack
│ ├── OtelEvents.Azure.Storage/ # Azure Storage integration pack
│ ├── OtelEvents.Health/ # Event-driven health state machine
│ ├── OtelEvents.Health.AspNetCore/ # K8s health probe endpoints
│ ├── OtelEvents.Health.Grpc/ # gRPC subchannel quorum adapter
│ └── OtelEvents.Cli/ # CLI tool entry-point
├── tools/
│ └── OtelEvents.Cli/ # CLI tool (validate, generate, diff, docs)
├── docs/
│ ├── user-guide/ # 14-chapter user guide
│ ├── security/ # Threat model, PII classification, OWASP mapping
│ ├── observability/ # SLI/SLO recommendations, alerting guides
│ └── deployment/ # K8s manifests, OTEL Collector config, Dockerfile
├── Directory.Build.props # Shared MSBuild properties
├── Directory.Packages.props # Central package management
└── OtelEvents.slnx # Solution file
See docs/security/ for standalone security documentation, including:
- Threat Model — Trust boundaries, threat vectors, and mitigations
- PII Classification — Sensitivity levels and redaction matrix
- Environment Profiles — Development, Staging, and Production defaults
- OWASP Mapping — OWASP Top 10 (2021) reference mapping
For vulnerability reporting, see SECURITY.md.
See docs/observability/ for operational guidance:
- SLI/SLO Recommendations — Service Level Indicators mapped to otel-events metrics, SLO targets by service tier, multi-window burn-rate alerting, and Grafana alert examples
- Performance Dashboards — Pre-built Grafana dashboard and OTEL Collector configuration
See the otel-events User Guide for comprehensive documentation:
- Getting Started — 10-minute tutorial
- Schema Reference — Complete YAML grammar
- Integration Packs — ASP.NET Core, gRPC, CosmosDB, Azure Storage
- Configuration — All configuration options
- OtelEvents.Health — Event-driven health intelligence, YAML components, K8s probes
- Migration Guide — Migrate from plain
ILoggerto otel-events - FAQ — Common questions
See SPECIFICATION.md for the full project specification, including architecture, YAML schema format, JSON envelope format, and design decisions.
See the Container & Kubernetes Deployment Guide for:
- OTEL Collector configuration for otel-events envelope parsing
- Sample Dockerfile (distroless, non-root, SBOM)
- Kubernetes manifests (Deployment, PDB, HPA, NetworkPolicy)
- Resource sizing recommendations
- TLS/mTLS configuration for OTLP endpoints
Contributions are welcome! Please open an issue or pull request.
This project is licensed under the MIT License — see the LICENSE file for details.