Skip to content
7 changes: 5 additions & 2 deletions packages/network-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Add `rpcMethodName` to `NetworkController:rpcEndpointDegraded` and `NetworkController:rpcEndpointChainDegraded` event payloads ([#7954](https://github.com/MetaMask/core/pull/7954))
- This field contains the JSON-RPC method name (e.g. `eth_blockNumber`) that was being processed when the event fired, enabling identification of which methods produce the most slow requests or retry exhaustions.
- Add `degradedType` and `retriedError` to `NetworkController:rpcEndpointDegraded` and `NetworkController:rpcEndpointChainDegraded` event payloads ([#7988](https://github.com/MetaMask/core/pull/7988))
- `degradedType` is `'slow_success'` when the request succeeded but was slow, or `'retries_exhausted'` when retries ran out.
- `retriedError` (only present when `degradedType` is `'retries_exhausted'`) classifies the error that was retried (e.g. `'non_success_http_status'`, `'timed_out'`, `'request_not_initiated'`).

### Changed

- **BREAKING:** The `RpcServiceRequestable` type's `onDegraded` listener now receives `rpcMethodName: string` in its data parameter ([#7954](https://github.com/MetaMask/core/pull/7954))
- Implementors of this interface will need to accept the new field in their `onDegraded` callback signature.
- **BREAKING:** The `RpcServiceRequestable` type's `onDegraded` listener now receives `rpcMethodName: string`, `degradedType: DegradedType`, and optionally `retriedError: RetriedError` in its data parameter ([#7954](https://github.com/MetaMask/core/pull/7954), [#7988](https://github.com/MetaMask/core/pull/7988))
- Implementors of this interface will need to accept the new fields in their `onDegraded` callback signature.
- Bump `@metamask/eth-json-rpc-middleware` from `^23.0.0` to `^23.1.0` ([#7810](https://github.com/MetaMask/core/pull/7810))
- Bump `@metamask/json-rpc-engine` from `^10.2.1` to `^10.2.2` ([#7856](https://github.com/MetaMask/core/pull/7856))

Expand Down
10 changes: 9 additions & 1 deletion packages/network-controller/src/NetworkController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ import type {
} from './create-auto-managed-network-client';
import { createAutoManagedNetworkClient } from './create-auto-managed-network-client';
import { projectLogger, createModuleLogger } from './logger';
import type { RpcServiceOptions } from './rpc-service/rpc-service';
import type {
DegradedType,
RetriedError,
RpcServiceOptions,
} from './rpc-service/rpc-service';
import { NetworkClientType } from './types';
import type {
BlockTracker,
Expand Down Expand Up @@ -524,8 +528,10 @@ export type NetworkControllerRpcEndpointChainDegradedEvent = {
payload: [
{
chainId: Hex;
degradedType: DegradedType;
error: unknown;
networkClientId: NetworkClientId;
retriedError?: RetriedError;
rpcMethodName: string;
},
];
Expand Down Expand Up @@ -561,10 +567,12 @@ export type NetworkControllerRpcEndpointDegradedEvent = {
payload: [
{
chainId: Hex;
degradedType: DegradedType;
endpointUrl: string;
error: unknown;
networkClientId: NetworkClientId;
primaryEndpointUrl: string;
retriedError?: RetriedError;
rpcMethodName: string;
},
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,10 @@ describe('createNetworkClient - RPC endpoint events', () => {
rpcEndpointChainDegradedEventHandler,
).toHaveBeenCalledWith({
chainId,
degradedType: 'retries_exhausted',
error: expectedDegradedError,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
retriedError: 'non_success_http_status',
rpcMethodName: 'eth_blockNumber',
});
},
Expand Down Expand Up @@ -660,8 +662,10 @@ describe('createNetworkClient - RPC endpoint events', () => {
rpcEndpointChainDegradedEventHandler,
).toHaveBeenCalledWith({
chainId,
degradedType: 'retries_exhausted',
error: expectedDegradedError,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
retriedError: 'non_success_http_status',
rpcMethodName: 'eth_blockNumber',
});
},
Expand Down Expand Up @@ -769,30 +773,36 @@ describe('createNetworkClient - RPC endpoint events', () => {
rpcEndpointDegradedEventHandler,
).toHaveBeenNthCalledWith(1, {
chainId,
degradedType: 'retries_exhausted',
endpointUrl: rpcUrl,
error: expectedDegradedError,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
primaryEndpointUrl: rpcUrl,
retriedError: 'non_success_http_status',
rpcMethodName: 'eth_blockNumber',
});
expect(
rpcEndpointDegradedEventHandler,
).toHaveBeenNthCalledWith(2, {
chainId,
degradedType: 'retries_exhausted',
endpointUrl: rpcUrl,
error: expectedDegradedError,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
primaryEndpointUrl: rpcUrl,
retriedError: 'non_success_http_status',
rpcMethodName: 'eth_blockNumber',
});
expect(
rpcEndpointDegradedEventHandler,
).toHaveBeenNthCalledWith(3, {
chainId,
degradedType: 'retries_exhausted',
endpointUrl: failoverEndpointUrl,
error: expectedDegradedError,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
primaryEndpointUrl: rpcUrl,
retriedError: 'non_success_http_status',
rpcMethodName: 'eth_blockNumber',
});
},
Expand Down Expand Up @@ -912,26 +922,31 @@ describe('createNetworkClient - RPC endpoint events', () => {
rpcEndpointDegradedEventHandler,
).toHaveBeenNthCalledWith(1, {
chainId,
degradedType: 'retries_exhausted',
endpointUrl: rpcUrl,
error: expectedDegradedError,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
primaryEndpointUrl: rpcUrl,
retriedError: 'non_success_http_status',
rpcMethodName: 'eth_blockNumber',
});
expect(
rpcEndpointDegradedEventHandler,
).toHaveBeenNthCalledWith(2, {
chainId,
degradedType: 'retries_exhausted',
endpointUrl: rpcUrl,
error: expectedDegradedError,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
primaryEndpointUrl: rpcUrl,
retriedError: 'non_success_http_status',
rpcMethodName: 'eth_blockNumber',
});
expect(
rpcEndpointDegradedEventHandler,
).toHaveBeenNthCalledWith(3, {
chainId,
degradedType: 'slow_success',
endpointUrl: failoverEndpointUrl,
error: undefined,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
Expand All @@ -942,6 +957,7 @@ describe('createNetworkClient - RPC endpoint events', () => {
rpcEndpointDegradedEventHandler,
).toHaveBeenNthCalledWith(4, {
chainId,
degradedType: 'slow_success',
endpointUrl: failoverEndpointUrl,
error: undefined,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
Expand Down Expand Up @@ -1143,8 +1159,10 @@ describe('createNetworkClient - RPC endpoint events', () => {
rpcEndpointChainDegradedEventHandler,
).toHaveBeenCalledWith({
chainId,
degradedType: 'retries_exhausted',
error: expectedDegradedError,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
retriedError: 'non_success_http_status',
rpcMethodName: 'eth_blockNumber',
});
},
Expand Down Expand Up @@ -1220,6 +1238,7 @@ describe('createNetworkClient - RPC endpoint events', () => {
rpcEndpointChainDegradedEventHandler,
).toHaveBeenCalledWith({
chainId,
degradedType: 'slow_success',
error: undefined,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
rpcMethodName: 'eth_blockNumber',
Expand Down Expand Up @@ -1305,18 +1324,22 @@ describe('createNetworkClient - RPC endpoint events', () => {
);
expect(rpcEndpointDegradedEventHandler).toHaveBeenCalledWith({
chainId,
degradedType: 'retries_exhausted',
endpointUrl: rpcUrl,
error: expectedDegradedError,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
primaryEndpointUrl: rpcUrl,
retriedError: 'non_success_http_status',
rpcMethodName: 'eth_blockNumber',
});
expect(rpcEndpointDegradedEventHandler).toHaveBeenCalledWith({
chainId,
degradedType: 'retries_exhausted',
endpointUrl: rpcUrl,
error: expectedDegradedError,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
primaryEndpointUrl: rpcUrl,
retriedError: 'non_success_http_status',
rpcMethodName: 'eth_blockNumber',
});
},
Expand Down Expand Up @@ -1543,6 +1566,7 @@ describe('createNetworkClient - RPC endpoint events', () => {
);
expect(rpcEndpointDegradedEventHandler).toHaveBeenCalledWith({
chainId,
degradedType: 'slow_success',
endpointUrl: rpcUrl,
error: undefined,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
Expand All @@ -1551,6 +1575,7 @@ describe('createNetworkClient - RPC endpoint events', () => {
});
expect(rpcEndpointDegradedEventHandler).toHaveBeenCalledWith({
chainId,
degradedType: 'slow_success',
endpointUrl: rpcUrl,
error: undefined,
networkClientId: 'AAAA-AAAA-AAAA-AAAA',
Expand Down
26 changes: 17 additions & 9 deletions packages/network-controller/src/create-network-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,21 +299,27 @@ function createRpcServiceChain({
},
);

rpcServiceChain.onDegraded(({ rpcMethodName, ...rest }) => {
const error = getError(rest);
messenger.publish('NetworkController:rpcEndpointChainDegraded', {
chainId: configuration.chainId,
networkClientId: id,
error,
rpcMethodName,
});
});
rpcServiceChain.onDegraded(
({ rpcMethodName, degradedType, retriedError, ...rest }) => {
const error = getError(rest);
messenger.publish('NetworkController:rpcEndpointChainDegraded', {
chainId: configuration.chainId,
networkClientId: id,
error,
rpcMethodName,
degradedType,
retriedError,
});
},
);

rpcServiceChain.onServiceDegraded(
({
endpointUrl,
primaryEndpointUrl: primaryEndpointUrlFromEvent,
rpcMethodName,
degradedType,
retriedError,
...rest
}) => {
const error = getError(rest);
Expand All @@ -325,6 +331,8 @@ function createRpcServiceChain({
endpointUrl,
error,
rpcMethodName,
degradedType,
retriedError,
});
},
);
Expand Down
1 change: 1 addition & 0 deletions packages/network-controller/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ export { NetworkClientType } from './types';
export type { NetworkClient } from './create-network-client';
export type { AbstractRpcService } from './rpc-service/abstract-rpc-service';
export type { RpcServiceRequestable } from './rpc-service/rpc-service-requestable';
export type { DegradedType, RetriedError } from './rpc-service/rpc-service';
export { isConnectionError } from './rpc-service/rpc-service';
Loading