Enrich fatal HLS errors in Sentry
This commit is contained in:
@@ -27,8 +27,22 @@ export class VideoNotFoundError extends Error {
|
|||||||
*/
|
*/
|
||||||
export class HLSFatalError extends Error {
|
export class HLSFatalError extends Error {
|
||||||
detail: string
|
detail: string
|
||||||
constructor(detail: string, cause: Error) {
|
type: string
|
||||||
|
diagnostics: Record<string, unknown>
|
||||||
|
constructor({
|
||||||
|
detail,
|
||||||
|
type,
|
||||||
|
cause,
|
||||||
|
diagnostics,
|
||||||
|
}: {
|
||||||
|
detail: string
|
||||||
|
type: string
|
||||||
|
cause: Error
|
||||||
|
diagnostics: Record<string, unknown>
|
||||||
|
}) {
|
||||||
super(cause.message, {cause})
|
super(cause.message, {cause})
|
||||||
this.detail = detail
|
this.detail = detail
|
||||||
|
this.type = type
|
||||||
|
this.diagnostics = diagnostics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -308,7 +308,53 @@ function useHLS({
|
|||||||
) {
|
) {
|
||||||
setError(new VideoNotFoundError())
|
setError(new VideoNotFoundError())
|
||||||
} else {
|
} else {
|
||||||
setError(new HLSFatalError(data.details, data.error))
|
const video = videoRef.current
|
||||||
|
const mediaError = video?.error
|
||||||
|
setError(
|
||||||
|
new HLSFatalError({
|
||||||
|
detail: data.details,
|
||||||
|
type: data.type,
|
||||||
|
cause: data.error,
|
||||||
|
diagnostics: {
|
||||||
|
hlsError: {
|
||||||
|
detail: data.details,
|
||||||
|
type: data.type,
|
||||||
|
sourceBufferName: data.sourceBufferName,
|
||||||
|
parent: data.parent,
|
||||||
|
reason: data.reason,
|
||||||
|
errorName: data.error.name,
|
||||||
|
errorCode: (data.error as DOMException).code,
|
||||||
|
},
|
||||||
|
fragment: data.frag
|
||||||
|
? {
|
||||||
|
sn: data.frag.sn,
|
||||||
|
level: data.frag.level,
|
||||||
|
type: data.frag.type,
|
||||||
|
start: data.frag.start,
|
||||||
|
duration: data.frag.duration,
|
||||||
|
cc: data.frag.cc,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
media: video
|
||||||
|
? {
|
||||||
|
errorCode: mediaError?.code,
|
||||||
|
errorMessage: mediaError?.message,
|
||||||
|
readyState: video.readyState,
|
||||||
|
networkState: video.networkState,
|
||||||
|
currentTime: video.currentTime,
|
||||||
|
paused: video.paused,
|
||||||
|
ended: video.ended,
|
||||||
|
seeking: video.seeking,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
lifecycle: {
|
||||||
|
documentVisibility: document.visibilityState,
|
||||||
|
hlsIsCurrent: hlsRef.current === hls,
|
||||||
|
},
|
||||||
|
playlist,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error(data.error)
|
console.error(data.error)
|
||||||
|
|||||||
@@ -82,6 +82,16 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
|
|||||||
),
|
),
|
||||||
[key, embed],
|
[key, embed],
|
||||||
)
|
)
|
||||||
|
const getErrorMetadata = useCallback((error: Error) => {
|
||||||
|
if (!(error instanceof HLSFatalError)) return {}
|
||||||
|
return {
|
||||||
|
tags: {
|
||||||
|
hls_error_detail: error.detail,
|
||||||
|
hls_error_type: error.type,
|
||||||
|
},
|
||||||
|
hls: error.diagnostics,
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
let aspectRatio: number | undefined
|
let aspectRatio: number | undefined
|
||||||
const dims = embed.aspectRatio
|
const dims = embed.aspectRatio
|
||||||
@@ -158,7 +168,10 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) {
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<ErrorBoundary renderError={renderError} key={key}>
|
<ErrorBoundary
|
||||||
|
renderError={renderError}
|
||||||
|
getErrorMetadata={getErrorMetadata}
|
||||||
|
key={key}>
|
||||||
<OnlyNearScreen>
|
<OnlyNearScreen>
|
||||||
<VideoEmbedInnerWeb
|
<VideoEmbedInnerWeb
|
||||||
embed={embed}
|
embed={embed}
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import {msg} from '@lingui/core/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
|
import {type Metadata} from '#/logger/types'
|
||||||
import {ErrorScreen} from './error/ErrorScreen'
|
import {ErrorScreen} from './error/ErrorScreen'
|
||||||
import {CenteredView} from './Views'
|
import {CenteredView} from './Views'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children?: ReactNode
|
children?: ReactNode
|
||||||
renderError?: (error: any) => ReactNode
|
renderError?: (error: any) => ReactNode
|
||||||
|
getErrorMetadata?: (error: Error) => Metadata
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,7 +31,10 @@ export class ErrorBoundary extends Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||||
logger.error(error, {errorInfo})
|
logger.error(error, {
|
||||||
|
errorInfo,
|
||||||
|
...this.props.getErrorMetadata?.(error),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
|
|||||||
Reference in New Issue
Block a user