Skip to content

Commit

Permalink
ECO-258: Log error to DD (#769)
Browse files Browse the repository at this point in the history
* Log error to DD in prod

* log error

* add context
  • Loading branch information
kirkas authored Aug 1, 2024
1 parent bd819d7 commit ceb87dc
Show file tree
Hide file tree
Showing 21 changed files with 214 additions and 92 deletions.
11 changes: 7 additions & 4 deletions apps/web/app/(basenames)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ErrorsProvider from 'apps/web/contexts/Errors';
import UsernameNav from 'apps/web/src/components/Layout/UsernameNav';

import type { Metadata } from 'next';
Expand Down Expand Up @@ -25,9 +26,11 @@ export default async function BasenameLayout({
children: React.ReactNode;
}) {
return (
<div className="max-w-screen flex min-h-screen flex-col">
<UsernameNav />
{children}
</div>
<ErrorsProvider context="basenames">
<div className="max-w-screen flex min-h-screen flex-col">
<UsernameNav />
{children}
</div>
</ErrorsProvider>
);
}
13 changes: 8 additions & 5 deletions apps/web/app/(basenames)/name/[username]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { redirect } from 'next/navigation';
import classNames from 'classnames';
import { BaseName } from '@coinbase/onchainkit/identity';
import UsernameProfile from 'apps/web/src/components/Basenames/UsernameProfile';
import ErrorsProvider from 'apps/web/contexts/Errors';

type UsernameProfileProps = {
params: { username: BaseName };
Expand Down Expand Up @@ -49,10 +50,12 @@ export default async function Username({ params }: UsernameProfileProps) {
);

return (
<ProfileProviders username={username} address={ensAddress}>
<main className={usernameProfilePageClasses}>
<UsernameProfile />
</main>
</ProfileProviders>
<ErrorsProvider context="profile">
<ProfileProviders username={username} address={ensAddress}>
<main className={usernameProfilePageClasses}>
<UsernameProfile />
</main>
</ProfileProviders>
</ErrorsProvider>
);
}
13 changes: 8 additions & 5 deletions apps/web/app/(basenames)/names/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import RegistrationProviders from 'apps/web/app/(basenames)/names/RegistrationProviders';
import ErrorsProvider from 'apps/web/contexts/Errors';
import RegistrationFlow from 'apps/web/src/components/Basenames/RegistrationFlow';
import type { Metadata } from 'next';
import { Suspense } from 'react';
Expand All @@ -16,10 +17,12 @@ export const metadata: Metadata = {

export default async function Page() {
return (
<RegistrationProviders>
<Suspense>
<RegistrationFlow />
</Suspense>
</RegistrationProviders>
<ErrorsProvider context="registration">
<RegistrationProviders>
<Suspense>
<RegistrationFlow />
</Suspense>
</RegistrationProviders>
</ErrorsProvider>
);
}
70 changes: 36 additions & 34 deletions apps/web/app/AppProviders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import { base, baseSepolia } from 'wagmi/chains';
import { cookieManagerConfig } from '../src/utils/cookieManagerConfig';
import ClientAnalyticsScript from 'apps/web/src/components/ClientAnalyticsScript/ClientAnalyticsScript';
import dynamic from 'next/dynamic';
import ErrorsProvider from 'apps/web/contexts/Errors';
import { isDevelopment } from 'apps/web/src/constants';

const DynamicCookieBannerWrapper = dynamic(
async () => import('apps/web/src/components/CookieBannerWrapper'),
Expand Down Expand Up @@ -102,42 +104,42 @@ export default function AppProviders({ children }: AppProvidersProps) {

const handleLogError = useCallback((err: Error) => console.error(err), []);

const isDevelopment = process.env.NODE_ENV === 'development';

useSprig(sprigEnvironmentId);

return (
<CookieManagerProvider
projectName="base_web"
locale="en"
region={Region.DEFAULT}
log={console.log}
onError={handleLogError}
onPreferenceChange={setTrackingPreference}
config={cookieManagerConfig}
>
<MotionConfig reducedMotion="user">
<ClientAnalyticsScript />
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<OnchainKitProvider
chain={isDevelopment ? baseSepolia : base}
apiKey={process.env.NEXT_PUBLIC_ONCHAINKIT_API_KEY}
>
<RainbowKitProvider modalSize="compact">
<TooltipProvider>
<ExperimentsProvider>
<>
{children}
<DynamicCookieBannerWrapper />
</>
</ExperimentsProvider>
</TooltipProvider>
</RainbowKitProvider>
</OnchainKitProvider>
</QueryClientProvider>
</WagmiProvider>
</MotionConfig>
</CookieManagerProvider>
<ErrorsProvider context="web">
<CookieManagerProvider
projectName="base_web"
locale="en"
region={Region.DEFAULT}
log={console.log}
onError={handleLogError}
onPreferenceChange={setTrackingPreference}
config={cookieManagerConfig}
>
<MotionConfig reducedMotion="user">
<ClientAnalyticsScript />
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<OnchainKitProvider
chain={isDevelopment ? baseSepolia : base}
apiKey={process.env.NEXT_PUBLIC_ONCHAINKIT_API_KEY}
>
<RainbowKitProvider modalSize="compact">
<TooltipProvider>
<ExperimentsProvider>
<>
{children}
<DynamicCookieBannerWrapper />
</>
</ExperimentsProvider>
</TooltipProvider>
</RainbowKitProvider>
</OnchainKitProvider>
</QueryClientProvider>
</WagmiProvider>
</MotionConfig>
</CookieManagerProvider>
</ErrorsProvider>
);
}
2 changes: 1 addition & 1 deletion apps/web/app/datadog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
'use client';

import { datadogRum } from '@datadog/browser-rum';
import { isDevelopment } from 'apps/web/src/constants';
import { useEffect } from 'react';

const nextPublicDatadogAppId = process.env.NEXT_PUBLIC_DATADOG_APP_ID ?? '';
const nextPublicDatadogClientToken = process.env.NEXT_PUBLIC_DATADOG_CLIENT_TOKEN ?? '';
const isDevelopment = process.env.NODE_ENV === 'development';

export default function DatadogInit() {
useEffect(() => {
Expand Down
57 changes: 57 additions & 0 deletions apps/web/contexts/Errors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
'use client';

import { datadogRum } from '@datadog/browser-rum';
import { isDevelopment } from 'apps/web/src/constants';
import { ReactNode, createContext, useCallback, useContext, useMemo } from 'react';

export type ErrorsContextProps = {
logError: (error: unknown, message: string) => void;
fullContext: string;
};

export const ErrorsContext = createContext<ErrorsContextProps>({
logError: function () {
return undefined;
},
fullContext: '',
});

export function useErrors() {
const context = useContext(ErrorsContext);
if (context === undefined) {
throw new Error('useErrors must be used within a ErrorsProvider');
}
return context;
}

type ErrorsProviderProps = {
children?: ReactNode;
context: string;
};

export default function ErrorsProvider({ children, context }: ErrorsProviderProps) {
const { fullContext: previousContext } = useErrors();

const fullContext = [previousContext, context].filter((c) => !!c).join('_');

const logError = useCallback(
(error: unknown, message: string) => {
if (isDevelopment) {
console.log('\n--------------------------------------');
console.info(`Error caught with message: "${message}"`);
console.error(error);
console.info(`Context: "${fullContext}"`);
console.log('--------------------------------------\n');
return;
}
datadogRum.addError(error, { context: fullContext, message: message });
},
[fullContext],
);

const values = useMemo(() => {
return { logError, context, fullContext };
}, [context, fullContext, logError]);

return <ErrorsContext.Provider value={values}>{children}</ErrorsContext.Provider>;
}
3 changes: 2 additions & 1 deletion apps/web/pages/api/basenames/[name]/assets/cardImage.svg.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { namehash } from 'viem';
import { getBasenamePublicClient } from 'apps/web/src/hooks/useBasenameChain';
import L2ResolverAbi from 'apps/web/src/abis/L2Resolver';
import { USERNAME_L2_RESOLVER_ADDRESSES } from 'apps/web/src/addresses/usernames';
import { isDevelopment } from 'apps/web/src/constants';

const emojiCache: Record<string, Promise<string>> = {};

Expand All @@ -33,7 +34,7 @@ export default async function handler(request: NextRequest) {
).then(async (res) => res.arrayBuffer());

const url = new URL(request.url);
const isDevelopment = process.env.NODE_ENV === 'development';

const username = url.searchParams.get('name') ?? 'yourname';
const domainName = isDevelopment ? `${url.protocol}//${url.host}` : 'https://www.base.org';
const profilePicture = getUserNamePicture(username);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { USERNAME_L2_RESOLVER_ADDRESSES } from 'apps/web/src/addresses/usernames
import L2ResolverAbi from 'apps/web/src/abis/L2Resolver';
import { base } from 'viem/chains';
import { getBasenamePublicClient } from 'apps/web/src/hooks/useBasenameChain';
import { isDevelopment } from 'apps/web/src/constants';

export const config = {
runtime: 'edge',
Expand All @@ -19,7 +20,6 @@ export default async function handler(request: NextRequest) {
).then(async (res) => res.arrayBuffer());

const url = new URL(request.url);
const isDevelopment = process.env.NODE_ENV === 'development';
const username = url.searchParams.get('name') ?? 'yourname';
const domainName = isDevelopment ? `${url.protocol}//${url.host}` : 'https://www.base.org';
const profilePicture = getUserNamePicture(username);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/pages/api/basenames/contract-uri.json.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isDevelopment } from 'apps/web/src/constants';
import { NextResponse } from 'next/server';
import { base } from 'viem/chains';

Expand All @@ -7,7 +8,6 @@ export const config = {

export default async function GET(request: Request) {
const url = new URL(request.url);
const isDevelopment = process.env.NODE_ENV === 'development';
const domainName = isDevelopment ? `${url.protocol}//${url.host}` : 'https://www.base.org';

const chainId = url.searchParams.get('chainId') ?? base.id;
Expand Down
3 changes: 2 additions & 1 deletion apps/web/pages/api/basenames/contract-uri.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isDevelopment } from 'apps/web/src/constants';
import { NextResponse } from 'next/server';
import { base } from 'viem/chains';

Expand All @@ -7,7 +8,7 @@ export const config = {

export default async function GET(request: Request) {
const url = new URL(request.url);
const isDevelopment = process.env.NODE_ENV === 'development';

const domainName = isDevelopment ? `${url.protocol}//${url.host}` : 'https://www.base.org';
const chainId = url.searchParams.get('chainId') ?? base.id;
if (!chainId) return NextResponse.json({ error: '406: chainId is missing' }, { status: 406 });
Expand Down
3 changes: 2 additions & 1 deletion apps/web/pages/api/basenames/metadata/[tokenId].ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { premintMapping } from 'apps/web/pages/api/basenames/metadata/premintsMapping';
import L2Resolver from 'apps/web/src/abis/L2Resolver';
import { USERNAME_L2_RESOLVER_ADDRESSES } from 'apps/web/src/addresses/usernames';
import { isDevelopment } from 'apps/web/src/constants';
import { getBasenamePublicClient } from 'apps/web/src/hooks/useBasenameChain';
import { USERNAME_DOMAINS } from 'apps/web/src/utils/usernames';
import { NextResponse } from 'next/server';
Expand All @@ -13,7 +14,7 @@ export const config = {

export default async function GET(request: Request) {
const url = new URL(request.url);
const isDevelopment = process.env.NODE_ENV === 'development';

const domainName = isDevelopment ? `${url.protocol}//${url.host}` : 'https://www.base.org';
let tokenId = url.searchParams.get('tokenId');
if (tokenId?.endsWith('.json')) tokenId = tokenId.slice(0, -5);
Expand Down
14 changes: 13 additions & 1 deletion apps/web/src/components/Basenames/RegistrationContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';
import { useAnalytics } from 'apps/web/contexts/Analytics';
import { useErrors } from 'apps/web/contexts/Errors';
import {
DiscountData,
findFirstValidDiscount,
Expand Down Expand Up @@ -113,6 +114,7 @@ export default function RegistrationProvider({ children }: RegistrationProviderP

// Analytics
const { logEventWithContext } = useAnalytics();
const { logError } = useErrors();

// Web3 data
const { address } = useAccount();
Expand Down Expand Up @@ -152,6 +154,7 @@ export default function RegistrationProvider({ children }: RegistrationProviderP
enabled: !!registerNameTransactionHash,
},
});

const [registerNameCallsBatchId, setRegisterNameCallsBatchId] = useState<string>('');

// The "correct" way to transition the UI would be to watch for call success, but this experimental
Expand All @@ -174,7 +177,9 @@ export default function RegistrationProvider({ children }: RegistrationProviderP
setRegistrationStep(RegistrationSteps.Success);
}
})
.catch(() => {});
.catch((error) => {
logError(error, 'Failed to refetch basename');
});
}, 1500);

const redirectToProfile = useCallback(() => {
Expand Down Expand Up @@ -232,6 +237,13 @@ export default function RegistrationProvider({ children }: RegistrationProviderP
logEventWithContext('selected_name', ActionType.change);
}, [logEventWithContext, selectedName]);

// Log error
useEffect(() => {
if (transactionError) {
logError(transactionError, 'Failed to fetch the transaction receipt');
}
}, [logError, transactionError]);

const values = useMemo(() => {
return {
searchInputFocused,
Expand Down
8 changes: 6 additions & 2 deletions apps/web/src/components/Basenames/RegistrationForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from '@heroicons/react/16/solid';
import { ConnectButton, useConnectModal } from '@rainbow-me/rainbowkit';
import { useAnalytics } from 'apps/web/contexts/Analytics';
import { useErrors } from 'apps/web/contexts/Errors';
import { useRegistration } from 'apps/web/src/components/Basenames/RegistrationContext';
import RegistrationLearnMoreModal from 'apps/web/src/components/Basenames/RegistrationLearnMoreModal';
import { Button, ButtonSizes, ButtonVariants } from 'apps/web/src/components/Button/Button';
Expand Down Expand Up @@ -50,6 +51,7 @@ export default function RegistrationForm() {
const chains = useChains();
const { openConnectModal } = useConnectModal();
const { logEventWithContext } = useAnalytics();
const { logError } = useErrors();
const { basenameChain } = useBasenameChain();
const { switchChain } = useSwitchChain();
const switchToIntendedNetwork = useCallback(
Expand Down Expand Up @@ -132,8 +134,10 @@ export default function RegistrationForm() {
const registerNameCallback = useCallback(() => {
registerName()
.then(() => {})
.catch(() => {});
}, [registerName]);
.catch((error) => {
logError(error, 'Failed to register name');
});
}, [logError, registerName]);

const { data: balance } = useBalance({ address, chainId: connectedChain?.id });
const insufficientBalanceToRegister =
Expand Down
Loading

0 comments on commit ceb87dc

Please sign in to comment.