chore: add additional telemetry for teams errors
This commit is contained in:
10
packages/hoppscotch-app/src/components.d.ts
vendored
10
packages/hoppscotch-app/src/components.d.ts
vendored
@@ -93,6 +93,16 @@ declare module '@vue/runtime-core' {
|
|||||||
HttpTestResultReport: typeof import('./components/http/TestResultReport.vue')['default']
|
HttpTestResultReport: typeof import('./components/http/TestResultReport.vue')['default']
|
||||||
HttpTests: typeof import('./components/http/Tests.vue')['default']
|
HttpTests: typeof import('./components/http/Tests.vue')['default']
|
||||||
HttpURLEncodedParams: typeof import('./components/http/URLEncodedParams.vue')['default']
|
HttpURLEncodedParams: typeof import('./components/http/URLEncodedParams.vue')['default']
|
||||||
|
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
||||||
|
IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
|
||||||
|
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
|
||||||
|
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
||||||
|
IconLucideInfo: typeof import('~icons/lucide/info')['default']
|
||||||
|
IconLucideLayers: typeof import('~icons/lucide/layers')['default']
|
||||||
|
IconLucideLoader: typeof import('~icons/lucide/loader')['default']
|
||||||
|
IconLucideMinus: typeof import('~icons/lucide/minus')['default']
|
||||||
|
IconLucideSearch: typeof import('~icons/lucide/search')['default']
|
||||||
|
IconLucideUsers: typeof import('~icons/lucide/users')['default']
|
||||||
LensesHeadersRenderer: typeof import('./components/lenses/HeadersRenderer.vue')['default']
|
LensesHeadersRenderer: typeof import('./components/lenses/HeadersRenderer.vue')['default']
|
||||||
LensesHeadersRendererEntry: typeof import('./components/lenses/HeadersRendererEntry.vue')['default']
|
LensesHeadersRendererEntry: typeof import('./components/lenses/HeadersRendererEntry.vue')['default']
|
||||||
LensesRenderersHTMLLensRenderer: typeof import('./components/lenses/renderers/HTMLLensRenderer.vue')['default']
|
LensesRenderersHTMLLensRenderer: typeof import('./components/lenses/renderers/HTMLLensRenderer.vue')['default']
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
errorExchange,
|
errorExchange,
|
||||||
CombinedError,
|
CombinedError,
|
||||||
Operation,
|
Operation,
|
||||||
|
OperationResult,
|
||||||
} from "@urql/core"
|
} from "@urql/core"
|
||||||
import { authExchange } from "@urql/exchange-auth"
|
import { authExchange } from "@urql/exchange-auth"
|
||||||
import { devtoolsExchange } from "@urql/devtools"
|
import { devtoolsExchange } from "@urql/devtools"
|
||||||
@@ -34,12 +35,18 @@ const BACKEND_GQL_URL =
|
|||||||
const BACKEND_WS_URL =
|
const BACKEND_WS_URL =
|
||||||
import.meta.env.VITE_BACKEND_WS_URL ?? "wss://api.hoppscotch.io/graphql"
|
import.meta.env.VITE_BACKEND_WS_URL ?? "wss://api.hoppscotch.io/graphql"
|
||||||
|
|
||||||
|
type GQLOpType = "query" | "mutation" | "subscription"
|
||||||
/**
|
/**
|
||||||
* A type that defines error events that are possible during backend operations on the GQLCLient
|
* A type that defines error events that are possible during backend operations on the GQLCLient
|
||||||
*/
|
*/
|
||||||
export type GQLClientErrorEvent =
|
export type GQLClientErrorEvent =
|
||||||
| { type: "SUBSCRIPTION_CONN_CALLBACK_ERR_REPORT"; errors: Error[] }
|
| { type: "SUBSCRIPTION_CONN_CALLBACK_ERR_REPORT"; errors: Error[] }
|
||||||
| { type: "CLIENT_REPORTED_ERROR"; error: CombinedError; op: Operation }
|
| { type: "CLIENT_REPORTED_ERROR"; error: CombinedError; op: Operation }
|
||||||
|
| {
|
||||||
|
type: "GQL_CLIENT_REPORTED_ERROR"
|
||||||
|
opType: GQLOpType
|
||||||
|
opResult: OperationResult
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A stream of the errors that occur during GQLClient operations.
|
* A stream of the errors that occur during GQLClient operations.
|
||||||
@@ -178,11 +185,20 @@ export const runGQLQuery = <DocType, DocVarType, DocErrorType extends string>(
|
|||||||
E.fromNullable(res.error?.message),
|
E.fromNullable(res.error?.message),
|
||||||
E.match(
|
E.match(
|
||||||
// The left case (network error was null)
|
// The left case (network error was null)
|
||||||
(gqlErr) =>
|
(gqlErr) => {
|
||||||
<GQLError<DocErrorType>>{
|
if (res.error) {
|
||||||
|
gqlClientError$.next({
|
||||||
|
type: "GQL_CLIENT_REPORTED_ERROR",
|
||||||
|
opType: "query",
|
||||||
|
opResult: res,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return <GQLError<DocErrorType>>{
|
||||||
type: "gql_error",
|
type: "gql_error",
|
||||||
error: parseGQLErrorString(gqlErr ?? "") as DocErrorType,
|
error: parseGQLErrorString(gqlErr ?? "") as DocErrorType,
|
||||||
},
|
}
|
||||||
|
},
|
||||||
// The right case (it was a GraphQL Error)
|
// The right case (it was a GraphQL Error)
|
||||||
(networkErr) =>
|
(networkErr) =>
|
||||||
<GQLError<DocErrorType>>{
|
<GQLError<DocErrorType>>{
|
||||||
@@ -230,11 +246,20 @@ export const runGQLSubscription = <
|
|||||||
E.fromNullable(res.error?.message),
|
E.fromNullable(res.error?.message),
|
||||||
E.match(
|
E.match(
|
||||||
// The left case (network error was null)
|
// The left case (network error was null)
|
||||||
(gqlErr) =>
|
(gqlErr) => {
|
||||||
<GQLError<DocErrorType>>{
|
if (res.error) {
|
||||||
|
gqlClientError$.next({
|
||||||
|
type: "GQL_CLIENT_REPORTED_ERROR",
|
||||||
|
opType: "subscription",
|
||||||
|
opResult: res,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return <GQLError<DocErrorType>>{
|
||||||
type: "gql_error",
|
type: "gql_error",
|
||||||
error: parseGQLErrorString(gqlErr ?? "") as DocErrorType,
|
error: parseGQLErrorString(gqlErr ?? "") as DocErrorType,
|
||||||
},
|
}
|
||||||
|
},
|
||||||
// The right case (it was a GraphQL Error)
|
// The right case (it was a GraphQL Error)
|
||||||
(networkErr) =>
|
(networkErr) =>
|
||||||
<GQLError<DocErrorType>>{
|
<GQLError<DocErrorType>>{
|
||||||
@@ -311,11 +336,20 @@ export const runMutation = <
|
|||||||
E.fromNullable(result.error?.message),
|
E.fromNullable(result.error?.message),
|
||||||
E.match(
|
E.match(
|
||||||
// The left case (network error was null)
|
// The left case (network error was null)
|
||||||
(gqlErr) =>
|
(gqlErr) => {
|
||||||
<GQLError<DocErrors>>{
|
if (result.error) {
|
||||||
|
gqlClientError$.next({
|
||||||
|
type: "GQL_CLIENT_REPORTED_ERROR",
|
||||||
|
opType: "mutation",
|
||||||
|
opResult: result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return <GQLError<DocErrors>>{
|
||||||
type: "gql_error",
|
type: "gql_error",
|
||||||
error: parseGQLErrorString(gqlErr ?? ""),
|
error: parseGQLErrorString(gqlErr ?? ""),
|
||||||
},
|
}
|
||||||
|
},
|
||||||
// The right case (it was a network error)
|
// The right case (it was a network error)
|
||||||
(networkErr) =>
|
(networkErr) =>
|
||||||
<GQLError<DocErrors>>{
|
<GQLError<DocErrors>>{
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { settingsStore } from "~/newstore/settings"
|
|||||||
import { App } from "vue"
|
import { App } from "vue"
|
||||||
import { APP_IS_IN_DEV_MODE } from "~/helpers/dev"
|
import { APP_IS_IN_DEV_MODE } from "~/helpers/dev"
|
||||||
import { gqlClientError$ } from "~/helpers/backend/GQLClient"
|
import { gqlClientError$ } from "~/helpers/backend/GQLClient"
|
||||||
|
import { currentUser$ } from "~/helpers/fb/auth"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The tag names we allow giving to Sentry
|
* The tag names we allow giving to Sentry
|
||||||
@@ -97,6 +98,12 @@ function reportErrors(
|
|||||||
}
|
}
|
||||||
if (extras !== null && extras === undefined) scope.setExtras(extras)
|
if (extras !== null && extras === undefined) scope.setExtras(extras)
|
||||||
|
|
||||||
|
scope.addAttachment({
|
||||||
|
filename: "extras-dump.json",
|
||||||
|
data: JSON.stringify(extras),
|
||||||
|
contentType: "application/json",
|
||||||
|
})
|
||||||
|
|
||||||
errs.forEach((err) => Sentry.captureException(err))
|
errs.forEach((err) => Sentry.captureException(err))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -137,6 +144,29 @@ function subscribeToAppEventsForReporting() {
|
|||||||
{ op: ev.op }
|
{ op: ev.op }
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
case "GQL_CLIENT_REPORTED_ERROR":
|
||||||
|
reportError(
|
||||||
|
new Error("Backend Query Failed"),
|
||||||
|
"BACKEND_OPERATIONS",
|
||||||
|
{ opType: ev.opType },
|
||||||
|
{
|
||||||
|
opResult: ev.opResult,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to app system events for adding
|
||||||
|
* additional data tags for the error reporting
|
||||||
|
*/
|
||||||
|
function subscribeForAppDataTags() {
|
||||||
|
currentUser$.subscribe((user) => {
|
||||||
|
if (sentryActive) {
|
||||||
|
Sentry.setTag("user_logged_in", !!user)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -163,5 +193,6 @@ export default <HoppModule>{
|
|||||||
})
|
})
|
||||||
|
|
||||||
subscribeToAppEventsForReporting()
|
subscribeToAppEventsForReporting()
|
||||||
|
subscribeForAppDataTags()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user