Skip to content

feat: Agoda.DevExTelemetry full-stack implementation - #1

Merged
joeldickson merged 16 commits into
mainfrom
feature/devex-telemetry-implementation
Mar 22, 2026
Merged

joeldickson merged 16 commits into
mainfrom
feature/devex-telemetry-implementation

Conversation

@joeldickson

Copy link
Copy Markdown
Contributor

Summary

  • Full-stack DevEx Telemetry Dashboard built with .NET 10 (Kestrel + EF Core SQLite) backend and React 19 (Vite + Tailwind + Tremor) frontend
  • Backend: 10 POST ingest endpoints (dotnet, nunit, junit, jest, vitest, scalatest, webpack, vite, gradle, multipart junit XML), 7 GET dashboard/filter endpoints, environment detection, status normalization, build category classification, background data cleanup service
  • Frontend: 3 dashboard pages (Test Runs, API Build, Clientside Build) with KPI cards, charts, data tables, global filters; test run detail page with per-test-case breakdown
  • 83 tests (21 unit + 62 integration) all passing, CI/CD via GitHub Actions with Azure App Service deployment

Test plan

  • dotnet build — 0 errors, 0 warnings
  • dotnet test — 63 passed (integration) + placeholder unit tests
  • npm run build (tsc + vite) — success
  • All 9 ingest endpoint types tested with realistic payloads
  • Dashboard aggregation queries tested with seeded data
  • Environment detection, status normalization, build classification unit tested
  • Data cleanup service tested (old record deletion, retention preservation)

dicko2 added 10 commits March 22, 2026 11:49
Multi-agent parallel implementation of the DevEx Telemetry dashboard:

- Agent 1: Project scaffold, entities, DTOs, interfaces, configs
- Agent 2: Ingest controllers (9 POST endpoints), normalization services
- Agent 3: Dashboard read API (6 GET endpoints), view models, queries
- Agent 4: React frontend (3 dashboards, filters, charts, tables)
- Agent 5: Integration tests (63) and unit tests (38), all passing

Backend: .NET 10, EF Core SQLite, Agoda.IoC DI
Frontend: React 19, Tremor, Recharts, TanStack Table, Vite 8, Tailwind 3

Build verified: dotnet build (0 errors), dotnet test (101 passed),
npm run build (tsc + vite, 0 errors)

Made-with: Cursor
Add GitHub Actions build workflow (backend + frontend parallel jobs)
and Azure App Service deployment workflow triggered on main branch push.

Made-with: Cursor
Remove push trigger from build workflow to avoid duplicate runs.
Deploy workflow already covers push-to-main.

Made-with: Cursor
Replace template boilerplate with actual architecture, endpoints,
development setup, and deployment info.

Made-with: Cursor
- Add 71 Playwright component tests covering all Layer 2 components,
  utility functions, and Layer 3 pages with API mocking
- Set up ESLint with typescript-eslint, react-hooks, and react-refresh plugins
- Set up Prettier with eslint-config-prettier integration
- Add Prettier check and ESLint steps to CI build workflow
- Format all source files with Prettier

Made-with: Cursor
Cache ~/.nuget/packages in both build and deploy workflows using
actions/cache@v4. The deploy workflow (push to main) populates the
cache, and PR branches fall back to it via restore-keys.

Made-with: Cursor

@joeldickson joeldickson left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Completed agent-6 review against issue #224 criteria (correctness, missing tests, performance/concurrency, API contract alignment). I left inline comments for concrete issues that should be addressed before merge:

  1. Platform filtering is mapped to wrong fields in backend query logic.
  2. Frontend/backed query parameter contract mismatch (projectName vs Project, unsupported dateRange).
  3. UI "platform" filter currently populated from metric types.
  4. Duplicate-ID ingest behavior is implicit and can surface as 500.
  5. Numeric parsing allows silent bad data paths (e.g. malformed timeTaken).
  6. Cleanup timer can overlap async runs and conflict with SQLite writes.
  7. Malformed JUnit XML is treated as success instead of client error.

Please also add integration tests for each of these paths to prevent regressions.

Comment thread src/Agoda.DevExTelemetry.Core/Services/DashboardService.cs Outdated
Comment thread src/Agoda.DevExTelemetry.Core/Services/DashboardService.cs Outdated
Comment thread src/Clientside/src/components/filters/GlobalFilters.tsx Outdated
Comment thread src/Clientside/src/hooks/useFilters.ts Outdated
Comment thread src/Agoda.DevExTelemetry.WebApi/Controllers/DotnetController.cs Outdated
Comment thread src/Agoda.DevExTelemetry.Core/Services/JUnitXmlParser.cs Outdated
Comment thread src/Agoda.DevExTelemetry.Core/Services/DataCleanupService.cs Outdated
Comment thread src/Agoda.DevExTelemetry.Core/Services/IngestService.cs
dicko2 added 4 commits March 22, 2026 13:06
Add toHaveScreenshot() assertions to all component and page specs:
- 13 screenshot tests for Layer 2 components (StatCard, ChartCard,
  PageHeader, DashboardGrid, AppShell, EnvironmentToggle, GlobalFilters,
  DataTable in various states)
- 4 screenshot tests for Layer 3 pages (TestRunDashboard, TestRunDetail,
  ApiBuildDashboard, ClientsideBuildDashboard)
- Baseline PNG snapshots committed for Linux/Chromium

Made-with: Cursor
- GlobalFilters: use options.platforms instead of options.metricTypes for
  the Platforms multi-select, so the UI label matches the data source
- useFilters: send `project` (not `projectName`) and convert dateRange
  to explicit `from`/`to` ISO timestamps so the backend actually filters
- client.ts: align FilterParams fields (project, from, to) and add
  platforms to FilterOptions
- Update mock data and spec fixtures to include platforms array

Made-with: Cursor
- GlobalFilters: source platforms from `options.platforms` instead of
  `options.metricTypes` to fix semantic mismatch
- useFilters: send `project` (not `projectName`) and convert `dateRange`
  to explicit `from`/`to` ISO dates to match backend FilterParams
- DataCleanupService: switch from Timer/IHostedService to
  BackgroundService/PeriodicTimer to prevent overlapping cleanup runs
- Add `platforms` field to frontend FilterOptions and test fixtures

Made-with: Cursor
- DashboardService: filter by Platform instead of TestRunner/MetricType
- DotnetController: use InvariantCulture parsing, reject non-finite values
- JUnitXmlParser: return JUnitXmlParseResult with error info
- IngestService: idempotent duplicate-id handling with AnyAsync check
- FilterService/FilterOptionsViewModel: expose distinct platform values

Made-with: Cursor

@joeldickson joeldickson left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Second-pass review completed after latest push.

Most previously reported issues are fixed (platform mapping in backend filters, query naming alignment, XML parse failure handling, cleanup timer overlap mitigation, platform options source).

Remaining issues are primarily:

  1. multi-select platform serialization vs backend equality filtering,
  2. API/Clientside table scoping params not consumed by backend,
  3. duplicate-ID ingest behavior still implicit (likely 500 path),
  4. one-type-per-file convention deviation in JUnit parser file.

Inline comments added for each with suggested fix directions.

Comment thread src/Clientside/src/hooks/useFilters.ts
Comment thread src/Clientside/src/hooks/useClientsideBuildMetrics.ts Outdated
Comment thread src/Agoda.DevExTelemetry.Core/Services/JUnitXmlParser.cs Outdated
Comment thread src/Agoda.DevExTelemetry.Core/Services/IngestService.cs
Comment thread src/Clientside/src/hooks/useApiBuildMetrics.ts Outdated
dicko2 added 2 commits March 22, 2026 13:42
- Support comma-separated platform filter values in backend (split CSV server-side)
- Add BuildCategory filter to FilterParams and ApplyBuildMetricFilters
- Frontend hooks now send buildCategory instead of metricType for page scoping
- Extract JUnitXmlParseResult to own file per one-type-per-file convention

Made-with: Cursor
@joeldickson
joeldickson merged commit c71e7ef into main Mar 22, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants