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
3 changes: 2 additions & 1 deletion frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ This creates `build.zip` with a top-level `dist/` directory, including `dist/ind
- Dashboards: server-backed lists and detail routes, search/tags/favourites/sort/pagination, ownership, full-document saves with conflict resolution, SQL and PromQL tiles, six variable types, URL time ranges and selections, classic import/export, and explicit migration of old browser-local dashboards. Demo dashboards use independent in-memory state per client.
- Team: native users and one-time passwords, role and privilege management, default OIDC role configuration, provider group mappings and role provenance, and API key creation/copy/deletion. Search and 25-row pagination apply to every tab; authorization stays with the backend.
- Agents: schema-discovered GenAI telemetry datasets, bounded recent records, time ranges, local search, record inspection and trace handoff.
- Cluster: registered node reachability and resource metrics with independent request states; read-only. Errors: paginated OTLP error spans and trace handoff; classic grouped issue analytics remain unavailable.
- Cluster: registered node reachability and resource metrics with independent request states; read-only.
- Errors: grouped issues, full-range frequency analytics, and occurrence inspection for OTLP traces and recognized log severity schemas, plus paginated OTLP error spans and trace handoff. Groups match exact service, error type and message values; issue assignment and resolution are not persisted.
- Workspace setup: `/onboarding` discovers accessible datasets and opens the matching explorer; `/new` explains server scope and provides connection/setup actions. Hosted workspace creation is not exposed by this server.
- Network access: edit the server’s outbound alert-target policy, including domain/CIDR rules, private IP access and TLS verification.
- Keystone and LLM settings: native capability pages with explicit limitations and deployment-dependent classic links. See [native screen scope](docs/prism-parity.md#native-missing-screen-scope-2026-10-12).
Expand Down
6 changes: 5 additions & 1 deletion frontend/docs/api-contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,11 @@ Agents uses existing dataset list, schema, metadata and SQL requests. Discovery

Cluster reads `GET /api/v1/cluster/info` and `/api/v1/cluster/metrics` through the shared authenticated client. The first returns node identity, storage/staging paths, reachability and nullable status/error text. Metrics are independent: a denied metrics request does not hide node health. Nonfinite Rust metric values serialized as null display as unavailable per field. Missing cluster routes (404/405) show a deployment-mode explanation; 403 and 401 retain shared permission/session handling. No node deletion is exposed.

Errors uses the existing trace-list contract with `options: "errorSpans"`, selectable UTC ranges, server sorting and pagination. The selected dataset must advertise `otel-traces`. Failed metadata inspection is distinguished from confirmed incompatibility and can be retried. Dataset/range changes reset pagination and cancel obsolete requests. Trace handoff preserves the captured query bounds. Classic grouped-issue and frequency endpoints are absent and are not called.
Errors aggregates grouped issues and frequency through the existing `POST /api/v1/query` contract. Dataset metadata and schema determine the trace or log interpretation and the time partition. OTLP spans are deduplicated before aggregation; log occurrences count severity-matched records. Exact service, error type and message values identify a group, with SQL NULL kept distinct from literal display placeholders. Aggregates cover the full captured interval independently of paginated issue and occurrence lists. SQL enforces precise half-open bounds inside a minute-expanded transport envelope.

Trace type and message come from one deterministic representative row, preferring populated exception events, so different events cannot form an invented pair. Logs recognize textual severity aliases, exact OTLP severity codes 17–24 and Pino/Bunyan `level` codes 50/60; `msg` is a recognized message alias. The log SQL handoff returns full stored records, with internal query metadata retained only in sample mode. See [the Errors runbook](error-analytics.md) for alias behavior, counting rules and real-server tests.

The Error spans view retains the native trace-list contract with `options: "errorSpans"`, server sorting and pagination for datasets advertising `otel-traces`. Failed metadata or schema requests remain explicit and retryable. Dataset/range changes cancel obsolete requests and reset pagination. Trace and SQL investigation links preserve captured query bounds. No classic grouped-issue endpoint or persisted issue lifecycle API is required.

Network access reads and replaces `GET/PUT /api/v1/alert-target-policy`. The complete object contains `allowPrivate`, `allowInvalidTls`, `allowedDomains`, `allowedCidrs`, `deniedDomains`, and `deniedCidrs`. All fields are required; the server is authoritative for authorization, CIDR validation and allow/deny overlaps. This policy governs outbound alert delivery, not ingress access to Parseable. The editor retains failed-save drafts and protects unsaved navigation. Demo writes are isolated within each client. The backend caches policy per node and loads it on startup; cross-node propagation is not guaranteed by a successful save.

Expand Down
53 changes: 53 additions & 0 deletions frontend/docs/error-analytics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Errors: grouping, frequency, and regression tests

The Errors page queries the existing SQL API for grouped issues and frequency. It also retains the native OTLP error-span list. The [Mayfly implementation record](https://mayfly-celld.tail835e0d.ts.net/w/46ncdGypknzAj7dnRkJ8bQ?page=1983eae1-fba9-4616-9643-1de4e746162c) records the scope and validation evidence.

## What the counts mean

An issue is an exact match of service, error type, and message. Empty strings and missing values are treated as absent; absent values remain distinct from literal text such as `(unknown)`. Variable IDs or numbers in messages create separate issues. There is no fuzzy grouping, saved resolution state, assignment, or cross-dataset correlation.

For OTLP traces, an occurrence is a distinct error span. The query deduplicates expanded event/link rows and retries by service, trace ID, and span ID before aggregating. A span must have error status `2`; an exception event alone does not make a successful span an error. When rows disagree, type and message come together from one representative row. A populated exception event takes priority over direct span attributes; ties use type then message in ascending order, with absent values last. This keeps groups deterministic without inventing a type/message combination that never occurred. The occurrence timestamp remains the earliest row in the selected interval.

For logs, an occurrence is one stored record. Repeated identical logs remain separate occurrences. Recognized textual severity fields are checked case-insensitively for error/fatal equivalents. OTLP numeric severity must be an integer code from 17 through 24; numeric `level` supports the standard Pino/Bunyan error (50) and fatal (60) codes. Fractional codes do not match. Message text is not searched for the word “error” to classify a record. The derived `p_log_category` field is excluded because OTLP ingestion can infer it from body text when severity is unspecified. A dataset with only that category and no explicit severity field is unsupported. Schema inspection selects available service, type and message aliases; unsupported schemas have an explicit explanation and a Log explorer link.

Each view covers one dataset and one captured time interval. The dataset's configured time partition defines that interval. SQL applies `start <= timestamp < end` precisely, while the request envelope expands to minute boundaries for the server planner. Frequency buckets divide the selected interval into at most 48 equal elapsed-time intervals, including zero-count buckets. Summary totals and frequency are independent of the current issue page.

Issue and occurrence pages request one extra row to decide whether another page exists. Sorting happens on the server with deterministic group tie-breakers. Dataset/range changes and refresh discard obsolete requests and selections. Native trace links preserve the captured bounds. Log investigation opens SQL with the same classification and exact issue predicates, returning full stored records so stack traces and other fields remain available. Live handoffs start with readable SQL; only sample mode retains the internal query marker needed by its restricted evaluator. A log trace ID does not imply a compatible trace dataset.

## Code map

- `src/lib/errorAnalytics.ts`: schema interpretation, safely quoted SQL, strict result decoding, loaders and group identity.
- `src/lib/errorAnalyticsDemo.ts`: deterministic sample-data evaluation, restricted to exact queries rebuilt from their metadata.
- `src/features/errors/`: page orchestration, grouped issues, frequency and occurrence inspection.
- `src/lib/errorAnalytics.test.ts`: fast data-contract and sample-data regressions.
- `src/lib/errorAnalytics.live.test.ts`: opt-in generated SQL checks against a real Parseable server.
- `e2e/errors.spec.ts`: browser state, navigation, pagination and failure behavior. API responses use fixture records; these tests do not establish SQL engine compatibility.

## Running the tests

From `frontend`, install dependencies with `npm ci`, then run focused unit tests:

```sh
npx vitest run src/lib/errorAnalytics.test.ts
```

The real-server suite is deliberately opt-in. It creates uniquely named disposable JSON-log, OTLP-log and OTLP-trace datasets and removes those datasets afterward. Use an isolated development server and an account allowed to ingest, query, and delete these fixtures:

```sh
ERRORS_REFERENCE_URL=http://127.0.0.1:8450 \
ERRORS_REFERENCE_USERNAME=fixture \
ERRORS_REFERENCE_PASSWORD=fixture-throwaway \
npx vitest run src/lib/errorAnalytics.live.test.ts
```

The example credentials belong to the local disposable fixture server. Without `ERRORS_REFERENCE_URL`, the suite skips its live tests. It derives bounds from persisted timestamps and polls for readiness instead of assuming ingestion is immediately queryable. Assertions use explicit fixture counts: they check retries and event expansion, nonerror exclusion, severity aliases, escaped message values, NULL identity, more than one page of groups, and agreement between frequency and summary counts.

Browser tests use the repository's Playwright configuration:

```sh
npx playwright test e2e/errors.spec.ts e2e/operations.spec.ts --workers=1
```

Ensure the configured server serves this checkout. A pre-existing server on the default port can belong to another worktree. Production build/type checking and the complete frontend unit suite are `npm run build` and `npm test`.

The Errors stories cover trace and log issues, loading, empty, permission, query failure, unsupported schema and unavailable metadata states. After building Storybook, run `native-screens.spec.ts --grep operations-errors` with `playwright.storybook.config.ts`. Detail stories exercise paging, trace links, keyboard dismissal and focus restoration; the suite also runs axe and a narrow dark viewport. Follow the shared Playwright lock instructions in the frontend README on shared hosts.
18 changes: 9 additions & 9 deletions frontend/docs/prism-parity.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@ The [observability validation record](observability-validation.md) documents ori

The previously classic-only routes below now resolve to native pages. `classicUi.ts` marks them `limited`, distinguishing a usable native subset or capability explanation from full classic parity. The existing Traces, APM, Add data and telemetry-aware dataset routes retain their behavior.

| Routes | Native behavior | Deliberate limits |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `/agents`, `/agents/:dataset` | Discover flattened GenAI fields through dataset schemas; query the latest 100 telemetry records in a selected time range; search loaded records; inspect full records; open compatible trace IDs | Individual events/spans, not classic run aggregation, evaluations, pricing or token-cost analytics. Demo uses explicit synthetic fixtures. |
| `/cluster` | Show registered distributed nodes, reachability, status, storage/staging locations and resource metrics from the existing cluster endpoints | Read-only. Standalone servers can report cluster administration unavailable. Node and metrics failures remain separate. |
| `/errors`, `/errors/:dataset` | Discover accessible OTLP trace datasets; list, sort and paginate error spans; open their trace waterfall | Classic grouped error issues and frequency endpoints are absent from this backend; arbitrary log issue aggregation is not fabricated. |
| `/onboarding` | Discover accessible datasets, link each to its confirmed explorer, and guide ingestion and team setup | Dataset presence is not presented as proof of event arrival. Existing Add data owns ingestion configuration and verification. |
| `/new` | Explain server workspace scope; open connection settings or native setup | No API in this checkout provisions a separate hosted workspace. |
| `/keystone`, `/keystone/:id` | Native availability page and classic investigation handoff where available | No supported investigation/conversation API in this checkout. No claim that an ID exists or is accessible. |
| `/settings/llm-key` | Native availability pages and deployment-dependent classic handoff | No provider-key management API. No credentials are read, stored or submitted. |
| Routes | Native behavior | Deliberate limits |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/agents`, `/agents/:dataset` | Discover flattened GenAI fields through dataset schemas; query the latest 100 telemetry records in a selected time range; search loaded records; inspect full records; open compatible trace IDs | Individual events/spans, not classic run aggregation, evaluations, pricing or token-cost analytics. Demo uses explicit synthetic fixtures. |
| `/cluster` | Show registered distributed nodes, reachability, status, storage/staging locations and resource metrics from the existing cluster endpoints | Read-only. Standalone servers can report cluster administration unavailable. Node and metrics failures remain separate. |
| `/errors`, `/errors/:dataset` | Discover trace and log error datasets; group issues, query full-range frequency, inspect occurrences, sort/page issues and OTLP spans, and open trace or SQL investigations | Exact service/type/message grouping with recognized severity schemas; persistent issue resolution, fuzzy grouping and cross-dataset correlation remain unavailable. See [Errors contracts and tests](error-analytics.md). |
| `/onboarding` | Discover accessible datasets, link each to its confirmed explorer, and guide ingestion and team setup | Dataset presence is not presented as proof of event arrival. Existing Add data owns ingestion configuration and verification. |
| `/new` | Explain server workspace scope; open connection settings or native setup | No API in this checkout provisions a separate hosted workspace. |
| `/keystone`, `/keystone/:id` | Native availability page and classic investigation handoff where available | No supported investigation/conversation API in this checkout. No claim that an ID exists or is accessible. |
| `/settings/llm-key` | Native availability pages and deployment-dependent classic handoff | No provider-key management API. No credentials are read, stored or submitted. |

Network access (`/settings/network-access`) edits the real outbound alert-target policy via `GET` and `PUT /api/v1/alert-target-policy`. It is distinct from ingress access control. The full policy includes private-IP and invalid-TLS switches plus allowed/denied domains and CIDRs. Backend authorization and validation remain authoritative; failed saves retain the draft. The policy cache is per server node and loaded at startup; cross-node propagation is a backend limitation, not asserted by the UI.

Expand Down
Loading
Loading