mirror of
https://github.com/supabase/supabase.git
synced 2026-10-19 08:09:11 +03:00
* Use Sentry Error boundary. * Add a button for throwing error to test the sentry error boundary. * trigger an error during rendering. * Move the throwing of error. * Fix the error boundary state. * Try to throw an error from the project list. * Revert to using react error boundary. * Minor fixes. * Add an example page for throwing an exception to be caught by Sentry. Remove the error filter from the Sentry client config. * Remove config for allowing errors only from our code. * When capturing an exception with Sentry, add a tag if the exception is in the boundary. * Minor fixes. * Remove testing code. * Move forgotten code. * Add a function for anonymized user id. * Set the sentry user id by anonymizing the actual user id. * Don't send Sentry reports if the user hasn't consented to the telemetry. * Add a helper function whether the studio can send telemetry data. * Reuse the helper function in the _app file.
148 lines
3.4 KiB
TypeScript
148 lines
3.4 KiB
TypeScript
import { Sha256 } from '@aws-crypto/sha256-browser'
|
|
import type { NextRouter } from 'next/router'
|
|
|
|
import { post } from 'lib/common/fetch'
|
|
import { API_URL, IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
|
|
import type { User } from 'types'
|
|
|
|
export interface TelemetryProps {
|
|
screenResolution?: string
|
|
language: string
|
|
}
|
|
|
|
/**
|
|
* Sends a telemetry event to Logflare for tracking by the product team.
|
|
*/
|
|
const sendEvent = (
|
|
event: {
|
|
category: string
|
|
action: string
|
|
label: string
|
|
value?: string
|
|
},
|
|
gaProps: TelemetryProps,
|
|
router: NextRouter
|
|
) => {
|
|
if (!IS_PLATFORM) return
|
|
|
|
const consent =
|
|
typeof window !== 'undefined'
|
|
? localStorage.getItem(LOCAL_STORAGE_KEYS.TELEMETRY_CONSENT)
|
|
: null
|
|
if (consent !== 'true') return
|
|
|
|
const { category, action, label, value } = event
|
|
|
|
// remove # section from router.asPath as it
|
|
// often includes sensitive information
|
|
// such as access/refresh tokens
|
|
const page_location = router.asPath.split('#')[0]
|
|
|
|
return post(`${API_URL}/telemetry/event`, {
|
|
action: action,
|
|
category: category,
|
|
label: label,
|
|
value: value,
|
|
page_referrer: document?.referrer,
|
|
page_title: document?.title,
|
|
page_location,
|
|
ga: {
|
|
screen_resolution: gaProps?.screenResolution,
|
|
language: gaProps?.language,
|
|
},
|
|
})
|
|
}
|
|
|
|
/**
|
|
* TODO: GA4 doesn't have identify method.
|
|
* We may or may not need gaClientId here. Confirm later
|
|
*/
|
|
const sendIdentify = (user: User, gaProps?: TelemetryProps) => {
|
|
if (!IS_PLATFORM) return
|
|
|
|
const consent =
|
|
typeof window !== 'undefined'
|
|
? localStorage.getItem(LOCAL_STORAGE_KEYS.TELEMETRY_CONSENT)
|
|
: null
|
|
if (consent !== 'true') return
|
|
|
|
return post(`${API_URL}/telemetry/identify`, {
|
|
user,
|
|
ga: {
|
|
screen_resolution: gaProps?.screenResolution,
|
|
language: gaProps?.language,
|
|
},
|
|
})
|
|
}
|
|
|
|
/**
|
|
* @deprecated use sendEvent instead.
|
|
*/
|
|
const sendActivity = (
|
|
event: {
|
|
activity: string
|
|
source: string
|
|
projectRef?: string
|
|
orgSlug?: string
|
|
data?: object
|
|
},
|
|
router: NextRouter
|
|
) => {
|
|
if (!IS_PLATFORM) return
|
|
|
|
const consent =
|
|
typeof window !== 'undefined'
|
|
? localStorage.getItem(LOCAL_STORAGE_KEYS.TELEMETRY_CONSENT)
|
|
: null
|
|
if (consent !== 'true') return
|
|
|
|
const { activity, source, projectRef, orgSlug, data } = event
|
|
|
|
const properties = {
|
|
activity,
|
|
source,
|
|
page: {
|
|
path: router.route,
|
|
location: router.asPath,
|
|
referrer: document?.referrer || '',
|
|
title: document?.title || '',
|
|
},
|
|
...(data && { data }),
|
|
...(projectRef && { projectRef }),
|
|
...(orgSlug && { orgSlug }),
|
|
}
|
|
return post(`${API_URL}/telemetry/activity`, properties)
|
|
}
|
|
|
|
/**
|
|
* Checks if the user has consented to sending telemetry data. Mainly used for Sentry reports.
|
|
*/
|
|
export const canSendTelemetry = () => {
|
|
const consent =
|
|
typeof window !== 'undefined'
|
|
? localStorage.getItem(LOCAL_STORAGE_KEYS.TELEMETRY_CONSENT)
|
|
: null
|
|
|
|
return IS_PLATFORM && consent === 'true'
|
|
}
|
|
|
|
/**
|
|
* Generates a unique identifier for an anonymous user based on their gotrue id.
|
|
*/
|
|
export const getAnonId = async (id: string) => {
|
|
const hash = new Sha256()
|
|
hash.update(id)
|
|
const u8Array = await hash.digest()
|
|
const binString = Array.from(u8Array, (byte) => String.fromCodePoint(byte)).join('')
|
|
const b64encoded = btoa(binString)
|
|
return b64encoded
|
|
}
|
|
|
|
const Telemetry = {
|
|
sendEvent,
|
|
sendIdentify,
|
|
sendActivity,
|
|
}
|
|
|
|
export default Telemetry
|