@dasasian/firebase-structured-logger 0.7.0 → 0.9.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 +183 -17
- package/dist/client/logger.d.ts +16 -0
- package/dist/client/logger.d.ts.map +1 -1
- package/dist/client/logger.js +137 -18
- package/dist/client/logger.js.map +1 -1
- package/dist/client/rateLimiter.d.ts +98 -10
- package/dist/client/rateLimiter.d.ts.map +1 -1
- package/dist/client/rateLimiter.js +282 -18
- package/dist/client/rateLimiter.js.map +1 -1
- package/dist/functions/httpHandler.d.ts.map +1 -1
- package/dist/functions/httpHandler.js +3 -0
- package/dist/functions/httpHandler.js.map +1 -1
- package/dist/functions/logHandler.d.ts +2 -1
- package/dist/functions/logHandler.d.ts.map +1 -1
- package/dist/functions/logHandler.js +16 -3
- package/dist/functions/logHandler.js.map +1 -1
- package/dist/functions/logger.d.ts +13 -0
- package/dist/functions/logger.d.ts.map +1 -1
- package/dist/functions/logger.js +299 -14
- package/dist/functions/logger.js.map +1 -1
- package/dist/functions/sourceMapCache.d.ts +14 -4
- package/dist/functions/sourceMapCache.d.ts.map +1 -1
- package/dist/functions/sourceMapCache.js +95 -6
- package/dist/functions/sourceMapCache.js.map +1 -1
- package/dist/functions/traceContext.d.ts +21 -7
- package/dist/functions/traceContext.d.ts.map +1 -1
- package/dist/functions/traceContext.js +60 -12
- package/dist/functions/traceContext.js.map +1 -1
- package/dist/shared/types.d.ts +7 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +11 -5
- package/skills/query-logs/SKILL.md +35 -0
|
@@ -34,18 +34,64 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.__cacheForTests = void 0;
|
|
37
|
+
exports.storageSource = storageSource;
|
|
37
38
|
exports.configureSourceMapBucket = configureSourceMapBucket;
|
|
38
39
|
exports.configureAttachments = configureAttachments;
|
|
39
40
|
exports.getAttachmentBucket = getAttachmentBucket;
|
|
40
41
|
exports.getAttachmentPrefix = getAttachmentPrefix;
|
|
41
42
|
exports.resetAttachmentConfig = resetAttachmentConfig;
|
|
42
43
|
exports.getBucket = getBucket;
|
|
44
|
+
exports.resetStorageResolution = resetStorageResolution;
|
|
43
45
|
exports.getSourceMap = getSourceMap;
|
|
44
46
|
exports.resetSourceMapWarnings = resetSourceMapWarnings;
|
|
45
47
|
exports.clearSourceMapCache = clearSourceMapCache;
|
|
46
48
|
const fs = __importStar(require("fs"));
|
|
47
|
-
const storage_1 = require("firebase-admin/storage");
|
|
48
49
|
const paths_js_1 = require("../shared/paths.js");
|
|
50
|
+
/**
|
|
51
|
+
* OPTIONAL PEER — firebase-admin is loaded lazily, on purpose.
|
|
52
|
+
*
|
|
53
|
+
* Storage is needed for two things only: maps of releases older than the deployed one,
|
|
54
|
+
* and attachments. A top-level import made the whole `/functions` entry point fail on
|
|
55
|
+
* `require` on a backend without firebase-admin, even one that never touches Storage
|
|
56
|
+
* (#39). So Storage is resolved on first use, down a chain:
|
|
57
|
+
*
|
|
58
|
+
* 1. firebase-admin installed -> its Storage, and its default bucket (today's path)
|
|
59
|
+
* 2. not installed, a bucket named -> @google-cloud/storage with that bucket
|
|
60
|
+
* 3. neither -> no Storage; warned once, see warnNoStorage
|
|
61
|
+
*
|
|
62
|
+
* Step 2 needs the name because only firebase-admin knows the app's default bucket.
|
|
63
|
+
* @google-cloud/storage is a regular dependency (the `fsl` CLI uses it); it is loaded
|
|
64
|
+
* lazily too, because it is heavy and a Cloud Functions instance never needs it.
|
|
65
|
+
*
|
|
66
|
+
* `require` rather than `await import`: `getBucket` is synchronous, and in this
|
|
67
|
+
* CommonJS build a dynamic import compiles to `require` anyway.
|
|
68
|
+
*/
|
|
69
|
+
function loadFirebaseAdminStorage() {
|
|
70
|
+
try {
|
|
71
|
+
return require('firebase-admin/storage');
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function loadCloudStorage() {
|
|
78
|
+
return require('@google-cloud/storage');
|
|
79
|
+
}
|
|
80
|
+
// undefined = not yet resolved. Resolved once: a package is either installed or not
|
|
81
|
+
// for the life of the process, and this sits on the per-error path.
|
|
82
|
+
let adminStorage;
|
|
83
|
+
let cloudStorage;
|
|
84
|
+
function resolveAdminStorage() {
|
|
85
|
+
if (adminStorage === undefined)
|
|
86
|
+
adminStorage = loadFirebaseAdminStorage();
|
|
87
|
+
return adminStorage;
|
|
88
|
+
}
|
|
89
|
+
/** Which step of the chain a lookup for `bucketName` would take. */
|
|
90
|
+
function storageSource(bucketName = defaultBucket) {
|
|
91
|
+
if (resolveAdminStorage())
|
|
92
|
+
return 'firebase-admin';
|
|
93
|
+
return bucketName ? 'google-cloud-storage' : 'none';
|
|
94
|
+
}
|
|
49
95
|
/**
|
|
50
96
|
* Storage-map cache, bounded by approximate bytes with LRU eviction.
|
|
51
97
|
*
|
|
@@ -144,7 +190,10 @@ function configureAttachments(options) {
|
|
|
144
190
|
}
|
|
145
191
|
let attachmentBucket;
|
|
146
192
|
let attachmentPrefix;
|
|
147
|
-
/**
|
|
193
|
+
/**
|
|
194
|
+
* Bucket for attachments: explicit, then the source-map bucket, then the project
|
|
195
|
+
* default. Null when there is no Storage at all — see loadFirebaseAdminStorage.
|
|
196
|
+
*/
|
|
148
197
|
function getAttachmentBucket() {
|
|
149
198
|
return getBucket(attachmentBucket ?? defaultBucket);
|
|
150
199
|
}
|
|
@@ -158,14 +207,45 @@ function resetAttachmentConfig() {
|
|
|
158
207
|
attachmentPrefix = undefined;
|
|
159
208
|
}
|
|
160
209
|
/**
|
|
161
|
-
* Resolve the configured Storage bucket, falling back to the project default
|
|
210
|
+
* Resolve the configured Storage bucket, falling back to the project default — or
|
|
211
|
+
* null when the chain ends with no Storage (see loadFirebaseAdminStorage).
|
|
162
212
|
*
|
|
163
213
|
* The return type is spelled out rather than inferred: without it the emitted
|
|
164
214
|
* `.d.ts` would need to name `Bucket` from a path inside `node_modules`, which
|
|
165
215
|
* TypeScript 7 rejects as non-portable (TS2883).
|
|
166
216
|
*/
|
|
167
217
|
function getBucket(bucketName = defaultBucket) {
|
|
168
|
-
|
|
218
|
+
const admin = resolveAdminStorage();
|
|
219
|
+
if (admin)
|
|
220
|
+
return bucketName ? admin.getStorage().bucket(bucketName) : admin.getStorage().bucket();
|
|
221
|
+
if (bucketName) {
|
|
222
|
+
cloudStorage ??= new (loadCloudStorage().Storage)();
|
|
223
|
+
return cloudStorage.bucket(bucketName);
|
|
224
|
+
}
|
|
225
|
+
warnNoStorage();
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
let warnedNoStorage = false;
|
|
229
|
+
/**
|
|
230
|
+
* Say once that there is no Storage, and what that costs. Nothing fails without it —
|
|
231
|
+
* which is exactly why it has to be said: errors from older releases simply stay
|
|
232
|
+
* minified and attachments simply vanish.
|
|
233
|
+
*/
|
|
234
|
+
function warnNoStorage() {
|
|
235
|
+
if (warnedNoStorage)
|
|
236
|
+
return;
|
|
237
|
+
warnedNoStorage = true;
|
|
238
|
+
console.warn('[fsl] No Storage: firebase-admin is not installed and no bucket is named.');
|
|
239
|
+
console.warn("[fsl] Only the source maps embedded in this deploy resolve; errors from older");
|
|
240
|
+
console.warn('[fsl] releases stay minified, and attachments are dropped (the log entry is kept).');
|
|
241
|
+
console.warn('[fsl] Fix: name a bucket (createHttpLogHandler({ bucketName }) or');
|
|
242
|
+
console.warn('[fsl] configureAttachments({ bucket })), or install firebase-admin.');
|
|
243
|
+
}
|
|
244
|
+
/** Forget which Storage the chain resolved to, and the warning. Tests only. */
|
|
245
|
+
function resetStorageResolution() {
|
|
246
|
+
adminStorage = undefined;
|
|
247
|
+
cloudStorage = undefined;
|
|
248
|
+
warnedNoStorage = false;
|
|
169
249
|
}
|
|
170
250
|
/**
|
|
171
251
|
* Load source map from embedded current release directory (instant for current release).
|
|
@@ -221,7 +301,13 @@ async function loadStorageSourceMap(releaseId, fileName, bucketName, prefix) {
|
|
|
221
301
|
if (hit)
|
|
222
302
|
return hit.map;
|
|
223
303
|
try {
|
|
224
|
-
|
|
304
|
+
// Inside the try: firebase-admin throws here, synchronously, when there is no
|
|
305
|
+
// initialised app or no default bucket — a miss, not a crash.
|
|
306
|
+
const bucket = getBucket(bucketName);
|
|
307
|
+
// No Storage at all: not a miss to cache — warnNoStorage has already said why.
|
|
308
|
+
if (!bucket)
|
|
309
|
+
return null;
|
|
310
|
+
const file = bucket.file((0, paths_js_1.storageMapPath)(releaseId, fileName, prefix));
|
|
225
311
|
const [exists] = await file.exists();
|
|
226
312
|
if (!exists) {
|
|
227
313
|
cacheSet(cacheKey, null, 0);
|
|
@@ -298,9 +384,12 @@ function warnNothingResolved(releaseId, fileName, bucketName, prefix) {
|
|
|
298
384
|
return;
|
|
299
385
|
warnedMisses.add(key);
|
|
300
386
|
const bucket = bucketName ?? defaultBucket ?? '<project default>';
|
|
387
|
+
const storage = storageSource(bucketName) === 'none'
|
|
388
|
+
? 'not available (no firebase-admin, no bucket named)'
|
|
389
|
+
: `gs://${bucket}/${(0, paths_js_1.storageMapPath)(releaseId, fileName, prefix)} (not found)`;
|
|
301
390
|
console.warn(`[fsl] No source map for '${fileName}' at release '${releaseId}' — this stack stays minified.`);
|
|
302
391
|
console.warn(`[fsl] embedded: ${(0, paths_js_1.embeddedMapPath)(process.cwd(), fileName)} (not found)`);
|
|
303
|
-
console.warn(`[fsl] storage:
|
|
392
|
+
console.warn(`[fsl] storage: ${storage}`);
|
|
304
393
|
console.warn('[fsl] Check that the deploy runs `fsl upload-sourcemaps`, and that its --prefix');
|
|
305
394
|
console.warn('[fsl] and --bucket match createClientLogHandler({ sourceMaps }). Nothing verifies that for you.');
|
|
306
395
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sourceMapCache.js","sourceRoot":"","sources":["../../src/functions/sourceMapCache.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"sourceMapCache.js","sourceRoot":"","sources":["../../src/functions/sourceMapCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,13 +28,27 @@ export declare function runWithTrace<T>(traceId: string | undefined, fn: () => T
|
|
|
28
28
|
/** The current request's trace id, if one was parsed. */
|
|
29
29
|
export declare function currentTraceId(): string | undefined;
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
31
|
+
* Find the project on a Google runtime that does not put it in the environment.
|
|
32
32
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* Why the resource name at all: Cloud Logging's LogEntry reference prefers the bare
|
|
34
|
+
* trace id, but stores whichever form it is given, and the console's "show entries
|
|
35
|
+
* for this trace" filters on the full `projects/<id>/traces/<trace>` — the form Cloud
|
|
36
|
+
* Run writes its own request log in. A bare id never meets that request log; the
|
|
37
|
+
* smoke run proved it. So the project has to be found.
|
|
38
|
+
*
|
|
39
|
+
* Asked of the metadata server, the way Google's own Cloud Run sample and its pino
|
|
40
|
+
* config do: once, cached, and only on Cloud Run (`K_SERVICE` is set) — anywhere
|
|
41
|
+
* else the lookup would only wait for a timeout. Async, so it is awaited where the
|
|
42
|
+
* request starts (createHttpLogHandler), not on the synchronous log path.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveTraceProject(): Promise<void>;
|
|
45
|
+
/** Forget the looked-up project. Tests only. */
|
|
46
|
+
export declare function resetTraceProject(): void;
|
|
47
|
+
/**
|
|
48
|
+
* The `logging.googleapis.com/trace` value: the full resource name when the project
|
|
49
|
+
* is known, and the bare id when it is not. The bare id is a valid LogEntry.trace —
|
|
50
|
+
* the entry still carries its trace — it only fails to meet the request log in the
|
|
51
|
+
* console, so it beats writing nothing.
|
|
36
52
|
*/
|
|
37
|
-
export declare function
|
|
38
|
-
/** The full `logging.googleapis.com/trace` value, or undefined if unavailable. */
|
|
39
|
-
export declare function traceResourceName(): string | undefined;
|
|
53
|
+
export declare function traceField(): string | undefined;
|
|
40
54
|
//# sourceMappingURL=traceContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traceContext.d.ts","sourceRoot":"","sources":["../../src/functions/traceContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA0BH;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GACrD,MAAM,GAAG,SAAS,CAepB;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE3E;AAED,yDAAyD;AACzD,wBAAgB,cAAc,IAAI,MAAM,GAAG,SAAS,CAEnD;
|
|
1
|
+
{"version":3,"file":"traceContext.d.ts","sourceRoot":"","sources":["../../src/functions/traceContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA0BH;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GACrD,MAAM,GAAG,SAAS,CAepB;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE3E;AAED,yDAAyD;AACzD,wBAAgB,cAAc,IAAI,MAAM,GAAG,SAAS,CAEnD;AAmBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAiBnD;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,MAAM,GAAG,SAAS,CAK/C"}
|
|
@@ -19,8 +19,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
19
19
|
exports.traceIdFromHeaders = traceIdFromHeaders;
|
|
20
20
|
exports.runWithTrace = runWithTrace;
|
|
21
21
|
exports.currentTraceId = currentTraceId;
|
|
22
|
-
exports.
|
|
23
|
-
exports.
|
|
22
|
+
exports.resolveTraceProject = resolveTraceProject;
|
|
23
|
+
exports.resetTraceProject = resetTraceProject;
|
|
24
|
+
exports.traceField = traceField;
|
|
24
25
|
const async_hooks_1 = require("async_hooks");
|
|
25
26
|
const traceStore = new async_hooks_1.AsyncLocalStorage();
|
|
26
27
|
/**
|
|
@@ -73,21 +74,68 @@ function currentTraceId() {
|
|
|
73
74
|
return traceStore.getStore();
|
|
74
75
|
}
|
|
75
76
|
/**
|
|
76
|
-
* The project a trace resource name belongs to.
|
|
77
|
+
* The project a trace resource name belongs to, from the environment.
|
|
77
78
|
*
|
|
78
|
-
* Cloud Functions sets `GCLOUD_PROJECT
|
|
79
|
-
*
|
|
80
|
-
*
|
|
79
|
+
* Cloud Functions sets `GCLOUD_PROJECT`. Cloud Run sets NEITHER variable — 0.7.0
|
|
80
|
+
* assumed it set `GOOGLE_CLOUD_PROJECT`, so on the backend createHttpLogHandler
|
|
81
|
+
* exists for, the trace was silently never written (#39). See resolveTraceProject.
|
|
81
82
|
*/
|
|
82
|
-
function
|
|
83
|
+
function envProject() {
|
|
83
84
|
return process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT || undefined;
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
const METADATA_PROJECT_URL = 'http://metadata.google.internal/computeMetadata/v1/project/project-id';
|
|
87
|
+
// undefined = not looked up; null = looked up and not found.
|
|
88
|
+
let metadataProject;
|
|
89
|
+
let metadataLookup;
|
|
90
|
+
/**
|
|
91
|
+
* Find the project on a Google runtime that does not put it in the environment.
|
|
92
|
+
*
|
|
93
|
+
* Why the resource name at all: Cloud Logging's LogEntry reference prefers the bare
|
|
94
|
+
* trace id, but stores whichever form it is given, and the console's "show entries
|
|
95
|
+
* for this trace" filters on the full `projects/<id>/traces/<trace>` — the form Cloud
|
|
96
|
+
* Run writes its own request log in. A bare id never meets that request log; the
|
|
97
|
+
* smoke run proved it. So the project has to be found.
|
|
98
|
+
*
|
|
99
|
+
* Asked of the metadata server, the way Google's own Cloud Run sample and its pino
|
|
100
|
+
* config do: once, cached, and only on Cloud Run (`K_SERVICE` is set) — anywhere
|
|
101
|
+
* else the lookup would only wait for a timeout. Async, so it is awaited where the
|
|
102
|
+
* request starts (createHttpLogHandler), not on the synchronous log path.
|
|
103
|
+
*/
|
|
104
|
+
function resolveTraceProject() {
|
|
105
|
+
if (envProject() || metadataProject !== undefined)
|
|
106
|
+
return Promise.resolve();
|
|
107
|
+
if (!process.env.K_SERVICE) {
|
|
108
|
+
metadataProject = null;
|
|
109
|
+
return Promise.resolve();
|
|
110
|
+
}
|
|
111
|
+
metadataLookup ??= fetch(METADATA_PROJECT_URL, {
|
|
112
|
+
headers: { 'Metadata-Flavor': 'Google' },
|
|
113
|
+
signal: AbortSignal.timeout(1_000),
|
|
114
|
+
})
|
|
115
|
+
.then(async (res) => {
|
|
116
|
+
metadataProject = res.ok ? (await res.text()).trim() || null : null;
|
|
117
|
+
})
|
|
118
|
+
.catch(() => {
|
|
119
|
+
metadataProject = null;
|
|
120
|
+
});
|
|
121
|
+
return metadataLookup;
|
|
122
|
+
}
|
|
123
|
+
/** Forget the looked-up project. Tests only. */
|
|
124
|
+
function resetTraceProject() {
|
|
125
|
+
metadataProject = undefined;
|
|
126
|
+
metadataLookup = undefined;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The `logging.googleapis.com/trace` value: the full resource name when the project
|
|
130
|
+
* is known, and the bare id when it is not. The bare id is a valid LogEntry.trace —
|
|
131
|
+
* the entry still carries its trace — it only fails to meet the request log in the
|
|
132
|
+
* console, so it beats writing nothing.
|
|
133
|
+
*/
|
|
134
|
+
function traceField() {
|
|
87
135
|
const traceId = currentTraceId();
|
|
88
|
-
|
|
89
|
-
if (!traceId || !project)
|
|
136
|
+
if (!traceId)
|
|
90
137
|
return undefined;
|
|
91
|
-
|
|
138
|
+
const project = envProject() ?? metadataProject ?? undefined;
|
|
139
|
+
return project ? `projects/${project}/traces/${traceId}` : traceId;
|
|
92
140
|
}
|
|
93
141
|
//# sourceMappingURL=traceContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traceContext.js","sourceRoot":"","sources":["../../src/functions/traceContext.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;AAkCH,gDAiBC;AAGD,oCAEC;AAGD,wCAEC;
|
|
1
|
+
{"version":3,"file":"traceContext.js","sourceRoot":"","sources":["../../src/functions/traceContext.ts"],"names":[],"mappings":"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"}
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -26,6 +26,13 @@ export interface LogPayload {
|
|
|
26
26
|
};
|
|
27
27
|
/** Base64-encoded attachments keyed by name. Uploaded to GCS, stripped before writing to Cloud Logging. */
|
|
28
28
|
attachments?: Record<string, string>;
|
|
29
|
+
/**
|
|
30
|
+
* Client-supplied ISO timestamp. Only honoured for a repeat summary
|
|
31
|
+
* (`labels.repeatCount` present), and only within the last 8 days and not
|
|
32
|
+
* more than 5 minutes in the future — see `writeLog`'s production branch.
|
|
33
|
+
* Anything else keeps the server's own time.
|
|
34
|
+
*/
|
|
35
|
+
timestamp?: string;
|
|
29
36
|
}
|
|
30
37
|
export interface BreadcrumbEntry {
|
|
31
38
|
timestamp: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;AAE3E,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,WAAW,CAAA;IACrB,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACvD,WAAW,CAAC,EAAE;QACZ,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;QAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjC,KAAK,CAAC,EAAE,YAAY,CAAA;KACrB,CAAA;IACD,2GAA2G;IAC3G,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;AAE3E,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,WAAW,CAAA;IACrB,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACvD,WAAW,CAAC,EAAE;QACZ,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;QAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjC,KAAK,CAAC,EAAE,YAAY,CAAA;KACrB,CAAA;IACD,2GAA2G;IAC3G,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAA;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dasasian/firebase-structured-logger",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Structured logging for Firebase apps —
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Structured logging for Firebase and Google Cloud web apps — browser, backend, and tools",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Dasasian",
|
|
7
7
|
"keywords": [
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
"source-maps",
|
|
14
14
|
"symbolication",
|
|
15
15
|
"observability",
|
|
16
|
-
"typescript"
|
|
16
|
+
"typescript",
|
|
17
|
+
"google-cloud",
|
|
18
|
+
"cloud-run",
|
|
19
|
+
"error-reporting"
|
|
17
20
|
],
|
|
18
21
|
"homepage": "https://dasasian.com/firebase-structured-logger",
|
|
19
22
|
"repository": {
|
|
@@ -65,10 +68,12 @@
|
|
|
65
68
|
"build:watch": "tsc --watch",
|
|
66
69
|
"clean": "rm -rf dist",
|
|
67
70
|
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.check.json",
|
|
68
|
-
"test": "tsx tests/logger.ts && tsx tests/breadcrumbs.ts && tsx tests/rateLimiter.ts && tsx tests/errorHandler.ts && tsx tests/attachments.ts && tsx tests/feedback.ts && tsx tests/paths.ts && tsx tests/sourceMapStripping.ts && FUNCTIONS_EMULATOR=true tsx tests/errorPayload.ts && FUNCTIONS_EMULATOR=true tsx tests/requestLogger.ts && FUNCTIONS_EMULATOR=true tsx tests/handler.ts && FUNCTIONS_EMULATOR=true tsx tests/httpHandler.ts && FUNCTIONS_EMULATOR=true tsx tests/symbolication.ts && FUNCTIONS_EMULATOR=true tsx tests/publicApi.ts && FUNCTIONS_EMULATOR=true tsx tests/configureTwice.ts && tsx tests/productionOutput.ts && tsx tests/handlerSymbolication.ts && tsx tests/releaseResolution.ts && tsx tests/sourceMapCacheBounds.ts",
|
|
71
|
+
"test": "tsx tests/logger.ts && tsx tests/browserBundle.ts && tsx tests/breadcrumbs.ts && tsx tests/rateLimiter.ts && tsx tests/errorHandler.ts && tsx tests/attachments.ts && tsx tests/feedback.ts && tsx tests/paths.ts && tsx tests/loadsWithoutOptionalPeers.ts && tsx tests/sourceMapStripping.ts && FUNCTIONS_EMULATOR=true tsx tests/errorPayload.ts && FUNCTIONS_EMULATOR=true tsx tests/requestLogger.ts && FUNCTIONS_EMULATOR=true tsx tests/handler.ts && FUNCTIONS_EMULATOR=true tsx tests/httpHandler.ts && FUNCTIONS_EMULATOR=true tsx tests/symbolication.ts && FUNCTIONS_EMULATOR=true tsx tests/publicApi.ts && FUNCTIONS_EMULATOR=true tsx tests/configureTwice.ts && tsx tests/productionOutput.ts && tsx tests/storageChain.ts && tsx tests/entrySize.ts && tsx tests/handlerSymbolication.ts && tsx tests/releaseResolution.ts && tsx tests/sourceMapCacheBounds.ts",
|
|
69
72
|
"prepublishOnly": "npm run clean && npm run build",
|
|
70
73
|
"smoke:deploy": "cd smoke/functions && npm install && npm run build && cd .. && firebase deploy --only functions --project $(grep '^FSL_SMOKE_PROJECT=' .env.local | cut -d= -f2)",
|
|
71
|
-
"smoke": "
|
|
74
|
+
"smoke:deploy:run": "bash smoke/cloudrun/deploy.sh",
|
|
75
|
+
"smoke": "tsx smoke/run.ts",
|
|
76
|
+
"smoke:install": "tsx smoke/install.ts"
|
|
72
77
|
},
|
|
73
78
|
"dependencies": {
|
|
74
79
|
"@google-cloud/storage": "^7.0.0",
|
|
@@ -95,6 +100,7 @@
|
|
|
95
100
|
"@google-cloud/logging": "^11.4.0",
|
|
96
101
|
"@types/jsdom": "^30.0.0",
|
|
97
102
|
"@types/node": "^26.2.0",
|
|
103
|
+
"esbuild": "^0.28.2",
|
|
98
104
|
"firebase": "^12.0.0",
|
|
99
105
|
"firebase-admin": "^14.2.0",
|
|
100
106
|
"firebase-functions": "^7.0.0",
|
|
@@ -25,6 +25,12 @@ All entries written by firebase-structured-logger include these labels:
|
|
|
25
25
|
| `functionName` | Cloud Function name (server-side logs only) |
|
|
26
26
|
| `logId` | ULID — unique per log entry, used to locate attachments in GCS |
|
|
27
27
|
| `hasAttachments` | `'true'` when attachments were uploaded alongside this entry |
|
|
28
|
+
| `repeatKey` | Client-side id carried by each full copy of an error that repeats |
|
|
29
|
+
| `repeatOf` | On a repeat summary: the `repeatKey` of the full copies it counts |
|
|
30
|
+
| `repeatCount` | On a repeat summary: how many further occurrences it stands for |
|
|
31
|
+
| `firstSeen`, `lastSeen` | On a repeat summary: the window those occurrences fell in |
|
|
32
|
+
| `sentLate` | `'true'` on a summary sent by a later visit than the one it counts |
|
|
33
|
+
| `truncated` | `'true'` when the entry was shortened to fit Cloud Logging's line limit |
|
|
28
34
|
|
|
29
35
|
App-specific labels are defined in each app's `AppLabels` type.
|
|
30
36
|
|
|
@@ -68,6 +74,35 @@ labels.releaseId="<hash>"
|
|
|
68
74
|
severity=ERROR timestamp>="<ISO8601>"
|
|
69
75
|
```
|
|
70
76
|
|
|
77
|
+
## How often did it really happen?
|
|
78
|
+
|
|
79
|
+
**Do not count entries.** A client sends an error in full only 3 times; after that it
|
|
80
|
+
counts the repeats and sends one `WARNING` summary per hour (and when the tab is hidden,
|
|
81
|
+
or on the user's next visit). Counting ERROR entries gives at most 3 per user, per
|
|
82
|
+
release, per hour — Cloud Error Reporting shows the same capped number.
|
|
83
|
+
|
|
84
|
+
The true count is the full copies plus the sum of `repeatCount`:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
labels.repeatKey="<key>" OR labels.repeatOf="<key>"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Take `repeatKey` from any full copy. Every entry this returns is one occurrence, except
|
|
91
|
+
summaries: each summary is `labels.repeatCount` occurrences, between `labels.firstSeen`
|
|
92
|
+
and `labels.lastSeen`. A summary is timestamped at `lastSeen`, and `sentLate="true"`
|
|
93
|
+
means it arrived on a later visit — it still belongs at its own time.
|
|
94
|
+
|
|
95
|
+
A summary has no stack and no breadcrumbs. For those, read one of the full copies.
|
|
96
|
+
|
|
97
|
+
## Shortened entries
|
|
98
|
+
|
|
99
|
+
Cloud Functions and Cloud Run cut a log line at 102,400 bytes, so the library shortens
|
|
100
|
+
any entry over 90 KiB before writing it: breadcrumb data, then other context, then the
|
|
101
|
+
tail of the stack. Such an entry carries `labels.truncated="true"`, and when Storage is
|
|
102
|
+
configured `labels.hasAttachments="true"` — the whole original entry is saved as
|
|
103
|
+
`logAttachments/{logId}/fsl-overflow.json`. Read that file (see below) whenever the
|
|
104
|
+
context or breadcrumbs you need are missing from a truncated entry.
|
|
105
|
+
|
|
71
106
|
## Retrieving Attachments
|
|
72
107
|
|
|
73
108
|
When a log entry has `labels.hasAttachments = "true"`, files were uploaded to GCS alongside it.
|