feat(search): Make default lookback configurable; reconstruct lookback from URL timestamps#3973
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3973 +/- ##
==========================================
+ Coverage 91.11% 91.13% +0.01%
==========================================
Files 342 342
Lines 10702 10723 +21
Branches 2819 2823 +4
==========================================
+ Hits 9751 9772 +21
Misses 826 826
Partials 125 125 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds a UI configuration knob to control the default Lookback selection in the Search form, allowing deployments to choose a less expensive default time range than the current hardcoded 1h.
Changes:
- Extends the UI
Configtype withsearch.defaultLookback?: string(documented as a Lookback dropdown value). - Applies
search.defaultLookbackinSearchFormfor initial form values and the Lookback dropdown default. - Adds unit tests verifying config default behavior and URL precedence, and documents why
url.tsretains a hardcoded fallback.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/jaeger-ui/src/types/config.ts | Adds search.defaultLookback to the typed UI config with documentation. |
| packages/jaeger-ui/src/components/SearchTracePage/url.ts | Documents why URL parsing still falls back to '1h' when lookback is absent. |
| packages/jaeger-ui/src/components/SearchTracePage/SearchForm.tsx | Reads search.defaultLookback to influence Lookback defaults and initial form state. |
| packages/jaeger-ui/src/components/SearchTracePage/SearchForm.test.jsx | Adds tests for config-driven default lookback and URL precedence. |
Comments suppressed due to low confidence (1)
packages/jaeger-ui/src/components/SearchTracePage/SearchForm.tsx:367
search.defaultLookbackis consumed directly as the Select default/initial value, but it is not validated against the allowedlookbackOptions(and can also be inconsistent withsearch.maxLookback). If it’s misconfigured (typo, unsupported unit, or a value filtered out byoptionsWithinMaxLookback()), AntD Select can render an empty value andsubmitForm()will compute timestamps from an invalid lookback. Consider normalizing/clamping the configured value: if it’s not in the allowed set (and within the maxLookback range), fall back toDEFAULT_LOOKBACK(or tosearchMaxLookback.value).
const { useOpenTelemetryTerms: useOtelTerms, search } = useConfig();
const searchMaxLookback: ILookbackOption | undefined = search?.maxLookback;
const searchAdjustEndTime: string | undefined = search?.adjustEndTime;
const defaultLookback: string = search?.defaultLookback ?? DEFAULT_LOOKBACK;
const [formData, setFormData] = useState<Partial<ISearchFormFields>>(() => ({
service: initialValues?.service,
operation: initialValues?.operation,
tags: initialValues?.tags,
lookback: initialValues?.lookback,
startDate: initialValues?.startDate,
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…okback Add search.defaultLookback to the UI config so operators can change the pre-selected Lookback dropdown value (e.g. '15m') without having to set maxLookback. When not set, falls back to the existing '1h' default. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
ac25afe to
05cc4ee
Compare
Add lookbackFromDuration() to time-range-options.ts: given a duration in milliseconds, returns the lookback string of the smallest standard option whose window covers that duration, or 'custom' if it exceeds the largest option (4 weeks). Use it in searchQueryFromUrl: when lookback is absent from the URL but start/end timestamps are present (shared link, external link), snap the time-range duration up to the nearest standard bucket instead of hardcoding '1h'. This keeps the dropdown in sync with the actual time range that was searched and avoids misleading the user. When neither timestamps nor lookback are present, return '' so that mapStateToProps can apply the configured defaultLookback instead. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
- isValidLookback() in time-range-options.ts validates config-supplied defaultLookback values; falls back to DEFAULT_LOOKBACK when invalid - Guard in searchQueryFromUrl changed from endUs > 0 to endUs > startUs to avoid negative duration when timestamps are inverted in the URL Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
Avoids ambiguity with the `search` URL string param used elsewhere in the same file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
…nfig Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
The module now contains functions (isValidLookback, lookbackFromDuration) in addition to constants, so utils/ is a more appropriate home. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
Returns the value itself (or undefined) instead of boolean, eliminating the repeated guard pattern at every call site. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
mapStateToProps already seeds initialValues.lookback with the config default, making the Select's defaultValue prop dead code (controlled components ignore defaultValue anyway). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
packages/jaeger-ui/src/utils/time-range-options.ts:113
- The PR description lists
constants/time-range-options.ts, but the helpers are added insrc/utils/time-range-options.ts(and there is noconstants/time-range-options.tsin this package). Updating the description/file list would avoid confusion for reviewers and future archeology.
When lookback is absent but start/end are present in the URL, mapStateToProps now derives the lookback from the timestamp range (same logic as searchQueryFromUrl), rather than falling back to the configured default. This ensures the form's dropdown reflects the actual searched window for shared/external links. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
URL input is external and should not be trusted blindly. An invalid lookback value in the URL now falls through to timestamp reconstruction or the configured default, same as an absent value. asValidLookback now also accepts 'custom' since that is a valid Select option rendered alongside TIME_RANGE_OPTIONS entries. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
mapStateToProps was duplicating the same lookback-derivation logic as searchQueryFromUrl. Extracted into lookbackFromUrl() in url.ts so both callers share a single implementation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
Extract lookbackFromUrlState() that operates on the already-parsed TUrlState; searchQueryFromUrl reuses the q it already holds. lookbackFromUrl() is a thin public wrapper for callers that only have the raw search string. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
An invalid lookback string in the URL now falls through to timestamp reconstruction, the same way an absent value does. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
Add asValidConfigLookback() which only accepts TIME_RANGE_OPTIONS entries (no 'custom'). Config validation now uses this stricter function; asValidLookback() (accepting 'custom') remains for URL param validation where 'custom' is a legitimate user selection. Also fix JSDoc placement: lookbackFromUrl gets a short summary that refers to lookbackFromUrlState; the full doc block sits above searchQueryFromUrl where it belongs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Yuri Shkuro <github@ysh.us>
…k from URL timestamps (jaegertracing#3973) ## Which problem is this PR solving? The Lookback dropdown in the Search form has two related issues: 1. The default value always hardcodes **1h** regardless of deployment context. Some deployments (e.g. high-cardinality environments, short-retention backends) want a shorter default like **15m** to avoid overwhelming the backend on every page load. 2. When a URL is shared without a `lookback` param (e.g. from an external system or manually crafted link), the form previously hardcoded `'1h'` as the selected option, misrepresenting the actual time range that was searched. `maxLookback` is already configurable but only controls the upper bound, not the pre-selected default. ## Description of the changes ### 1. Configurable default lookback Adds `search.defaultLookback` to the UI config object. When set to a recognized option, it overrides the hardcoded `'1h'` default used when the lookback cannot be derived from the URL. Invalid values are silently ignored and fall back to `'1h'`. **Example `jaeger-ui.json`:** ```json { "search": { "defaultLookback": "15m" } } ``` Valid values: `"5m"`, `"15m"`, `"30m"`, `"1h"`, `"2h"`, `"3h"`, `"6h"`, `"12h"`, `"24h"`, `"2d"`, `"3d"`, `"5d"`, `"7d"`, `"2w"`, `"3w"`, `"4w"`, `"custom"`. ### 2. Reconstruct lookback from URL timestamps When `lookback` is absent or invalid in the URL but valid `start`/`end` timestamps are present, the lookback is now reconstructed by rounding up to the smallest standard option that covers the full range (or `'custom'` when the range exceeds all standard options). The config default is applied only when timestamps are absent or invalid too. This logic lives in `lookbackFromUrlState()` in `url.ts` and is shared by both `searchQueryFromUrl()` and `mapStateToProps` via the public `lookbackFromUrl()` wrapper. ### Files changed - `types/config.ts` — adds `defaultLookback?: string` to the `search` section - `utils/time-range-options.ts` — adds `asValidLookback()` (validates + accepts `'custom'`) and `lookbackFromDuration()` helpers; moved from `constants/` to `utils/` - `SearchForm.tsx` — reads `search.defaultLookback` via `lookbackFromUrl()` + `asValidLookback()` fallback chain; removes `lookback` from `queryString.parse` destructure - `url.ts` — adds `lookbackFromUrlState()` (shared core logic), `lookbackFromUrl()` (public string wrapper); `searchQueryFromUrl` delegates to `lookbackFromUrlState` to avoid double-parsing ## How was this change tested? - `time-range-options.test.ts`: 4 new tests for `lookbackFromDuration` - `url.test.js`: 5 new tests for `searchQueryFromUrl` lookback reconstruction - `SearchForm.test.jsx`: 2 new tests for `mapStateToProps` — config default used when no URL lookback, URL lookback takes precedence ## Checklist - [x] I have read https://github.com/jaegertracing/jaeger/blob/main/CONTRIBUTING_GUIDELINES.md - [x] I have signed all commits - [x] I have added unit tests for the new functionality - [x] I have run lint and test steps successfully: `make lint test` ## AI Usage in this PR - [x] **Moderate**: AI helped with code generation 🤖 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>
Which problem is this PR solving?
The Lookback dropdown in the Search form has two related issues:
The default value always hardcodes 1h regardless of deployment context. Some deployments (e.g. high-cardinality environments, short-retention backends) want a shorter default like 15m to avoid overwhelming the backend on every page load.
When a URL is shared without a
lookbackparam (e.g. from an external system or manually crafted link), the form previously hardcoded'1h'as the selected option, misrepresenting the actual time range that was searched.maxLookbackis already configurable but only controls the upper bound, not the pre-selected default.Description of the changes
1. Configurable default lookback
Adds
search.defaultLookbackto the UI config object. When set to a recognized option, it overrides the hardcoded'1h'default used when the lookback cannot be derived from the URL. Invalid values are silently ignored and fall back to'1h'.Example
jaeger-ui.json:{ "search": { "defaultLookback": "15m" } }Valid values:
"5m","15m","30m","1h","2h","3h","6h","12h","24h","2d","3d","5d","7d","2w","3w","4w","custom".2. Reconstruct lookback from URL timestamps
When
lookbackis absent or invalid in the URL but validstart/endtimestamps are present, the lookback is now reconstructed by rounding up to the smallest standard option that covers the full range (or'custom'when the range exceeds all standard options). The config default is applied only when timestamps are absent or invalid too.This logic lives in
lookbackFromUrlState()inurl.tsand is shared by bothsearchQueryFromUrl()andmapStateToPropsvia the publiclookbackFromUrl()wrapper.Files changed
types/config.ts— addsdefaultLookback?: stringto thesearchsectionutils/time-range-options.ts— addsasValidLookback()(validates + accepts'custom') andlookbackFromDuration()helpers; moved fromconstants/toutils/SearchForm.tsx— readssearch.defaultLookbackvialookbackFromUrl()+asValidLookback()fallback chain; removeslookbackfromqueryString.parsedestructureurl.ts— addslookbackFromUrlState()(shared core logic),lookbackFromUrl()(public string wrapper);searchQueryFromUrldelegates tolookbackFromUrlStateto avoid double-parsingHow was this change tested?
time-range-options.test.ts: 4 new tests forlookbackFromDurationurl.test.js: 5 new tests forsearchQueryFromUrllookback reconstructionSearchForm.test.jsx: 2 new tests formapStateToProps— config default used when no URL lookback, URL lookback takes precedenceChecklist
make lint testAI Usage in this PR
🤖 Generated with Claude Code