[Instrumentation] Signin (#7742)
* first pass at instrumenting login * round time taken
This commit is contained in:
@@ -51,6 +51,22 @@ export type LogEvents = {
|
||||
}
|
||||
'signup:captchaSuccess': {}
|
||||
'signup:captchaFailure': {}
|
||||
'signin:hostingProviderPressed': {
|
||||
hostingProviderDidChange: boolean
|
||||
}
|
||||
'signin:hostingProviderFailedResolution': {}
|
||||
'signin:success': {
|
||||
failedAttemptsCount: number
|
||||
isUsingCustomProvider: boolean
|
||||
timeTakenSeconds: number
|
||||
}
|
||||
'signin:backPressed': {
|
||||
failedAttemptsCount: number
|
||||
}
|
||||
'signin:forgotPasswordPressed': {}
|
||||
'signin:passwordReset': {}
|
||||
'signin:passwordResetSuccess': {}
|
||||
'signin:passwordResetFailure': {}
|
||||
'onboarding:interests:nextPressed': {
|
||||
selectedInterests: string[]
|
||||
selectedInterestsLength: number
|
||||
|
||||
@@ -45,6 +45,8 @@ export const LoginForm = ({
|
||||
onPressRetryConnect,
|
||||
onPressBack,
|
||||
onPressForgotPassword,
|
||||
onAttemptSuccess,
|
||||
onAttemptFailed,
|
||||
}: {
|
||||
error: string
|
||||
serviceUrl: string
|
||||
@@ -55,6 +57,8 @@ export const LoginForm = ({
|
||||
onPressRetryConnect: () => void
|
||||
onPressBack: () => void
|
||||
onPressForgotPassword: () => void
|
||||
onAttemptSuccess: () => void
|
||||
onAttemptFailed: () => void
|
||||
}) => {
|
||||
const t = useTheme()
|
||||
const [isProcessing, setIsProcessing] = useState<boolean>(false)
|
||||
@@ -131,6 +135,7 @@ export const LoginForm = ({
|
||||
},
|
||||
'LoginForm',
|
||||
)
|
||||
onAttemptSuccess()
|
||||
setShowLoggedOut(false)
|
||||
setHasCheckedForStarterPack(true)
|
||||
requestNotificationsPermission('Login')
|
||||
@@ -142,29 +147,32 @@ export const LoginForm = ({
|
||||
e instanceof ComAtprotoServerCreateSession.AuthFactorTokenRequiredError
|
||||
) {
|
||||
setIsAuthFactorTokenNeeded(true)
|
||||
} else if (errMsg.includes('Token is invalid')) {
|
||||
logger.debug('Failed to login due to invalid 2fa token', {
|
||||
error: errMsg,
|
||||
})
|
||||
setError(_(msg`Invalid 2FA confirmation code.`))
|
||||
} else if (
|
||||
errMsg.includes('Authentication Required') ||
|
||||
errMsg.includes('Invalid identifier or password')
|
||||
) {
|
||||
logger.debug('Failed to login due to invalid credentials', {
|
||||
error: errMsg,
|
||||
})
|
||||
setError(_(msg`Incorrect username or password`))
|
||||
} else if (isNetworkError(e)) {
|
||||
logger.warn('Failed to login due to network error', {error: errMsg})
|
||||
setError(
|
||||
_(
|
||||
msg`Unable to contact your service. Please check your Internet connection.`,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
logger.warn('Failed to login', {error: errMsg})
|
||||
setError(cleanError(errMsg))
|
||||
onAttemptFailed()
|
||||
if (errMsg.includes('Token is invalid')) {
|
||||
logger.debug('Failed to login due to invalid 2fa token', {
|
||||
error: errMsg,
|
||||
})
|
||||
setError(_(msg`Invalid 2FA confirmation code.`))
|
||||
} else if (
|
||||
errMsg.includes('Authentication Required') ||
|
||||
errMsg.includes('Invalid identifier or password')
|
||||
) {
|
||||
logger.debug('Failed to login due to invalid credentials', {
|
||||
error: errMsg,
|
||||
})
|
||||
setError(_(msg`Incorrect username or password`))
|
||||
} else if (isNetworkError(e)) {
|
||||
logger.warn('Failed to login due to network error', {error: errMsg})
|
||||
setError(
|
||||
_(
|
||||
msg`Unable to contact your service. Please check your Internet connection.`,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
logger.warn('Failed to login', {error: errMsg})
|
||||
setError(cleanError(errMsg))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {BskyAgent} from '@atproto/api'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {isNetworkError} from '#/lib/strings/errors'
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {checkAndFormatResetCode} from '#/lib/strings/password'
|
||||
@@ -48,6 +49,7 @@ export const SetNewPasswordForm = ({
|
||||
msg`You have entered an invalid code. It should look like XXXXX-XXXXX.`,
|
||||
),
|
||||
)
|
||||
logEvent('signin:passwordResetFailure', {})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -67,9 +69,11 @@ export const SetNewPasswordForm = ({
|
||||
password,
|
||||
})
|
||||
onPasswordSet()
|
||||
logEvent('signin:passwordResetSuccess', {})
|
||||
} catch (e: any) {
|
||||
const errMsg = e.toString()
|
||||
logger.warn('Failed to set new password', {error: e})
|
||||
logEvent('signin:passwordResetFailure', {})
|
||||
setIsProcessing(false)
|
||||
if (isNetworkError(e)) {
|
||||
setError(
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from 'react'
|
||||
import React, {useRef} from 'react'
|
||||
import {KeyboardAvoidingView} from 'react-native'
|
||||
import {LayoutAnimationConfig} from 'react-native-reanimated'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {DEFAULT_SERVICE} from '#/lib/constants'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {logger} from '#/logger'
|
||||
import {useServiceQuery} from '#/state/queries/service'
|
||||
import {SessionAccount, useSession} from '#/state/session'
|
||||
@@ -28,6 +29,8 @@ enum Forms {
|
||||
|
||||
export const Login = ({onPressBack}: {onPressBack: () => void}) => {
|
||||
const {_} = useLingui()
|
||||
const failedAttemptCountRef = useRef(0)
|
||||
const startTimeRef = useRef(Date.now())
|
||||
|
||||
const {accounts} = useSession()
|
||||
const {requestedAccountSwitchTo} = useLoggedOutView()
|
||||
@@ -79,6 +82,7 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
|
||||
logger.warn(`Failed to fetch service description for ${serviceUrl}`, {
|
||||
error: String(serviceError),
|
||||
})
|
||||
logEvent('signin:hostingProviderFailedResolution', {})
|
||||
} else {
|
||||
setError('')
|
||||
}
|
||||
@@ -86,6 +90,27 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
|
||||
|
||||
const onPressForgotPassword = () => {
|
||||
setCurrentForm(Forms.ForgotPassword)
|
||||
logEvent('signin:forgotPasswordPressed', {})
|
||||
}
|
||||
|
||||
const handlePressBack = () => {
|
||||
onPressBack()
|
||||
logEvent('signin:backPressed', {
|
||||
failedAttemptsCount: failedAttemptCountRef.current,
|
||||
})
|
||||
}
|
||||
|
||||
const onAttemptSuccess = () => {
|
||||
logEvent('signin:success', {
|
||||
isUsingCustomProvider: serviceUrl !== DEFAULT_SERVICE,
|
||||
timeTakenSeconds: Math.round((Date.now() - startTimeRef.current) / 1000),
|
||||
failedAttemptsCount: failedAttemptCountRef.current,
|
||||
})
|
||||
setCurrentForm(Forms.Login)
|
||||
}
|
||||
|
||||
const onAttemptFailed = () => {
|
||||
failedAttemptCountRef.current += 1
|
||||
}
|
||||
|
||||
let content = null
|
||||
@@ -103,9 +128,11 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
|
||||
serviceDescription={serviceDescription}
|
||||
initialHandle={initialHandle}
|
||||
setError={setError}
|
||||
onAttemptFailed={onAttemptFailed}
|
||||
onAttemptSuccess={onAttemptSuccess}
|
||||
setServiceUrl={setServiceUrl}
|
||||
onPressBack={() =>
|
||||
accounts.length ? gotoForm(Forms.ChooseAccount) : onPressBack()
|
||||
accounts.length ? gotoForm(Forms.ChooseAccount) : handlePressBack()
|
||||
}
|
||||
onPressForgotPassword={onPressForgotPassword}
|
||||
onPressRetryConnect={refetchService}
|
||||
@@ -118,7 +145,7 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
|
||||
content = (
|
||||
<ChooseAccountForm
|
||||
onSelectAccount={onSelectAccount}
|
||||
onPressBack={onPressBack}
|
||||
onPressBack={handlePressBack}
|
||||
/>
|
||||
)
|
||||
break
|
||||
|
||||
@@ -5,6 +5,7 @@ import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {BSKY_SERVICE} from '#/lib/constants'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import * as persisted from '#/state/persisted'
|
||||
import {useSession} from '#/state/session'
|
||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||
@@ -39,7 +40,10 @@ export function ServerInputDialog({
|
||||
setPreviousCustomAddress(result)
|
||||
}
|
||||
}
|
||||
}, [onSelect])
|
||||
logEvent('signin:hostingProviderPressed', {
|
||||
hostingProviderDidChange: fixedOption !== BSKY_SERVICE,
|
||||
})
|
||||
}, [onSelect, fixedOption])
|
||||
|
||||
return (
|
||||
<Dialog.Outer
|
||||
|
||||
Reference in New Issue
Block a user