Conversation
Add utility functions for time-series chart implementation: - getTimeBucketConfig: returns bucket interval and count for time range - bucketTimestamps: groups timestamps into bucket indices - fillMissingBuckets: fills gaps with zero counts - formatBucketLabel: formats bucket timestamps for chart axis Install layerchart@1.0.13 for charting capabilities. Includes 17 unit tests covering all edge cases.
Add GET /api/projects/[id]/stats/timeseries endpoint that returns time-bucketed log counts for visualization in an area chart. Features: - Supports 15m, 1h, 24h, 7d time ranges with appropriate granularity - Returns buckets array with timestamp and count for each interval - Properly filters by project ID and time range - Handles empty state with zero-filled buckets Includes 14 integration tests covering: - Authentication requirements - Project validation (404 for non-existent) - All time range variations - Bucket ordering and timestamp validation - Project isolation (no cross-project data leakage)
Add area chart component for displaying log volume over time: - Uses LayerChart with dynamic imports (browser-only rendering) - Time scale X-axis with appropriate formatting per time range - Touch-friendly tooltips using mode: 'band' - Loading skeleton, error, and empty states - Responsive design with CSS custom properties for theming Includes 22 component tests covering: - Container rendering and accessibility attributes - Loading, error, and empty state displays - Different time range support - Edge cases (large counts, zero data, single point)
Add "Logs Over Time" area chart section to the stats page: - Fetches timeseries data from API on mount and range change - Displays area chart below the level distribution donut chart - Handles loading, error, and empty states - Responsive design for mobile and desktop Add @types/d3-scale for TypeScript support.
Add end-to-end tests for the new timeseries chart feature: Stats Page - Timeseries Chart: - should display timeseries chart on stats page - should show loading state then chart - should update timeseries chart when time range changes Stats Page - Timeseries Empty State: - should display empty state when no logs exist Tests verify chart visibility, loading states, API interactions, and time range changes.
Auto-format code changes from biome linter.
There was a problem hiding this comment.
Pull request overview
This PR adds a time-series area chart to the stats page that visualizes log volume over time across different time ranges (15m, 1h, 24h, 7d). The implementation follows a thorough TDD approach with comprehensive test coverage at all levels.
Changes:
- Added time-bucketing utility functions for grouping logs into time intervals
- Created new API endpoint
/api/projects/[id]/stats/timeseriesfor fetching time-bucketed log counts - Implemented LayerChart-based area chart component with loading, error, and empty states
- Integrated chart into stats page with automatic updates when time range changes
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/lib/utils/timeseries.ts |
Utility functions for time bucketing with 4 exported functions |
src/lib/utils/timeseries.unit.test.ts |
17 unit tests covering all utility functions |
src/routes/api/projects/[id]/stats/timeseries/+server.ts |
API endpoint with authentication and project validation |
tests/integration/api/projects/[id]/stats/timeseries.integration.test.ts |
14 integration tests for API endpoint |
src/lib/components/timeseries-chart.svelte |
Chart component with loading/error/empty states |
src/lib/components/__tests__/timeseries-chart.component.test.ts |
22 component tests |
src/routes/(app)/projects/[id]/stats/+page.svelte |
Page integration with $effect for reactivity |
tests/e2e/stats.spec.ts |
4 E2E tests for user interactions |
package.json |
Added layerchart@1.0.13 and @types/d3-scale@4.0.9 |
bun.lock |
Lock file updates for new dependencies |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
CSS custom properties (var(--primary)) don't work inside LayerChart's SVG/D3 rendering context. Replace with actual HSL color value that works in both light and dark modes.
The donut chart and timeseries chart were using different time ranges because they calculated the 'from' timestamp independently. This caused logs to appear in the donut but not in the timeseries for narrow ranges like 15m. Fix by: - Page server now returns the exact 'from' timestamp it used - Timeseries API accepts optional 'from' parameter - Page passes the 'from' timestamp to ensure both use the same range
7ad4787 to
6c076af
Compare
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 24037119 | Triggered | Generic Password | 3b8122b | tests/integration/api/projects/[id]/stats/timeseries.integration.test.ts | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
Move waitForResponse() listeners before page.goto() to ensure the response is captured regardless of timing. The previous approach could miss responses on slower CI machines where the API call completed before the listener was set up. Affected tests: - should show loading state then chart - should update timeseries chart when time range changes - should display empty state when no logs exist
…ltip
- select.svelte: Replace `bind:value={value as never}` with function binding
pattern to satisfy Svelte 5's stricter bind expression validation while
working around bits-ui discriminated union type inference issues
- timeseries-chart.svelte: Add explicit type annotation to tooltip snippet
parameter to fix implicit any error with noImplicitAny enabled
Add layerchart and @types/d3-scale to ignoreDependencies in knip.json. These packages are imported dynamically in timeseries-chart.svelte and are incorrectly flagged as unused by knip's static analysis.
Summary
Changes
src/lib/utils/timeseries.ts): Time bucketing utilities for grouping logs/api/projects/[id]/stats/timeseries): Returns time-bucketed log countssrc/lib/components/timeseries-chart.svelte): LayerChart-based area chartTest plan