Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/observability.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ qyl component to its OTel role, so contributors (human or agent) share one preci
## qyl components in OTel terms

- **Instrumentation Library — generic:** [`Qyl.OpenTelemetry.AutoInstrumentation`](https://github.com/ANcpLua/Qyl.OpenTelemetry.AutoInstrumentation) (`4.0.3`). A vendor-neutral, NativeAOT-ready **Automatic Instrumentation** library. Zero source changes: a `PackageReference` is the supported path. Packages: `.Hosting`, `.EntityFrameworkCore`, `.SqlClient`, `.DiagnosticListeners`, `.SourceGenerators`. Public surface: `QylActivitySource`, `QylActivityNames`, `QylAutoInstrumentationIds`, `QylAutoInstrumentationOptions` (per-signal enablement + header/URL redaction), `AddQylAutoInstrumentation(...)` (zero-config via `.Hosting`), and `AddQylAspNetCoreInstrumentation(...)` (opt-in server-span middleware). A single-owner-per-signal registry keeps the interceptor, middleware, and DiagnosticListener lanes from double-instrumenting the same operation.
- **Instrumentation Library — qyl domain:** [`internal/qyl.instrumentation`](../internal/qyl.instrumentation) (namespace `Qyl.Instrumentation`) + its generator. Provides ServiceDefaults (DI/health/endpoints/discovery/resilience) **and** instrumentation for domains the generic library cannot know about: **GenAI** (`Microsoft.Extensions.AI` `IChatClient`) and **agents** (`QylAgentActivityProcessor`, `AddQylAgentInventory`). Its `WebApplicationBuilder.Build()` interceptor composes the generic library in (diagnostic `QYL0138` errors if `Qyl.OpenTelemetry.AutoInstrumentation` is missing).
- **Instrumentation Library — qyl domain:** [`internal/qyl.instrumentation`](../internal/qyl.instrumentation) (namespace `Qyl.Instrumentation`) + its generator. Provides ServiceDefaults (DI/health/endpoints/discovery/resilience) **and** instrumentation for domains the generic library cannot know about: **GenAI** (`Microsoft.Extensions.AI` `IChatClient`) and **agents** (`QylAgentActivityProcessor`, `AddQylAgentInventory`). Its `WebApplicationBuilder.Build()` interceptor wires the ServiceDefaults at the build call site.
- **Instrumentation Library — Agent Framework:** `ANcpLua.Agents.Instrumentation` — MAF-native, wraps agents in an `OpenTelemetryAgent` emitting `invoke_agent` / `execute_tool` spans (sensitive data off by default).
- **Semantic Conventions:** `Qyl.OpenTelemetry.SemanticConventions` — the vocabulary the instrumentation libraries emit against. Not itself an instrumentation library.
- **Backend (not an instrumentation library):** `qyl.collector` — OTLP ingest + DuckDB storage + REST API + dashboard. It *receives* signals; it instruments only itself (via `qyl.instrumentation`).
Expand Down
9 changes: 0 additions & 9 deletions docs/typespec-maf-prd.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,6 @@ authoritative copy and all execution now live there:

This stub remains so existing links into qyl don't 404.

## What stays in qyl

The flagship depends on these qyl assets — they stay here, not in the new repo:

- **`qyl.conformance`** — the runtime verifier (declared-vs-observed diff engine,
`conformant` gate). The flagship's PR-7 wires `qyl verify` against it.
- **`Qyl.Api.Contracts`** — the `TelemetryControlGraph` / `ConformanceReport` types
(published to nuget.org via `qyl-api-schema`) that the loop's reports round-trip through.

## Status

Campaign live: building `typespec-agent-framework` through the PRD's PR-0→~PR-8
Expand Down
2 changes: 0 additions & 2 deletions eng/build/BuildVerify.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2019,8 +2019,6 @@ void EnsureStorageIdentity(
"AttributeKeyPrefix",
"StartsWithOrdinal(QylCapabilityPrefix)",
"Paths.Any(path.StartsWithIgnoreCase)",
"status_message",
"span.Status?.Message",
"ProfileDataJson",
"profile_data_json",
"ProfileFrameType",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,8 @@ private static void AppendBuildInterceptorMethod(
// Wire qyl ServiceDefaults (conventions, generated service + health-check registration, and
// default endpoints) at the single WebApplicationBuilder.Build() call site, then build the host.
// The OTel ASP.NET Core server-span middleware is registered independently via
// AddQylAspNetCoreInstrumentation() (an IStartupFilter), so this interceptor no longer composes it
// and no longer contends with the OTel package for the Build() call site (the CS9153 collision that
// the old QylInterceptedAspNetCore.Build wrapper + opt-out property existed to work around).
// AddQylAspNetCoreInstrumentation() (an IStartupFilter); composing it here would contend with the
// OTel package for the Build() call site (CS9153 duplicate interceptor).
sb.AppendLine($$"""
// Intercepted call at {{displayLocation}}
{{interceptAttribute}}
Expand Down
3 changes: 1 addition & 2 deletions packages/Qyl.Run.Host/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
// files), then blocks with the live TUI. The runner's own read-only resource state is exposed at
// http://127.0.0.1:18888/runner/resources (+ /stream) for qyl.run.dashboard.
//
// Note: resources are launched via `dotnet run --project <path>`, so only .NET projects can be added
// today; launching the dashboard's Vite dev server (npm) is a separate, planned launcher capability.
// Note: resources are launched via `dotnet run --project <path>`, so only .NET projects can be added.
var app = QylAppBuilder.Create(args);

app.AddCollector("collector", port: 5100, project: "services/qyl.collector");
Expand Down
2 changes: 1 addition & 1 deletion packages/Qyl.Run/Internal/QylResourceRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal sealed class QylResourceRegistry(TimeProvider time)
{
// Broadcast fan-out: every subscriber (the Spectre TUI, an SSE endpoint, …) owns its own channel.
// Publish records the latest state and mirrors the event into every subscriber's channel, so a second
// consumer never steals events from the first (the old single-reader channel could not be shared).
// consumer never steals events from the first.
private readonly ConcurrentDictionary<Guid, Channel<QylResourceState>> _subscribers = new();

private readonly ConcurrentDictionary<string, QylResourceState> _latest = new(StringComparer.Ordinal);
Expand Down
2 changes: 0 additions & 2 deletions services/qyl.collector/Ingestion/OtlpConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,6 @@ private static Dictionary<string, OtlpAttributeValue> ExtractAttributesFromProto
return attributes;
}

// CODE RED #4: OTLP span Events (including OTel exception events) and Links were dropped on ingest.
// Capture them here so ingest -> storage -> span-detail API preserves them.
private static IReadOnlyDictionary<string, OtlpAttributeValue> ConvertSpanChildAttributes(
RepeatedField<ProtoKeyValue> protoAttributes)
{
Expand Down
1 change: 0 additions & 1 deletion services/qyl.collector/Mapping/Mappers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ private static SpanStatusCode MapStatus(byte statusCode) =>
_ => SpanStatusCode.Unset
};

// CODE RED #4: rehydrate the span's events (incl. exception events) and links from storage.
private static IReadOnlyList<SpanEvent> MapEvents(string? eventsJson)
{
var stored = SpanChildStorage.DeserializeEvents(eventsJson);
Expand Down
1 change: 0 additions & 1 deletion services/qyl.collector/Storage/DuckDbReaderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ internal sealed partial record SpanStorageRow
[DuckDbColumn(SqlType = "VARCHAR(256)")]
public string? SchemaUrl { get; init; }

// CODE RED #4: previously dropped on ingest — status message + events (incl. exception events) + links.
[DuckDbColumn(SqlType = "VARCHAR")]
public string? StatusMessage { get; init; }
[DuckDbColumn(SqlType = "JSON")]
Expand Down
5 changes: 2 additions & 3 deletions services/qyl.collector/Storage/SpanChildStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ internal sealed class SpanLinkJson
}

/// <summary>
/// Serializes a span's events and links to JSON for the spans row. Previously OTLP span Events (including
/// OTel exception events) and Links were dropped on ingest (CODE RED #4); they are now persisted so the
/// span-detail API can return them. Each child's attributes reuse the same safe-attribute JSON as the span.
/// Serializes a span's events and links to JSON for the spans row. Each child's attributes reuse the
/// same safe-attribute JSON as the span.
/// </summary>
internal static class SpanChildStorage
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export function DownloadButton<T extends Record<string, unknown>>({
try {
const data = getData();
if (data.length === 0) {
// Could show a toast here, but for now just skip
return;
}
downloadData(data, format, filenamePrefix, columns);
Expand Down
2 changes: 0 additions & 2 deletions services/qyl.dashboard/src/pages/LogsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,6 @@ export function LogsPage() {
const currentGen = logsBufferRef.current.generation;
if (currentGen !== lastGenerationRef.current) {
lastGenerationRef.current = currentGen;
// With composite keys, we don't need to clear expanded state anymore!
// Just remeasure since indices may have shifted
rowVirtualizer.measure();
}
}, [logsVersion, rowVirtualizer]);
Expand Down
Loading