Skip to content

Commit

Permalink
migration: switch error reporting from posthog events to datadog rum …
Browse files Browse the repository at this point in the history
…errors (#573)
  • Loading branch information
abvthecity authored Mar 25, 2024
1 parent 0f76888 commit efb93e6
Show file tree
Hide file tree
Showing 26 changed files with 193 additions and 88 deletions.
12 changes: 12 additions & 0 deletions packages/ui/app/src/analytics/datadogRum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { datadogRum } from "@datadog/browser-rum";

interface FernUIErrorContext {
context: string;
errorSource: string;
errorDescription: string;
data?: Record<string, unknown>;
}

export function emitDatadogError(e: unknown, context: FernUIErrorContext): void {
datadogRum.addError(e, context);
}
6 changes: 3 additions & 3 deletions packages/ui/app/src/api-page/ApiPackageContents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const ApiPackageContents: React.FC<ApiPackageContents.Props> = ({
return (
<>
{endpoints.map((endpoint, idx) => (
<FernErrorBoundary type="endpoint" key={endpoint.id}>
<FernErrorBoundary component="ApiPackageContents" key={endpoint.id}>
<Endpoint
api={api}
showErrors={showErrors}
Expand All @@ -52,7 +52,7 @@ export const ApiPackageContents: React.FC<ApiPackageContents.Props> = ({
</FernErrorBoundary>
))}
{websockets.map((websocket, idx) => (
<FernErrorBoundary type="websocket" key={websocket.id}>
<FernErrorBoundary component="ApiPackageContents" key={websocket.id}>
<WebSocket
api={api}
websocket={websocket}
Expand All @@ -62,7 +62,7 @@ export const ApiPackageContents: React.FC<ApiPackageContents.Props> = ({
</FernErrorBoundary>
))}
{webhooks.map((webhook, idx) => (
<FernErrorBoundary type="webhook" key={webhook.id}>
<FernErrorBoundary component="ApiPackageContents" key={webhook.id}>
<Webhook
key={webhook.id}
webhook={webhook}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,18 @@ export const EndpointResponseSection: React.FC<EndpointResponseSection.Props> =
console.error(
"Generated API Reference contains a deprecated streamingText shape. Please upgrade Fern CLI and regenerate the API Reference.",
);
return <FernErrorTag error="Stream condition cannot be rendered" />;
return (
<FernErrorTag component="EndpointResponseSection" error="Stream condition cannot be rendered" />
);
},
streamCondition: () => {
// eslint-disable-next-line no-console
console.error(
"Generated API Reference contains a deprecated streamCondition shape. Please upgrade Fern CLI and regenerate the API Reference.",
);
return <FernErrorTag error="Stream condition cannot be rendered" />;
return (
<FernErrorTag component="EndpointResponseSection" error="Stream condition cannot be rendered" />
);
},
stream: (stream) => (
<TypeReferenceDefinitions
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/app/src/api-page/endpoints/EndpointSection.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MinusIcon, PlusIcon } from "@radix-ui/react-icons";
import dynamic from "next/dynamic";
import { createElement, ReactNode, useRef } from "react";
import { ReactNode, createElement, useRef } from "react";
import { AbsolutelyPositionedAnchor } from "../../commons/AbsolutelyPositionedAnchor";
import { FernButton, FernButtonGroup } from "../../components/FernButton";
import { FernErrorBoundary } from "../../components/FernErrorBoundary";
Expand Down Expand Up @@ -39,7 +39,7 @@ export const EndpointSection: React.FC<EndpointSection.Props> = ({
const anchorId = getAnchorId(anchorIdParts);
const anchorRoute = `${route}#${anchorId}`;
return (
<FernErrorBoundary type="endpoint_section">
<FernErrorBoundary component="EndpointSection">
<div ref={ref} data-route={anchorRoute.toLowerCase()} className="scroll-mt-header-height-padded">
<div className="group/anchor-container relative flex items-baseline justify-between gap-4 pb-3">
{createElement(
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/app/src/api-page/examples/AudioExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const AudioExampleInternal: FC<AudioExample.Props> = ({ ...props }) => {

export const AudioExample: FC<AudioExample.Props> = (props) => {
return (
<FernErrorBoundary type="audio_example">
<FernErrorBoundary component="AudioExample">
<AudioExampleInternal {...props} />
</FernErrorBoundary>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const CodeSnippetExampleInternal: FC<CodeSnippetExample.Props> = ({

export const CodeSnippetExample: FC<CodeSnippetExample.Props> = (props) => {
return (
<FernErrorBoundary type="code_snippet_example">
<FernErrorBoundary component="CodeSnippetExample">
<CodeSnippetExampleInternal {...props} />
</FernErrorBoundary>
);
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/app/src/api-page/examples/getJsonLineNumbers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isPlainObject } from "@fern-ui/core-utils";
import jp from "jsonpath";
import { capturePosthogEvent } from "../../analytics/posthog";
import { emitDatadogError } from "../../analytics/datadogRum";
import { JsonPropertyPath, JsonPropertyPathPart } from "./JsonPropertyPath";
import { lineNumberOf } from "./utils";

Expand All @@ -21,7 +21,14 @@ export function getJsonLineNumbers(json: unknown, path: JsonPropertyPath, start
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
capturePosthogEvent("jsonpath_error", { error: e, query });

emitDatadogError(e, {
context: "ApiPage",
errorSource: "getJsonLineNumbers",
errorDescription:
"Jsonpath failed to query JSON object. Check the query that was constructed when the user hovered over a specific property",
data: { json, query },
});
}

if (part.type === "objectFilter") {
Expand Down
9 changes: 9 additions & 0 deletions packages/ui/app/src/api-page/examples/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { APIV1Read } from "@fern-api/fdr-sdk";
import { isPlainObject, visitDiscriminatedUnion } from "@fern-ui/core-utils";
import { keyBy, mapValues, noop } from "lodash-es";
import { emitDatadogError } from "../../analytics/datadogRum";
import { buildRequestUrl } from "../../api-playground/utils";
import { getEndpointEnvironmentUrl } from "../../util/endpoint";
import {
Expand Down Expand Up @@ -86,6 +87,14 @@ export function stringifyHttpRequestExampleToCurl(request: HttpRequestExample):
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);

emitDatadogError(e, {
context: "ApiPage",
errorSource: "unsafeStringifyHttpRequestExampleToCurl",
errorDescription:
"Unable to stringify HTTP request example to curl. This is used to generate a curl command for the user to copy and paste into their terminal. When this fails, the user will not be able to see the curl command.",
});

return "";
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/app/src/api-page/types/object/ObjectProperty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import {
useTypeDefinitionContext,
} from "../context/TypeDefinitionContext";
import {
hasInternalTypeReference,
InternalTypeReferenceDefinitions,
hasInternalTypeReference,
} from "../type-reference/InternalTypeReferenceDefinitions";
import { renderTypeShorthandRoot } from "../type-shorthand/TypeShorthand";

Expand Down Expand Up @@ -130,7 +130,7 @@ const ObjectPropertyInternal = memo<ObjectPropertyInternalProps>(function Object
<ApiPageDescription isMarkdown={true} description={property.description} className="text-sm" />
)}
{hasInternalTypeReference(property.valueShape, types) && (
<FernErrorBoundary type="object_property">
<FernErrorBoundary component="ObjectProperty">
<TypeDefinitionContext.Provider value={newContextValue}>
<InternalTypeReferenceDefinitions
shape={property.valueShape}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { visitDiscriminatedUnion } from "@fern-ui/core-utils";
import { useBooleanState, useIsHovering } from "@fern-ui/react-commons";
import cn from "clsx";
import { useRouter } from "next/router";
import { memo, ReactElement, useCallback, useEffect, useMemo } from "react";
import { ReactElement, memo, useCallback, useEffect, useMemo } from "react";
import { Chip } from "../../../components/Chip";
import { FernErrorBoundary } from "../../../components/FernErrorBoundary";
import { FernTooltipProvider } from "../../../components/FernTooltip";
import { getAnchorId } from "../../../util/anchor";
import { dereferenceObjectProperties, ResolvedTypeDefinition } from "../../../util/resolver";
import { ResolvedTypeDefinition, dereferenceObjectProperties } from "../../../util/resolver";
import {
TypeDefinitionContext,
TypeDefinitionContextValue,
Expand Down Expand Up @@ -148,7 +148,7 @@ export const InternalTypeDefinition = memo<InternalTypeDefinition.Props>(functio

if (!isCollapsible) {
return (
<FernErrorBoundary type="type_definition">
<FernErrorBoundary component="InternalTypeDefinition">
<FernTooltipProvider>
<TypeDefinitionDetails
elements={collapsableContent.elements}
Expand Down Expand Up @@ -205,7 +205,7 @@ export const InternalTypeDefinition = memo<InternalTypeDefinition.Props>(functio
);

return (
<FernErrorBoundary type="type_definition">
<FernErrorBoundary component="InternalTypeDefinition">
<FernTooltipProvider>{renderContent()}</FernTooltipProvider>
</FernErrorBoundary>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const TypeReferenceDefinitions = memo<TypeReferenceDefinitions.Props>(fun
isResponse,
}) {
return (
<FernErrorBoundary type="type_reference_definitions">
<FernErrorBoundary component="TypeReferenceDefinitions">
<TypeDefinitionContextProvider onHoverProperty={onHoverProperty} isResponse={isResponse}>
<InternalTypeReferenceDefinitions
shape={shape}
Expand Down
6 changes: 3 additions & 3 deletions packages/ui/app/src/api-playground/PlaygroundDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import { FernTooltip, FernTooltipProvider } from "../components/FernTooltip";
import { useDocsContext } from "../contexts/docs-context/useDocsContext";
import {
FlattenedRootPackage,
isEndpoint,
isWebSocket,
ResolvedApiDefinition,
ResolvedEndpointDefinition,
ResolvedExampleEndpointCall,
ResolvedTypeDefinition,
ResolvedWebSocketChannel,
isEndpoint,
isWebSocket,
} from "../util/resolver";
import { PLAYGROUND_FORM_STATE_ATOM, PLAYGROUND_OPEN_ATOM, usePlaygroundContext } from "./PlaygroundContext";
import { PlaygroundEndpoint } from "./PlaygroundEndpoint";
Expand Down Expand Up @@ -315,7 +315,7 @@ export const PlaygroundDrawer: FC<PlaygroundDrawerProps> = ({ navigation, apis }
</div>
</div>
</div>
<FernErrorBoundary type="playground" className="flex h-full items-center justify-center">
<FernErrorBoundary component="PlaygroundDrawer" className="flex h-full items-center justify-center">
{selectionState?.type === "endpoint" && matchedEndpoint != null ? (
<PlaygroundEndpoint
endpoint={matchedEndpoint}
Expand Down
20 changes: 14 additions & 6 deletions packages/ui/app/src/api-playground/PlaygroundEndpoint.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { assertNever, isNonNullish } from "@fern-ui/core-utils";
import { joinUrlSlugs } from "@fern-ui/fdr-utils";
import { failed, Loadable, loaded, loading, notStartedLoading } from "@fern-ui/loadable";
import { Loadable, failed, loaded, loading, notStartedLoading } from "@fern-ui/loadable";
import { PaperPlaneIcon } from "@radix-ui/react-icons";
import { Dispatch, FC, ReactElement, SetStateAction, useCallback, useState } from "react";
import { resolve } from "url";
import { emitDatadogError } from "../analytics/datadogRum";
import { capturePosthogEvent } from "../analytics/posthog";
import { FernTooltipProvider } from "../components/FernTooltip";
import { useDocsContext } from "../contexts/docs-context/useDocsContext";
Expand Down Expand Up @@ -225,11 +226,18 @@ export const PlaygroundEndpoint: FC<PlaygroundEndpointProps> = ({
// eslint-disable-next-line no-console
console.error(e);
setResponse(failed(e));
capturePosthogEvent("api_playground_request_failed", {
endpointId: endpoint.id,
endpointName: endpoint.name,
method: endpoint.method,
docsRoute: `/${joinUrlSlugs(...endpoint.slug)}`,

emitDatadogError(e, {
context: "ApiPlayground",
errorSource: "sendRequest",
errorDescription:
"An unexpected error occurred while sending request to the proxy server. This is likely a bug, rather than a user error.",
data: {
endpointId: endpoint.id,
endpointName: endpoint.name,
method: endpoint.method,
route: `/${joinUrlSlugs(...endpoint.slug)}`,
},
});
}
}, [basePath, endpoint, formState]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Dispatch, FC, SetStateAction, useEffect, useRef, useState } from "react
import { FernAudioPlayer } from "../components/FernAudioPlayer";
import { FernButton, FernButtonGroup } from "../components/FernButton";
import { FernCard } from "../components/FernCard";
import { FernErrorTag, stringifyError } from "../components/FernErrorBoundary";
import { FernErrorTag } from "../components/FernErrorBoundary";
import { CopyToClipboardButton } from "../syntax-highlighting/CopyToClipboardButton";
import { ResolvedEndpointDefinition, ResolvedTypeDefinition } from "../util/resolver";
import { PlaygroundAuthorizationFormCard } from "./PlaygroundAuthorizationForm";
Expand All @@ -16,10 +16,10 @@ import { PlaygroundEndpointFormAside } from "./PlaygroundEndpointFormAside";
import { PlaygroundRequestPreview } from "./PlaygroundRequestPreview";
import { PlaygroundResponsePreview } from "./PlaygroundResponsePreview";
import { PlaygroundSendRequestButton } from "./PlaygroundSendRequestButton";
import { HorizontalSplitPane, VerticalSplitPane } from "./VerticalSplitPane";
import { PlaygroundEndpointRequestFormState } from "./types";
import { PlaygroundResponse } from "./types/playgroundResponse";
import { stringifyCurl, stringifyFetch, stringifyPythonRequests } from "./utils";
import { HorizontalSplitPane, VerticalSplitPane } from "./VerticalSplitPane";

interface PlaygroundEndpointContentProps {
endpoint: ResolvedEndpointDefinition;
Expand Down Expand Up @@ -244,13 +244,15 @@ export const PlaygroundEndpointContent: FC<PlaygroundEndpointContentProps> = ({
/>
) : (
<FernErrorTag
component="PlaygroundEndpointContent"
error={`File preview not supported for ${response.response.contentType}`}
className="flex h-full items-center justify-center"
/>
),
failed: (e) => (
<FernErrorTag
error={stringifyError(e)}
component="PlaygroundEndpointContent"
error={e}
className="flex h-full items-center justify-center"
/>
),
Expand Down
7 changes: 5 additions & 2 deletions packages/ui/app/src/api-playground/PlaygroundEndpointForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { Dispatch, FC, SetStateAction, useCallback } from "react";
import { FernCard } from "../components/FernCard";
import { FernErrorTag } from "../components/FernErrorBoundary";
import {
dereferenceObjectProperties,
ResolvedEndpointDefinition,
ResolvedTypeDefinition,
dereferenceObjectProperties,
unwrapReference,
visitResolvedHttpRequestBodyShape,
} from "../util/resolver";
Expand Down Expand Up @@ -237,7 +237,10 @@ export const PlaygroundEndpointForm: FC<PlaygroundEndpointFormProps> = ({
<div className="mb-4 px-4">
<h5 className="t-muted m-0">Body</h5>
</div>
<FernErrorTag error="File upload is not supported on this endpoint" />
<FernErrorTag
component="PlaygroundEndpointForm"
error="File upload is not supported on this endpoint"
/>
</div>
) : (
<div className="min-w-0 flex-1 shrink">
Expand Down
Loading

0 comments on commit efb93e6

Please sign in to comment.