Skip to content

refactor: Control Monitor tab visibility via storage capabilities of the backend#3554

Merged
yurishkuro merged 1 commit intojaegertracing:mainfrom
hharshhsaini:refactor/simplify-atm-configuration-3540
Mar 10, 2026
Merged

refactor: Control Monitor tab visibility via storage capabilities of the backend#3554
yurishkuro merged 1 commit intojaegertracing:mainfrom
hharshhsaini:refactor/simplify-atm-configuration-3540

Conversation

@hharshhsaini
Copy link
Copy Markdown
Contributor

@hharshhsaini hharshhsaini commented Mar 2, 2026

Which problem is this PR solving?

Part of #3540 - Control Monitor tab visibility via storage capabilities

Problem

Three overlapping mechanisms controlled Monitor/SPM tab visibility:

  • monitor.menuEnabled — static local config flag (default true, always on)
  • isATMActivated — fragile runtime detection via HTTP 501 probing
  • StorageCapabilities — correct server-reported mechanism, but only had archiveStorage

Changes

Replace isATMActivated and monitor.menuEnabled with a single source of truth: storageCapabilities.metricsStorage, reported by the query service at startup.

  • Types: added metricsStorage?: boolean to StorageCapabilities; removed menuEnabled/emptyState from MonitorConfig; deleted MonitorEmptyStateConfig; removed isATMActivated from MetricsReduxState
  • Defaults: added metricsStorage: false to default storageCapabilities and index.html; removed monitor.menuEnabled/emptyState from default config
  • Reducer: removed isATMActivated state and HTTP 501 detection; 501 errors now stored in serviceError like any other API error
  • Components: TopNav reads storageCapabilities.metricsStorage instead of monitor.menuEnabled; ServicesView drops isATMActivated fetch guard and EmptyState render
  • Deleted: Monitor/EmptyState/ directory (4 files)
  • Tests: removed all isATMActivated references; updated config mocks; deleted obsolete EmptyState tests

Copilot AI review requested due to automatic review settings March 2, 2026 19:15
@hharshhsaini hharshhsaini requested a review from a team as a code owner March 2, 2026 19:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 replaces three overlapping ATM/Monitor tab visibility mechanisms (monitor.menuEnabled, isATMActivated, and partial use of StorageCapabilities) with a single source of truth: storageCapabilities.metricsStorage, reported by the query service at startup.

Changes:

  • Added metricsStorage?: boolean to StorageCapabilities and removed MonitorEmptyStateConfig, menuEnabled, and emptyState from MonitorConfig and related types/defaults.
  • Removed the isATMActivated runtime 501-detection mechanism from the metrics reducer and all related component/test references.
  • Deleted the Monitor/EmptyState/ component directory (4 files) and updated TopNav to gate the Monitor tab on storageCapabilities.metricsStorage.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/types/config.ts Adds metricsStorage to StorageCapabilities; removes MonitorEmptyStateConfig and cleans up MonitorConfig
src/types/metrics.ts Removes isATMActivated field from MetricsReduxState
src/reducers/metrics.ts Removes isATMActivated from initial state and 501-detection logic
src/reducers/metrics.mock.ts Removes isATMActivated from mock initial state
src/reducers/metrics.test.js Removes isATMActivated from all expected state objects
src/constants/default-config.ts Adds metricsStorage: false default; removes monitor.emptyState and menuEnabled
index.html Adds metricsStorage: false to DEFAULT_STORAGE_CAPABILITIES
src/components/App/TopNav.tsx Switches Monitor tab guard to storageCapabilities.metricsStorage
src/components/App/TopNav.test.js Updates mock config key to match new guard
src/components/Monitor/ServicesView/index.tsx Removes isATMActivated fetch guard and EmptyState render block
src/components/Monitor/ServicesView/index.test.js Removes isATMActivated from all test props/state
src/components/Monitor/index.test.js Removes isATMActivated from initial state and deletes EmptyState test
src/components/Monitor/EmptyState/index.tsx Deleted entirely
src/components/Monitor/EmptyState/index.test.js Deleted entirely
src/components/Monitor/EmptyState/index.css Deleted entirely

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

@github-actions github-actions bot added the pr-quota-reached PR is on hold due to quota limits for new contributors label Mar 2, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 2, 2026

Hi @hharshhsaini, thanks for your contribution! To ensure quality reviews, we limit how many concurrent PRs new contributors can open:

  • Open: 7
  • Limit: 2

This PR is currently on hold. We will automatically move this into the review queue once your existing PRs are merged or closed.

Please see our Contributing Guidelines for details on our tiered quota policy.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.15%. Comparing base (e7d1e62) to head (88c5ed8).
⚠️ Report is 25 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3554      +/-   ##
==========================================
+ Coverage   88.60%   89.15%   +0.55%     
==========================================
  Files         299      304       +5     
  Lines        9484     9719     +235     
  Branches     2420     2562     +142     
==========================================
+ Hits         8403     8665     +262     
+ Misses       1078     1050      -28     
- Partials        3        4       +1     

☔ 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.

@hharshhsaini
Copy link
Copy Markdown
Contributor Author

Codecov Report

✅ All modified and coverable lines are covered by tests. ✅ Project coverage is 88.59%. Comparing base (e7d1e62) to head (6eeca16).

Additional details and impacted files

@@            Coverage Diff             @@
##             main    #3554      +/-   ##
==========================================
- Coverage   88.60%   88.59%   -0.01%     
==========================================
  Files         299      298       -1     
  Lines        9484     9468      -16     
  Branches     2420     2492      +72     
==========================================
- Hits         8403     8388      -15     
+ Misses       1078     1077       -1     
  Partials        3        3              

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

🚀 New features to boost your workflow:

Codecov reports -0.01% drop due to deletion of Monitor/EmptyState/ (dead code). All modified and coverable lines remain covered per Codecov's own report. The

ServicesView/index.test.js
suite cannot be counted because of a pre-existing redux-first-history module resolution failure on main (unrelated to this PR). Net coverage delta from actual code changes is neutral/positive.

@hharshhsaini hharshhsaini force-pushed the refactor/simplify-atm-configuration-3540 branch from 6eeca16 to 54b33fb Compare March 3, 2026 12:33
Copilot AI review requested due to automatic review settings March 3, 2026 12:33
@hharshhsaini
Copy link
Copy Markdown
Contributor Author

@yurishkuro please add the appropriate changelog:refactoring label. This is a pure refactoring PR with no user-visible behavior changes.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 15 out of 16 changed files in this pull request and generated 2 comments.


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

Copilot AI review requested due to automatic review settings March 3, 2026 17:01
@hharshhsaini hharshhsaini force-pushed the refactor/simplify-atm-configuration-3540 branch from 8a4b7c1 to 1328737 Compare March 3, 2026 17:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 15 out of 16 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

packages/jaeger-ui/src/components/Monitor/ServicesView/index.test.js:291

  • Two isATMActivated references remain in index.test.js that were not cleaned up in this refactor:
  1. Line 239: isATMActivated: true is still present in the propsNoServices metrics object inside the 'fetches metrics only when services are available' test. This is now a stale property that no longer exists on MetricsReduxState.

  2. Lines 270–291: The test 'fetches metrics when isATMActivated is null (initial state)' and its associated isATMActivated: null at line 282 still exist. The PR description explicitly states this test should have been deleted ("Delete the 'fetches metrics when isATMActivated is null' test"), and the comment on line 282 ("Initial state before any metrics fetch") still references the removed concept. These leftover references should be removed.

        isATMActivated: true,
      },
      fetchAllServiceMetrics: mockFetchAllServiceMetrics,
      fetchAggregatedServiceMetrics: mockFetchAggregatedServiceMetrics,
    };
    useServices.mockReturnValue({ data: [], isLoading: false });
    cleanup();
    renderWithRouter(<MonitorATMServicesView {...propsNoServices} />);

    // Should not fetch when no services
    expect(mockFetchAllServiceMetrics).not.toHaveBeenCalled();
    expect(mockFetchAggregatedServiceMetrics).not.toHaveBeenCalled();

    cleanup();
    const propsWithServices = {
      ...props,
      metrics: {
        ...originInitialState,
        serviceMetrics,
        serviceOpsMetrics,
        loading: false,
      },
      fetchAllServiceMetrics: mockFetchAllServiceMetrics,
      fetchAggregatedServiceMetrics: mockFetchAggregatedServiceMetrics,
    };
    useServices.mockReturnValue({ data: ['apple'], isLoading: false });
    renderWithRouter(<MonitorATMServicesView {...propsWithServices} />);
    expect(mockFetchAllServiceMetrics).toHaveBeenCalled();
    expect(mockFetchAggregatedServiceMetrics).toHaveBeenCalled();
  });

  it('fetches metrics when isATMActivated is null (initial state)', () => {
    cleanup();
    mockFetchAllServiceMetrics.mockClear();
    mockFetchAggregatedServiceMetrics.mockClear();

    const propsWithNullATM = {
      ...props,
      metrics: {
        ...originInitialState,
        serviceMetrics: null,
        serviceOpsMetrics: undefined,
        loading: false,
        isATMActivated: null, // Initial state before any metrics fetch
      },
      fetchAllServiceMetrics: mockFetchAllServiceMetrics,
      fetchAggregatedServiceMetrics: mockFetchAggregatedServiceMetrics,
    };
    useServices.mockReturnValue({ data: ['apple'], isLoading: false });
    renderWithRouter(<MonitorATMServicesView {...propsWithNullATM} />);
    expect(mockFetchAllServiceMetrics).toHaveBeenCalled();
    expect(mockFetchAggregatedServiceMetrics).toHaveBeenCalled();
  });

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

@hharshhsaini
Copy link
Copy Markdown
Contributor Author

@yurishkuro @Parship12 Could you please take a look.

This implements everything from issue #3540. two checks still need a maintainer:

  1. 'check-label' needs a 'changelog:refactoring' label
  2. 'codecov/project' shows -0.01% but 'codecov/patch' is 100% so all changed lines are covered, the drop is just from deleting the 'EmptyState' dead code

@hharshhsaini hharshhsaini force-pushed the refactor/simplify-atm-configuration-3540 branch from 1328737 to b2bacbe Compare March 3, 2026 19:05
@jkowall jkowall added the changelog:refactoring Internal, non-functional code improvements label Mar 5, 2026
@jkowall jkowall requested a review from Copilot March 6, 2026 02:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 15 out of 16 changed files in this pull request and generated no new comments.


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

jkowall
jkowall previously approved these changes Mar 6, 2026
Copy link
Copy Markdown
Contributor

@jkowall jkowall left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution

@jkowall jkowall enabled auto-merge March 6, 2026 02:08
Copy link
Copy Markdown
Member

@yurishkuro yurishkuro left a comment

Choose a reason for hiding this comment

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

PR removes existing configuration options

@hharshhsaini
Copy link
Copy Markdown
Contributor Author

PR removes existing configuration options

@yurishkuro the PR follows the implementation steps in this issue exactly -> Step 2 asks to remove menuEnabled from MonitorConfig and Step 3 asks to remove emptyState from defaults.

Could you clarify what you'd like? Options:

  1. Keep monitor.menuEnabled as a deprecated alias that maps to storageCapabilities.metricsStorage
  2. Remove as specified in the issue (current approach)

Happy to go with whichever direction you prefer.

@github-actions github-actions bot removed the pr-quota-reached PR is on hold due to quota limits for new contributors label Mar 6, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 6, 2026

PR quota unlocked!

@hharshhsaini, this PR has been moved out of the waiting room and into the active review queue:

  • Open: 6
  • Limit: 10

Thank you for your patience.

@yurishkuro
Copy link
Copy Markdown
Member

Resolves #3540

how does this resolve the issue if step 1 (server side) is not implemented?

@github-actions github-actions bot added the waiting-for-author PR is waiting for author to respond to maintainer's comments label Mar 8, 2026
@hharshhsaini
Copy link
Copy Markdown
Contributor Author

Resolves #3540

how does this resolve the issue if step 1 (server side) is not implemented?

@yurishkuro , This PR strictly covers the frontend React implementation (Steps 2-7 of the issue design) to remove the fragile isATMActivated ping checks and cleanly wire up storageCapabilities.metricsStorage across the Redux/TypeScript layers.

Because JAEGER_STORAGE_CAPABILITIES is injected at serve-time by the query-service backend, the Step 1 requirement actually requires a companion PR in the main jaegertracing/jaeger Go repository to build and inject the metricsStorage boolean. My intention was to land the UI readiness first, and then follow up with the Go backend PR so the entire pipeline connects. Does this staged approach work for you, or would you prefer I link a companion backend PR before we merge this UI state?"

@github-actions github-actions bot removed the waiting-for-author PR is waiting for author to respond to maintainer's comments label Mar 9, 2026
@yurishkuro
Copy link
Copy Markdown
Member

no it doesn't make sense. If we land this PR the SPM functionality will become permanently disabled since the backend is not going to send the right capabilities.

@github-actions github-actions bot added the waiting-for-author PR is waiting for author to respond to maintainer's comments label Mar 9, 2026
@yurishkuro
Copy link
Copy Markdown
Member

Please do not follow the roadmap from the issue verbatim. Aim for smaller changes. I think we can first switch the logic to use capability settings instead of config flag, and then clean up unused config flags later.

auto-merge was automatically disabled March 9, 2026 23:43

Head branch was pushed to by a user without write access

@hharshhsaini hharshhsaini force-pushed the refactor/simplify-atm-configuration-3540 branch from b2bacbe to 68b0363 Compare March 9, 2026 23:43
@github-actions github-actions bot removed the waiting-for-author PR is waiting for author to respond to maintainer's comments label Mar 9, 2026
@hharshhsaini
Copy link
Copy Markdown
Contributor Author

@yurishkuro, doing it all at once was far too heavy. I have completely reverted the MonitorEmptyState component deletions and the 501 isATMActivated Redux cleanup logic. I heavily stripped down this PR so it's strictly laser-focused on just swapping out the TopNav configuration read from monitor.menuEnabled over to storageCapabilities.metricsStorage as you requested! We can do the flag cleanups in a later PR...

Signed-off-by: hharshhsaini <sainiharsh3311@gmail.com>
@hharshhsaini hharshhsaini force-pushed the refactor/simplify-atm-configuration-3540 branch from 68b0363 to 88c5ed8 Compare March 9, 2026 23:48
@yurishkuro yurishkuro changed the title refactor: simplify ATM configuration (#3540) refactor: Control Monitor tab visibility via storage capabilities of the backend Mar 10, 2026
@yurishkuro yurishkuro added changelog:breaking-change and removed changelog:refactoring Internal, non-functional code improvements labels Mar 10, 2026
@yurishkuro yurishkuro enabled auto-merge March 10, 2026 00:21
@hharshhsaini
Copy link
Copy Markdown
Contributor Author

@yurishkuro @jkowall The code changes are ready and passing perfectly locally, but the Unit Tests GitHub Action workflow has randomly deadlocked on the Run npm ci caching step for the last few hours.

Since I don't have the permissions to cancel/restart the worker on this repository from my fork, could you please either smash the "Re-run" button on the stuck job, or just squash and merge it manually since the code is approved?

@yurishkuro yurishkuro added this pull request to the merge queue Mar 10, 2026
Merged via the queue into jaegertracing:main with commit 0127635 Mar 10, 2026
16 of 17 checks passed
@hharshhsaini
Copy link
Copy Markdown
Contributor Author

hharshhsaini commented Mar 10, 2026

@yurishkuro @jkowall Thank you so much for the review and merge. As discussed, the capability injection is now live.

For the follow-up cleanup PR, I plan to:

  • Strip the isATMActivated Redux state logic and its associated HTTP 501 ping checks from reducers/metrics.ts.
  • Delete the Monitor/EmptyState folder/component entirely since the UI no longer needs to query the backend during runtime to test SPM availability.
  • Clean up the unused monitor.menuEnabled configurations from the JS types.

Would you like me to tackle all three of these dead-code cleanups in a single PR, or should I break them down further? Let me know

hharshhsaini added a commit to hharshhsaini/jaeger-ui that referenced this pull request Mar 10, 2026
This continues PR jaegertracing#3554 by selectively cleaning up the old menuEnabled and isATMActivated capabilities from the TypeScript definitions and Redux states. A follow up PR will strip the components from the DOM.

Signed-off-by: hharshhsaini <sainiharsh3311@gmail.com>
@yurishkuro yurishkuro added changelog:refactoring Internal, non-functional code improvements and removed changelog:breaking-change labels Mar 10, 2026
yurishkuro added a commit that referenced this pull request Mar 10, 2026
…for SPM availability (#3587)

## Problem
- Part of #3540
- Previous PR #3554 made the whole Monitor tab conditional on storage
support, but we want to keep the Empty state as advertisement of the
capabilities unless explicitly turned off in the config.

The Service Performance Monitoring (SPM) Monitor page had several
interconnected issues:

1. **Page crash on load** — `MonitorATMEmptyState` crashed with
`TypeError: Cannot read properties of undefined (reading 'mainTitle')`
because the embedded config provided a `monitor` key that completely
overwrote `defaultConfig.monitor` (including `emptyState`), due to a
shallow merge.

2. **Unnecessary API calls** — When metrics storage is not configured,
the Monitor page fired API requests on load and only showed the empty
state after receiving a `501 Not Implemented` response. The intent was
always to use `storageCapabilities.metricsStorage` from config as the
authoritative signal, not a runtime API probe.

3. **`storageCapabilities` in `jaeger-ui.config.json` was silently
ignored** — The Vite dev-server plugin injected the JSON config into
`getJaegerUiConfig()` but never into `getJaegerStorageCapabilities()`.
Since `index.html` always defines `getJaegerStorageCapabilities`
(hardcoded to return `metricsStorage: false`), the config file value was
always overwritten.

## Changes

### `default-config.ts` — add `monitor` to `mergeFields`

`mergeFields` controls which top-level config keys are shallow-merged
(rather than wholesale replaced) when the embedded config is combined
with defaults. `monitor` was missing, so a backend-provided `monitor: {
menuEnabled: true }` silently dropped `emptyState`, causing the crash.

### `vite.config.mts` — inject `storageCapabilities` into
`getJaegerStorageCapabilities()`

The Go query-service injects `storageCapabilities` into `index.html` via
a separate search-replace on `JAEGER_STORAGE_CAPABILITIES`. The Vite
plugin was only replicating the `JAEGER_CONFIG` injection. It now also
replaces `JAEGER_STORAGE_CAPABILITIES` when `storageCapabilities` is
present in `jaeger-ui.config.json`, making local dev fully equivalent to
production.

### `get-config.ts` — add comments clarifying the two-source design

`storageCapabilities` is intentionally loaded from a separate source
(`getJaegerStorageCapabilities`) and always overrides anything in the
main UI config, keeping the backend authoritative. This was not
documented; comments now explain the three-priority merge model.

### `Monitor/ServicesView/index.tsx` — gate on config, not runtime API
response

- Reads `storageCapabilities.metricsStorage` from config at render time.
- Returns `<MonitorATMEmptyState />` immediately when it is `false`,
with no API calls made.
- Removed the `isATMActivated !== false` guard from `fetchMetrics` (it
was checking a Redux flag that was only set after a 501 response).

### `reducers/metrics.ts` / `types/metrics.ts` — remove `isATMActivated`

`isATMActivated` was a runtime approximation of
`storageCapabilities.metricsStorage`: it started as `null`, then flipped
to `false` upon a `501` response. Now that the config is the
authoritative source (known at page load), this redundant state and the
501-detection logic have been removed entirely.

### Tests

- `get-config.test.js` — new `storageCapabilities` describe block
covering: backend injection, fallback to defaults, and precedence of
`getJaegerStorageCapabilities` over the UI config.
- `reducers/metrics.test.js` — removed `isATMActivated` assertions and
the dedicated "501 Not Implemented" test case.
- `Monitor/ServicesView/index.test.js` — updated `getConfigValue` mock
to return `true` for `storageCapabilities.metricsStorage`; empty-state
test now toggles the config mock instead of setting `isATMActivated:
false`.
- `Monitor/index.test.js` — added `getConfigValue` mock; updated
empty-state test accordingly.

## How the config loading works (for reference)

```
jaeger-ui.config.json
        │
        ▼
[dev] Vite plugin injects into index.html:
  • JAEGER_CONFIG            → consumed by getJaegerUiConfig()
  • JAEGER_STORAGE_CAPABILITIES → consumed by getJaegerStorageCapabilities()   ← was missing

[prod] Go query-service does the same search-replace

        │
        ▼
get-config.ts  assembles the final Config from three sources (lowest → highest priority):
  1. defaultConfig                 (compile-time defaults)
  2. getJaegerUiConfig()           (full UI config)
  3. getJaegerStorageCapabilities() (always wins for storageCapabilities)
```

## AI Usage in this PR (choose one)
See [AI Usage
Policy](https://github.com/jaegertracing/jaeger/blob/main/CONTRIBUTING_GUIDELINES.md#ai-usage-policy).
- [ ] **None**: No AI tools were used in creating this PR
- [ ] **Light**: AI provided minor assistance (formatting, simple
suggestions)
- [ ] **Moderate**: AI helped with code generation or debugging specific
parts
- [x] **Heavy**: AI generated most or all of the code changes

---------

Signed-off-by: Yuri Shkuro <github@ysh.us>
Signed-off-by: Yuri Shkuro <yurishkuro@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.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.

4 participants