@dasasian/firebase-structured-logger 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/client/breadcrumbs.d.ts.map +1 -1
- package/dist/client/breadcrumbs.js +8 -3
- package/dist/client/breadcrumbs.js.map +1 -1
- package/dist/client/errorHandler.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/logger.d.ts +5 -5
- package/dist/client/logger.d.ts.map +1 -1
- package/dist/client/logger.js +40 -54
- package/dist/client/logger.js.map +1 -1
- package/dist/client/rateLimiter.d.ts +26 -4
- package/dist/client/rateLimiter.d.ts.map +1 -1
- package/dist/client/rateLimiter.js +36 -31
- package/dist/client/rateLimiter.js.map +1 -1
- package/dist/functions/logHandler.d.ts.map +1 -1
- package/dist/functions/logHandler.js +9 -38
- package/dist/functions/logHandler.js.map +1 -1
- package/dist/functions/logger.d.ts +8 -3
- package/dist/functions/logger.d.ts.map +1 -1
- package/dist/functions/logger.js +46 -68
- package/dist/functions/logger.js.map +1 -1
- package/dist/functions/requestLogger.d.ts.map +1 -1
- package/dist/functions/requestLogger.js +2 -5
- package/dist/functions/requestLogger.js.map +1 -1
- package/dist/functions/sourceMapCache.d.ts +10 -2
- package/dist/functions/sourceMapCache.d.ts.map +1 -1
- package/dist/functions/sourceMapCache.js +37 -14
- package/dist/functions/sourceMapCache.js.map +1 -1
- package/dist/functions/symbolicate.d.ts +6 -2
- package/dist/functions/symbolicate.d.ts.map +1 -1
- package/dist/functions/symbolicate.js +23 -5
- package/dist/functions/symbolicate.js.map +1 -1
- package/dist/shared/error.d.ts +6 -0
- package/dist/shared/error.d.ts.map +1 -0
- package/dist/shared/error.js +18 -0
- package/dist/shared/error.js.map +1 -0
- package/dist/shared/severity.d.ts +9 -0
- package/dist/shared/severity.d.ts.map +1 -0
- package/dist/shared/severity.js +16 -0
- package/dist/shared/severity.js.map +1 -0
- package/dist/shared/types.d.ts +7 -6
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<a href="https://www.npmjs.com/package/@dasasian/firebase-structured-logger"><img alt="npm" src="https://img.shields.io/npm/v/@dasasian/firebase-structured-logger?style=flat-square&color=235a9b"></a>
|
|
7
|
-
<a href="
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
<a href="https://www.npmjs.com/package/@dasasian/firebase-structured-logger"><img alt="npm" src="https://img.shields.io/npm/v/@dasasian/firebase-structured-logger?style=flat-square&label=npm&color=235a9b"></a>
|
|
7
|
+
<a href="https://github.com/dasasian/firebase-structured-logger/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/dasasian/firebase-structured-logger/ci.yml?branch=main&style=flat-square&label=CI"></a>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<a href="https://dasasian.com/firebase-structured-logger"><strong>dasasian.com/firebase-structured-logger</strong></a>
|
|
10
12
|
</p>
|
|
11
13
|
|
|
12
14
|
# @dasasian/firebase-structured-logger
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAStD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEpE;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAErD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAEtD;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI,
|
|
1
|
+
{"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAStD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEpE;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAErD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAEtD;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI,CAeN;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,CAEnE;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED,eAAO,MAAM,EAAE;mBACE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBACtC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBACpC,MAAM;kBACR,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CACtD,CAAA"}
|
|
@@ -27,10 +27,15 @@ function getActiveActivity() {
|
|
|
27
27
|
return activeActivity;
|
|
28
28
|
}
|
|
29
29
|
function addBreadcrumb(type, name, data) {
|
|
30
|
-
const
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
const entry = { timestamp: now, type, name, data };
|
|
31
32
|
breadcrumbs.push(entry);
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
// Entries are appended in timestamp order, so only rebuild the array when the
|
|
34
|
+
// oldest one has actually aged out — otherwise there is nothing to drop.
|
|
35
|
+
const cutoff = now - MAX_AGE_MS;
|
|
36
|
+
if (breadcrumbs[0].timestamp <= cutoff) {
|
|
37
|
+
breadcrumbs = breadcrumbs.filter((bc) => bc.timestamp > cutoff);
|
|
38
|
+
}
|
|
34
39
|
if (breadcrumbs.length > MAX_BREADCRUMBS) {
|
|
35
40
|
breadcrumbs = breadcrumbs.slice(breadcrumbs.length - MAX_BREADCRUMBS);
|
|
36
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"breadcrumbs.js","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":";;;AASA,4CAGC;AAED,8CAEC;AAED,4CAEC;AAED,8CAEC;AAED,
|
|
1
|
+
{"version":3,"file":"breadcrumbs.js","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":";;;AASA,4CAGC;AAED,8CAEC;AAED,4CAEC;AAED,8CAEC;AAED,sCAmBC;AAED,gDAEC;AAED,4CAIC;AArDD,MAAM,eAAe,GAAG,EAAE,CAAA;AAC1B,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,YAAY;AAE7C,IAAI,aAAiC,CAAA;AACrC,IAAI,cAAkC,CAAA;AACtC,IAAI,WAAW,GAAsB,EAAE,CAAA;AAEvC,SAAgB,gBAAgB,CAAC,MAAc;IAC7C,aAAa,GAAG,MAAM,CAAA;IACtB,aAAa,CAAC,KAAK,EAAE,YAAY,MAAM,EAAE,CAAC,CAAA;AAC5C,CAAC;AAED,SAAgB,iBAAiB,CAAC,QAA4B;IAC5D,cAAc,GAAG,QAAQ,CAAA;AAC3B,CAAC;AAED,SAAgB,gBAAgB;IAC9B,OAAO,aAAa,CAAA;AACtB,CAAC;AAED,SAAgB,iBAAiB;IAC/B,OAAO,cAAc,CAAA;AACvB,CAAC;AAED,SAAgB,aAAa,CAC3B,IAA6B,EAC7B,IAAY,EACZ,IAA8B;IAE9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,MAAM,KAAK,GAAoB,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACnE,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAEvB,8EAA8E;IAC9E,yEAAyE;IACzE,MAAM,MAAM,GAAG,GAAG,GAAG,UAAU,CAAA;IAC/B,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,MAAM,EAAE,CAAC;QACvC,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,GAAG,MAAM,CAAC,CAAA;IACjE,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACzC,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,eAAe,CAAC,CAAA;IACvE,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAa;IAC9C,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAA;AACnE,CAAC;AAED,SAAgB,gBAAgB;IAC9B,WAAW,GAAG,EAAE,CAAA;IAChB,aAAa,GAAG,SAAS,CAAA;IACzB,cAAc,GAAG,SAAS,CAAA;AAC5B,CAAC;AAEY,QAAA,EAAE,GAAG;IAChB,MAAM,EAAE,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC;IAC7F,KAAK,EAAG,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;IAC5F,GAAG,EAAK,CAAC,MAAc,EAAE,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC;IACpD,KAAK,EAAG,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;CAC7F,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/client/errorHandler.ts"],"names":[],"mappings":";;AAEA,0DAUC;AAED,4CASC;AAvBD,qCAA0C;AAE1C,SAAgB,uBAAuB;IACrC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACzC,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;QACnD,IAAA,wBAAe,GAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/client/errorHandler.ts"],"names":[],"mappings":";;AAEA,0DAUC;AAED,4CASC;AAvBD,qCAA0C;AAE1C,SAAgB,uBAAuB;IACrC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACzC,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;QACnD,IAAA,wBAAe,GAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC,CAAA;IAC9F,CAAC,CAAC,CAAA;IAEF,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE;QACtD,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;QACzD,IAAA,wBAAe,GAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC,CAAA;IACpG,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAgB,gBAAgB,CAC9B,KAAY,EACZ,SAAqC;IAErC,IAAA,wBAAe,GAAE,CAAC,KAAK,CACrB,KAAK,EACL,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,EACnD,EAAE,cAAc,EAAE,SAAS,CAAC,cAAc,EAAE,CAC7C,CAAA;AACH,CAAC"}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { initLogger, getClientLogger,
|
|
2
|
-
export type { InitLoggerConfig, RateLimitConfig } from './logger';
|
|
1
|
+
export { initLogger, getClientLogger, triggerTestLog } from './logger';
|
|
2
|
+
export type { Logger, InitLoggerConfig, RateLimitConfig } from './logger';
|
|
3
3
|
export { setupGlobalErrorHandler, handleReactError } from './errorHandler';
|
|
4
4
|
export { addBreadcrumb, setActiveActivity, bc } from './breadcrumbs';
|
|
5
5
|
export type { LogSeverity, LogPayload, BreadcrumbEntry, BaseLabels } from '../shared/types';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAMtE,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AACzE,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,eAAe,CAAA;AACpE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA"}
|
package/dist/client/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bc = exports.setActiveActivity = exports.addBreadcrumb = exports.handleReactError = exports.setupGlobalErrorHandler = exports.triggerTestLog = exports.
|
|
3
|
+
exports.bc = exports.setActiveActivity = exports.addBreadcrumb = exports.handleReactError = exports.setupGlobalErrorHandler = exports.triggerTestLog = exports.getClientLogger = exports.initLogger = void 0;
|
|
4
4
|
var logger_1 = require("./logger");
|
|
5
5
|
Object.defineProperty(exports, "initLogger", { enumerable: true, get: function () { return logger_1.initLogger; } });
|
|
6
6
|
Object.defineProperty(exports, "getClientLogger", { enumerable: true, get: function () { return logger_1.getClientLogger; } });
|
|
7
|
-
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
|
|
8
7
|
Object.defineProperty(exports, "triggerTestLog", { enumerable: true, get: function () { return logger_1.triggerTestLog; } });
|
|
9
8
|
var errorHandler_1 = require("./errorHandler");
|
|
10
9
|
Object.defineProperty(exports, "setupGlobalErrorHandler", { enumerable: true, get: function () { return errorHandler_1.setupGlobalErrorHandler; } });
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;AAAA,mCAAsE;AAA7D,oGAAA,UAAU,OAAA;AAAE,yGAAA,eAAe,OAAA;AAAE,wGAAA,cAAc,OAAA;AAOpD,+CAA0E;AAAjE,uHAAA,uBAAuB,OAAA;AAAE,gHAAA,gBAAgB,OAAA;AAClD,6CAAoE;AAA3D,4GAAA,aAAa,OAAA;AAAE,gHAAA,iBAAiB,OAAA;AAAE,iGAAA,EAAE,OAAA"}
|
package/dist/client/logger.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LogSeverity, LogPayload } from '../shared/types';
|
|
1
|
+
import type { LogSeverity, LogPayload, BaseLabels } from '../shared/types';
|
|
2
2
|
import { type RateLimitConfig } from './rateLimiter';
|
|
3
3
|
export type { RateLimitConfig };
|
|
4
4
|
type LogCallable = (data: LogPayload) => Promise<unknown>;
|
|
@@ -19,10 +19,10 @@ export declare class Logger<AppLabels extends Record<string, string | undefined>
|
|
|
19
19
|
clearUser(): void;
|
|
20
20
|
setScreen(screen: string): void;
|
|
21
21
|
addBreadcrumb(type: 'action' | 'state' | 'nav' | 'error', name: string, data?: Record<string, unknown>): void;
|
|
22
|
-
error(raw: unknown, labels?: Partial<AppLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
|
|
23
|
-
info(message: string, labels?: Partial<AppLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
|
|
24
|
-
warning(message: string, labels?: Partial<AppLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
|
|
25
|
-
debug(message: string, labels?: Partial<AppLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
|
|
22
|
+
error(raw: unknown, labels?: Partial<AppLabels & BaseLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
|
|
23
|
+
info(message: string, labels?: Partial<AppLabels & BaseLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
|
|
24
|
+
warning(message: string, labels?: Partial<AppLabels & BaseLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
|
|
25
|
+
debug(message: string, labels?: Partial<AppLabels & BaseLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
|
|
26
26
|
private send;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"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"}
|
package/dist/client/logger.js
CHANGED
|
@@ -4,49 +4,39 @@ exports.Logger = void 0;
|
|
|
4
4
|
exports.triggerTestLog = triggerTestLog;
|
|
5
5
|
exports.initLogger = initLogger;
|
|
6
6
|
exports.getClientLogger = getClientLogger;
|
|
7
|
+
const severity_1 = require("../shared/severity");
|
|
8
|
+
const error_1 = require("../shared/error");
|
|
7
9
|
const breadcrumbs_1 = require("./breadcrumbs");
|
|
8
10
|
const rateLimiter_1 = require("./rateLimiter");
|
|
9
|
-
const SEVERITY_ORDER = {
|
|
10
|
-
ERROR: 0,
|
|
11
|
-
WARNING: 1,
|
|
12
|
-
INFO: 2,
|
|
13
|
-
DEBUG: 3,
|
|
14
|
-
};
|
|
15
11
|
function defaultMinLevel() {
|
|
16
12
|
if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production')
|
|
17
13
|
return 'WARNING';
|
|
18
14
|
return 'DEBUG';
|
|
19
15
|
}
|
|
20
|
-
|
|
16
|
+
// Order matters — first match wins.
|
|
17
|
+
const PLATFORMS = [
|
|
18
|
+
[/iPhone|iPad|iPod/, 'ios'],
|
|
19
|
+
[/Android/, 'android'],
|
|
20
|
+
[/Mac/, 'macos'],
|
|
21
|
+
[/Win/, 'windows'],
|
|
22
|
+
[/Linux/, 'linux'],
|
|
23
|
+
];
|
|
24
|
+
const BROWSERS = [
|
|
25
|
+
[/Firefox/, 'firefox'],
|
|
26
|
+
[/Edg/, 'edge'],
|
|
27
|
+
[/Chrome/, 'chrome'],
|
|
28
|
+
[/Safari/, 'safari'],
|
|
29
|
+
];
|
|
30
|
+
function matchUserAgent(table, fallback) {
|
|
21
31
|
if (typeof navigator === 'undefined')
|
|
22
32
|
return 'unknown';
|
|
23
33
|
const ua = navigator.userAgent;
|
|
24
|
-
|
|
25
|
-
return 'ios';
|
|
26
|
-
if (/Android/.test(ua))
|
|
27
|
-
return 'android';
|
|
28
|
-
if (/Mac/.test(ua))
|
|
29
|
-
return 'macos';
|
|
30
|
-
if (/Win/.test(ua))
|
|
31
|
-
return 'windows';
|
|
32
|
-
if (/Linux/.test(ua))
|
|
33
|
-
return 'linux';
|
|
34
|
-
return 'web';
|
|
35
|
-
}
|
|
36
|
-
function getBrowser() {
|
|
37
|
-
if (typeof navigator === 'undefined')
|
|
38
|
-
return 'unknown';
|
|
39
|
-
const ua = navigator.userAgent;
|
|
40
|
-
if (/Firefox/.test(ua))
|
|
41
|
-
return 'firefox';
|
|
42
|
-
if (/Edg/.test(ua))
|
|
43
|
-
return 'edge';
|
|
44
|
-
if (/Chrome/.test(ua))
|
|
45
|
-
return 'chrome';
|
|
46
|
-
if (/Safari/.test(ua))
|
|
47
|
-
return 'safari';
|
|
48
|
-
return 'unknown';
|
|
34
|
+
return table.find(([pattern]) => pattern.test(ua))?.[1] ?? fallback;
|
|
49
35
|
}
|
|
36
|
+
// The user agent never changes for the lifetime of the page, so resolve both
|
|
37
|
+
// once at module load rather than re-running the regexes on every log call.
|
|
38
|
+
const PLATFORM = matchUserAgent(PLATFORMS, 'web');
|
|
39
|
+
const BROWSER = matchUserAgent(BROWSERS, 'unknown');
|
|
50
40
|
async function blobToBase64(blob) {
|
|
51
41
|
return new Promise((resolve, reject) => {
|
|
52
42
|
const reader = new FileReader();
|
|
@@ -70,7 +60,7 @@ class Logger {
|
|
|
70
60
|
userLabels = {};
|
|
71
61
|
constructor(config) {
|
|
72
62
|
this.config = config;
|
|
73
|
-
this.minLevel = SEVERITY_ORDER[config.minLogLevel ?? defaultMinLevel()];
|
|
63
|
+
this.minLevel = severity_1.SEVERITY_ORDER[config.minLogLevel ?? defaultMinLevel()];
|
|
74
64
|
if (config.rateLimitOptions) {
|
|
75
65
|
(0, rateLimiter_1.configureRateLimiter)(config.rateLimitOptions);
|
|
76
66
|
}
|
|
@@ -91,24 +81,12 @@ class Logger {
|
|
|
91
81
|
(0, breadcrumbs_1.addBreadcrumb)(type, name, data);
|
|
92
82
|
}
|
|
93
83
|
error(raw, labels, context, attachments) {
|
|
94
|
-
const error =
|
|
95
|
-
const screen = (0, breadcrumbs_1.getCurrentScreen)();
|
|
96
|
-
const activity = (0, breadcrumbs_1.getActiveActivity)();
|
|
97
|
-
if (!(0, rateLimiter_1.canLogError)(error, screen, activity)) {
|
|
98
|
-
console.error('[fsl] Error suppressed:', error.message);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
(0, rateLimiter_1.recordError)(error, screen, activity);
|
|
84
|
+
const error = (0, error_1.toError)(raw);
|
|
102
85
|
const errorLabels = {
|
|
103
86
|
errorType: error.name || 'UnknownError',
|
|
104
87
|
...labels,
|
|
105
88
|
};
|
|
106
|
-
void this.send(error.message, 'ERROR', errorLabels, context, attachments,
|
|
107
|
-
message: error.message,
|
|
108
|
-
stack: error.stack,
|
|
109
|
-
name: error.name,
|
|
110
|
-
cause: error.cause != null ? String(error.cause) : undefined,
|
|
111
|
-
});
|
|
89
|
+
void this.send(error.message, 'ERROR', errorLabels, context, attachments, (0, error_1.toErrorPayload)(error), (0, rateLimiter_1.signatureFor)(error, (0, breadcrumbs_1.getCurrentScreen)(), (0, breadcrumbs_1.getActiveActivity)()));
|
|
112
90
|
}
|
|
113
91
|
info(message, labels, context, attachments) {
|
|
114
92
|
void this.send(message, 'INFO', labels, context, attachments);
|
|
@@ -119,11 +97,20 @@ class Logger {
|
|
|
119
97
|
debug(message, labels, context, attachments) {
|
|
120
98
|
void this.send(message, 'DEBUG', labels, context, attachments);
|
|
121
99
|
}
|
|
122
|
-
async send(message, severity, labels, context, attachments, error) {
|
|
123
|
-
if (SEVERITY_ORDER[severity] > this.minLevel)
|
|
100
|
+
async send(message, severity, labels, context, attachments, error, signature) {
|
|
101
|
+
if (severity_1.SEVERITY_ORDER[severity] > this.minLevel)
|
|
124
102
|
return;
|
|
125
|
-
|
|
126
|
-
|
|
103
|
+
// One gate for every severity. Passing a signature opts this log into
|
|
104
|
+
// duplicate suppression; the check and the budget spend are one operation,
|
|
105
|
+
// so a log can neither be counted twice nor checked without being counted.
|
|
106
|
+
const decision = (0, rateLimiter_1.allow)(signature);
|
|
107
|
+
if (!decision.allowed) {
|
|
108
|
+
if (decision.reason === 'duplicate') {
|
|
109
|
+
console.warn(`[fsl] Duplicate suppressed: ${decision.signature}`);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
console.warn('[fsl] Session log limit reached');
|
|
113
|
+
}
|
|
127
114
|
return;
|
|
128
115
|
}
|
|
129
116
|
try {
|
|
@@ -132,8 +119,8 @@ class Logger {
|
|
|
132
119
|
releaseId: this.config.releaseId,
|
|
133
120
|
screen: (0, breadcrumbs_1.getCurrentScreen)(),
|
|
134
121
|
userId: this.userId,
|
|
135
|
-
platform:
|
|
136
|
-
browser:
|
|
122
|
+
platform: PLATFORM,
|
|
123
|
+
browser: BROWSER,
|
|
137
124
|
...this.userLabels,
|
|
138
125
|
...labels,
|
|
139
126
|
};
|
|
@@ -155,7 +142,6 @@ class Logger {
|
|
|
155
142
|
},
|
|
156
143
|
...(base64Attachments ? { attachments: base64Attachments } : {}),
|
|
157
144
|
};
|
|
158
|
-
(0, rateLimiter_1.recordLog)();
|
|
159
145
|
await this.config.logFunction(payload);
|
|
160
146
|
}
|
|
161
147
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":";;;AAmPA,wCAWC;AAKD,gCAKC;AAED,0CAKC;AA9QD,+CAOsB;AACtB,+
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,9 +4,31 @@ export interface RateLimitConfig {
|
|
|
4
4
|
storageKey?: string;
|
|
5
5
|
}
|
|
6
6
|
export declare function configureRateLimiter(options: RateLimitConfig): void;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Build the key used to recognise a repeat of the same problem. Two occurrences
|
|
9
|
+
* count as duplicates only if the message, the screen and the activity all match,
|
|
10
|
+
* so the same error from two different places is not collapsed into one.
|
|
11
|
+
*/
|
|
12
|
+
export declare function signatureFor(error: Error | string, screen?: string, activity?: string): string;
|
|
13
|
+
export type RateLimitDecision = {
|
|
14
|
+
allowed: true;
|
|
15
|
+
} | {
|
|
16
|
+
allowed: false;
|
|
17
|
+
reason: 'session-limit' | 'duplicate';
|
|
18
|
+
signature?: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Decide whether one log may be sent, and consume its budget if so.
|
|
22
|
+
*
|
|
23
|
+
* Check and consume are one operation on purpose. They used to be separate
|
|
24
|
+
* exports called from two different layers, which meant an error was checked
|
|
25
|
+
* against the session limit twice and counted against it twice — a configured
|
|
26
|
+
* limit of 50 was really 25 for errors. A single call cannot double-count, and
|
|
27
|
+
* cannot be checked without consuming.
|
|
28
|
+
*
|
|
29
|
+
* Pass a `signature` to opt this log into duplicate suppression. Any severity
|
|
30
|
+
* may do so; it is not reserved for errors.
|
|
31
|
+
*/
|
|
32
|
+
export declare function allow(signature?: string): RateLimitDecision;
|
|
11
33
|
export declare function resetRateLimiter(): void;
|
|
12
34
|
//# sourceMappingURL=rateLimiter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rateLimiter.d.ts","sourceRoot":"","sources":["../../src/client/rateLimiter.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;
|
|
1
|
+
{"version":3,"file":"rateLimiter.d.ts","sourceRoot":"","sources":["../../src/client/rateLimiter.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAeD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAEnE;AAmBD;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,KAAK,GAAG,MAAM,EACrB,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAGR;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjF;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAkB3D;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.configureRateLimiter = configureRateLimiter;
|
|
4
|
-
exports.
|
|
5
|
-
exports.
|
|
6
|
-
exports.recordLog = recordLog;
|
|
7
|
-
exports.recordError = recordError;
|
|
4
|
+
exports.signatureFor = signatureFor;
|
|
5
|
+
exports.allow = allow;
|
|
8
6
|
exports.resetRateLimiter = resetRateLimiter;
|
|
9
7
|
const DEFAULT_SESSION_LIMIT = 50;
|
|
10
8
|
const DEFAULT_DUPLICATE_LIMIT = 3;
|
|
11
9
|
const DEFAULT_STORAGE_KEY = 'fsl_ratelimit';
|
|
10
|
+
// Session-scoped by design: one browser session, one budget. Deliberately not
|
|
11
|
+
// per-Logger — see the module-scoped state rule in CLAUDE.md.
|
|
12
12
|
let config = {
|
|
13
13
|
sessionLimit: DEFAULT_SESSION_LIMIT,
|
|
14
14
|
duplicateLimit: DEFAULT_DUPLICATE_LIMIT,
|
|
@@ -17,7 +17,7 @@ let config = {
|
|
|
17
17
|
function configureRateLimiter(options) {
|
|
18
18
|
config = { ...config, ...options };
|
|
19
19
|
}
|
|
20
|
-
function
|
|
20
|
+
function readState() {
|
|
21
21
|
try {
|
|
22
22
|
const stored = sessionStorage.getItem(config.storageKey);
|
|
23
23
|
return stored ? JSON.parse(stored) : { logCount: 0, errorSignatures: {} };
|
|
@@ -26,45 +26,50 @@ function getState() {
|
|
|
26
26
|
return { logCount: 0, errorSignatures: {} };
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
function
|
|
29
|
+
function writeState(state) {
|
|
30
30
|
try {
|
|
31
31
|
sessionStorage.setItem(config.storageKey, JSON.stringify(state));
|
|
32
32
|
}
|
|
33
33
|
catch {
|
|
34
|
-
//
|
|
34
|
+
// sessionStorage full or unavailable — rate limiting degrades, logging continues
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Build the key used to recognise a repeat of the same problem. Two occurrences
|
|
39
|
+
* count as duplicates only if the message, the screen and the activity all match,
|
|
40
|
+
* so the same error from two different places is not collapsed into one.
|
|
41
|
+
*/
|
|
42
|
+
function signatureFor(error, screen, activity) {
|
|
38
43
|
const str = error instanceof Error ? `${error.name}:${error.message}` : String(error);
|
|
39
44
|
return `${str}|${screen ?? ''}|${activity ?? ''}`;
|
|
40
45
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Decide whether one log may be sent, and consume its budget if so.
|
|
48
|
+
*
|
|
49
|
+
* Check and consume are one operation on purpose. They used to be separate
|
|
50
|
+
* exports called from two different layers, which meant an error was checked
|
|
51
|
+
* against the session limit twice and counted against it twice — a configured
|
|
52
|
+
* limit of 50 was really 25 for errors. A single call cannot double-count, and
|
|
53
|
+
* cannot be checked without consuming.
|
|
54
|
+
*
|
|
55
|
+
* Pass a `signature` to opt this log into duplicate suppression. Any severity
|
|
56
|
+
* may do so; it is not reserved for errors.
|
|
57
|
+
*/
|
|
58
|
+
function allow(signature) {
|
|
59
|
+
const state = readState();
|
|
46
60
|
if (state.logCount >= config.sessionLimit) {
|
|
47
|
-
|
|
48
|
-
return false;
|
|
61
|
+
return { allowed: false, reason: 'session-limit' };
|
|
49
62
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
63
|
+
if (signature !== undefined) {
|
|
64
|
+
const seen = state.errorSignatures[signature] ?? 0;
|
|
65
|
+
if (seen >= config.duplicateLimit) {
|
|
66
|
+
return { allowed: false, reason: 'duplicate', signature };
|
|
67
|
+
}
|
|
68
|
+
state.errorSignatures[signature] = seen + 1;
|
|
54
69
|
}
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
|
-
function recordLog() {
|
|
58
|
-
const state = getState();
|
|
59
|
-
state.logCount++;
|
|
60
|
-
saveState(state);
|
|
61
|
-
}
|
|
62
|
-
function recordError(error, screen, activity) {
|
|
63
|
-
const state = getState();
|
|
64
|
-
const sig = getErrorSignature(error, screen, activity);
|
|
65
|
-
state.errorSignatures[sig] = (state.errorSignatures[sig] ?? 0) + 1;
|
|
66
70
|
state.logCount++;
|
|
67
|
-
|
|
71
|
+
writeState(state);
|
|
72
|
+
return { allowed: true };
|
|
68
73
|
}
|
|
69
74
|
function resetRateLimiter() {
|
|
70
75
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rateLimiter.js","sourceRoot":"","sources":["../../src/client/rateLimiter.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"rateLimiter.js","sourceRoot":"","sources":["../../src/client/rateLimiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logHandler.d.ts","sourceRoot":"","sources":["../../src/functions/logHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAA;AACtF,OAAO,KAAK,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"logHandler.d.ts","sourceRoot":"","sources":["../../src/functions/logHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAA;AACtF,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,iBAAiB,CAAA;AAU/D,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;IAClC,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AA8DD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,IAGrD,SAAS,eAAe,CAAC,UAAU,CAAC,KAAG,OAAO,CAAC,IAAI,CAAC,CAgCnE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,sBAAsB,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,8FAM/F"}
|
|
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createClientLogHandler = createClientLogHandler;
|
|
4
4
|
exports.createClientLogFunction = createClientLogFunction;
|
|
5
5
|
const https_1 = require("firebase-functions/v2/https");
|
|
6
|
+
const severity_1 = require("../shared/severity");
|
|
6
7
|
const logger_1 = require("./logger");
|
|
7
8
|
const sourceMapCache_1 = require("./sourceMapCache");
|
|
8
9
|
const symbolicate_1 = require("./symbolicate");
|
|
9
|
-
const VALID_SEVERITIES = new Set(
|
|
10
|
+
const VALID_SEVERITIES = new Set(severity_1.SEVERITIES);
|
|
10
11
|
/**
|
|
11
12
|
* Extract the bundle filename (e.g. "index-DnZ05f3M.js") from a frame URL.
|
|
12
13
|
*/
|
|
@@ -18,7 +19,7 @@ function bundleFileFromUrl(url) {
|
|
|
18
19
|
* Attempt to symbolicate a minified error stack trace using source maps.
|
|
19
20
|
* Loads source maps per-bundle so multiple chunks are handled correctly.
|
|
20
21
|
*/
|
|
21
|
-
async function symbolicateError(releaseId, error) {
|
|
22
|
+
async function symbolicateError(releaseId, error, bucketName) {
|
|
22
23
|
if (!error?.stack)
|
|
23
24
|
return error;
|
|
24
25
|
try {
|
|
@@ -37,32 +38,16 @@ async function symbolicateError(releaseId, error) {
|
|
|
37
38
|
// Load source map for each unique bundle (getSourceMap handles caching)
|
|
38
39
|
const sourceMaps = new Map();
|
|
39
40
|
await Promise.all(Array.from(bundleFiles).map(async (bundle) => {
|
|
40
|
-
const map = await (0, sourceMapCache_1.getSourceMap)(releaseId, bundle);
|
|
41
|
+
const map = await (0, sourceMapCache_1.getSourceMap)(releaseId, bundle, bucketName);
|
|
41
42
|
if (map)
|
|
42
43
|
sourceMaps.set(bundle, map);
|
|
43
44
|
}));
|
|
44
45
|
if (sourceMaps.size === 0)
|
|
45
46
|
return error;
|
|
46
47
|
// Symbolicate each frame with its bundle's source map
|
|
47
|
-
const symbolicated =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const bundle = bundleFileFromUrl(frame.fileName);
|
|
51
|
-
if (!bundle)
|
|
52
|
-
return frame;
|
|
53
|
-
const sourceMap = sourceMaps.get(bundle);
|
|
54
|
-
if (!sourceMap)
|
|
55
|
-
return frame;
|
|
56
|
-
const result = (0, symbolicate_1.symbolicate)(sourceMap, frame.lineNumber, frame.columnNumber);
|
|
57
|
-
if (!result)
|
|
58
|
-
return frame;
|
|
59
|
-
return {
|
|
60
|
-
...frame,
|
|
61
|
-
fileName: result.source,
|
|
62
|
-
lineNumber: result.line,
|
|
63
|
-
columnNumber: result.column,
|
|
64
|
-
functionName: result.name ?? frame.functionName,
|
|
65
|
-
};
|
|
48
|
+
const symbolicated = (0, symbolicate_1.symbolicateStackTrace)(frames, (frame) => {
|
|
49
|
+
const bundle = frame.fileName && bundleFileFromUrl(frame.fileName);
|
|
50
|
+
return bundle ? sourceMaps.get(bundle) : null;
|
|
66
51
|
});
|
|
67
52
|
return { ...error, stack: (0, symbolicate_1.formatStackTrace)(symbolicated) };
|
|
68
53
|
}
|
|
@@ -71,20 +56,6 @@ async function symbolicateError(releaseId, error) {
|
|
|
71
56
|
}
|
|
72
57
|
return error;
|
|
73
58
|
}
|
|
74
|
-
/**
|
|
75
|
-
* Strip null/undefined labels and convert all values to strings for Cloud Logging.
|
|
76
|
-
*/
|
|
77
|
-
function cleanLabels(labels) {
|
|
78
|
-
if (!labels)
|
|
79
|
-
return {};
|
|
80
|
-
const cleaned = {};
|
|
81
|
-
for (const [key, value] of Object.entries(labels)) {
|
|
82
|
-
if (value !== null && value !== undefined) {
|
|
83
|
-
cleaned[key] = String(value);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return cleaned;
|
|
87
|
-
}
|
|
88
59
|
/**
|
|
89
60
|
* Create an onCall handler that receives LogPayload from the client,
|
|
90
61
|
* symbolicates stack traces, and writes structured entries to Cloud Logging.
|
|
@@ -108,12 +79,12 @@ function createClientLogHandler(config) {
|
|
|
108
79
|
let processedError = jsonPayload?.error;
|
|
109
80
|
if (processedError?.stack && !isEmulator) {
|
|
110
81
|
const releaseId = labels?.releaseId ?? 'unknown';
|
|
111
|
-
processedError = await symbolicateError(releaseId, processedError);
|
|
82
|
+
processedError = await symbolicateError(releaseId, processedError, config.bucketName);
|
|
112
83
|
}
|
|
113
84
|
(0, logger_1.writeLog)({
|
|
114
85
|
message,
|
|
115
86
|
severity,
|
|
116
|
-
labels: cleanLabels(labels),
|
|
87
|
+
labels: (0, logger_1.cleanLabels)(labels),
|
|
117
88
|
jsonPayload: { ...jsonPayload, error: processedError },
|
|
118
89
|
attachments: request.data.attachments,
|
|
119
90
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logHandler.js","sourceRoot":"","sources":["../../src/functions/logHandler.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"logHandler.js","sourceRoot":"","sources":["../../src/functions/logHandler.ts"],"names":[],"mappings":";;AAoFA,wDAmCC;AASD,0DAOC;AAvID,uDAAsF;AAEtF,iDAA+C;AAC/C,qCAAgD;AAChD,qDAAyE;AACzE,+CAIsB;AAQtB,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAS,qBAAU,CAAC,CAAA;AAEpD;;GAEG;AACH,SAAS,iBAAiB,CAAC,GAAW;IACpC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAA;IACpD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAChC,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,gBAAgB,CAC7B,SAAiB,EACjB,KAA+B,EAC/B,UAAmB;IAEnB,IAAI,CAAC,KAAK,EAAE,KAAK;QAAE,OAAO,KAAK,CAAA;IAE/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,6BAAe,EAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAE3C,+DAA+D;QAC/D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;QACrC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;gBAChD,IAAI,MAAM;oBAAE,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACrC,CAAC;QACH,CAAC;QAED,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,KAAK,CAAA;QAExC,wEAAwE;QACxE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAoD,CAAA;QAC9E,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YAC3C,MAAM,GAAG,GAAG,MAAM,IAAA,6BAAY,EAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,CAAA;YAC7D,IAAI,GAAG;gBAAE,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QACtC,CAAC,CAAC,CACH,CAAA;QAED,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,KAAK,CAAA;QAEvC,sDAAsD;QACtD,MAAM,YAAY,GAAG,IAAA,mCAAqB,EAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,IAAI,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;YAClE,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAC/C,CAAC,CAAC,CAAA;QAEF,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,IAAA,8BAAgB,EAAC,YAAY,CAAC,EAAE,CAAA;IAC5D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAA;IAClD,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,sBAAsB,CAAC,MAA8B;IACnE,IAAI,MAAM,CAAC,UAAU;QAAE,IAAA,yCAAwB,EAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IAElE,OAAO,KAAK,EAAE,OAAoC,EAAiB,EAAE;QACnE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAA;QAE/D,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1B,MAAM,IAAI,kBAAU,CAAC,kBAAkB,EAAE,6BAA6B,CAAC,CAAA;QACzE,CAAC;QAED,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,kBAAU,CAAC,kBAAkB,EAAE,qBAAqB,QAAQ,EAAE,CAAC,CAAA;QAC3E,CAAC;QAED,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,MAAM,CAAA;QAE5D,IAAI,CAAC;YACH,IAAI,cAAc,GAAG,WAAW,EAAE,KAAK,CAAA;YACvC,IAAI,cAAc,EAAE,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;gBACzC,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,IAAI,SAAS,CAAA;gBAChD,cAAc,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC,UAAU,CAAC,CAAA;YACvF,CAAC;YAED,IAAA,iBAAQ,EAAC;gBACP,OAAO;gBACP,QAAQ;gBACR,MAAM,EAAE,IAAA,oBAAW,EAAC,MAAM,CAAyB;gBACnD,WAAW,EAAE,EAAE,GAAG,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE;gBACtD,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW;aACtC,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAA;YACxD,MAAM,IAAI,kBAAU,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAA;QAC3D,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,uBAAuB,CACrC,MAA8F;IAE9F,OAAO,IAAA,cAAM,EACX,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,CAAC,EAAE,EACrE,sBAAsB,CAAC,MAAM,CAAC,CAC/B,CAAA;AACH,CAAC"}
|