From 6f29619ec5042cdfebdb195f1b5baf0a767c3e73 Mon Sep 17 00:00:00 2001 From: WRadoslaw <92513933+WRadoslaw@users.noreply.github.com> Date: Wed, 9 Aug 2023 13:42:54 +0200 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=94=A8=20Sentry=20overload=20v2=20(#4?= =?UTF-8?q?600)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove error link * Handle axios errors * Fix nft carousel * Create sentry filter for apollo server errors * Fix video DOMException error * Adjust deps * Transfer sentry plugin to the end * Transfer flag --- packages/atlas/src/api/client/index.ts | 35 +---------------- .../NftCarousel/MarketplaceCarousel.tsx | 2 +- .../NftCarouselDetails.tsx | 1 - .../BackgroundVideoPlayer.tsx | 36 +++++++++++------ .../atlas/src/hooks/useTimeMismatchWarning.ts | 39 +++++++++++-------- packages/atlas/src/utils/logs/sentry.ts | 8 ++++ .../studio/MyVideosView/MyVideosView.tsx | 7 +++- packages/atlas/vite.config.ts | 12 +++--- 8 files changed, 67 insertions(+), 73 deletions(-) diff --git a/packages/atlas/src/api/client/index.ts b/packages/atlas/src/api/client/index.ts index ea9ccf3fe2..b4c2b572a9 100644 --- a/packages/atlas/src/api/client/index.ts +++ b/packages/atlas/src/api/client/index.ts @@ -1,12 +1,10 @@ import { ApolloClient, ApolloLink, FetchResult, HttpLink, Observable, split } from '@apollo/client' -import { onError } from '@apollo/client/link/error' import { GraphQLWsLink } from '@apollo/client/link/subscriptions' import { getMainDefinition } from '@apollo/client/utilities' import { createClient } from 'graphql-ws' import { ORION_GRAPHQL_URL, QUERY_NODE_GRAPHQL_SUBSCRIPTION_URL } from '@/config/env' import { useUserLocationStore } from '@/providers/userLocation' -import { SentryLogger } from '@/utils/logs' import { cache } from './cache' @@ -25,33 +23,6 @@ const delayLink = new ApolloLink((operation, forward) => { }) }) -const errorLink = onError(({ graphQLErrors, networkError, operation, forward, response }) => { - if (graphQLErrors?.some(({ message }) => message === 'Unauthorized')) { - forward(operation) - return - } - if (networkError?.message === 'Response not successful: Received status code 400') { - forward(operation) - return - } - - SentryLogger.error( - 'Apollo Error', - 'Error Link', - { - graphQLErrors, - networkError, - }, - { - data: { - operation: JSON.stringify(operation), - response: JSON.stringify(response), - }, - } - ) - forward(operation) -}) - export const createApolloClient = () => { const subscriptionLink = new GraphQLWsLink( createClient({ @@ -60,11 +31,7 @@ export const createApolloClient = () => { }) ) - const orionLink = ApolloLink.from([ - errorLink, - delayLink, - new HttpLink({ uri: ORION_GRAPHQL_URL, credentials: 'include' }), - ]) + const orionLink = ApolloLink.from([delayLink, new HttpLink({ uri: ORION_GRAPHQL_URL, credentials: 'include' })]) const operationSplitLink = split( ({ query, setContext }) => { diff --git a/packages/atlas/src/components/NftCarousel/MarketplaceCarousel.tsx b/packages/atlas/src/components/NftCarousel/MarketplaceCarousel.tsx index cd4aec2127..2c028db2bb 100644 --- a/packages/atlas/src/components/NftCarousel/MarketplaceCarousel.tsx +++ b/packages/atlas/src/components/NftCarousel/MarketplaceCarousel.tsx @@ -48,7 +48,7 @@ export const MarketplaceCarousel = ({ carouselProps, isLoading, ...rest }: Marke const handlePrevSlide = useCallback( (slideIndex: string, nft?: GetFeaturedNftsVideosQuery['ownedNfts'][number]) => { trackNFTCarouselPrev(slideIndex, nft?.id) - glider?.slideNext() + glider?.slidePrev() }, [glider, trackNFTCarouselPrev] ) diff --git a/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/NftCarouselDetails.tsx b/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/NftCarouselDetails.tsx index 0572ece26f..b9b6a10b5f 100644 --- a/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/NftCarouselDetails.tsx +++ b/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/NftCarouselDetails.tsx @@ -162,7 +162,6 @@ export const NftCarouselDetails = ({ setIsPaused(true)} diff --git a/packages/atlas/src/components/_video/BackgroundVideoPlayer/BackgroundVideoPlayer.tsx b/packages/atlas/src/components/_video/BackgroundVideoPlayer/BackgroundVideoPlayer.tsx index 65ca1ca418..cd13f486c3 100644 --- a/packages/atlas/src/components/_video/BackgroundVideoPlayer/BackgroundVideoPlayer.tsx +++ b/packages/atlas/src/components/_video/BackgroundVideoPlayer/BackgroundVideoPlayer.tsx @@ -1,4 +1,4 @@ -import { FC, SyntheticEvent, VideoHTMLAttributes, useEffect, useRef, useState } from 'react' +import { FC, SyntheticEvent, VideoHTMLAttributes, useCallback, useEffect, useRef, useState } from 'react' import { CSSTransition } from 'react-transition-group' import { SvgActionPause, SvgActionPlay, SvgActionSoundOff, SvgActionSoundOn } from '@/assets/icons' @@ -39,6 +39,7 @@ export const BackgroundVideoPlayer: FC = ({ const [isPosterVisible, setIsPosterVisible] = useState(true) const [isPlaying, setIsPlaying] = useState(autoPlay) const [isMuted, setIsMuted] = useState(true) + const [canPlay, setCanPlay] = useState(false) const initialRender = useRef(true) useEffect(() => { @@ -50,27 +51,34 @@ export const BackgroundVideoPlayer: FC = ({ } }, [autoPlay, playing]) - const playVideo = () => { - videoRef.current?.play().then(() => { - setIsPlaying(true) - setIsPosterVisible(false) - }) - } + const playVideo = useCallback(() => { + if (videoRef.current && canPlay) { + videoRef.current + .play() + .then(() => { + setIsPlaying(true) + setIsPosterVisible(false) + }) + .catch((error) => { + ConsoleLogger.error('Failed to play video', error) + }) + } + }, [canPlay]) - const pauseVideo = () => { - if (videoRef.current) { + const pauseVideo = useCallback(() => { + if (videoRef.current && canPlay) { videoRef.current.pause() setIsPlaying(false) if (videoRef.current?.currentTime && videoRef.current.currentTime < 1) { setIsPosterVisible(true) } } - } + }, [canPlay]) useEffect(() => { // show poster again when src changes setIsPosterVisible(true) - if (!videoRef.current || playing === undefined) { + if (!videoRef.current || playing === undefined || !canPlay) { return } if (playing) { @@ -78,7 +86,7 @@ export const BackgroundVideoPlayer: FC = ({ } else { pauseVideo() } - }, [handleActions, playing, src]) + }, [canPlay, handleActions, pauseVideo, playVideo, playing, src]) const handlePlay = (e: SyntheticEvent) => { setIsPlaying(true) @@ -118,6 +126,10 @@ export const BackgroundVideoPlayer: FC = ({ ref={videoRef} onEnded={handleEnded} onPlay={handlePlay} + onCanPlay={(event) => { + setCanPlay(true) + props.onCanPlay?.(event) + }} resolvedPosterUrls={poster} {...props} muted={handleActions ? isMuted : props.muted} diff --git a/packages/atlas/src/hooks/useTimeMismatchWarning.ts b/packages/atlas/src/hooks/useTimeMismatchWarning.ts index 3c028853ef..1accb75e36 100644 --- a/packages/atlas/src/hooks/useTimeMismatchWarning.ts +++ b/packages/atlas/src/hooks/useTimeMismatchWarning.ts @@ -3,7 +3,7 @@ import { useEffect } from 'react' import { axiosInstance } from '@/api/axios' import { usePersonalDataStore } from '@/providers/personalData' import { useSnackbar } from '@/providers/snackbars' -import { SentryLogger } from '@/utils/logs' +import { ConsoleLogger, SentryLogger } from '@/utils/logs' const TIME_MISMATCH_ID = 'time-mismatch' @@ -16,22 +16,27 @@ export const useTimeMismatchWarning = () => { useEffect(() => { if (!timeMismatchDisabled) { - axiosInstance.get('https://worldtimeapi.org/api/ip').then((response) => { - const serverTime = response.data.unixtime * 1000 - const clientTime = Date.now() - const timeDiff = serverTime - clientTime - if (Math.abs(timeDiff) > 1000 * 60 * 5) { - displaySnackbar({ - title: `Time mismatch detected`, - description: `Set your system time to automatic matching your actual timezone to prevent errors with transactions.`, - iconType: 'warning', - }) - SentryLogger.error( - `Time mismatch detected. Server time: ${serverTime}, client time: ${clientTime}`, - 'UseTimeMismatchWarning' - ) - } - }) + axiosInstance + .get('https://worldtimeapi.org/api/ip') + .then((response) => { + const serverTime = response.data.unixtime * 1000 + const clientTime = Date.now() + const timeDiff = serverTime - clientTime + if (Math.abs(timeDiff) > 1000 * 60 * 5) { + displaySnackbar({ + title: `Time mismatch detected`, + description: `Set your system time to automatic matching your actual timezone to prevent errors with transactions.`, + iconType: 'warning', + }) + SentryLogger.error( + `Time mismatch detected. Server time: ${serverTime}, client time: ${clientTime}`, + 'UseTimeMismatchWarning' + ) + } + }) + .catch(() => { + ConsoleLogger.error('Failed to fetch global timestamp') + }) } updateDismissedMessages(TIME_MISMATCH_ID) }, [displaySnackbar, timeMismatchDisabled, updateDismissedMessages]) diff --git a/packages/atlas/src/utils/logs/sentry.ts b/packages/atlas/src/utils/logs/sentry.ts index 3106c364c4..5e4f61dd19 100644 --- a/packages/atlas/src/utils/logs/sentry.ts +++ b/packages/atlas/src/utils/logs/sentry.ts @@ -1,3 +1,4 @@ +import { ApolloError } from '@apollo/client' import * as Sentry from '@sentry/react' import { Replay, Severity, SeverityLevel } from '@sentry/react' @@ -33,6 +34,13 @@ class _SentryLogger { // This sets the sample rate to be 0%, so we'll only use manually recorded replays replaysSessionSampleRate: 0, replaysOnErrorSampleRate: 0, + beforeSend: (event, hint) => { + if ('message' in (hint.originalException as ApolloError)) { + const error = hint.originalException as ApolloError + return error.message.includes('code 400') ? null : error + } + return event + }, }) this.replay = new Sentry.Replay({ sessionSampleRate: 0, errorSampleRate: 0 }) this.initialized = true diff --git a/packages/atlas/src/views/studio/MyVideosView/MyVideosView.tsx b/packages/atlas/src/views/studio/MyVideosView/MyVideosView.tsx index 777e36082a..4f1f5cb75d 100644 --- a/packages/atlas/src/views/studio/MyVideosView/MyVideosView.tsx +++ b/packages/atlas/src/views/studio/MyVideosView/MyVideosView.tsx @@ -31,7 +31,7 @@ import { useAuthorizedUser } from '@/providers/user/user.hooks' import { useVideoWorkspace } from '@/providers/videoWorkspace' import { sizes } from '@/styles' import { createPlaceholderData } from '@/utils/data' -import { SentryLogger } from '@/utils/logs' +import { ConsoleLogger, SentryLogger } from '@/utils/logs' import { useGetYppSyncedChannels } from '@/views/global/YppLandingView/useGetYppSyncedChannels' import { YppVideoDto } from '@/views/studio/MyVideosView/MyVideosView.types' @@ -72,7 +72,10 @@ export const MyVideosView = () => { const { isLoading: isCurrentlyUploadedVideoIdsLoading, data: yppDAta } = useQuery( `ypp-ba-videos-${channelId}`, - () => axiosInstance.get(`${YOUTUBE_BACKEND_URL}/channels/${channelId}/videos`), + () => + axiosInstance + .get(`${YOUTUBE_BACKEND_URL}/channels/${channelId}/videos`) + .catch(() => ConsoleLogger.error('Failed to fetch YPP videos from channel')), { enabled: !!channelId && !!YOUTUBE_BACKEND_URL, retry: 1, diff --git a/packages/atlas/vite.config.ts b/packages/atlas/vite.config.ts index cd300addfe..5f9f88301e 100644 --- a/packages/atlas/vite.config.ts +++ b/packages/atlas/vite.config.ts @@ -24,10 +24,10 @@ export default defineConfig(({ mode }) => { build: { target: ['chrome87', 'edge88', 'es2020', 'firefox78', 'safari14'], emptyOutDir: true, + sourcemap: true, outDir: path.resolve(__dirname, 'dist'), rollupOptions: { output: { - sourcemap: true, sourcemapIgnoreList: (relativeSourcePath) => { // will ignore-list all files with node_modules in their paths return relativeSourcePath.includes('node_modules') @@ -76,11 +76,6 @@ export default defineConfig(({ mode }) => { EmbeddedFallbackPlugin, OptimizePlugin, ViteYaml(), - sentryVitePlugin({ - authToken: env.VITE_SENTRY_AUTH_TOKEN, - org: 'jsgenesis', - project: 'atlas', - }), react({ exclude: /\.stories\.[tj]sx?$/, }), @@ -104,6 +99,11 @@ export default defineConfig(({ mode }) => { }), enforce: 'post', }, + sentryVitePlugin({ + authToken: env.VITE_SENTRY_AUTH_TOKEN, + org: 'jsgenesis', + project: 'atlas', + }), ], resolve: { alias: { From eb9ed7424d78b5d7b48d486e92748789047d2c7a Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 9 Aug 2023 14:26:52 +0200 Subject: [PATCH 2/2] changelog and version bump --- CHANGELOG.md | 6 ++++++ packages/atlas/package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88aaa1ee3d..8aaadc9db0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.4.1] - 2023-08-09 + +### Fixed + +- Fixed sentry sourcemaps and removed useless events + ## [4.4.0] - 2023-08-08 ### Added diff --git a/packages/atlas/package.json b/packages/atlas/package.json index 70c7870789..da0d201a7d 100644 --- a/packages/atlas/package.json +++ b/packages/atlas/package.json @@ -1,7 +1,7 @@ { "name": "@joystream/atlas", "description": "UI for consuming Joystream - a user governed video platform", - "version": "4.4.0", + "version": "4.4.1", "license": "GPL-3.0", "scripts": { "start": "vite",