mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-07-26 16:09:50 +03:00
feat(rtk-query): add timings to apiStats sections
This commit is contained in:
parent
136fd02ff8
commit
c3b6887e82
|
@ -122,7 +122,8 @@ class RtkQueryInspector<S, A extends Action<unknown>> extends PureComponent<
|
|||
const currentQueryInfo =
|
||||
this.selectors.selectCurrentQueryInfo(selectorsSource);
|
||||
|
||||
const currentRtkApi = getApiStateOf(currentQueryInfo, apiStates);
|
||||
const currentRtkApi =
|
||||
this.selectors.selectApiOfCurrentQuery(selectorsSource);
|
||||
const currentQuerySubscriptions = getQuerySubscriptionsOf(
|
||||
currentQueryInfo,
|
||||
apiStates
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
import { Action, createSelector, Selector } from '@reduxjs/toolkit';
|
||||
import { RtkQueryInspectorProps } from './containers/RtkQueryInspector';
|
||||
import { ApiStats, QueryInfo, RtkQueryTag, SelectorsSource } from './types';
|
||||
import {
|
||||
ApiStats,
|
||||
QueryInfo,
|
||||
RtkQueryApiState,
|
||||
RtkQueryTag,
|
||||
SelectorsSource,
|
||||
RtkQueryProvided,
|
||||
} from './types';
|
||||
import { Comparator, queryComparators } from './utils/comparators';
|
||||
import { FilterList, queryListFilters } from './utils/filters';
|
||||
import { escapeRegExpSpecialCharacter } from './utils/regexp';
|
||||
|
@ -52,6 +59,10 @@ export interface InspectorSelectors<S> {
|
|||
readonly selectSearchQueryRegex: InspectorSelector<S, RegExp | null>;
|
||||
readonly selectCurrentQueryTags: InspectorSelector<S, RtkQueryTag[]>;
|
||||
readonly selectApiStatsOfCurrentQuery: InspectorSelector<S, ApiStats | null>;
|
||||
readonly selectApiOfCurrentQuery: InspectorSelector<
|
||||
S,
|
||||
RtkQueryApiState | null
|
||||
>;
|
||||
}
|
||||
|
||||
export function createInspectorSelectors<S>(): InspectorSelectors<S> {
|
||||
|
@ -131,17 +142,33 @@ export function createInspectorSelectors<S>(): InspectorSelectors<S> {
|
|||
}
|
||||
);
|
||||
|
||||
const selectApiOfCurrentQuery: InspectorSelector<S, null | RtkQueryApiState> =
|
||||
(selectorsSource: SelectorsSource<S>) => {
|
||||
const apiStates = selectApiStates(selectorsSource);
|
||||
const currentQueryInfo = selectCurrentQueryInfo(selectorsSource);
|
||||
|
||||
if (!apiStates || !currentQueryInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return apiStates[currentQueryInfo.reducerPath] ?? null;
|
||||
};
|
||||
|
||||
const selectProvidedOfCurrentQuery: InspectorSelector<
|
||||
S,
|
||||
null | RtkQueryProvided
|
||||
> = (selectorsSource: SelectorsSource<S>) => {
|
||||
return selectApiOfCurrentQuery(selectorsSource)?.provided ?? null;
|
||||
};
|
||||
|
||||
const selectCurrentQueryTags = createSelector(
|
||||
selectApiStates,
|
||||
selectCurrentQueryInfo,
|
||||
(apiState, currentQueryInfo) => getQueryTagsOf(currentQueryInfo, apiState)
|
||||
[selectCurrentQueryInfo, selectProvidedOfCurrentQuery],
|
||||
getQueryTagsOf
|
||||
);
|
||||
|
||||
const selectApiStatsOfCurrentQuery = createSelector(
|
||||
selectApiStates,
|
||||
selectCurrentQueryInfo,
|
||||
(apiState, currentQueryInfo) =>
|
||||
generateApiStatsOfCurrentQuery(currentQueryInfo, apiState)
|
||||
selectApiOfCurrentQuery,
|
||||
generateApiStatsOfCurrentQuery
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -153,5 +180,6 @@ export function createInspectorSelectors<S>(): InspectorSelectors<S> {
|
|||
selectCurrentQueryInfo,
|
||||
selectCurrentQueryTags,
|
||||
selectApiStatsOfCurrentQuery,
|
||||
selectApiOfCurrentQuery,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -109,13 +109,24 @@ export type QueryTally = {
|
|||
} &
|
||||
Tally;
|
||||
|
||||
export interface QueryTimings {
|
||||
readonly oldestFetch: { key: string; at: string } | null;
|
||||
readonly latestFetch: { key: string; at: string } | null;
|
||||
}
|
||||
|
||||
export interface ApiTimings {
|
||||
readonly queries: QueryTimings;
|
||||
readonly mutations: QueryTimings;
|
||||
}
|
||||
|
||||
export interface ApiStats {
|
||||
readonly tally: {
|
||||
readonly timings: ApiTimings;
|
||||
readonly tally: Readonly<{
|
||||
subscriptions: Tally;
|
||||
queries: QueryTally;
|
||||
tagTypes: Tally;
|
||||
mutations: QueryTally;
|
||||
};
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface QueryPreviewTabProps extends StyleUtils {
|
||||
|
|
|
@ -11,6 +11,9 @@ import {
|
|||
MutationInfo,
|
||||
ApiStats,
|
||||
QueryTally,
|
||||
RtkQueryProvided,
|
||||
ApiTimings,
|
||||
QueryTimings,
|
||||
} from '../types';
|
||||
import { missingTagId } from '../monitor-config';
|
||||
import { Comparator } from './comparators';
|
||||
|
@ -192,18 +195,75 @@ function tallySubscriptions(
|
|||
return output;
|
||||
}
|
||||
|
||||
function computeQueryApiTimings(
|
||||
queriesOrMutations:
|
||||
| RtkQueryApiState['queries']
|
||||
| RtkQueryApiState['mutations']
|
||||
): QueryTimings {
|
||||
let latestFetch = null;
|
||||
let latestFetchedQueryKey: string | null = null;
|
||||
let latestFetchedQueryTiming = -1;
|
||||
let oldestFetch = null;
|
||||
let oldestFetchedQueryKey: string | null = null;
|
||||
let oldestFetchedQueryTiming = Number.MAX_SAFE_INTEGER;
|
||||
|
||||
const queryKeys = Object.keys(queriesOrMutations);
|
||||
|
||||
for (let i = 0, len = queryKeys.length; i < len; i++) {
|
||||
const queryKey = queryKeys[i];
|
||||
const query = queriesOrMutations[queryKey];
|
||||
|
||||
const fulfilledTimeStamp = query?.fulfilledTimeStamp;
|
||||
|
||||
if (typeof fulfilledTimeStamp === 'number') {
|
||||
if (fulfilledTimeStamp > latestFetchedQueryTiming) {
|
||||
latestFetchedQueryKey = queryKey;
|
||||
latestFetchedQueryTiming = fulfilledTimeStamp;
|
||||
}
|
||||
|
||||
if (fulfilledTimeStamp < oldestFetchedQueryTiming) {
|
||||
oldestFetchedQueryKey = queryKey;
|
||||
oldestFetchedQueryTiming = fulfilledTimeStamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (latestFetchedQueryKey) {
|
||||
latestFetch = {
|
||||
key: latestFetchedQueryKey,
|
||||
at: new Date(latestFetchedQueryTiming).toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
if (oldestFetchedQueryKey) {
|
||||
oldestFetch = {
|
||||
key: oldestFetchedQueryKey,
|
||||
at: new Date(oldestFetchedQueryTiming).toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
latestFetch,
|
||||
oldestFetch,
|
||||
};
|
||||
}
|
||||
|
||||
function computeApiTimings(api: RtkQueryApiState): ApiTimings {
|
||||
return {
|
||||
queries: computeQueryApiTimings(api.queries),
|
||||
mutations: computeQueryApiTimings(api.mutations),
|
||||
};
|
||||
}
|
||||
|
||||
export function generateApiStatsOfCurrentQuery(
|
||||
queryInfo: QueryInfo | null,
|
||||
apiStates: ReturnType<typeof getApiStatesOf>
|
||||
api: RtkQueryApiState | null
|
||||
): ApiStats | null {
|
||||
if (!apiStates || !queryInfo) {
|
||||
if (!api) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { reducerPath } = queryInfo;
|
||||
const api = apiStates[reducerPath];
|
||||
|
||||
return {
|
||||
timings: computeApiTimings(api),
|
||||
tally: {
|
||||
subscriptions: tallySubscriptions(api.subscriptions),
|
||||
queries: computeQueryTallyOf(api.queries),
|
||||
|
@ -268,14 +328,12 @@ export function getProvidedOf(
|
|||
|
||||
export function getQueryTagsOf(
|
||||
queryInfo: QueryInfo | null,
|
||||
apiStates: ReturnType<typeof getApiStatesOf>
|
||||
provided: RtkQueryProvided | null
|
||||
): RtkQueryTag[] {
|
||||
if (!apiStates || !queryInfo) {
|
||||
if (!queryInfo || !provided) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
const provided = apiStates[queryInfo.reducerPath].provided;
|
||||
|
||||
const tagTypes = Object.keys(provided);
|
||||
|
||||
if (tagTypes.length < 1) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user