feat(environment): avoid logging node check queries (#3830)

This commit is contained in:
Matthew Russell 2023-05-19 06:32:27 -07:00 committed by GitHub
parent 9e2474d39a
commit 42c316c8e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 163 additions and 144 deletions

View File

@ -115,7 +115,19 @@ export function createClient({
) )
: httpLink; : httpLink;
const errorLink = onError(({ graphQLErrors, networkError }) => { const errorLink = onError(({ graphQLErrors, networkError, operation }) => {
// if any of these queries error don't capture any errors, its
// likely the user is connecting to a dodgy node, NodeGuard gets
// called on startup, NodeCheck and NodeCheckTimeUpdate are called
// by the NodeSwitcher component and the useNodeHealth hook
if (
['NodeGuard', 'NodeCheck', 'NodeCheckTimeUpdate'].includes(
operation.operationName
)
) {
return;
}
if (graphQLErrors) { if (graphQLErrors) {
graphQLErrors.forEach((e) => { graphQLErrors.forEach((e) => {
if (e.extensions && e.extensions['type'] !== NOT_FOUND) { if (e.extensions && e.extensions['type'] !== NOT_FOUND) {

View File

@ -3,11 +3,13 @@ import { MockedProvider } from '@apollo/react-testing';
import { act, render, screen, waitFor } from '@testing-library/react'; import { act, render, screen, waitFor } from '@testing-library/react';
import { RadioGroup } from '@vegaprotocol/ui-toolkit'; import { RadioGroup } from '@vegaprotocol/ui-toolkit';
import type { import type {
BlockTimeSubscription, NodeCheckTimeUpdateSubscription,
StatisticsQuery, NodeCheckQuery,
} from '../../utils/__generated__/Node'; } from '../../utils/__generated__/NodeCheck';
import { BlockTimeDocument } from '../../utils/__generated__/Node'; import {
import { StatisticsDocument } from '../../utils/__generated__/Node'; NodeCheckDocument,
NodeCheckTimeUpdateDocument,
} from '../../utils/__generated__/NodeCheck';
import type { RowDataProps } from './row-data'; import type { RowDataProps } from './row-data';
import { POLL_INTERVAL } from './row-data'; import { POLL_INTERVAL } from './row-data';
import { BLOCK_THRESHOLD, RowData } from './row-data'; import { BLOCK_THRESHOLD, RowData } from './row-data';
@ -19,9 +21,9 @@ jest.mock('@vegaprotocol/apollo-client', () => ({
useHeaderStore: jest.fn().mockReturnValue({}), useHeaderStore: jest.fn().mockReturnValue({}),
})); }));
const statsQueryMock: MockedResponse<StatisticsQuery> = { const statsQueryMock: MockedResponse<NodeCheckQuery> = {
request: { request: {
query: StatisticsDocument, query: NodeCheckDocument,
}, },
result: { result: {
data: { data: {
@ -34,9 +36,9 @@ const statsQueryMock: MockedResponse<StatisticsQuery> = {
}, },
}; };
const subMock: MockedResponse<BlockTimeSubscription> = { const subMock: MockedResponse<NodeCheckTimeUpdateSubscription> = {
request: { request: {
query: BlockTimeDocument, query: NodeCheckTimeUpdateDocument,
}, },
result: { result: {
data: { data: {
@ -71,8 +73,8 @@ const mockHeaders = (
const renderComponent = ( const renderComponent = (
props: RowDataProps, props: RowDataProps,
queryMock: MockedResponse<StatisticsQuery>, queryMock: MockedResponse<NodeCheckQuery>,
subMock: MockedResponse<BlockTimeSubscription> subMock: MockedResponse<NodeCheckTimeUpdateSubscription>
) => { ) => {
return ( return (
<MockedProvider mocks={[queryMock, subMock, subMock, subMock]}> <MockedProvider mocks={[queryMock, subMock, subMock, subMock]}>
@ -127,16 +129,16 @@ describe('RowData', () => {
it('radio button still enabled if query fails', async () => { it('radio button still enabled if query fails', async () => {
mockHeaders(props.url, {}); mockHeaders(props.url, {});
const failedQueryMock: MockedResponse<StatisticsQuery> = { const failedQueryMock: MockedResponse<NodeCheckQuery> = {
request: { request: {
query: StatisticsDocument, query: NodeCheckDocument,
}, },
error: new Error('failed'), error: new Error('failed'),
}; };
const failedSubMock: MockedResponse<BlockTimeSubscription> = { const failedSubMock: MockedResponse<NodeCheckTimeUpdateSubscription> = {
request: { request: {
query: BlockTimeDocument, query: NodeCheckTimeUpdateDocument,
}, },
error: new Error('failed'), error: new Error('failed'),
}; };
@ -244,10 +246,10 @@ describe('RowData', () => {
jest.useFakeTimers(); jest.useFakeTimers();
const createStatsQueryMock = ( const createStatsQueryMock = (
blockHeight: string blockHeight: string
): MockedResponse<StatisticsQuery> => { ): MockedResponse<NodeCheckQuery> => {
return { return {
request: { request: {
query: StatisticsDocument, query: NodeCheckDocument,
}, },
result: { result: {
data: { data: {
@ -261,10 +263,10 @@ describe('RowData', () => {
}; };
}; };
const createFailedStatsQueryMock = (): MockedResponse<StatisticsQuery> => { const createFailedStatsQueryMock = (): MockedResponse<NodeCheckQuery> => {
return { return {
request: { request: {
query: StatisticsDocument, query: NodeCheckDocument,
}, },
result: { result: {
data: undefined, data: undefined,

View File

@ -6,9 +6,9 @@ import { Radio } from '@vegaprotocol/ui-toolkit';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { CUSTOM_NODE_KEY } from '../../types'; import { CUSTOM_NODE_KEY } from '../../types';
import { import {
useBlockTimeSubscription, useNodeCheckQuery,
useStatisticsQuery, useNodeCheckTimeUpdateSubscription,
} from '../../utils/__generated__/Node'; } from '../../utils/__generated__/NodeCheck';
import { LayoutCell } from './layout-cell'; import { LayoutCell } from './layout-cell';
export const POLL_INTERVAL = 1000; export const POLL_INTERVAL = 1000;
@ -30,13 +30,14 @@ export const RowData = ({
const [subFailed, setSubFailed] = useState(false); const [subFailed, setSubFailed] = useState(false);
const [time, setTime] = useState<number>(); const [time, setTime] = useState<number>();
// no use of data here as we need the data nodes reference to block height // no use of data here as we need the data nodes reference to block height
const { data, error, loading, startPolling, stopPolling } = const { data, error, loading, startPolling, stopPolling } = useNodeCheckQuery(
useStatisticsQuery({ {
pollInterval: POLL_INTERVAL, pollInterval: POLL_INTERVAL,
// fix for pollInterval // fix for pollInterval
// https://github.com/apollographql/apollo-client/issues/9819 // https://github.com/apollographql/apollo-client/issues/9819
ssr: false, ssr: false,
}); }
);
const headerStore = useHeaderStore(); const headerStore = useHeaderStore();
const headers = headerStore[url]; const headers = headerStore[url];
@ -44,7 +45,7 @@ export const RowData = ({
data: subData, data: subData,
error: subError, error: subError,
loading: subLoading, loading: subLoading,
} = useBlockTimeSubscription(); } = useNodeCheckTimeUpdateSubscription();
useEffect(() => { useEffect(() => {
const timeout = setTimeout(() => { const timeout = setTimeout(() => {

View File

@ -1,11 +1,11 @@
import { import {
StatisticsDocument, NodeCheckDocument,
BlockTimeDocument, NodeCheckTimeUpdateDocument,
} from '../../utils/__generated__/Node'; } from '../../utils/__generated__/NodeCheck';
import type { import type {
StatisticsQuery, NodeCheckQuery,
BlockTimeSubscription, NodeCheckTimeUpdateSubscription,
} from '../../utils/__generated__/Node'; } from '../../utils/__generated__/NodeCheck';
import { Networks } from '../../types'; import { Networks } from '../../types';
import type { RequestHandlerResponse } from 'mock-apollo-client'; import type { RequestHandlerResponse } from 'mock-apollo-client';
import { createMockClient } from 'mock-apollo-client'; import { createMockClient } from 'mock-apollo-client';
@ -21,7 +21,7 @@ type MockClientProps = {
busEvents?: MockRequestConfig; busEvents?: MockRequestConfig;
}; };
export const getMockBusEventsResult = (): BlockTimeSubscription => ({ export const getMockBusEventsResult = (): NodeCheckTimeUpdateSubscription => ({
busEvents: [ busEvents: [
{ {
__typename: 'BusEvent', __typename: 'BusEvent',
@ -32,19 +32,21 @@ export const getMockBusEventsResult = (): BlockTimeSubscription => ({
export const getMockStatisticsResult = ( export const getMockStatisticsResult = (
env: Networks = Networks.TESTNET env: Networks = Networks.TESTNET
): StatisticsQuery => ({ ): NodeCheckQuery => ({
statistics: { statistics: {
__typename: 'Statistics', __typename: 'Statistics',
chainId: `${env.toLowerCase()}-0123`, chainId: `${env.toLowerCase()}-0123`,
blockHeight: '11', blockHeight: '11',
vegaTime: new Date().toISOString(),
}, },
}); });
export const getMockQueryResult = (env: Networks): StatisticsQuery => ({ export const getMockQueryResult = (env: Networks): NodeCheckQuery => ({
statistics: { statistics: {
__typename: 'Statistics', __typename: 'Statistics',
chainId: `${env.toLowerCase()}-0123`, chainId: `${env.toLowerCase()}-0123`,
blockHeight: '11', blockHeight: '11',
vegaTime: new Date().toISOString(),
}, },
}); });
@ -72,11 +74,11 @@ export default function ({
const mockClient = createMockClient(); const mockClient = createMockClient();
mockClient.setRequestHandler( mockClient.setRequestHandler(
StatisticsDocument, NodeCheckDocument,
getHandler(statistics, getMockStatisticsResult(network)) getHandler(statistics, getMockStatisticsResult(network))
); );
mockClient.setRequestHandler( mockClient.setRequestHandler(
BlockTimeDocument, NodeCheckTimeUpdateDocument,
getHandler(busEvents, getMockBusEventsResult()) getHandler(busEvents, getMockBusEventsResult())
); );

View File

@ -5,11 +5,13 @@ import { useEffect } from 'react';
import { create } from 'zustand'; import { create } from 'zustand';
import { createClient } from '@vegaprotocol/apollo-client'; import { createClient } from '@vegaprotocol/apollo-client';
import type { import type {
BlockTimeSubscription, NodeCheckTimeUpdateSubscription,
StatisticsQuery, NodeCheckQuery,
} from '../utils/__generated__/Node'; } from '../utils/__generated__/NodeCheck';
import { BlockTimeDocument } from '../utils/__generated__/Node'; import {
import { StatisticsDocument } from '../utils/__generated__/Node'; NodeCheckDocument,
NodeCheckTimeUpdateDocument,
} from '../utils/__generated__/NodeCheck';
import type { Environment } from '../types'; import type { Environment } from '../types';
import { Networks } from '../types'; import { Networks } from '../types';
import { compileErrors } from '../utils/compile-errors'; import { compileErrors } from '../utils/compile-errors';
@ -220,8 +222,8 @@ const testNode = async (
*/ */
const testQuery = async (client: Client) => { const testQuery = async (client: Client) => {
try { try {
const result = await client.query<StatisticsQuery>({ const result = await client.query<NodeCheckQuery>({
query: StatisticsDocument, query: NodeCheckDocument,
}); });
if (!result || result.error) { if (!result || result.error) {
return false; return false;
@ -240,8 +242,8 @@ const testQuery = async (client: Client) => {
const testSubscription = (client: Client) => { const testSubscription = (client: Client) => {
return new Promise((resolve) => { return new Promise((resolve) => {
const sub = client const sub = client
.subscribe<BlockTimeSubscription>({ .subscribe<NodeCheckTimeUpdateSubscription>({
query: BlockTimeDocument, query: NodeCheckTimeUpdateDocument,
errorPolicy: 'all', errorPolicy: 'all',
}) })
.subscribe({ .subscribe({

View File

@ -2,8 +2,8 @@ import { renderHook, waitFor } from '@testing-library/react';
import { useNodeHealth } from './use-node-health'; import { useNodeHealth } from './use-node-health';
import type { MockedResponse } from '@apollo/react-testing'; import type { MockedResponse } from '@apollo/react-testing';
import { MockedProvider } from '@apollo/react-testing'; import { MockedProvider } from '@apollo/react-testing';
import type { StatisticsQuery } from '../utils/__generated__/Node'; import type { NodeCheckQuery } from '../utils/__generated__/NodeCheck';
import { StatisticsDocument } from '../utils/__generated__/Node'; import { NodeCheckDocument } from '../utils/__generated__/NodeCheck';
import { useHeaderStore } from '@vegaprotocol/apollo-client'; import { useHeaderStore } from '@vegaprotocol/apollo-client';
import { Intent } from '@vegaprotocol/ui-toolkit'; import { Intent } from '@vegaprotocol/ui-toolkit';
@ -16,10 +16,10 @@ jest.mock('@vegaprotocol/apollo-client');
const createStatsMock = ( const createStatsMock = (
blockHeight: number blockHeight: number
): MockedResponse<StatisticsQuery> => { ): MockedResponse<NodeCheckQuery> => {
return { return {
request: { request: {
query: StatisticsDocument, query: NodeCheckDocument,
}, },
result: { result: {
data: { data: {
@ -34,7 +34,7 @@ const createStatsMock = (
}; };
function setup( function setup(
mock: MockedResponse<StatisticsQuery>, mock: MockedResponse<NodeCheckQuery>,
headers: headers:
| { | {
blockHeight: number; blockHeight: number;
@ -93,9 +93,9 @@ describe('useNodeHealth', () => {
); );
it('block diff is null if query fails indicating non operational', async () => { it('block diff is null if query fails indicating non operational', async () => {
const failedQuery: MockedResponse<StatisticsQuery> = { const failedQuery: MockedResponse<NodeCheckQuery> = {
request: { request: {
query: StatisticsDocument, query: NodeCheckDocument,
}, },
result: { result: {
// @ts-ignore failed query with no result // @ts-ignore failed query with no result

View File

@ -1,5 +1,5 @@
import { useEffect, useMemo } from 'react'; import { useEffect, useMemo } from 'react';
import { useStatisticsQuery } from '../utils/__generated__/Node'; import { useNodeCheckQuery } from '../utils/__generated__/NodeCheck';
import { useHeaderStore } from '@vegaprotocol/apollo-client'; import { useHeaderStore } from '@vegaprotocol/apollo-client';
import { useEnvironment } from './use-environment'; import { useEnvironment } from './use-environment';
import { useNavigatorOnline } from '@vegaprotocol/react-helpers'; import { useNavigatorOnline } from '@vegaprotocol/react-helpers';
@ -16,7 +16,7 @@ export const useNodeHealth = () => {
const url = useEnvironment((store) => store.VEGA_URL); const url = useEnvironment((store) => store.VEGA_URL);
const headerStore = useHeaderStore(); const headerStore = useHeaderStore();
const headers = url ? headerStore[url] : undefined; const headers = url ? headerStore[url] : undefined;
const { data, error, startPolling, stopPolling } = useStatisticsQuery({ const { data, error, startPolling, stopPolling } = useNodeCheckQuery({
fetchPolicy: 'no-cache', fetchPolicy: 'no-cache',
}); });

View File

@ -8,4 +8,4 @@ export * from './hooks';
export * from './types'; export * from './types';
// Utils // Utils
export * from './utils/__generated__/Node'; export * from './utils/__generated__/NodeCheck';

View File

@ -1,4 +1,4 @@
query Statistics { query NodeCheck {
statistics { statistics {
chainId chainId
blockHeight blockHeight
@ -6,7 +6,7 @@ query Statistics {
} }
} }
subscription BlockTime { subscription NodeCheckTimeUpdate {
busEvents(types: TimeUpdate, batchSize: 1) { busEvents(types: TimeUpdate, batchSize: 1) {
id id
} }

View File

@ -1,81 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type StatisticsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type StatisticsQuery = { __typename?: 'Query', statistics: { __typename?: 'Statistics', chainId: string, blockHeight: string, vegaTime: any } };
export type BlockTimeSubscriptionVariables = Types.Exact<{ [key: string]: never; }>;
export type BlockTimeSubscription = { __typename?: 'Subscription', busEvents?: Array<{ __typename?: 'BusEvent', id: string }> | null };
export const StatisticsDocument = gql`
query Statistics {
statistics {
chainId
blockHeight
vegaTime
}
}
`;
/**
* __useStatisticsQuery__
*
* To run a query within a React component, call `useStatisticsQuery` and pass it any options that fit your needs.
* When your component renders, `useStatisticsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useStatisticsQuery({
* variables: {
* },
* });
*/
export function useStatisticsQuery(baseOptions?: Apollo.QueryHookOptions<StatisticsQuery, StatisticsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<StatisticsQuery, StatisticsQueryVariables>(StatisticsDocument, options);
}
export function useStatisticsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<StatisticsQuery, StatisticsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<StatisticsQuery, StatisticsQueryVariables>(StatisticsDocument, options);
}
export type StatisticsQueryHookResult = ReturnType<typeof useStatisticsQuery>;
export type StatisticsLazyQueryHookResult = ReturnType<typeof useStatisticsLazyQuery>;
export type StatisticsQueryResult = Apollo.QueryResult<StatisticsQuery, StatisticsQueryVariables>;
export const BlockTimeDocument = gql`
subscription BlockTime {
busEvents(types: TimeUpdate, batchSize: 1) {
id
}
}
`;
/**
* __useBlockTimeSubscription__
*
* To run a query within a React component, call `useBlockTimeSubscription` and pass it any options that fit your needs.
* When your component renders, `useBlockTimeSubscription` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useBlockTimeSubscription({
* variables: {
* },
* });
*/
export function useBlockTimeSubscription(baseOptions?: Apollo.SubscriptionHookOptions<BlockTimeSubscription, BlockTimeSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<BlockTimeSubscription, BlockTimeSubscriptionVariables>(BlockTimeDocument, options);
}
export type BlockTimeSubscriptionHookResult = ReturnType<typeof useBlockTimeSubscription>;
export type BlockTimeSubscriptionResult = Apollo.SubscriptionResult<BlockTimeSubscription>;

View File

@ -0,0 +1,81 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type NodeCheckQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type NodeCheckQuery = { __typename?: 'Query', statistics: { __typename?: 'Statistics', chainId: string, blockHeight: string, vegaTime: any } };
export type NodeCheckTimeUpdateSubscriptionVariables = Types.Exact<{ [key: string]: never; }>;
export type NodeCheckTimeUpdateSubscription = { __typename?: 'Subscription', busEvents?: Array<{ __typename?: 'BusEvent', id: string }> | null };
export const NodeCheckDocument = gql`
query NodeCheck {
statistics {
chainId
blockHeight
vegaTime
}
}
`;
/**
* __useNodeCheckQuery__
*
* To run a query within a React component, call `useNodeCheckQuery` and pass it any options that fit your needs.
* When your component renders, `useNodeCheckQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useNodeCheckQuery({
* variables: {
* },
* });
*/
export function useNodeCheckQuery(baseOptions?: Apollo.QueryHookOptions<NodeCheckQuery, NodeCheckQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<NodeCheckQuery, NodeCheckQueryVariables>(NodeCheckDocument, options);
}
export function useNodeCheckLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<NodeCheckQuery, NodeCheckQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<NodeCheckQuery, NodeCheckQueryVariables>(NodeCheckDocument, options);
}
export type NodeCheckQueryHookResult = ReturnType<typeof useNodeCheckQuery>;
export type NodeCheckLazyQueryHookResult = ReturnType<typeof useNodeCheckLazyQuery>;
export type NodeCheckQueryResult = Apollo.QueryResult<NodeCheckQuery, NodeCheckQueryVariables>;
export const NodeCheckTimeUpdateDocument = gql`
subscription NodeCheckTimeUpdate {
busEvents(types: TimeUpdate, batchSize: 1) {
id
}
}
`;
/**
* __useNodeCheckTimeUpdateSubscription__
*
* To run a query within a React component, call `useNodeCheckTimeUpdateSubscription` and pass it any options that fit your needs.
* When your component renders, `useNodeCheckTimeUpdateSubscription` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useNodeCheckTimeUpdateSubscription({
* variables: {
* },
* });
*/
export function useNodeCheckTimeUpdateSubscription(baseOptions?: Apollo.SubscriptionHookOptions<NodeCheckTimeUpdateSubscription, NodeCheckTimeUpdateSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<NodeCheckTimeUpdateSubscription, NodeCheckTimeUpdateSubscriptionVariables>(NodeCheckTimeUpdateDocument, options);
}
export type NodeCheckTimeUpdateSubscriptionHookResult = ReturnType<typeof useNodeCheckTimeUpdateSubscription>;
export type NodeCheckTimeUpdateSubscriptionResult = Apollo.SubscriptionResult<NodeCheckTimeUpdateSubscription>;

View File

@ -1,11 +1,11 @@
import type { StatisticsQuery } from './__generated__/Node'; import type { NodeCheckQuery } from './__generated__/NodeCheck';
import merge from 'lodash/merge'; import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest'; import type { PartialDeep } from 'type-fest';
export const statisticsQuery = ( export const statisticsQuery = (
override?: PartialDeep<StatisticsQuery> override?: PartialDeep<NodeCheckQuery>
): StatisticsQuery => { ): NodeCheckQuery => {
const defaultResult: StatisticsQuery = { const defaultResult: NodeCheckQuery = {
statistics: { statistics: {
__typename: 'Statistics', __typename: 'Statistics',
chainId: 'chain-id', chainId: 'chain-id',