Skip to content

refactor(search): Introduce TraceSummary type for search results#3941

Merged
yurishkuro merged 3 commits into
jaegertracing:mainfrom
yurishkuro:search-trace-summary-type
May 21, 2026
Merged

refactor(search): Introduce TraceSummary type for search results#3941
yurishkuro merged 3 commits into
jaegertracing:mainfrom
yurishkuro:search-trace-summary-type

Conversation

@yurishkuro

@yurishkuro yurishkuro commented May 21, 2026

Copy link
Copy Markdown
Member

Summary

  • Introduces TraceSummary and ServiceSummary types in src/types/trace-summary.ts as a lightweight alternative to IOtelTrace for the search results view
  • Replaces IOtelTrace with TraceSummary in ResultItem, SearchResults, and SearchTracePage — error counts and per-service error flags are now read from pre-computed fields instead of iterating spans on every render
  • Adds traceToTraceSummary(trace: IOtelTrace): TraceSummary adapter in src/model/trace-summary.ts so the existing sortedTracesXformer path continues to work unchanged
  • ResultItemTitle.duration prop type simplified from IOtelTrace['duration'] to Microseconds directly, removing the dependency on IOtelTrace
  • Prepares for ADR-010 Milestone 2: once the UI calls GET /api/v3/trace-summaries, the reducer can populate TraceSummary directly from the API response without the transformTraceData aggregation step

Test plan

  • New unit tests in src/model/trace-summary.test.ts cover: empty trace, root service/operation extraction, error span counting (total and per-service), zero-error case, orphan count propagation, and a round-trip through traceGenerator + transformTraceData
  • Existing ResultItem.test.jsx and SearchResults/index.test.jsx updated to use TraceSummary-shaped fixtures
  • npm test, npm run lint, npm run build all pass

Related

🤖 Generated with Claude Code

Replace IOtelTrace with a lightweight TraceSummary in the search
results components (ResultItem, SearchResults, SearchTracePage).

TraceSummary carries only the fields needed for the search results
row and scatter plot: traceID, traceName, root service/operation,
startTime, duration, spanCount, errorSpanCount, orphanSpanCount,
and a per-service breakdown (ServiceSummary). All error counts are
pre-computed, removing the span iteration that ResultItem previously
did on every render.

A traceToTraceSummary() adapter converts IOtelTrace to TraceSummary
so the existing sortedTracesXformer path continues to work until
Milestone 2 wires in the new backend endpoint.

Prepares for ADR-010 Milestone 2 (UI migration to /api/v3/trace-summaries).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Yuri Shkuro <github@ysh.us>
@codecov

codecov Bot commented May 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.05882% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 90.89%. Comparing base (b618d3c) to head (d9da45f).

Files with missing lines Patch % Lines
...jaeger-ui/src/components/SearchTracePage/index.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3941   +/-   ##
=======================================
  Coverage   90.89%   90.89%           
=======================================
  Files         334      335    +1     
  Lines       10505    10505           
  Branches     2748     2751    +3     
=======================================
  Hits         9549     9549           
  Misses        831      831           
  Partials      125      125           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the search results flow to use a lightweight TraceSummary shape instead of IOtelTrace, moving expensive per-render aggregation (error counts / per-service error flags) into a single transformation step.

Changes:

  • Added TraceSummary / ServiceSummary types plus a traceToTraceSummary(trace: IOtelTrace) adapter.
  • Updated Search UI components (SearchTracePage, SearchResults, ResultItem) and tests to consume TraceSummary and rely on precomputed counts/flags.
  • Simplified ResultItemTitle.duration to use Microseconds directly.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/jaeger-ui/src/types/trace-summary.ts Introduces TraceSummary and ServiceSummary types for search results.
packages/jaeger-ui/src/model/trace-summary.ts Adds traceToTraceSummary() adapter to compute summary fields from IOtelTrace.
packages/jaeger-ui/src/model/trace-summary.test.ts Adds unit tests validating traceToTraceSummary() behavior and integration with existing trace transformation.
packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItemTitle.tsx Decouples duration prop type from IOtelTrace to Microseconds.
packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItem.tsx Switches ResultItem to render from TraceSummary and removes per-render span iteration for error/service flags.
packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItem.test.jsx Updates fixtures/tests to pass TraceSummary (via adapter) into ResultItem.
packages/jaeger-ui/src/components/SearchTracePage/SearchResults/index.tsx Updates search results view/scatterplot data mapping to use TraceSummary fields.
packages/jaeger-ui/src/components/SearchTracePage/SearchResults/index.test.jsx Updates SearchResults tests to use TraceSummary-shaped fixtures and adjusts download expectations.
packages/jaeger-ui/src/components/SearchTracePage/index.tsx Updates sorting transformer to return TraceSummary[] by adapting asOtelTrace() results.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/jaeger-ui/src/model/trace-summary.test.ts Outdated
Comment thread packages/jaeger-ui/src/model/trace-summary.test.ts Outdated
Comment thread packages/jaeger-ui/src/components/SearchTracePage/SearchResults/index.tsx Outdated
Comment thread packages/jaeger-ui/src/model/trace-summary.ts Outdated
Comment thread packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItem.tsx Outdated
Comment thread packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItem.tsx Outdated
Comment thread packages/jaeger-ui/src/components/SearchTracePage/SearchResults/index.tsx Outdated
yurishkuro and others added 2 commits May 21, 2026 19:04
…in ScatterPlot

The scatter plot only needed services.length for the tooltip and
spans.length for dot sizing — it never used individual service
names or span counts. Replace the services array with two scalar
fields (spanCount, serviceCount) in TScatterPlotPoint, removing
the unnecessary array mapping at the call site.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Yuri Shkuro <github@ysh.us>
- Use `import type` for type-only imports in trace-summary.ts and test
- Require spanID in makeSpan helper (remove ambiguity)
- Type onValueClick param as `{ traceID: string }` (not TScatterPlotPoint)
- Type ResultItemTitle.duration as TraceSummary['duration']
- Rename ResultItem prop `trace` -> `traceSummary`
- Use service field names directly (no redundant aliases)
- Rename SearchResults prop `traces` -> `traceSummaries` throughout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Yuri Shkuro <github@ysh.us>
Copilot AI review requested due to automatic review settings May 21, 2026 23:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

@yurishkuro yurishkuro added the changelog:refactoring Internal, non-functional code improvements label May 21, 2026
@yurishkuro yurishkuro merged commit 571e8dc into jaegertracing:main May 21, 2026
15 of 16 checks passed
@yurishkuro yurishkuro deleted the search-trace-summary-type branch May 21, 2026 23:45
yurishkuro added a commit to jaegertracing/jaeger that referenced this pull request May 25, 2026
… results (#8604)

## Summary

- Part of #8606

Implements Milestone 1 from ADR-010 (#8602): a working `GET
/api/v3/trace-summaries` HTTP endpoint backed by fallback aggregation,
entirely within `jaeger/` with no `jaeger-idl` changes.

- **`tracestore.TraceSummary` / `ServiceSummary`** types and optional
**`tracestore.SummaryReader`** interface
(`internal/storage/v2/api/tracestore/summary.go`) — existing storage
implementations require no changes
- **`querysvc.FindTraceSummaries`** with fallback: type-asserts to
`SummaryReader`; if absent, calls `FindTraces` and computes summaries
via `computeSummaries` (`querysvc/summary.go`)
- **`GET /api/v3/trace-summaries`** HTTP handler
(`apiv3/http_gateway.go`), reusing the existing query-parameter parser
from `FindTraces`; response is plain JSON (proto formalisation is
Milestone 3)
- Unit tests: `computeSummaries` (empty, error, multi-service with
per-service error counts), `FindTraceSummaries` (fallback path + native
`SummaryReader` path), HTTP handler (success + storage error)

## Response shape

Timestamps are Unix nanoseconds encoded as **decimal strings**,
consistent with OTLP proto3 JSON encoding (`startTimeUnixNano` in `GET
/api/v3/traces`). String encoding avoids float64 precision loss in
JavaScript for values above 2⁵³ (~9×10¹⁵); nanosecond timestamps
(~1.7×10¹⁸) are well above that threshold. Duration is intentionally
omitted — callers derive it as `BigInt(maxEndTimeUnixNano) -
BigInt(minStartTimeUnixNano)`.

```json
{
  "summaries": [
    {
      "traceID": "00000000000000000000000000000001",
      "rootServiceName": "frontend",
      "rootOperationName": "HTTP GET /",
      "minStartTimeUnixNano": "1000000000000000000",
      "maxEndTimeUnixNano":   "1001000000000000000",
      "spanCount": 3,
      "errorSpanCount": 1,
      "orphanSpanCount": 0,
      "services": [
        {"name": "backend",  "spanCount": 1, "errorSpanCount": 0},
        {"name": "frontend", "spanCount": 2, "errorSpanCount": 1}
      ]
    }
  ]
}
```

## Example

```
curl 'http://localhost:16686/api/v3/trace-summaries?query.service_name=frontend&query.start_time_min=2026-05-21T23:00:00Z&query.start_time_max=2026-05-22T00:00:00Z&query.num_traces=20'
```

## Test plan

- [x] `make fmt lint` — clean
- [x] `go test ./cmd/jaeger/internal/extension/jaegerquery/...` — all
pass
- [x] Manual smoke test with `curl` against a running Jaeger-all-in-one
— returns correct summaries

## Related

- ADR-010: #8602
- IDL cleanup: #8603
- UI PR: jaegertracing/jaeger-ui#3941

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Yuri Shkuro <github@ysh.us>
Signed-off-by: Yuri Shkuro <yurishkuro@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
M-DEV-1 pushed a commit to M-DEV-1/jaeger-ui that referenced this pull request May 25, 2026
…gertracing#3941)

## Summary

- Introduces `TraceSummary` and `ServiceSummary` types in
`src/types/trace-summary.ts` as a lightweight alternative to
`IOtelTrace` for the search results view
- Replaces `IOtelTrace` with `TraceSummary` in `ResultItem`,
`SearchResults`, and `SearchTracePage` — error counts and per-service
error flags are now read from pre-computed fields instead of iterating
spans on every render
- Adds `traceToTraceSummary(trace: IOtelTrace): TraceSummary` adapter in
`src/model/trace-summary.ts` so the existing `sortedTracesXformer` path
continues to work unchanged
- `ResultItemTitle.duration` prop type simplified from
`IOtelTrace['duration']` to `Microseconds` directly, removing the
dependency on `IOtelTrace`
- Prepares for ADR-010 Milestone 2: once the UI calls `GET
/api/v3/trace-summaries`, the reducer can populate `TraceSummary`
directly from the API response without the `transformTraceData`
aggregation step

## Test plan

- [ ] New unit tests in `src/model/trace-summary.test.ts` cover: empty
trace, root service/operation extraction, error span counting (total and
per-service), zero-error case, orphan count propagation, and a
round-trip through `traceGenerator` + `transformTraceData`
- [ ] Existing `ResultItem.test.jsx` and `SearchResults/index.test.jsx`
updated to use `TraceSummary`-shaped fixtures
- [ ] `npm test`, `npm run lint`, `npm run build` all pass

## Related

- Part of jaegertracing/jaeger#8606
- ADR-010: jaegertracing/jaeger#8602
- Backend PR: jaegertracing/jaeger#8604

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Yuri Shkuro <github@ysh.us>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
yurishkuro added a commit to jaegertracing/jaeger that referenced this pull request May 25, 2026
…Depth in trace-summaries endpoint (#8633)

## Summary

Three fixes to the `GET /api/v3/trace-summaries` endpoint introduced in
#8604:

- **`traceId` field name casing**: the response was returning `traceID`
(uppercase D) but the OpenAPI spec and the generated Zod client expect
`traceId` (lowercase d, matching proto3 JSON naming). The UI worked
around this defensively; this fixes the backend.
- **`SearchDepth` default**: `parseFindTracesQuery` was not applying a
default when `query.search_depth` is absent, causing the memory backend
to return a 500 on every unauthenticated request. Now defaults to 100,
matching the v1 HTTP handler.
- **Snapshot test**: adds a golden-file test for the full
`FindTraceSummaries` JSON response so field name and encoding
regressions are caught automatically.

## Changes

- `summaries.go`: change JSON tag from `"traceID"` to `"traceId"`
- `query_parser.go`: add `defaultSearchDepth = 100`; apply it when
`query.search_depth` is absent
- `gateway_test.go` + `snapshots/FindTraceSummaries.json`: snapshot test
for the HTTP response
- `docs/adr/010-trace-summary-api.md`: reflect M1/M2 completion, note
that jaeger-idl already has all M3/M4 proto work merged, add PR sequence
for remaining work

## Test plan

- [x] `go test ./cmd/jaeger/internal/extension/jaegerquery/...` passes
- [x] `make lint` passes

## Related

- #8604 — main implementation this PR fixes
- #8617 — tracking issue for `search_depth` naming / default
- #8618 — rename `num_traces` → `search_depth` (cherry-picked)
- jaegertracing/jaeger-ui#3941

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Yuri Shkuro <github@ysh.us>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
vic-comm pushed a commit to vic-comm/jaeger that referenced this pull request Jun 11, 2026
… results (jaegertracing#8604)

## Summary

- Part of jaegertracing#8606

Implements Milestone 1 from ADR-010 (jaegertracing#8602): a working `GET
/api/v3/trace-summaries` HTTP endpoint backed by fallback aggregation,
entirely within `jaeger/` with no `jaeger-idl` changes.

- **`tracestore.TraceSummary` / `ServiceSummary`** types and optional
**`tracestore.SummaryReader`** interface
(`internal/storage/v2/api/tracestore/summary.go`) — existing storage
implementations require no changes
- **`querysvc.FindTraceSummaries`** with fallback: type-asserts to
`SummaryReader`; if absent, calls `FindTraces` and computes summaries
via `computeSummaries` (`querysvc/summary.go`)
- **`GET /api/v3/trace-summaries`** HTTP handler
(`apiv3/http_gateway.go`), reusing the existing query-parameter parser
from `FindTraces`; response is plain JSON (proto formalisation is
Milestone 3)
- Unit tests: `computeSummaries` (empty, error, multi-service with
per-service error counts), `FindTraceSummaries` (fallback path + native
`SummaryReader` path), HTTP handler (success + storage error)

## Response shape

Timestamps are Unix nanoseconds encoded as **decimal strings**,
consistent with OTLP proto3 JSON encoding (`startTimeUnixNano` in `GET
/api/v3/traces`). String encoding avoids float64 precision loss in
JavaScript for values above 2⁵³ (~9×10¹⁵); nanosecond timestamps
(~1.7×10¹⁸) are well above that threshold. Duration is intentionally
omitted — callers derive it as `BigInt(maxEndTimeUnixNano) -
BigInt(minStartTimeUnixNano)`.

```json
{
  "summaries": [
    {
      "traceID": "00000000000000000000000000000001",
      "rootServiceName": "frontend",
      "rootOperationName": "HTTP GET /",
      "minStartTimeUnixNano": "1000000000000000000",
      "maxEndTimeUnixNano":   "1001000000000000000",
      "spanCount": 3,
      "errorSpanCount": 1,
      "orphanSpanCount": 0,
      "services": [
        {"name": "backend",  "spanCount": 1, "errorSpanCount": 0},
        {"name": "frontend", "spanCount": 2, "errorSpanCount": 1}
      ]
    }
  ]
}
```

## Example

```
curl 'http://localhost:16686/api/v3/trace-summaries?query.service_name=frontend&query.start_time_min=2026-05-21T23:00:00Z&query.start_time_max=2026-05-22T00:00:00Z&query.num_traces=20'
```

## Test plan

- [x] `make fmt lint` — clean
- [x] `go test ./cmd/jaeger/internal/extension/jaegerquery/...` — all
pass
- [x] Manual smoke test with `curl` against a running Jaeger-all-in-one
— returns correct summaries

## Related

- ADR-010: jaegertracing#8602
- IDL cleanup: jaegertracing#8603
- UI PR: jaegertracing/jaeger-ui#3941

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Yuri Shkuro <github@ysh.us>
Signed-off-by: Yuri Shkuro <yurishkuro@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Victor Chidera Obiezue <obiezuechidera@gmail.com>
vic-comm pushed a commit to vic-comm/jaeger that referenced this pull request Jun 11, 2026
…Depth in trace-summaries endpoint (jaegertracing#8633)

## Summary

Three fixes to the `GET /api/v3/trace-summaries` endpoint introduced in
jaegertracing#8604:

- **`traceId` field name casing**: the response was returning `traceID`
(uppercase D) but the OpenAPI spec and the generated Zod client expect
`traceId` (lowercase d, matching proto3 JSON naming). The UI worked
around this defensively; this fixes the backend.
- **`SearchDepth` default**: `parseFindTracesQuery` was not applying a
default when `query.search_depth` is absent, causing the memory backend
to return a 500 on every unauthenticated request. Now defaults to 100,
matching the v1 HTTP handler.
- **Snapshot test**: adds a golden-file test for the full
`FindTraceSummaries` JSON response so field name and encoding
regressions are caught automatically.

## Changes

- `summaries.go`: change JSON tag from `"traceID"` to `"traceId"`
- `query_parser.go`: add `defaultSearchDepth = 100`; apply it when
`query.search_depth` is absent
- `gateway_test.go` + `snapshots/FindTraceSummaries.json`: snapshot test
for the HTTP response
- `docs/adr/010-trace-summary-api.md`: reflect M1/M2 completion, note
that jaeger-idl already has all M3/M4 proto work merged, add PR sequence
for remaining work

## Test plan

- [x] `go test ./cmd/jaeger/internal/extension/jaegerquery/...` passes
- [x] `make lint` passes

## Related

- jaegertracing#8604 — main implementation this PR fixes
- jaegertracing#8617 — tracking issue for `search_depth` naming / default
- jaegertracing#8618 — rename `num_traces` → `search_depth` (cherry-picked)
- jaegertracing/jaeger-ui#3941

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Yuri Shkuro <github@ysh.us>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Victor Chidera Obiezue <obiezuechidera@gmail.com>
Harizz076 pushed a commit to Harizz076/jaeger-ui that referenced this pull request Jul 4, 2026
…gertracing#3941)

## Summary

- Introduces `TraceSummary` and `ServiceSummary` types in
`src/types/trace-summary.ts` as a lightweight alternative to
`IOtelTrace` for the search results view
- Replaces `IOtelTrace` with `TraceSummary` in `ResultItem`,
`SearchResults`, and `SearchTracePage` — error counts and per-service
error flags are now read from pre-computed fields instead of iterating
spans on every render
- Adds `traceToTraceSummary(trace: IOtelTrace): TraceSummary` adapter in
`src/model/trace-summary.ts` so the existing `sortedTracesXformer` path
continues to work unchanged
- `ResultItemTitle.duration` prop type simplified from
`IOtelTrace['duration']` to `Microseconds` directly, removing the
dependency on `IOtelTrace`
- Prepares for ADR-010 Milestone 2: once the UI calls `GET
/api/v3/trace-summaries`, the reducer can populate `TraceSummary`
directly from the API response without the `transformTraceData`
aggregation step

## Test plan

- [ ] New unit tests in `src/model/trace-summary.test.ts` cover: empty
trace, root service/operation extraction, error span counting (total and
per-service), zero-error case, orphan count propagation, and a
round-trip through `traceGenerator` + `transformTraceData`
- [ ] Existing `ResultItem.test.jsx` and `SearchResults/index.test.jsx`
updated to use `TraceSummary`-shaped fixtures
- [ ] `npm test`, `npm run lint`, `npm run build` all pass

## Related

- Part of jaegertracing/jaeger#8606
- ADR-010: jaegertracing/jaeger#8602
- Backend PR: jaegertracing/jaeger#8604

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Yuri Shkuro <github@ysh.us>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog:refactoring Internal, non-functional code improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants