Reduce Sentry noise from logger transport and expected-failure call sites
This commit is contained in:
@@ -1058,11 +1058,6 @@
|
|||||||
"count": 1
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/logger/transports/sentry.ts": {
|
|
||||||
"@typescript-eslint/no-unsafe-enum-comparison": {
|
|
||||||
"count": 3
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src/logger/types.ts": {
|
"src/logger/types.ts": {
|
||||||
"@typescript-eslint/no-redundant-type-constituents": {
|
"@typescript-eslint/no-redundant-type-constituents": {
|
||||||
"count": 1
|
"count": 1
|
||||||
|
|||||||
+1
-1
@@ -124,7 +124,7 @@ function InnerApp() {
|
|||||||
await features.init
|
await features.init
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(`session: resume failed`, {message: e})
|
logger.warn(`session: resume failed`, {message: e})
|
||||||
} finally {
|
} finally {
|
||||||
setIsReady(true)
|
setIsReady(true)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -103,7 +103,7 @@ function InnerApp() {
|
|||||||
await features.init
|
await features.init
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('session: resumeSession failed', {message: e})
|
logger.warn('session: resumeSession failed', {message: e})
|
||||||
} finally {
|
} finally {
|
||||||
setIsReady(true)
|
setIsReady(true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ export function Root({children}: {children: React.ReactNode}) {
|
|||||||
const onHoverableTouchUp = useCallback((id: string) => {
|
const onHoverableTouchUp = useCallback((id: string) => {
|
||||||
const hoverable = hoverables.current.get(id)
|
const hoverable = hoverables.current.get(id)
|
||||||
if (!hoverable) {
|
if (!hoverable) {
|
||||||
logger.warn(`No such hoverable with id ${id}`)
|
logger.warn(`No such hoverable`, {id})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
hoverable.onTouchUp()
|
hoverable.onTouchUp()
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ export function useVideoElement(ref: RefObject<HTMLVideoElement | null>) {
|
|||||||
`The play() request was interrupted by a call to pause()`,
|
`The play() request was interrupted by a call to pause()`,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
logger.error('Error playing video:', {message: err})
|
logger.warn('Error playing video:', {message: err})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ async function _registerPushToken({
|
|||||||
notyLogger.debug(`registerPushToken: success`)
|
notyLogger.debug(`registerPushToken: success`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!isNetworkError(error)) {
|
if (!isNetworkError(error)) {
|
||||||
notyLogger.error(`registerPushToken: failed`, {safeMessage: error})
|
notyLogger.warn(`registerPushToken: failed`, {safeMessage: error})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
|
|||||||
}))
|
}))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const e = err as Error
|
const e = err as Error
|
||||||
logger.error('Failed to translate text on device', {safeMessage: e})
|
logger.warn('Failed to translate text on device', {safeMessage: e})
|
||||||
// On-device translation failed (language pack missing or user
|
// On-device translation failed (language pack missing or user
|
||||||
// dismissed the download prompt).
|
// dismissed the download prompt).
|
||||||
ax.metric('translate:result', {
|
ax.metric('translate:result', {
|
||||||
|
|||||||
@@ -182,11 +182,7 @@ describe('general functionality', () => {
|
|||||||
timestamp: sentryTimestamp,
|
timestamp: sentryTimestamp,
|
||||||
})
|
})
|
||||||
jest.runAllTimers()
|
jest.runAllTimers()
|
||||||
expect(Sentry.captureMessage).toHaveBeenCalledWith(message, {
|
expect(Sentry.captureMessage).not.toHaveBeenCalled()
|
||||||
level: 'log',
|
|
||||||
tags: {category: 'logger'},
|
|
||||||
extra: {__context__: 'logger'},
|
|
||||||
})
|
|
||||||
|
|
||||||
sentryTransport(
|
sentryTransport(
|
||||||
LogLevel.Warn,
|
LogLevel.Warn,
|
||||||
@@ -204,8 +200,18 @@ describe('general functionality', () => {
|
|||||||
timestamp: sentryTimestamp,
|
timestamp: sentryTimestamp,
|
||||||
})
|
})
|
||||||
jest.runAllTimers()
|
jest.runAllTimers()
|
||||||
|
expect(Sentry.captureMessage).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
sentryTransport(
|
||||||
|
LogLevel.Error,
|
||||||
|
Logger.Context.Default,
|
||||||
|
message,
|
||||||
|
{},
|
||||||
|
timestamp,
|
||||||
|
)
|
||||||
|
jest.runAllTimers()
|
||||||
expect(Sentry.captureMessage).toHaveBeenCalledWith(message, {
|
expect(Sentry.captureMessage).toHaveBeenCalledWith(message, {
|
||||||
level: 'warning',
|
level: 'error',
|
||||||
tags: {category: 'logger'},
|
tags: {category: 'logger'},
|
||||||
extra: {__context__: 'logger'},
|
extra: {__context__: 'logger'},
|
||||||
})
|
})
|
||||||
@@ -259,6 +265,42 @@ describe('general functionality', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('sentryTransport filters network errors', () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
const timestamp = Date.now()
|
||||||
|
|
||||||
|
// network error in the message itself
|
||||||
|
sentryTransport(
|
||||||
|
LogLevel.Error,
|
||||||
|
Logger.Context.Default,
|
||||||
|
'Network request failed',
|
||||||
|
{},
|
||||||
|
timestamp,
|
||||||
|
)
|
||||||
|
|
||||||
|
// network error in metadata, message is something else
|
||||||
|
sentryTransport(
|
||||||
|
LogLevel.Error,
|
||||||
|
Logger.Context.Default,
|
||||||
|
'poll failed',
|
||||||
|
{safeMessage: new Error('Network request failed')},
|
||||||
|
timestamp,
|
||||||
|
)
|
||||||
|
|
||||||
|
jest.runAllTimers()
|
||||||
|
expect(Sentry.captureMessage).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
// network Error object
|
||||||
|
sentryTransport(
|
||||||
|
LogLevel.Error,
|
||||||
|
Logger.Context.Default,
|
||||||
|
new Error('Network request failed'),
|
||||||
|
{},
|
||||||
|
timestamp,
|
||||||
|
)
|
||||||
|
expect(Sentry.captureException).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
test('add/remove transport', () => {
|
test('add/remove transport', () => {
|
||||||
const timestamp = Date.now()
|
const timestamp = Date.now()
|
||||||
const logger = new Logger({})
|
const logger = new Logger({})
|
||||||
|
|||||||
@@ -47,16 +47,24 @@ export const sentryTransport: Transport = (
|
|||||||
timestamp: timestamp / 1000, // Sentry expects seconds
|
timestamp: timestamp / 1000, // Sentry expects seconds
|
||||||
})
|
})
|
||||||
|
|
||||||
// We don't want to send any network errors to sentry
|
// We don't want to send any network errors to sentry. The underlying
|
||||||
if (isNetworkError(message)) {
|
// cause is often passed via metadata rather than the message itself, so
|
||||||
|
// check the common metadata keys too.
|
||||||
|
if (
|
||||||
|
isNetworkError(message) ||
|
||||||
|
isNetworkError(metadata.safeMessage) ||
|
||||||
|
isNetworkError(metadata.message) ||
|
||||||
|
isNetworkError(metadata.error)
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send all higher levels with `captureMessage`, with appropriate severity
|
* Only error-level strings are reported to Sentry as events. Lower levels
|
||||||
* level
|
* are captured as breadcrumbs above and attached to the next event, if
|
||||||
|
* any.
|
||||||
*/
|
*/
|
||||||
if (level === 'error' || level === 'warn' || level === 'log') {
|
if (level === LogLevel.Error) {
|
||||||
// Defer non-critical messages so they're sent in a batch
|
// Defer non-critical messages so they're sent in a batch
|
||||||
queueMessageForSentry(message, {
|
queueMessageForSentry(message, {
|
||||||
level: severity,
|
level: severity,
|
||||||
@@ -65,6 +73,11 @@ export const sentryTransport: Transport = (
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// We don't want to send any network errors to sentry
|
||||||
|
if (isNetworkError(message)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It's otherwise an Error and should be reported with captureException
|
* It's otherwise an Error and should be reported with captureException
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const ChooseAccountForm = ({
|
|||||||
})
|
})
|
||||||
Toast.show(_(msg`Signed in as @${account.handle}`))
|
Toast.show(_(msg`Signed in as @${account.handle}`))
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.error('choose account: initSession failed', {
|
logger.warn('choose account: initSession failed', {
|
||||||
message: e instanceof Error ? e.message : 'Unknown error',
|
message: e instanceof Error ? e.message : 'Unknown error',
|
||||||
})
|
})
|
||||||
// Move to login form.
|
// Move to login form.
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ export class MessagesEventBus {
|
|||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
if (!isNetworkError(e) && !isErrorMaybeAppPasswordPermissions(e)) {
|
if (!isNetworkError(e) && !isErrorMaybeAppPasswordPermissions(e)) {
|
||||||
logger.error(`poll events failed`, {
|
logger.warn(`poll events failed`, {
|
||||||
safeMessage: e.message,
|
safeMessage: e.message,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ let PostFeed = ({
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!isNetworkError(e)) {
|
if (!isNetworkError(e)) {
|
||||||
logger.error('Poll latest failed', {feed, message: String(e)})
|
logger.warn('Poll latest failed', {feed, message: String(e)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user