UNPKG

@snap/camera-kit

Version:
82 lines 4.08 kB
import { isState } from "@snap/state-management"; import { filter, map, scan, Subject, takeUntil } from "rxjs"; import { Injectable } from "@snap/ts-inject"; import { entries } from "../../common/entries"; import { stringifyError, stringifyErrorMessage } from "../../common/errorHelpers"; import { TypedCustomEvent } from "../../events/TypedCustomEvent"; import { logEntriesFactory } from "../../logger/logEntries"; import { logLevelMap } from "../../logger/logger"; import { metricsEventTargetFactory } from "../metricsEventTarget"; import { metricsClientFactory } from "../../clients/metricsClient"; import { Count } from "../operational/Count"; const logMethods = entries(logLevelMap).map(([level]) => level); const maxBufferedEntries = 15; const contextSeparator = "\n\n----------------- Context -----------------\n\n"; const methodLength = logMethods.reduce((max, method) => Math.max(max, method.length), 0); export function getContextString(logEntries) { const result = []; for (const { entry, count, lastTime } of logEntries) { const time = entry.time.toISOString(); const method = entry.level.padStart(methodLength); const messages = entry.messages.map(prettyPrintMessage).join(" "); let dupSuffix = count > 1 ? ` (Repeated ${count} times with the last occurrence at ${lastTime.toISOString()})` : ""; result.push(`${time} [${entry.module}] ${method}: ${messages}${dupSuffix}`); } return result.join("\n"); } function prettyPrintMessage(message) { if (message instanceof Error) return stringifyErrorMessage(message); if (message instanceof Date) return message.toISOString(); return message + ""; } export function reportExceptionToBlizzard(logEntries, metricsEventTarget, metrics, lensState) { logEntries .pipe(scan(({ entries }, newEntry) => { const lastEntry = entries[entries.length - 1]; const isNewEntryRepeated = lastEntry && lastEntry.entry.messages.join() === newEntry.messages.join() && lastEntry.entry.level === newEntry.level; if (isNewEntryRepeated) { lastEntry.count += 1; lastEntry.lastTime = newEntry.time; } else { entries.push({ entry: newEntry, count: 1, lastTime: newEntry.time, }); } return { entries: entries.slice(-maxBufferedEntries), recent: newEntry, }; }, { entries: [], recent: { time: new Date(), module: "any", level: "debug", messages: [] } }), filter(({ recent }) => recent.level === "error"), map(({ entries, recent }) => ({ context: entries, error: recent.messages.find((e) => e instanceof Error), })), filter(({ error }) => !!error)) .subscribe(({ error, context }) => { const currentLensState = lensState === null || lensState === void 0 ? void 0 : lensState.getState(); const lensId = currentLensState && !isState(currentLensState, "noLensApplied") ? currentLensState.data.id : "none"; metricsEventTarget.dispatchEvent(new TypedCustomEvent("exception", { name: "exception", lensId, type: error.name, reason: `${stringifyError(error)}${contextSeparator}${getContextString(context)}`, })); metrics.setOperationalMetrics(Count.count("handled_exception", 1, { type: error.name })); }); } export const reportGlobalException = Injectable("reportGlobalException", [logEntriesFactory.token, metricsEventTargetFactory.token, metricsClientFactory.token], (logEntries, metricsEventTarget, metrics) => { const cancellationSubject = new Subject(); reportExceptionToBlizzard(logEntries.pipe(takeUntil(cancellationSubject)), metricsEventTarget, metrics); return { attachLensContext: (lensState) => { cancellationSubject.next(); reportExceptionToBlizzard(logEntries, metricsEventTarget, metrics, lensState); }, }; }); //# sourceMappingURL=reportGlobalException.js.map