Explorer: add error reporting (#11627)
This commit is contained in:
parent
8f88ab1a05
commit
4773e13ef7
|
@ -2649,6 +2649,76 @@
|
||||||
"resolved": "https://registry.npmjs.org/@react-hook/latest/-/latest-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@react-hook/latest/-/latest-1.0.2.tgz",
|
||||||
"integrity": "sha512-zLtOIToct1EBTbwldkMJsXC2eCsmWOOP7z6UG0M/sCgnPExtIjvVMCpPESvPnMbQzDZytXVy0nvMbUuK2gZs2A=="
|
"integrity": "sha512-zLtOIToct1EBTbwldkMJsXC2eCsmWOOP7z6UG0M/sCgnPExtIjvVMCpPESvPnMbQzDZytXVy0nvMbUuK2gZs2A=="
|
||||||
},
|
},
|
||||||
|
"@sentry/browser": {
|
||||||
|
"version": "5.21.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-5.21.1.tgz",
|
||||||
|
"integrity": "sha512-sUxsW545klZxJE4iBAYQ8SuVS85HTOGNmIIIZWFUogB5oW3O0L+nJluXEqf/pHU82LnjDIzqsWCYQ0cRUaeYow==",
|
||||||
|
"requires": {
|
||||||
|
"@sentry/core": "5.21.1",
|
||||||
|
"@sentry/types": "5.21.1",
|
||||||
|
"@sentry/utils": "5.21.1",
|
||||||
|
"tslib": "^1.9.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@sentry/core": {
|
||||||
|
"version": "5.21.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.21.1.tgz",
|
||||||
|
"integrity": "sha512-Luulwx3GLUiY0gmHOhU+4eSga28Ce8DwoBcRq9GkGuhPu9r80057d5urxrDLp/leIZBXVvpY7tvmSN/rMtvF9w==",
|
||||||
|
"requires": {
|
||||||
|
"@sentry/hub": "5.21.1",
|
||||||
|
"@sentry/minimal": "5.21.1",
|
||||||
|
"@sentry/types": "5.21.1",
|
||||||
|
"@sentry/utils": "5.21.1",
|
||||||
|
"tslib": "^1.9.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@sentry/hub": {
|
||||||
|
"version": "5.21.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.21.1.tgz",
|
||||||
|
"integrity": "sha512-x5i9Ggi5ZYMhBYL5kyTu2fUJ6owjKH2tgJL3UExoZdRyZkbLAFZb+DtfSnteWgQ6wriGfgPD3r/hAIEdaomk2A==",
|
||||||
|
"requires": {
|
||||||
|
"@sentry/types": "5.21.1",
|
||||||
|
"@sentry/utils": "5.21.1",
|
||||||
|
"tslib": "^1.9.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@sentry/minimal": {
|
||||||
|
"version": "5.21.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.21.1.tgz",
|
||||||
|
"integrity": "sha512-OBVPASZ+mcXMKajvJon9RjEZ+ny3+VGhOI66acoP1hmYxKvji1OC2bYEuP1r4qtHxWVLAdV7qFj3EQ9ckErZmQ==",
|
||||||
|
"requires": {
|
||||||
|
"@sentry/hub": "5.21.1",
|
||||||
|
"@sentry/types": "5.21.1",
|
||||||
|
"tslib": "^1.9.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@sentry/react": {
|
||||||
|
"version": "5.21.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-5.21.1.tgz",
|
||||||
|
"integrity": "sha512-e60erzdQOwZ88+j6Hi1AnRlxex7ZmwQPGSoFjtihQJR3Xv9Esj5DBKVrWu6Z/QCDxTc8uaX08XjUyhse2YyutQ==",
|
||||||
|
"requires": {
|
||||||
|
"@sentry/browser": "5.21.1",
|
||||||
|
"@sentry/minimal": "5.21.1",
|
||||||
|
"@sentry/types": "5.21.1",
|
||||||
|
"@sentry/utils": "5.21.1",
|
||||||
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
|
"tslib": "^1.9.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@sentry/types": {
|
||||||
|
"version": "5.21.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.21.1.tgz",
|
||||||
|
"integrity": "sha512-hFN4aDduMpjj6vZSIIp+9kSr8MglcKO/UmbuUXN6hKLewhxt+Zj2wjXN7ulSs5OK5mjXP9QLA5YJvVQsl2//qw=="
|
||||||
|
},
|
||||||
|
"@sentry/utils": {
|
||||||
|
"version": "5.21.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.21.1.tgz",
|
||||||
|
"integrity": "sha512-p5vPuc7+GfOmW8CXxWd0samS77Q00YrN8q5TC/ztF8nBhEF18GiMeWAdQnlSwt3iWal3q3gSSrbF4c9guIugng==",
|
||||||
|
"requires": {
|
||||||
|
"@sentry/types": "5.21.1",
|
||||||
|
"tslib": "^1.9.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@solana/web3.js": {
|
"@solana/web3.js": {
|
||||||
"version": "0.70.3",
|
"version": "0.70.3",
|
||||||
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.70.3.tgz",
|
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.70.3.tgz",
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-hook/debounce": "^3.0.0",
|
"@react-hook/debounce": "^3.0.0",
|
||||||
|
"@sentry/react": "^5.21.1",
|
||||||
"@solana/web3.js": "^0.70.3",
|
"@solana/web3.js": "^0.70.3",
|
||||||
"@testing-library/jest-dom": "^5.11.3",
|
"@testing-library/jest-dom": "^5.11.3",
|
||||||
"@testing-library/react": "^10.4.8",
|
"@testing-library/react": "^10.4.8",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import { Account, useFetchAccountInfo } from "providers/accounts";
|
import { Account, useFetchAccountInfo } from "providers/accounts";
|
||||||
import {
|
import {
|
||||||
TokenAccount,
|
TokenAccount,
|
||||||
|
@ -37,7 +38,13 @@ export function TokenAccountSection({
|
||||||
return <MultisigAccountCard account={account} info={info} />;
|
return <MultisigAccountCard account={account} info={info} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {}
|
} catch (err) {
|
||||||
|
Sentry.captureException(err, {
|
||||||
|
tags: {
|
||||||
|
address: account.pubkey.toBase58(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
return <UnknownAccountCard account={account} />;
|
return <UnknownAccountCard account={account} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ export function AuthorizeDetailsCard(props: {
|
||||||
try {
|
try {
|
||||||
params = StakeInstruction.decodeAuthorize(ix);
|
params = StakeInstruction.decodeAuthorize(ix);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
return <UnknownDetailsCard {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import { coerce } from "superstruct";
|
import { coerce } from "superstruct";
|
||||||
import {
|
import {
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
|
@ -29,6 +30,11 @@ export function TokenDetailsCard(props: DetailsProps) {
|
||||||
const coerced = coerce(info, IX_STRUCTS[type] as any);
|
const coerced = coerce(info, IX_STRUCTS[type] as any);
|
||||||
return <TokenInstruction title={title} info={coerced} {...props} />;
|
return <TokenInstruction title={title} info={coerced} {...props} />;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
Sentry.captureException(err, {
|
||||||
|
tags: {
|
||||||
|
signature: props.tx.signatures[0],
|
||||||
|
},
|
||||||
|
});
|
||||||
return <UnknownDetailsCard {...props} />;
|
return <UnknownDetailsCard {...props} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import { BrowserRouter as Router } from "react-router-dom";
|
import { BrowserRouter as Router } from "react-router-dom";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import "./scss/theme-dark.scss";
|
import "./scss/theme-dark.scss";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
import * as serviceWorker from "./serviceWorker";
|
|
||||||
import { ClusterProvider } from "./providers/cluster";
|
import { ClusterProvider } from "./providers/cluster";
|
||||||
import { RichListProvider } from "./providers/richList";
|
import { RichListProvider } from "./providers/richList";
|
||||||
import { SupplyProvider } from "./providers/supply";
|
import { SupplyProvider } from "./providers/supply";
|
||||||
|
@ -12,6 +12,11 @@ import { AccountsProvider } from "./providers/accounts";
|
||||||
import { StatsProvider } from "providers/stats";
|
import { StatsProvider } from "providers/stats";
|
||||||
import { MintsProvider } from "providers/mints";
|
import { MintsProvider } from "providers/mints";
|
||||||
|
|
||||||
|
Sentry.init({
|
||||||
|
dsn:
|
||||||
|
"https://5efdc15b4828434fbe949b5daed472be@o434108.ingest.sentry.io/5390542",
|
||||||
|
});
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Router>
|
<Router>
|
||||||
<ClusterProvider>
|
<ClusterProvider>
|
||||||
|
@ -32,8 +37,3 @@ ReactDOM.render(
|
||||||
</Router>,
|
</Router>,
|
||||||
document.getElementById("root")
|
document.getElementById("root")
|
||||||
);
|
);
|
||||||
|
|
||||||
// If you want your app to work offline and load faster, you can change
|
|
||||||
// unregister() to register() below. Note this comes with some pitfalls.
|
|
||||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
|
||||||
serviceWorker.unregister();
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import {
|
import {
|
||||||
PublicKey,
|
PublicKey,
|
||||||
ConfirmedSignatureInfo,
|
ConfirmedSignatureInfo,
|
||||||
|
@ -101,7 +102,7 @@ async function fetchAccountHistory(
|
||||||
};
|
};
|
||||||
status = FetchStatus.Fetched;
|
status = FetchStatus.Fetched;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch account history", error);
|
Sentry.captureException(error, { tags: { url } });
|
||||||
status = FetchStatus.FetchFailed;
|
status = FetchStatus.FetchFailed;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import { StakeAccount as StakeAccountWasm } from "solana-sdk-wasm";
|
import { StakeAccount as StakeAccountWasm } from "solana-sdk-wasm";
|
||||||
import { PublicKey, Connection, StakeProgram } from "@solana/web3.js";
|
import { PublicKey, Connection, StakeProgram } from "@solana/web3.js";
|
||||||
import { useCluster } from "../cluster";
|
import { useCluster } from "../cluster";
|
||||||
|
@ -111,7 +112,9 @@ async function fetchAccountInfo(
|
||||||
parsed,
|
parsed,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to parse stake account", err);
|
Sentry.captureException(err, {
|
||||||
|
tags: { url, address: pubkey.toBase58() },
|
||||||
|
});
|
||||||
// TODO store error state in Account info
|
// TODO store error state in Account info
|
||||||
}
|
}
|
||||||
} else if ("parsed" in result.data) {
|
} else if ("parsed" in result.data) {
|
||||||
|
@ -124,6 +127,9 @@ async function fetchAccountInfo(
|
||||||
parsed,
|
parsed,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
Sentry.captureException(err, {
|
||||||
|
tags: { url, address: pubkey.toBase58() },
|
||||||
|
});
|
||||||
// TODO store error state in Account info
|
// TODO store error state in Account info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +145,7 @@ async function fetchAccountInfo(
|
||||||
data = { pubkey, lamports, details };
|
data = { pubkey, lamports, details };
|
||||||
fetchStatus = FetchStatus.Fetched;
|
fetchStatus = FetchStatus.Fetched;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch account info", error);
|
Sentry.captureException(error, { tags: { url } });
|
||||||
fetchStatus = FetchStatus.FetchFailed;
|
fetchStatus = FetchStatus.FetchFailed;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import { Connection, PublicKey } from "@solana/web3.js";
|
import { Connection, PublicKey } from "@solana/web3.js";
|
||||||
import * as Cache from "providers/cache";
|
import * as Cache from "providers/cache";
|
||||||
import { ActionType, FetchStatus } from "providers/cache";
|
import { ActionType, FetchStatus } from "providers/cache";
|
||||||
|
@ -72,6 +73,7 @@ async function fetchAccountTokens(
|
||||||
};
|
};
|
||||||
status = FetchStatus.Fetched;
|
status = FetchStatus.Fetched;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
Sentry.captureException(error, { tags: { url } });
|
||||||
status = FetchStatus.FetchFailed;
|
status = FetchStatus.FetchFailed;
|
||||||
}
|
}
|
||||||
dispatch({ type: ActionType.Update, url, status, data, key });
|
dispatch({ type: ActionType.Update, url, status, data, key });
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import { clusterApiUrl, Connection } from "@solana/web3.js";
|
import { clusterApiUrl, Connection } from "@solana/web3.js";
|
||||||
import { useQuery } from "../utils/url";
|
import { useQuery } from "../utils/url";
|
||||||
import { useHistory, useLocation } from "react-router-dom";
|
import { useHistory, useLocation } from "react-router-dom";
|
||||||
|
@ -182,7 +183,9 @@ async function updateCluster(
|
||||||
firstAvailableBlock,
|
firstAvailableBlock,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to update cluster", error);
|
Sentry.captureException(error, {
|
||||||
|
tags: { clusterUrl: clusterUrl(cluster, customUrl) },
|
||||||
|
});
|
||||||
dispatch({ status: ClusterStatus.Failure, cluster, customUrl });
|
dispatch({ status: ClusterStatus.Failure, cluster, customUrl });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import { useCluster } from "providers/cluster";
|
import { useCluster } from "providers/cluster";
|
||||||
import * as Cache from "providers/cache";
|
import * as Cache from "providers/cache";
|
||||||
import { ActionType, FetchStatus } from "providers/cache";
|
import { ActionType, FetchStatus } from "providers/cache";
|
||||||
|
@ -59,6 +60,7 @@ async function fetchLargestAccounts(
|
||||||
};
|
};
|
||||||
fetchStatus = FetchStatus.Fetched;
|
fetchStatus = FetchStatus.Fetched;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
Sentry.captureException(error, { tags: { url } });
|
||||||
fetchStatus = FetchStatus.FetchFailed;
|
fetchStatus = FetchStatus.FetchFailed;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import { useCluster } from "providers/cluster";
|
import { useCluster } from "providers/cluster";
|
||||||
import * as Cache from "providers/cache";
|
import * as Cache from "providers/cache";
|
||||||
import { ActionType, FetchStatus } from "providers/cache";
|
import { ActionType, FetchStatus } from "providers/cache";
|
||||||
|
@ -44,6 +45,7 @@ async function fetchSupply(dispatch: Dispatch, pubkey: PublicKey, url: string) {
|
||||||
|
|
||||||
fetchStatus = FetchStatus.Fetched;
|
fetchStatus = FetchStatus.Fetched;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
Sentry.captureException(error, { tags: { url } });
|
||||||
fetchStatus = FetchStatus.FetchFailed;
|
fetchStatus = FetchStatus.FetchFailed;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
|
|
||||||
import { AccountBalancePair, Connection } from "@solana/web3.js";
|
import { AccountBalancePair, Connection } from "@solana/web3.js";
|
||||||
import { useCluster, ClusterStatus } from "./cluster";
|
import { useCluster, ClusterStatus } from "./cluster";
|
||||||
|
@ -70,7 +71,7 @@ async function fetch(dispatch: Dispatch, url: string) {
|
||||||
return { total, circulating, nonCirculating };
|
return { total, circulating, nonCirculating };
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to fetch", err);
|
Sentry.captureException(err, { tags: { url } });
|
||||||
dispatch("Failed to fetch top accounts");
|
dispatch("Failed to fetch top accounts");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
|
|
||||||
import { Supply, Connection } from "@solana/web3.js";
|
import { Supply, Connection } from "@solana/web3.js";
|
||||||
import { useCluster, ClusterStatus } from "./cluster";
|
import { useCluster, ClusterStatus } from "./cluster";
|
||||||
|
@ -50,7 +51,7 @@ async function fetch(dispatch: Dispatch, url: string) {
|
||||||
return supply;
|
return supply;
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to fetch", err);
|
Sentry.captureException(err, { tags: { url } });
|
||||||
dispatch("Failed to fetch supply");
|
dispatch("Failed to fetch supply");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import {
|
import {
|
||||||
Connection,
|
Connection,
|
||||||
TransactionSignature,
|
TransactionSignature,
|
||||||
|
@ -63,7 +64,7 @@ async function fetchDetails(
|
||||||
);
|
);
|
||||||
fetchStatus = FetchStatus.Fetched;
|
fetchStatus = FetchStatus.Fetched;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch confirmed transaction", error);
|
Sentry.captureException(error, { tags: { url } });
|
||||||
fetchStatus = FetchStatus.FetchFailed;
|
fetchStatus = FetchStatus.FetchFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import {
|
import {
|
||||||
TransactionSignature,
|
TransactionSignature,
|
||||||
Connection,
|
Connection,
|
||||||
|
@ -85,12 +86,7 @@ export async function fetchTransactionStatus(
|
||||||
try {
|
try {
|
||||||
blockTime = await connection.getBlockTime(value.slot);
|
blockTime = await connection.getBlockTime(value.slot);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
Sentry.captureException(error, { tags: { slot: `${value.slot}` } });
|
||||||
"Failed to fetch block time for slot ",
|
|
||||||
value.slot,
|
|
||||||
":",
|
|
||||||
error
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let timestamp: Timestamp =
|
let timestamp: Timestamp =
|
||||||
blockTime !== null ? blockTime : "unavailable";
|
blockTime !== null ? blockTime : "unavailable";
|
||||||
|
@ -112,7 +108,7 @@ export async function fetchTransactionStatus(
|
||||||
data = { signature, info };
|
data = { signature, info };
|
||||||
fetchStatus = FetchStatus.Fetched;
|
fetchStatus = FetchStatus.Fetched;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch transaction status", error);
|
Sentry.captureException(error, { tags: { url } });
|
||||||
fetchStatus = FetchStatus.FetchFailed;
|
fetchStatus = FetchStatus.FetchFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue