mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
Inject readiness state through context (#11617)
Signed-off-by: Levi Harrison <git@leviharrison.dev> Signed-off-by: Levi Harrison <git@leviharrison.dev>
This commit is contained in:
parent
5a485e15ea
commit
3b4cbf8da4
|
@ -16,10 +16,14 @@
|
||||||
- PROMETHEUS_AGENT_MODE is replaced by a boolean indicating if Prometheus is running in agent mode.
|
- PROMETHEUS_AGENT_MODE is replaced by a boolean indicating if Prometheus is running in agent mode.
|
||||||
It true, it will disable querying capacities in the UI and generally adapt the UI to the agent mode.
|
It true, it will disable querying capacities in the UI and generally adapt the UI to the agent mode.
|
||||||
It has to be represented as a string, because booleans can be mangled to !1 in production builds.
|
It has to be represented as a string, because booleans can be mangled to !1 in production builds.
|
||||||
|
- PROMETHEUS_READY is replaced by a boolean indicating whether Prometheus was ready at the time the
|
||||||
|
web app was served. It has to be represented as a string, because booleans can be mangled to !1 in
|
||||||
|
production builds.
|
||||||
-->
|
-->
|
||||||
<script>
|
<script>
|
||||||
const GLOBAL_CONSOLES_LINK='CONSOLES_LINK_PLACEHOLDER';
|
const GLOBAL_CONSOLES_LINK='CONSOLES_LINK_PLACEHOLDER';
|
||||||
const GLOBAL_AGENT_MODE='AGENT_MODE_PLACEHOLDER';
|
const GLOBAL_AGENT_MODE='AGENT_MODE_PLACEHOLDER';
|
||||||
|
const GLOBAL_READY='READY_PLACEHOLDER';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
|
@ -18,7 +18,7 @@ import {
|
||||||
} from './pages';
|
} from './pages';
|
||||||
|
|
||||||
describe('App', () => {
|
describe('App', () => {
|
||||||
const app = shallow(<App consolesLink={null} agentMode={false} />);
|
const app = shallow(<App consolesLink={null} agentMode={false} ready={false} />);
|
||||||
|
|
||||||
it('navigates', () => {
|
it('navigates', () => {
|
||||||
expect(app.find(Navigation)).toHaveLength(1);
|
expect(app.find(Navigation)).toHaveLength(1);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Navigation from './Navbar';
|
||||||
import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom';
|
import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom';
|
||||||
import { PathPrefixContext } from './contexts/PathPrefixContext';
|
import { PathPrefixContext } from './contexts/PathPrefixContext';
|
||||||
import { ThemeContext, themeName, themeSetting } from './contexts/ThemeContext';
|
import { ThemeContext, themeName, themeSetting } from './contexts/ThemeContext';
|
||||||
|
import { ReadyContext } from './contexts/ReadyContext';
|
||||||
import { useLocalStorage } from './hooks/useLocalStorage';
|
import { useLocalStorage } from './hooks/useLocalStorage';
|
||||||
import useMedia from './hooks/useMedia';
|
import useMedia from './hooks/useMedia';
|
||||||
import {
|
import {
|
||||||
|
@ -24,9 +25,10 @@ import { Theme, themeLocalStorageKey } from './Theme';
|
||||||
interface AppProps {
|
interface AppProps {
|
||||||
consolesLink: string | null;
|
consolesLink: string | null;
|
||||||
agentMode: boolean;
|
agentMode: boolean;
|
||||||
|
ready: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const App: FC<AppProps> = ({ consolesLink, agentMode }) => {
|
const App: FC<AppProps> = ({ consolesLink, agentMode, ready }) => {
|
||||||
// This dynamically/generically determines the pathPrefix by stripping the first known
|
// This dynamically/generically determines the pathPrefix by stripping the first known
|
||||||
// endpoint suffix from the window location path. It works out of the box for both direct
|
// endpoint suffix from the window location path. It works out of the box for both direct
|
||||||
// hosting and reverse proxy deployments with no additional configurations required.
|
// hosting and reverse proxy deployments with no additional configurations required.
|
||||||
|
@ -72,48 +74,50 @@ const App: FC<AppProps> = ({ consolesLink, agentMode }) => {
|
||||||
>
|
>
|
||||||
<Theme />
|
<Theme />
|
||||||
<PathPrefixContext.Provider value={basePath}>
|
<PathPrefixContext.Provider value={basePath}>
|
||||||
<Router basename={basePath}>
|
<ReadyContext.Provider value={ready}>
|
||||||
<Navigation consolesLink={consolesLink} agentMode={agentMode} />
|
<Router basename={basePath}>
|
||||||
<Container fluid style={{ paddingTop: 70 }}>
|
<Navigation consolesLink={consolesLink} agentMode={agentMode} />
|
||||||
<Switch>
|
<Container fluid style={{ paddingTop: 70 }}>
|
||||||
<Redirect exact from="/" to={agentMode ? '/agent' : '/graph'} />
|
<Switch>
|
||||||
{/*
|
<Redirect exact from="/" to={agentMode ? '/agent' : '/graph'} />
|
||||||
|
{/*
|
||||||
NOTE: Any route added here needs to also be added to the list of
|
NOTE: Any route added here needs to also be added to the list of
|
||||||
React-handled router paths ("reactRouterPaths") in /web/web.go.
|
React-handled router paths ("reactRouterPaths") in /web/web.go.
|
||||||
*/}
|
*/}
|
||||||
<Route path="/agent">
|
<Route path="/agent">
|
||||||
<AgentPage />
|
<AgentPage />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/graph">
|
<Route path="/graph">
|
||||||
<PanelListPage />
|
<PanelListPage />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/alerts">
|
<Route path="/alerts">
|
||||||
<AlertsPage />
|
<AlertsPage />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/config">
|
<Route path="/config">
|
||||||
<ConfigPage />
|
<ConfigPage />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/flags">
|
<Route path="/flags">
|
||||||
<FlagsPage />
|
<FlagsPage />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/rules">
|
<Route path="/rules">
|
||||||
<RulesPage />
|
<RulesPage />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/service-discovery">
|
<Route path="/service-discovery">
|
||||||
<ServiceDiscoveryPage />
|
<ServiceDiscoveryPage />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/status">
|
<Route path="/status">
|
||||||
<StatusPage agentMode={agentMode} />
|
<StatusPage agentMode={agentMode} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/tsdb-status">
|
<Route path="/tsdb-status">
|
||||||
<TSDBStatusPage />
|
<TSDBStatusPage />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/targets">
|
<Route path="/targets">
|
||||||
<TargetsPage />
|
<TargetsPage />
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Container>
|
</Container>
|
||||||
</Router>
|
</Router>
|
||||||
|
</ReadyContext.Provider>
|
||||||
</PathPrefixContext.Provider>
|
</PathPrefixContext.Provider>
|
||||||
</ThemeContext.Provider>
|
</ThemeContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { Progress, Alert } from 'reactstrap';
|
||||||
import { useFetchReadyInterval } from '../hooks/useFetch';
|
import { useFetchReadyInterval } from '../hooks/useFetch';
|
||||||
import { WALReplayData } from '../types/types';
|
import { WALReplayData } from '../types/types';
|
||||||
import { usePathPrefix } from '../contexts/PathPrefixContext';
|
import { usePathPrefix } from '../contexts/PathPrefixContext';
|
||||||
|
import { useReady } from '../contexts/ReadyContext';
|
||||||
|
|
||||||
interface StartingContentProps {
|
interface StartingContentProps {
|
||||||
isUnexpected: boolean;
|
isUnexpected: boolean;
|
||||||
|
@ -48,8 +49,9 @@ export const withStartingIndicator =
|
||||||
({ ...rest }) => {
|
({ ...rest }) => {
|
||||||
const pathPrefix = usePathPrefix();
|
const pathPrefix = usePathPrefix();
|
||||||
const { ready, walReplayStatus, isUnexpected } = useFetchReadyInterval(pathPrefix);
|
const { ready, walReplayStatus, isUnexpected } = useFetchReadyInterval(pathPrefix);
|
||||||
|
const staticReady = useReady();
|
||||||
|
|
||||||
if (ready || isUnexpected) {
|
if (staticReady || ready || isUnexpected) {
|
||||||
return <Page {...(rest as T)} />;
|
return <Page {...(rest as T)} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
web/ui/react-app/src/contexts/ReadyContext.tsx
Normal file
9
web/ui/react-app/src/contexts/ReadyContext.tsx
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const ReadyContext = React.createContext(false);
|
||||||
|
|
||||||
|
function useReady(): boolean {
|
||||||
|
return React.useContext(ReadyContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useReady, ReadyContext };
|
|
@ -11,9 +11,11 @@ import { isPresent } from './utils';
|
||||||
// Declared/defined in public/index.html, value replaced by Prometheus when serving bundle.
|
// Declared/defined in public/index.html, value replaced by Prometheus when serving bundle.
|
||||||
declare const GLOBAL_CONSOLES_LINK: string;
|
declare const GLOBAL_CONSOLES_LINK: string;
|
||||||
declare const GLOBAL_AGENT_MODE: string;
|
declare const GLOBAL_AGENT_MODE: string;
|
||||||
|
declare const GLOBAL_READY: string;
|
||||||
|
|
||||||
let consolesLink: string | null = GLOBAL_CONSOLES_LINK;
|
let consolesLink: string | null = GLOBAL_CONSOLES_LINK;
|
||||||
const agentMode: string | null = GLOBAL_AGENT_MODE;
|
const agentMode: string | null = GLOBAL_AGENT_MODE;
|
||||||
|
const ready: string | null = GLOBAL_READY;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
GLOBAL_CONSOLES_LINK === 'CONSOLES_LINK_PLACEHOLDER' ||
|
GLOBAL_CONSOLES_LINK === 'CONSOLES_LINK_PLACEHOLDER' ||
|
||||||
|
@ -23,4 +25,7 @@ if (
|
||||||
consolesLink = null;
|
consolesLink = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.render(<App consolesLink={consolesLink} agentMode={agentMode === 'true'} />, document.getElementById('root'));
|
ReactDOM.render(
|
||||||
|
<App consolesLink={consolesLink} agentMode={agentMode === 'true'} ready={ready === 'true'} />,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
|
|
@ -401,6 +401,7 @@ func New(logger log.Logger, o *Options) *Handler {
|
||||||
replacedIdx := bytes.ReplaceAll(idx, []byte("CONSOLES_LINK_PLACEHOLDER"), []byte(h.consolesPath()))
|
replacedIdx := bytes.ReplaceAll(idx, []byte("CONSOLES_LINK_PLACEHOLDER"), []byte(h.consolesPath()))
|
||||||
replacedIdx = bytes.ReplaceAll(replacedIdx, []byte("TITLE_PLACEHOLDER"), []byte(h.options.PageTitle))
|
replacedIdx = bytes.ReplaceAll(replacedIdx, []byte("TITLE_PLACEHOLDER"), []byte(h.options.PageTitle))
|
||||||
replacedIdx = bytes.ReplaceAll(replacedIdx, []byte("AGENT_MODE_PLACEHOLDER"), []byte(strconv.FormatBool(h.options.IsAgent)))
|
replacedIdx = bytes.ReplaceAll(replacedIdx, []byte("AGENT_MODE_PLACEHOLDER"), []byte(strconv.FormatBool(h.options.IsAgent)))
|
||||||
|
replacedIdx = bytes.ReplaceAll(replacedIdx, []byte("READY_PLACEHOLDER"), []byte(strconv.FormatBool(h.isReady())))
|
||||||
w.Write(replacedIdx)
|
w.Write(replacedIdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue