-
-
Save KeKs0r/ece9a454561bb864f806549d3b8e715c to your computer and use it in GitHub Desktop.
Replicache Log Sink
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { parse } from 'querystring' | |
import type { LogSink } from 'replicache' | |
import { isPlainObject } from 'lodash' | |
import { logger } from '@laserfocus/ui/logger' | |
// Those just wrap the sentry SDK | |
import { captureException, setExtra } from '@laserfocus/ui/error-reporting' | |
import { WrappedBaseError, BaseError } from '@laserfocus/shared/util-error' | |
class WrappedReplicacheError extends WrappedBaseError { | |
isOperational = true | |
name = 'WrappedReplicacheError' | |
} | |
class ReplicacheError extends BaseError { | |
isOperational = true | |
name = 'ReplicacheError' | |
} | |
export const SentryLogSink: LogSink = { | |
log(level, ...args) { | |
if (level === 'error') { | |
const parsed = parseLogSinkMessage(args) | |
try { | |
if (typeof navigator.storage?.estimate === 'function') { | |
// Add Storage info to replicache related errors | |
navigator.storage.estimate().then((quota) => { | |
setExtra('storage', quota) | |
captureException(parsed) | |
}) | |
} else { | |
captureException(parsed) | |
} | |
} catch (e: unknown) { | |
console.error(e) | |
} | |
captureException(parsed) | |
} else if (level === 'info') { | |
logger.info(...args) | |
} | |
}, | |
} | |
export function parseLogSinkMessage(args: unknown[]): WrappedReplicacheError | ReplicacheError { | |
const message: string = | |
args.filter(isString).find((a) => !a.includes('=')) || 'Replicache Error' | |
const remaining = args.filter((a) => a !== message) | |
const initialContext: Record<string, string | string[] | undefined> = {} | |
const contextStringArgs: string[] = remaining.filter(isString).filter((a) => a.includes('=')) | |
const contextValues = contextStringArgs.reduce((context, curr) => { | |
const parsed = parse(curr) | |
return { | |
...context, | |
...parsed, | |
} | |
}, initialContext) | |
const cause = remaining.find(isCause) | |
if (cause) { | |
return new WrappedReplicacheError(message, cause, contextValues) | |
} | |
return new ReplicacheError(message, contextValues) | |
} | |
function isString(a: unknown): a is string { | |
return typeof a === 'string' | |
} | |
function isCause(a: unknown): a is Error { | |
return a instanceof Error || isErrorIsh(a) | |
} | |
function isErrorIsh(a: any) { | |
return isPlainObject(a) && a?.name && a?.stack && a?.message | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment