From efa62aed8a775325bbb9f3a709924224b05f4232 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 16 Aug 2023 19:29:26 +0200 Subject: [PATCH 1/2] feat: debug instrumentation --- web/.gitignore | 4 +++ web/package.json | 2 +- web/scripts/gitInfo.js | 40 ++++++++++++++++++++++++ web/scripts/runEnv.sh | 1 + web/src/app.tsx | 7 +++-- web/src/consts/index.ts | 8 +++++ web/src/hooks/queries/usePhase.ts | 17 +++++++++++ web/src/index.tsx | 19 ++---------- web/src/layout/Footer/index.tsx | 7 +---- web/src/layout/Header/navbar/Debug.tsx | 42 ++++++++++++++++++++++++++ web/src/layout/Header/navbar/index.tsx | 3 ++ web/src/utils/sentry.ts | 39 ++++++++++++++++++++++++ 12 files changed, 163 insertions(+), 26 deletions(-) create mode 100644 web/scripts/gitInfo.js create mode 100644 web/src/hooks/queries/usePhase.ts create mode 100644 web/src/layout/Header/navbar/Debug.tsx create mode 100644 web/src/utils/sentry.ts diff --git a/web/.gitignore b/web/.gitignore index e3d0ce574..15391189f 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -22,9 +22,13 @@ parcel-bundle-reports .env.development.local .env.test.local .env.production.local + +# generated code src/hooks/contracts src/graphql +generatedGitInfo.json +# logs npm-debug.log* yarn-debug.log* yarn-error.log* diff --git a/web/package.json b/web/package.json index ae2a2e903..ae193c00b 100644 --- a/web/package.json +++ b/web/package.json @@ -27,7 +27,7 @@ "start": "scripts/runEnv.sh devnet 'yarn generate && parcel'", "start-testnet": "scripts/runEnv.sh testnet 'yarn generate && parcel'", "start-local": "scripts/runEnv.sh local 'yarn generate && parcel'", - "build": "yarn generate && parcel build", + "build": "node scripts/gitInfo.js && yarn generate && parcel build", "build-devnet": "scripts/runEnv.sh devnet 'yarn generate && parcel build'", "build-testnet": "scripts/runEnv.sh testnet 'yarn generate && parcel build'", "check-style": "eslint 'src/**/*.{js,jsx,ts,tsx}'", diff --git a/web/scripts/gitInfo.js b/web/scripts/gitInfo.js new file mode 100644 index 000000000..c25cb500c --- /dev/null +++ b/web/scripts/gitInfo.js @@ -0,0 +1,40 @@ +/* eslint-disable max-len */ +const fs = require("fs"); +const path = require("path"); +const { execSync } = require("child_process"); +const packageJson = require("../package.json"); + +const execSyncWrapper = (command) => { + let stdout = null; + try { + stdout = execSync(command).toString().trim(); + } catch (error) { + console.error(error); + } + return stdout; +}; + +const main = () => { + let version = packageJson.version; + let gitCommitHash = execSyncWrapper("git rev-parse HEAD"); + let gitCommitShortHash = execSyncWrapper("git rev-parse --short=7 HEAD"); + let gitBranch = execSyncWrapper("git rev-parse --abbrev-ref HEAD"); + let clean = + execSyncWrapper(`[ -z "$(git status --short | ggrep -v '^??')" ] && echo clean || echo dirty`) === "clean"; + + const obj = { + version, + gitCommitHash, + gitCommitShortHash, + gitBranch, + clean, + }; + + const filePath = path.resolve("src", "generatedGitInfo.json"); + const fileContents = JSON.stringify(obj, null, 2); + + fs.writeFileSync(filePath, fileContents); + // console.log(`Wrote the following contents to ${filePath}\n${fileContents}`); +}; + +main(); diff --git a/web/scripts/runEnv.sh b/web/scripts/runEnv.sh index e6636724a..a64063790 100755 --- a/web/scripts/runEnv.sh +++ b/web/scripts/runEnv.sh @@ -17,6 +17,7 @@ if [[ ! " ${valid_deployments[@]} " =~ " ${deployment} " ]]; then exit 1 fi +node $SCRIPT_DIR/gitInfo.js . $SCRIPT_DIR/../.env.${deployment}.public . $SCRIPT_DIR/../.env.${deployment} eval "$commands" diff --git a/web/src/app.tsx b/web/src/app.tsx index a18340484..f6a705ac6 100644 --- a/web/src/app.tsx +++ b/web/src/app.tsx @@ -1,5 +1,6 @@ import React from "react"; -import { Routes, Route } from "react-router-dom"; +import { Route } from "react-router-dom"; +import { SentryRoutes } from "./utils/sentry"; import "react-loading-skeleton/dist/skeleton.css"; import "react-toastify/dist/ReactToastify.css"; import Web3Provider from "context/Web3Provider"; @@ -19,7 +20,7 @@ const App: React.FC = () => { - + }> } /> } /> @@ -28,7 +29,7 @@ const App: React.FC = () => { } /> Justice not found here ¯\_( ͡° ͜ʖ ͡°)_/¯} /> - + diff --git a/web/src/consts/index.ts b/web/src/consts/index.ts index 22713af5b..82f965019 100644 --- a/web/src/consts/index.ts +++ b/web/src/consts/index.ts @@ -1,3 +1,5 @@ +import { version, gitCommitHash, gitCommitShortHash, gitBranch, clean } from "../generatedGitInfo.json"; + export const ONE_BASIS_POINT = 10000n; export const KLEROS_CONTRACT_ADDRESS = "ethereum:0x93ed3fbe21207ec2e8f2d3c3de6e058cb73bc04d"; @@ -5,3 +7,9 @@ export const WETH_CONTRACT_ADDRESS = "ethereum:0xC02aaA39b223FE8D0A0e5C4F27eAD90 export const PNK_FAUCET_CONTRACT_ADDRESS = "0x05648Ee14941630a649082e0dA5cb80D29cC9002"; export const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY || "https://cdn.kleros.link"; + +export const GIT_BRANCH = gitBranch; +export const GIT_HASH = gitCommitShortHash; +export const GIT_DIRTY = clean ? "" : "-dirty"; +export const GIT_URL = `https://github.com/kleros/kleros-v2/tree/${gitCommitHash}/web`; +export const RELEASE_VERSION = version; diff --git a/web/src/hooks/queries/usePhase.ts b/web/src/hooks/queries/usePhase.ts new file mode 100644 index 000000000..9d9102790 --- /dev/null +++ b/web/src/hooks/queries/usePhase.ts @@ -0,0 +1,17 @@ +import { useQuery } from "@tanstack/react-query"; +import { getSortitionModule } from "hooks/contracts/generated"; +import { isUndefined } from "utils/index"; + +export const usePhase = () => { + const sortitionModule = getSortitionModule({}); + const isEnabled = !isUndefined(sortitionModule); + return useQuery({ + queryKey: [`Phase`], + enabled: isEnabled, + staleTime: 20 * 1000, // 20 seconds + queryFn: async () => { + if (!sortitionModule) return; + return await sortitionModule.read.phase(); + }, + }); +}; diff --git a/web/src/index.tsx b/web/src/index.tsx index a5f6a2bb2..a8678fb09 100644 --- a/web/src/index.tsx +++ b/web/src/index.tsx @@ -1,29 +1,16 @@ import React from "react"; import { createRoot } from "react-dom/client"; -import * as Sentry from "@sentry/react"; -import { BrowserTracing } from "@sentry/tracing"; import App from "./app"; import Modal from "react-modal"; -import { HashRouter as Router } from "react-router-dom"; - -Sentry.init({ - dsn: process.env.REACT_APP_SENTRY_ENDPOINT, - environment: process.env.REACT_APP_CONTEXT, - integrations: [new BrowserTracing()], - - // Set tracesSampleRate to 1.0 to capture 100% - // of transactions for performance monitoring. - // We recommend adjusting this value in production - tracesSampleRate: 1.0, -}); +import { HashRouter } from "react-router-dom"; const container = document.getElementById("app"); Modal.setAppElement(container!); const root = createRoot(container!); root.render( - + - + ); diff --git a/web/src/layout/Footer/index.tsx b/web/src/layout/Footer/index.tsx index ee84ed8e9..fe5bc92d8 100644 --- a/web/src/layout/Footer/index.tsx +++ b/web/src/layout/Footer/index.tsx @@ -36,12 +36,7 @@ const Container = styled.div` `; const SecuredByKleros: React.FC = () => ( - + ); diff --git a/web/src/layout/Header/navbar/Debug.tsx b/web/src/layout/Header/navbar/Debug.tsx new file mode 100644 index 000000000..a6fe21fbb --- /dev/null +++ b/web/src/layout/Header/navbar/Debug.tsx @@ -0,0 +1,42 @@ +import React from "react"; +import styled from "styled-components"; +import { GIT_BRANCH, GIT_DIRTY, GIT_HASH, GIT_URL, RELEASE_VERSION } from "../../../consts"; +import { usePhase } from "~src/hooks/queries/usePhase"; + +const Container = styled.div` + label, + a { + font-family: "Roboto Mono", monospace; + line-height: 10px; + font-size: 10px; + color: ${({ theme }) => theme.stroke}; + } +`; + +const Version = () => ( + +); + +const Phase = () => { + const { data: phase } = usePhase(); + return ; +}; + +const Debug: React.FC = () => { + return ( + + + + + + ); +}; + +export default Debug; diff --git a/web/src/layout/Header/navbar/index.tsx b/web/src/layout/Header/navbar/index.tsx index fa778723b..684a36ebf 100644 --- a/web/src/layout/Header/navbar/index.tsx +++ b/web/src/layout/Header/navbar/index.tsx @@ -8,6 +8,7 @@ import { useOpenContext } from "../index"; import DappList from "./DappList"; import Explore from "./Explore"; import Menu from "./Menu"; +import Debug from "./Debug"; const Container = styled.div<{ isOpen: boolean }>` position: absolute; @@ -54,6 +55,8 @@ const NavBar: React.FC = () => {
+
+ ); }; diff --git a/web/src/utils/sentry.ts b/web/src/utils/sentry.ts new file mode 100644 index 000000000..ef0472d54 --- /dev/null +++ b/web/src/utils/sentry.ts @@ -0,0 +1,39 @@ +import React from "react"; +import * as Sentry from "@sentry/react"; +import { Routes, createRoutesFromChildren, matchRoutes, useLocation, useNavigationType } from "react-router-dom"; +import { GIT_DIRTY, GIT_HASH, RELEASE_VERSION } from "../consts"; + +Sentry.init({ + dsn: process.env.REACT_APP_SENTRY_ENDPOINT, + environment: process.env.REACT_APP_CONTEXT, + release: `court-v2@${RELEASE_VERSION}-${GIT_HASH}${GIT_DIRTY}`, + integrations: [ + new Sentry.BrowserProfilingIntegration(), + new Sentry.BrowserTracing({ + routingInstrumentation: Sentry.reactRouterV6Instrumentation( + React.useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes + ), + }), + ], + + // Set tracesSampleRate to 1.0 to capture 100% + // of transactions for performance monitoring. + // We recommend adjusting this value in production + tracesSampleRate: 1.0, + + // Set `tracePropagationTargets` to control for which URLs distributed tracing should be enabled + tracePropagationTargets: ["localhost", /^https:\/\/.*--kleros-v2\.netlify\.app/], + + // Set profilesSampleRate to 1.0 to profile every transaction. + // Since profilesSampleRate is relative to tracesSampleRate, + // the final profiling rate can be computed as tracesSampleRate * profilesSampleRate + // For example, a tracesSampleRate of 0.5 and profilesSampleRate of 0.5 would + // results in 25% of transactions being profiled (0.5*0.5=0.25) + profilesSampleRate: 1.0, +}); + +export const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes); From e7dc6aa728f91293241d563ce24de15e292bc056 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 16 Aug 2023 22:31:06 +0200 Subject: [PATCH 2/2] feat: added git tags --- web/scripts/gitInfo.js | 3 ++- web/src/consts/index.ts | 3 ++- web/src/hooks/queries/usePhase.ts | 2 +- web/src/layout/Header/navbar/Debug.tsx | 12 ++++++------ 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/web/scripts/gitInfo.js b/web/scripts/gitInfo.js index c25cb500c..94920da5e 100644 --- a/web/scripts/gitInfo.js +++ b/web/scripts/gitInfo.js @@ -19,6 +19,7 @@ const main = () => { let gitCommitHash = execSyncWrapper("git rev-parse HEAD"); let gitCommitShortHash = execSyncWrapper("git rev-parse --short=7 HEAD"); let gitBranch = execSyncWrapper("git rev-parse --abbrev-ref HEAD"); + let gitTags = execSyncWrapper("git tag --points-at HEAD --omit-empty | tr '\n' ',' | sed 's/,$//'"); let clean = execSyncWrapper(`[ -z "$(git status --short | ggrep -v '^??')" ] && echo clean || echo dirty`) === "clean"; @@ -27,6 +28,7 @@ const main = () => { gitCommitHash, gitCommitShortHash, gitBranch, + gitTags, clean, }; @@ -34,7 +36,6 @@ const main = () => { const fileContents = JSON.stringify(obj, null, 2); fs.writeFileSync(filePath, fileContents); - // console.log(`Wrote the following contents to ${filePath}\n${fileContents}`); }; main(); diff --git a/web/src/consts/index.ts b/web/src/consts/index.ts index 82f965019..551c10b0f 100644 --- a/web/src/consts/index.ts +++ b/web/src/consts/index.ts @@ -1,4 +1,4 @@ -import { version, gitCommitHash, gitCommitShortHash, gitBranch, clean } from "../generatedGitInfo.json"; +import { version, gitCommitHash, gitCommitShortHash, gitBranch, gitTags, clean } from "../generatedGitInfo.json"; export const ONE_BASIS_POINT = 10000n; @@ -9,6 +9,7 @@ export const PNK_FAUCET_CONTRACT_ADDRESS = "0x05648Ee14941630a649082e0dA5cb80D29 export const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY || "https://cdn.kleros.link"; export const GIT_BRANCH = gitBranch; +export const GIT_TAGS = gitTags; export const GIT_HASH = gitCommitShortHash; export const GIT_DIRTY = clean ? "" : "-dirty"; export const GIT_URL = `https://github.com/kleros/kleros-v2/tree/${gitCommitHash}/web`; diff --git a/web/src/hooks/queries/usePhase.ts b/web/src/hooks/queries/usePhase.ts index 9d9102790..5a33bba46 100644 --- a/web/src/hooks/queries/usePhase.ts +++ b/web/src/hooks/queries/usePhase.ts @@ -8,7 +8,7 @@ export const usePhase = () => { return useQuery({ queryKey: [`Phase`], enabled: isEnabled, - staleTime: 20 * 1000, // 20 seconds + staleTime: Infinity, queryFn: async () => { if (!sortitionModule) return; return await sortitionModule.read.phase(); diff --git a/web/src/layout/Header/navbar/Debug.tsx b/web/src/layout/Header/navbar/Debug.tsx index a6fe21fbb..b7ee7c131 100644 --- a/web/src/layout/Header/navbar/Debug.tsx +++ b/web/src/layout/Header/navbar/Debug.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled from "styled-components"; -import { GIT_BRANCH, GIT_DIRTY, GIT_HASH, GIT_URL, RELEASE_VERSION } from "../../../consts"; +import { GIT_BRANCH, GIT_DIRTY, GIT_HASH, GIT_TAGS, GIT_URL, RELEASE_VERSION } from "../../../consts"; import { usePhase } from "~src/hooks/queries/usePhase"; const Container = styled.div` @@ -18,22 +18,22 @@ const Version = () => ( v{RELEASE_VERSION}{" "} #{GIT_HASH} - {" "} - {GIT_BRANCH} - {GIT_DIRTY && " dirty"} + + {GIT_BRANCH && GIT_BRANCH !== "HEAD" && ` ${GIT_BRANCH}`} + {GIT_TAGS && ` ${GIT_TAGS}`} + {GIT_DIRTY && ` dirty`} ); const Phase = () => { const { data: phase } = usePhase(); - return ; + return phase && ; }; const Debug: React.FC = () => { return ( - );