From 32ec5330b0ed8f6b1f473cc75358cc20ee0c6ce6 Mon Sep 17 00:00:00 2001 From: Spence Pope Date: Wed, 5 Aug 2026 10:15:26 -0400 Subject: [PATCH] Enrich fatal HLS errors in Sentry (#11359) --- .../VideoEmbedInnerWeb.shared.ts | 16 ++++++- .../VideoEmbedInner/VideoEmbedInnerWeb.tsx | 48 ++++++++++++++++++- .../Post/Embed/VideoEmbed/index.web.tsx | 15 +++++- src/view/com/util/ErrorBoundary.tsx | 7 ++- 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts index d7c44b0d91..9184ccf37c 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts @@ -27,8 +27,22 @@ export class VideoNotFoundError extends Error { */ export class HLSFatalError extends Error { detail: string - constructor(detail: string, cause: Error) { + type: string + diagnostics: Record + constructor({ + detail, + type, + cause, + diagnostics, + }: { + detail: string + type: string + cause: Error + diagnostics: Record + }) { super(cause.message, {cause}) this.detail = detail + this.type = type + this.diagnostics = diagnostics } } diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx index 6ece8f5a9b..0599240816 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx @@ -308,7 +308,53 @@ function useHLS({ ) { setError(new VideoNotFoundError()) } 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 { console.error(data.error) diff --git a/src/components/Post/Embed/VideoEmbed/index.web.tsx b/src/components/Post/Embed/VideoEmbed/index.web.tsx index ee44ba33e8..0eb622bad7 100644 --- a/src/components/Post/Embed/VideoEmbed/index.web.tsx +++ b/src/components/Post/Embed/VideoEmbed/index.web.tsx @@ -82,6 +82,16 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) { ), [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 const dims = embed.aspectRatio @@ -158,7 +168,10 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) { /> )} - + ReactNode + getErrorMetadata?: (error: Error) => Metadata style?: StyleProp } @@ -29,7 +31,10 @@ export class ErrorBoundary extends Component { } public componentDidCatch(error: Error, errorInfo: ErrorInfo) { - logger.error(error, {errorInfo}) + logger.error(error, { + errorInfo, + ...this.props.getErrorMetadata?.(error), + }) } public render() {