mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 06:08:59 +08:00
Merge pull request #118 from SigNoz/fix-api-call-twice
fix: call api with update value
This commit is contained in:
commit
1cbbdd8265
@ -17,6 +17,7 @@ import {
|
||||
SettingsPage,
|
||||
IntstrumentationPage,
|
||||
} from "Src/pages";
|
||||
import { RouteProvider } from "./RouteProvider";
|
||||
|
||||
const App = () => {
|
||||
const { status } = useThemeSwitcher();
|
||||
@ -30,36 +31,38 @@ const App = () => {
|
||||
<Suspense fallback={<Spin size="large" />}>
|
||||
<Route path={"/"}>
|
||||
<Switch>
|
||||
<BaseLayout>
|
||||
<Route path={ROUTES.SIGN_UP} exact component={Signup} />
|
||||
<Route path={ROUTES.APPLICATION} exact component={ServicesTable} />
|
||||
<Route path={ROUTES.SERVICE_METRICS} exact component={ServiceMetrics} />
|
||||
<Route path={ROUTES.SERVICE_MAP} exact component={ServiceMap} />
|
||||
<Route path={ROUTES.TRACES} exact component={TraceDetail} />
|
||||
<Route path={ROUTES.TRACE_GRAPH} exact component={TraceGraph} />
|
||||
<Route path={ROUTES.SETTINGS} exact component={SettingsPage} />
|
||||
<Route
|
||||
path={ROUTES.INSTRUMENTATION}
|
||||
exact
|
||||
component={IntstrumentationPage}
|
||||
/>
|
||||
<Route
|
||||
path={ROUTES.USAGE_EXPLORER}
|
||||
exactexact
|
||||
component={UsageExplorer}
|
||||
/>
|
||||
<Route
|
||||
path="/"
|
||||
exact
|
||||
render={() => {
|
||||
return localStorage.getItem(IS_LOGGED_IN) === "yes" ? (
|
||||
<Redirect to={ROUTES.APPLICATION} />
|
||||
) : (
|
||||
<Redirect to={ROUTES.SIGN_UP} />
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</BaseLayout>
|
||||
<RouteProvider>
|
||||
<BaseLayout>
|
||||
<Route path={ROUTES.SIGN_UP} exact component={Signup} />
|
||||
<Route path={ROUTES.APPLICATION} exact component={ServicesTable} />
|
||||
<Route path={ROUTES.SERVICE_METRICS} exact component={ServiceMetrics} />
|
||||
<Route path={ROUTES.SERVICE_MAP} exact component={ServiceMap} />
|
||||
<Route path={ROUTES.TRACES} exact component={TraceDetail} />
|
||||
<Route path={ROUTES.TRACE_GRAPH} exact component={TraceGraph} />
|
||||
<Route path={ROUTES.SETTINGS} exact component={SettingsPage} />
|
||||
<Route
|
||||
path={ROUTES.INSTRUMENTATION}
|
||||
exact
|
||||
component={IntstrumentationPage}
|
||||
/>
|
||||
<Route
|
||||
path={ROUTES.USAGE_EXPLORER}
|
||||
exactexact
|
||||
component={UsageExplorer}
|
||||
/>
|
||||
<Route
|
||||
path="/"
|
||||
exact
|
||||
render={() => {
|
||||
return localStorage.getItem(IS_LOGGED_IN) === "yes" ? (
|
||||
<Redirect to={ROUTES.APPLICATION} />
|
||||
) : (
|
||||
<Redirect to={ROUTES.SIGN_UP} />
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</BaseLayout>
|
||||
</RouteProvider>
|
||||
</Switch>
|
||||
</Route>
|
||||
</Suspense>
|
||||
|
@ -1,8 +1,12 @@
|
||||
import React, { ReactNode } from "react";
|
||||
import React, { ReactNode, useEffect } from "react";
|
||||
|
||||
import { Layout } from "antd";
|
||||
import SideNav from "./Nav/SideNav";
|
||||
import TopNav from "./Nav/TopNav";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
import { useRoute } from "./RouteProvider";
|
||||
|
||||
const { Content, Footer } = Layout;
|
||||
|
||||
interface BaseLayoutProps {
|
||||
@ -10,6 +14,13 @@ interface BaseLayoutProps {
|
||||
}
|
||||
|
||||
const BaseLayout: React.FC<BaseLayoutProps> = ({ children }) => {
|
||||
const location = useLocation();
|
||||
const { dispatch } = useRoute();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({ type: "UPDATE_IS_LOADED", payload: location.pathname });
|
||||
}, [location]);
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: "100vh" }}>
|
||||
<SideNav />
|
||||
|
83
frontend/src/modules/RouteProvider.tsx
Normal file
83
frontend/src/modules/RouteProvider.tsx
Normal file
@ -0,0 +1,83 @@
|
||||
import React, { useContext, createContext, ReactNode, Dispatch } from "react";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
|
||||
type State = {
|
||||
[key: string]: {
|
||||
route: string;
|
||||
isLoaded: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
enum ActionTypes {
|
||||
UPDATE_IS_LOADED = "UPDATE_IS_LOADED",
|
||||
}
|
||||
|
||||
type Action = {
|
||||
type: ActionTypes;
|
||||
payload: string;
|
||||
};
|
||||
|
||||
interface ContextType {
|
||||
state: State;
|
||||
dispatch: Dispatch<Action>;
|
||||
}
|
||||
|
||||
const RouteContext = createContext<ContextType | null>(null);
|
||||
|
||||
interface RouteProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
interface RouteObj {
|
||||
[key: string]: {
|
||||
route: string;
|
||||
isLoaded: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
const updateLocation = (state: State, action: Action): State => {
|
||||
if (action.type === ActionTypes.UPDATE_IS_LOADED) {
|
||||
/*
|
||||
Update the isLoaded property in routes obj
|
||||
if the route matches the current pathname
|
||||
|
||||
Why: Checkout this issue https://github.com/SigNoz/signoz/issues/110
|
||||
To avoid calling the api's twice for Date picker,
|
||||
We will only call once the route is changed
|
||||
*/
|
||||
Object.keys(ROUTES).map((items) => {
|
||||
state[items].isLoaded = state[items].route === action.payload;
|
||||
});
|
||||
return {
|
||||
...state,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
};
|
||||
};
|
||||
|
||||
const getInitialState = () => {
|
||||
const routes: RouteObj = {};
|
||||
Object.keys(ROUTES).map((items) => {
|
||||
routes[items] = {
|
||||
route: `${ROUTES[items]}`,
|
||||
isLoaded: false,
|
||||
};
|
||||
});
|
||||
return routes;
|
||||
};
|
||||
|
||||
const RouteProvider: React.FC<RouteProviderProps> = ({ children }) => {
|
||||
const [state, dispatch] = React.useReducer(updateLocation, getInitialState());
|
||||
const value = { state, dispatch };
|
||||
return <RouteContext.Provider value={value}>{children}</RouteContext.Provider>;
|
||||
};
|
||||
|
||||
const useRoute = (): ContextType => {
|
||||
const context = useContext(RouteContext);
|
||||
if (context === undefined) {
|
||||
throw new Error("useRoute must be used within a RouteProvider");
|
||||
}
|
||||
return context as ContextType;
|
||||
};
|
||||
export { RouteProvider, useRoute };
|
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import React, { useContext, useEffect, useRef } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import {
|
||||
@ -14,6 +14,7 @@ import { StoreState } from "../../store/reducers";
|
||||
import { getZoomPx, getGraphData, getTooltip, transformLabel } from "./utils";
|
||||
import SelectService from "./SelectService";
|
||||
import { ForceGraph2D } from "react-force-graph";
|
||||
import { useRoute } from "../RouteProvider";
|
||||
|
||||
const Container = styled.div`
|
||||
.force-graph-container .graph-tooltip {
|
||||
@ -53,6 +54,8 @@ export interface graphDataType {
|
||||
|
||||
const ServiceMap = (props: ServiceMapProps) => {
|
||||
const fgRef = useRef();
|
||||
const { state } = useRoute();
|
||||
|
||||
const {
|
||||
getDetailedServiceMapItems,
|
||||
getServiceMapItems,
|
||||
@ -61,8 +64,14 @@ const ServiceMap = (props: ServiceMapProps) => {
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
getServiceMapItems(globalTime);
|
||||
getDetailedServiceMapItems(globalTime);
|
||||
/*
|
||||
Call the apis only when the route is loaded.
|
||||
Check this issue: https://github.com/SigNoz/signoz/issues/110
|
||||
*/
|
||||
if (state.SERVICE_MAP.isLoaded) {
|
||||
getServiceMapItems(globalTime);
|
||||
getDetailedServiceMapItems(globalTime);
|
||||
}
|
||||
}, [globalTime]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
GlobalTime,
|
||||
TraceFilters,
|
||||
} from "../../store/actions";
|
||||
import { useRoute } from "../RouteProvider";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@ -81,6 +82,8 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
const [selectedEntity, setSelectedEntity] = useState("calls");
|
||||
const [selectedAggOption, setSelectedAggOption] = useState("count");
|
||||
const [selectedStep, setSelectedStep] = useState("60");
|
||||
const { state } = useRoute();
|
||||
|
||||
// Step should be multiples of 60, 60 -> 1 min
|
||||
|
||||
useEffect(() => {
|
||||
@ -109,7 +112,14 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
minTime: props.globalTime.minTime - 15 * 60 * 1000000000,
|
||||
maxTime: props.globalTime.maxTime + 15 * 60 * 1000000000,
|
||||
};
|
||||
props.getFilteredTraceMetrics(request_string, plusMinus15);
|
||||
|
||||
/*
|
||||
Call the apis only when the route is loaded.
|
||||
Check this issue: https://github.com/SigNoz/signoz/issues/110
|
||||
*/
|
||||
if (state.TRACES.isLoaded) {
|
||||
props.getFilteredTraceMetrics(request_string, plusMinus15);
|
||||
}
|
||||
}, [selectedEntity, selectedAggOption, props.traceFilters, props.globalTime]);
|
||||
|
||||
//Custom metrics API called if time, tracefilters, selected entity or agg option changes
|
||||
|
@ -18,6 +18,7 @@ import FormItem from "antd/lib/form/FormItem";
|
||||
import api, { apiV1 } from "../../api";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { METRICS_PAGE_QUERY_PARAM } from "Src/constants/query";
|
||||
import { useRoute } from "../RouteProvider";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@ -45,6 +46,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
const [tagKeyOptions, setTagKeyOptions] = useState<TagKeyOptionItem[]>([]);
|
||||
const location = useLocation();
|
||||
const urlParams = new URLSearchParams(location.search.split("?")[1]);
|
||||
const { state } = useRoute();
|
||||
|
||||
useEffect(() => {
|
||||
handleApplyFilterForm({
|
||||
@ -122,7 +124,13 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
"&tags=" +
|
||||
encodeURIComponent(JSON.stringify(props.traceFilters.tags));
|
||||
|
||||
props.fetchTraces(props.globalTime, request_string);
|
||||
/*
|
||||
Call the apis only when the route is loaded.
|
||||
Check this issue: https://github.com/SigNoz/signoz/issues/110
|
||||
*/
|
||||
if (state.TRACES.isLoaded) {
|
||||
props.fetchTraces(props.globalTime, request_string);
|
||||
}
|
||||
}, [props.traceFilters, props.globalTime]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
import { StoreState } from "../../store/reducers";
|
||||
import moment from "moment";
|
||||
import { isOnboardingSkipped } from "../../utils/app";
|
||||
import { useRoute } from "../RouteProvider";
|
||||
const { Option } = Select;
|
||||
|
||||
interface UsageExplorerProps {
|
||||
@ -56,6 +57,8 @@ const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
const [selectedInterval, setSelectedInterval] = useState(interval[2]);
|
||||
const [selectedService, setSelectedService] = useState<string>("");
|
||||
|
||||
const { state } = useRoute();
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedTime && selectedInterval) {
|
||||
const maxTime = new Date().getTime() * 1000000;
|
||||
@ -71,7 +74,13 @@ const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
}, [selectedTime, selectedInterval, selectedService]);
|
||||
|
||||
useEffect(() => {
|
||||
props.getServicesList(props.globalTime);
|
||||
/*
|
||||
Call the apis only when the route is loaded.
|
||||
Check this issue: https://github.com/SigNoz/signoz/issues/110
|
||||
*/
|
||||
if (state.USAGE_EXPLORER.isLoaded) {
|
||||
props.getServicesList(props.globalTime);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const data = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user