qyl is an OpenTelemetry-compatible observability platform. OpenTelemetry is the ingestion and instrumentation layer; qyl's product identity is the collector, storage model, API, and dashboard built around telemetry investigation.
typespec-otel-semconv
|
v
qyl-api-schema -> OpenAPI / JSON Schema / Qyl.Api.Contracts / TS contract types
|
v
qyl.collector -> DuckDB storage, REST API, OTLP ingest, SSE
|
v
qyl.dashboard -> operator UI
| Project | Purpose |
|---|---|
services/qyl.collector |
OTLP ingest (traces, logs, profiles), REST API, SSE streaming, DuckDB storage |
services/qyl.dashboard |
React dashboard for traces, logs, services, issues, alerts, errors, performance, cost, conversations, and agents |
internal/qyl.instrumentation |
.NET instrumentation helpers and OpenTelemetry setup |
internal/qyl.instrumentation.generators |
Roslyn source generator for service-defaults discovery and DB instrumentation |
internal/qyl.collector.storage.generators |
DuckDB storage source generation |
packages/Qyl.Run |
local distributed-app runner library for collector/dashboard workflows |
packages/Qyl.Run.Host |
executable host for the runner (dotnet run --project packages/Qyl.Run.Host) |
packages/Qyl.Run.Dashboard |
standalone dev-only resource dashboard for the runner (Vite/React) |
eng/build |
build/verify pipeline (BuildVerify guards, semantic catalog) |
qyl consumes API DTOs from Qyl.Api.Contracts, generated by the external qyl-api-schema TypeSpec repo.
The intended contract path is:
Schema -> OpenAPI -> DTO contracts -> clients
Do not recreate a second contract source in this monorepo. Update TypeSpec in qyl-api-schema, regenerate there, publish or locally pack Qyl.Api.Contracts, then update qyl's package reference.
Do not add new public API request, response, DTO, or schema models in qyl.collector.
Public API shapes belong in qyl-api-schema and must flow into qyl through
Qyl.Api.Contracts or generated OpenAPI-derived client types. Runtime storage rows,
ingest wire types, and internal projections may exist only when they are not returned
as the product API contract.
qyl uses OpenTelemetry terminology precisely. In OTel terms: the Instrumentation Library
(the thing that makes other libraries observable via Automatic Instrumentation — here,
AOT-safe compile-time interceptors + DiagnosticListener, not a CLR profiler) is
Qyl.OpenTelemetry.AutoInstrumentation;
internal/qyl.instrumentation adds qyl's GenAI/agent domain instrumentation and composes
it in; Qyl.OpenTelemetry.SemanticConventions is the emitted vocabulary; and qyl.collector
is the backend that receives the signals.
The OTel role mapping, the AOT automatic-instrumentation method, and the signal coverage
(all three signals — traces, metrics, logs — implemented across the 60-item contract and
NativeAOT-verified in the external Qyl.OpenTelemetry.AutoInstrumentation repo) are
documented in docs/observability.md. That AOT claim scopes
to the instrumentation library; the in-repo collector and internal/qyl.instrumentation
are ASP.NET Core components that neither need nor claim NativeAOT.
dotnet run --project services/qyl.collectorcd services/qyl.dashboard
npm install
npm run devOr run collector + dashboard together via the local runner:
dotnet run --project packages/Qyl.Run.HostPoint OpenTelemetry exporters at the collector:
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:5100"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"| Port | Protocol | Purpose |
|---|---|---|
| 5100 | HTTP | REST API, dashboard host, OTLP/HTTP |
| 4317 | gRPC | OTLP/gRPC ingestion |
| 4318 | HTTP | OTLP HTTP/protobuf ingestion |
dotnet build services/qyl.collector/qyl.collector.csprojcd services/qyl.dashboard
npm run buildGenerated files are not hand-edited. Fix the generator or schema input, regenerate, then commit the result.
MIT