@dasasian/firebase-structured-logger 0.6.0 → 0.7.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 +598 -102
- package/dist/functions/httpHandler.d.ts +89 -0
- package/dist/functions/httpHandler.d.ts.map +1 -0
- package/dist/functions/httpHandler.js +112 -0
- package/dist/functions/httpHandler.js.map +1 -0
- package/dist/functions/index.d.ts +5 -2
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +6 -1
- package/dist/functions/index.js.map +1 -1
- package/dist/functions/logHandler.d.ts +53 -2
- package/dist/functions/logHandler.d.ts.map +1 -1
- package/dist/functions/logHandler.js +38 -7
- package/dist/functions/logHandler.js.map +1 -1
- package/dist/functions/logger.d.ts.map +1 -1
- package/dist/functions/logger.js +54 -3
- package/dist/functions/logger.js.map +1 -1
- package/dist/functions/sourceMapCache.d.ts +27 -1
- package/dist/functions/sourceMapCache.d.ts.map +1 -1
- package/dist/functions/sourceMapCache.js +84 -9
- package/dist/functions/sourceMapCache.js.map +1 -1
- package/dist/functions/traceContext.d.ts +40 -0
- package/dist/functions/traceContext.d.ts.map +1 -0
- package/dist/functions/traceContext.js +93 -0
- package/dist/functions/traceContext.js.map +1 -0
- package/dist/shared/paths.d.ts +59 -0
- package/dist/shared/paths.d.ts.map +1 -0
- package/dist/shared/paths.js +126 -0
- package/dist/shared/paths.js.map +1 -0
- package/dist/tools/index.js +13 -4
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/uploadSourceMaps.d.ts +24 -1
- package/dist/tools/uploadSourceMaps.d.ts.map +1 -1
- package/dist/tools/uploadSourceMaps.js +31 -4
- package/dist/tools/uploadSourceMaps.js.map +1 -1
- package/package.json +3 -3
- package/skills/query-logs/SKILL.md +14 -1
|
@@ -20,6 +20,30 @@ export declare const __cacheForTests: {
|
|
|
20
20
|
};
|
|
21
21
|
};
|
|
22
22
|
export declare function configureSourceMapBucket(bucketName: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Where attachments are written.
|
|
25
|
+
*
|
|
26
|
+
* Global on purpose, and global in the API so the shape does not lie. The
|
|
27
|
+
* upload happens in `writeLog`, which is reached from every log call — including
|
|
28
|
+
* `logError()` inside a handler that never went through `createClientLogHandler`
|
|
29
|
+
* — so there is no per-instance config for it to read. Accepting this as a field
|
|
30
|
+
* on the handler would let a second handler silently retarget the first's
|
|
31
|
+
* attachments, which is the module-scoped-state trap in CLAUDE.md.
|
|
32
|
+
*
|
|
33
|
+
* Unset fields keep today's behaviour: the bucket falls back to
|
|
34
|
+
* `configureSourceMapBucket`'s value and then to the project default, and the
|
|
35
|
+
* prefix to `logAttachments/`. Never calling this changes nothing.
|
|
36
|
+
*/
|
|
37
|
+
export declare function configureAttachments(options: {
|
|
38
|
+
bucket?: string;
|
|
39
|
+
prefix?: string;
|
|
40
|
+
}): void;
|
|
41
|
+
/** Bucket for attachments: explicit, then the source-map bucket, then the project default. */
|
|
42
|
+
export declare function getAttachmentBucket(): Bucket;
|
|
43
|
+
/** Prefix for attachments, defaulting to the documented one. */
|
|
44
|
+
export declare function getAttachmentPrefix(): string | undefined;
|
|
45
|
+
/** Reset attachment config. Tests only — production configures once at module load. */
|
|
46
|
+
export declare function resetAttachmentConfig(): void;
|
|
23
47
|
/**
|
|
24
48
|
* Resolve the configured Storage bucket, falling back to the project default.
|
|
25
49
|
*
|
|
@@ -49,7 +73,9 @@ export declare function getBucket(bucketName?: string | undefined): Bucket;
|
|
|
49
73
|
* That is strictly better than preferring embedded in every case, and it leaves
|
|
50
74
|
* the unversioned setup working exactly as before.
|
|
51
75
|
*/
|
|
52
|
-
export declare function getSourceMap(releaseId: string, fileName: string, bucketName?: string): Promise<EncodedSourceMap | null>;
|
|
76
|
+
export declare function getSourceMap(releaseId: string, fileName: string, bucketName?: string, prefix?: string): Promise<EncodedSourceMap | null>;
|
|
77
|
+
/** Reset the warn-once sets. Tests only. */
|
|
78
|
+
export declare function resetSourceMapWarnings(): void;
|
|
53
79
|
export declare function clearSourceMapCache(): void;
|
|
54
80
|
export {};
|
|
55
81
|
//# sourceMappingURL=sourceMapCache.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sourceMapCache.d.ts","sourceRoot":"","sources":["../../src/functions/sourceMapCache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sourceMapCache.d.ts","sourceRoot":"","sources":["../../src/functions/sourceMapCache.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAkBjE,UAAU,UAAU;IAClB,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC5B,KAAK,EAAE,MAAM,CAAA;CACd;AAgCD;;;;GAIG;AACH,eAAO,MAAM,eAAe;eACf,MAAM;eACN,MAAM,OAAO,gBAAgB,GAAG,IAAI,SAAS,MAAM;;;;;;;CAG/D,CAAA;AAuBD,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGxF;AAKD,8FAA8F;AAC9F,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,gEAAgE;AAChE,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,SAAS,CAExD;AAED,uFAAuF;AACvF,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,UAAU,qBAAgB,GAAG,MAAM,CAE5D;AAiFD;;GAEG;AACH;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAkBlC;AAyCD,4CAA4C;AAC5C,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C;AAiBD,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C"}
|
|
@@ -35,12 +35,17 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.__cacheForTests = void 0;
|
|
37
37
|
exports.configureSourceMapBucket = configureSourceMapBucket;
|
|
38
|
+
exports.configureAttachments = configureAttachments;
|
|
39
|
+
exports.getAttachmentBucket = getAttachmentBucket;
|
|
40
|
+
exports.getAttachmentPrefix = getAttachmentPrefix;
|
|
41
|
+
exports.resetAttachmentConfig = resetAttachmentConfig;
|
|
38
42
|
exports.getBucket = getBucket;
|
|
39
43
|
exports.getSourceMap = getSourceMap;
|
|
44
|
+
exports.resetSourceMapWarnings = resetSourceMapWarnings;
|
|
40
45
|
exports.clearSourceMapCache = clearSourceMapCache;
|
|
41
46
|
const fs = __importStar(require("fs"));
|
|
42
|
-
const path = __importStar(require("path"));
|
|
43
47
|
const storage_1 = require("firebase-admin/storage");
|
|
48
|
+
const paths_js_1 = require("../shared/paths.js");
|
|
44
49
|
/**
|
|
45
50
|
* Storage-map cache, bounded by approximate bytes with LRU eviction.
|
|
46
51
|
*
|
|
@@ -117,6 +122,41 @@ let defaultBucket;
|
|
|
117
122
|
function configureSourceMapBucket(bucketName) {
|
|
118
123
|
defaultBucket = bucketName;
|
|
119
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Where attachments are written.
|
|
127
|
+
*
|
|
128
|
+
* Global on purpose, and global in the API so the shape does not lie. The
|
|
129
|
+
* upload happens in `writeLog`, which is reached from every log call — including
|
|
130
|
+
* `logError()` inside a handler that never went through `createClientLogHandler`
|
|
131
|
+
* — so there is no per-instance config for it to read. Accepting this as a field
|
|
132
|
+
* on the handler would let a second handler silently retarget the first's
|
|
133
|
+
* attachments, which is the module-scoped-state trap in CLAUDE.md.
|
|
134
|
+
*
|
|
135
|
+
* Unset fields keep today's behaviour: the bucket falls back to
|
|
136
|
+
* `configureSourceMapBucket`'s value and then to the project default, and the
|
|
137
|
+
* prefix to `logAttachments/`. Never calling this changes nothing.
|
|
138
|
+
*/
|
|
139
|
+
function configureAttachments(options) {
|
|
140
|
+
if (options.bucket !== undefined)
|
|
141
|
+
attachmentBucket = options.bucket;
|
|
142
|
+
if (options.prefix !== undefined)
|
|
143
|
+
attachmentPrefix = options.prefix;
|
|
144
|
+
}
|
|
145
|
+
let attachmentBucket;
|
|
146
|
+
let attachmentPrefix;
|
|
147
|
+
/** Bucket for attachments: explicit, then the source-map bucket, then the project default. */
|
|
148
|
+
function getAttachmentBucket() {
|
|
149
|
+
return getBucket(attachmentBucket ?? defaultBucket);
|
|
150
|
+
}
|
|
151
|
+
/** Prefix for attachments, defaulting to the documented one. */
|
|
152
|
+
function getAttachmentPrefix() {
|
|
153
|
+
return attachmentPrefix;
|
|
154
|
+
}
|
|
155
|
+
/** Reset attachment config. Tests only — production configures once at module load. */
|
|
156
|
+
function resetAttachmentConfig() {
|
|
157
|
+
attachmentBucket = undefined;
|
|
158
|
+
attachmentPrefix = undefined;
|
|
159
|
+
}
|
|
120
160
|
/**
|
|
121
161
|
* Resolve the configured Storage bucket, falling back to the project default.
|
|
122
162
|
*
|
|
@@ -145,7 +185,7 @@ function readEmbeddedRelease() {
|
|
|
145
185
|
if (embeddedRelease !== undefined)
|
|
146
186
|
return embeddedRelease;
|
|
147
187
|
try {
|
|
148
|
-
const markerPath =
|
|
188
|
+
const markerPath = (0, paths_js_1.embeddedMarkerPath)(process.cwd());
|
|
149
189
|
embeddedRelease = fs.existsSync(markerPath)
|
|
150
190
|
? fs.readFileSync(markerPath, 'utf-8').trim() || null
|
|
151
191
|
: null;
|
|
@@ -157,8 +197,9 @@ function readEmbeddedRelease() {
|
|
|
157
197
|
}
|
|
158
198
|
function readEmbeddedSourceMap(fileName) {
|
|
159
199
|
try {
|
|
160
|
-
//
|
|
161
|
-
|
|
200
|
+
// Resolved against the process working directory — the deployed backend's,
|
|
201
|
+
// whether that is Cloud Functions or anything else that ships the directory.
|
|
202
|
+
const mapPath = (0, paths_js_1.embeddedMapPath)(process.cwd(), fileName);
|
|
162
203
|
if (!fs.existsSync(mapPath))
|
|
163
204
|
return null;
|
|
164
205
|
return JSON.parse(fs.readFileSync(mapPath, 'utf-8'));
|
|
@@ -170,15 +211,17 @@ function readEmbeddedSourceMap(fileName) {
|
|
|
170
211
|
/**
|
|
171
212
|
* Load source map from Firebase Storage (for older releases).
|
|
172
213
|
*/
|
|
173
|
-
async function loadStorageSourceMap(releaseId, fileName, bucketName) {
|
|
214
|
+
async function loadStorageSourceMap(releaseId, fileName, bucketName, prefix) {
|
|
174
215
|
// The bucket is part of the key: the same release/file in two buckets is two
|
|
175
216
|
// different maps, and caching them under one key would serve the wrong one.
|
|
176
|
-
|
|
217
|
+
// The prefix is part of the key for the same reason the bucket is: the same
|
|
218
|
+
// release and file under two prefixes are two different objects.
|
|
219
|
+
const cacheKey = `${bucketName ?? defaultBucket ?? ''}/${prefix ?? ''}/${releaseId}/${fileName}`;
|
|
177
220
|
const hit = cacheGet(cacheKey);
|
|
178
221
|
if (hit)
|
|
179
222
|
return hit.map;
|
|
180
223
|
try {
|
|
181
|
-
const file = getBucket(bucketName).file(
|
|
224
|
+
const file = getBucket(bucketName).file((0, paths_js_1.storageMapPath)(releaseId, fileName, prefix));
|
|
182
225
|
const [exists] = await file.exists();
|
|
183
226
|
if (!exists) {
|
|
184
227
|
cacheSet(cacheKey, null, 0);
|
|
@@ -218,22 +261,54 @@ async function loadStorageSourceMap(releaseId, fileName, bucketName) {
|
|
|
218
261
|
* That is strictly better than preferring embedded in every case, and it leaves
|
|
219
262
|
* the unversioned setup working exactly as before.
|
|
220
263
|
*/
|
|
221
|
-
async function getSourceMap(releaseId, fileName, bucketName) {
|
|
264
|
+
async function getSourceMap(releaseId, fileName, bucketName, prefix) {
|
|
222
265
|
const embedded = loadEmbeddedSourceMap(fileName);
|
|
223
266
|
const marker = readEmbeddedRelease();
|
|
224
267
|
// No marker means we cannot tell whether this stack belongs to the embedded
|
|
225
268
|
// release. Older deploys have none, so keep the previous behaviour.
|
|
226
269
|
if (embedded && (marker === null || marker === releaseId))
|
|
227
270
|
return embedded;
|
|
228
|
-
const stored = await loadStorageSourceMap(releaseId, fileName, bucketName);
|
|
271
|
+
const stored = await loadStorageSourceMap(releaseId, fileName, bucketName, prefix);
|
|
229
272
|
if (stored)
|
|
230
273
|
return stored;
|
|
231
274
|
if (embedded) {
|
|
232
275
|
warnReleaseFallback(releaseId, marker);
|
|
233
276
|
return embedded;
|
|
234
277
|
}
|
|
278
|
+
warnNothingResolved(releaseId, fileName, bucketName, prefix);
|
|
235
279
|
return null;
|
|
236
280
|
}
|
|
281
|
+
// Warn once per (release, prefix). This sits on the per-error path.
|
|
282
|
+
const warnedMisses = new Set();
|
|
283
|
+
/**
|
|
284
|
+
* Say so when a stack could not be symbolicated from anywhere.
|
|
285
|
+
*
|
|
286
|
+
* Silence here is the expensive failure. A wrong bucket, a wrong prefix, a
|
|
287
|
+
* release whose maps were never uploaded and an `fsl` step missing from the
|
|
288
|
+
* deploy script all produce the same thing — a minified stack, and no signal
|
|
289
|
+
* which of the four it was. With the prefix configurable (#35) there is one more
|
|
290
|
+
* way to land here, and the two ends are checked against each other by nothing.
|
|
291
|
+
*
|
|
292
|
+
* So name the exact places that were looked in. A prefix mismatch is obvious the
|
|
293
|
+
* moment you see the object name that was tried.
|
|
294
|
+
*/
|
|
295
|
+
function warnNothingResolved(releaseId, fileName, bucketName, prefix) {
|
|
296
|
+
const key = `${releaseId}|${prefix ?? ''}`;
|
|
297
|
+
if (warnedMisses.has(key))
|
|
298
|
+
return;
|
|
299
|
+
warnedMisses.add(key);
|
|
300
|
+
const bucket = bucketName ?? defaultBucket ?? '<project default>';
|
|
301
|
+
console.warn(`[fsl] No source map for '${fileName}' at release '${releaseId}' — this stack stays minified.`);
|
|
302
|
+
console.warn(`[fsl] embedded: ${(0, paths_js_1.embeddedMapPath)(process.cwd(), fileName)} (not found)`);
|
|
303
|
+
console.warn(`[fsl] storage: gs://${bucket}/${(0, paths_js_1.storageMapPath)(releaseId, fileName, prefix)} (not found)`);
|
|
304
|
+
console.warn('[fsl] Check that the deploy runs `fsl upload-sourcemaps`, and that its --prefix');
|
|
305
|
+
console.warn('[fsl] and --bucket match createClientLogHandler({ sourceMaps }). Nothing verifies that for you.');
|
|
306
|
+
}
|
|
307
|
+
/** Reset the warn-once sets. Tests only. */
|
|
308
|
+
function resetSourceMapWarnings() {
|
|
309
|
+
warnedMisses.clear();
|
|
310
|
+
warnedFallbacks.clear();
|
|
311
|
+
}
|
|
237
312
|
// Warn once per (release, marker) pair — this sits on the per-error path.
|
|
238
313
|
const warnedFallbacks = new Set();
|
|
239
314
|
function warnReleaseFallback(releaseId, marker) {
|
|
@@ -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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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request trace ids, for backends that are not Cloud Functions (#34).
|
|
3
|
+
*
|
|
4
|
+
* `firebase-functions/logger`'s `write()` attaches
|
|
5
|
+
* `logging.googleapis.com/trace` from an AsyncLocalStorage that
|
|
6
|
+
* firebase-functions populates inside its own request wrapper. Outside one —
|
|
7
|
+
* Cloud Run, or anything behind `createHttpLogHandler` — that store is empty, so
|
|
8
|
+
* no trace id is attached and Cloud Logging cannot group a request's entries.
|
|
9
|
+
*
|
|
10
|
+
* That is silent: the logs arrive, they simply do not correlate, and nothing
|
|
11
|
+
* says why. So the adapter reads the headers itself and stores the id here.
|
|
12
|
+
*
|
|
13
|
+
* Inside Cloud Functions this is dormant — the store is never populated, and
|
|
14
|
+
* firebase-functions' own value takes precedence anyway, since it overwrites the
|
|
15
|
+
* field after we set it.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Pull a trace id out of request headers, preferring Cloud Trace's own format.
|
|
19
|
+
*
|
|
20
|
+
* Returns undefined rather than a partial id when nothing matches. A malformed
|
|
21
|
+
* header is not worth guessing at: an invalid trace resource name is rejected by
|
|
22
|
+
* Cloud Logging, which would cost the whole entry rather than just its
|
|
23
|
+
* correlation.
|
|
24
|
+
*/
|
|
25
|
+
export declare function traceIdFromHeaders(headers: Record<string, string | string[] | undefined>): string | undefined;
|
|
26
|
+
/** Run `fn` with `traceId` attached to every log written inside it. */
|
|
27
|
+
export declare function runWithTrace<T>(traceId: string | undefined, fn: () => T): T;
|
|
28
|
+
/** The current request's trace id, if one was parsed. */
|
|
29
|
+
export declare function currentTraceId(): string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* The project a trace resource name belongs to.
|
|
32
|
+
*
|
|
33
|
+
* Cloud Functions sets `GCLOUD_PROJECT`; Cloud Run sets `GOOGLE_CLOUD_PROJECT`.
|
|
34
|
+
* With neither there is no valid resource name to build, so the field is left
|
|
35
|
+
* off rather than written wrong.
|
|
36
|
+
*/
|
|
37
|
+
export declare function traceProject(): string | undefined;
|
|
38
|
+
/** The full `logging.googleapis.com/trace` value, or undefined if unavailable. */
|
|
39
|
+
export declare function traceResourceName(): string | undefined;
|
|
40
|
+
//# sourceMappingURL=traceContext.d.ts.map
|
|
@@ -0,0 +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;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjD;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAKtD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Request trace ids, for backends that are not Cloud Functions (#34).
|
|
4
|
+
*
|
|
5
|
+
* `firebase-functions/logger`'s `write()` attaches
|
|
6
|
+
* `logging.googleapis.com/trace` from an AsyncLocalStorage that
|
|
7
|
+
* firebase-functions populates inside its own request wrapper. Outside one —
|
|
8
|
+
* Cloud Run, or anything behind `createHttpLogHandler` — that store is empty, so
|
|
9
|
+
* no trace id is attached and Cloud Logging cannot group a request's entries.
|
|
10
|
+
*
|
|
11
|
+
* That is silent: the logs arrive, they simply do not correlate, and nothing
|
|
12
|
+
* says why. So the adapter reads the headers itself and stores the id here.
|
|
13
|
+
*
|
|
14
|
+
* Inside Cloud Functions this is dormant — the store is never populated, and
|
|
15
|
+
* firebase-functions' own value takes precedence anyway, since it overwrites the
|
|
16
|
+
* field after we set it.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.traceIdFromHeaders = traceIdFromHeaders;
|
|
20
|
+
exports.runWithTrace = runWithTrace;
|
|
21
|
+
exports.currentTraceId = currentTraceId;
|
|
22
|
+
exports.traceProject = traceProject;
|
|
23
|
+
exports.traceResourceName = traceResourceName;
|
|
24
|
+
const async_hooks_1 = require("async_hooks");
|
|
25
|
+
const traceStore = new async_hooks_1.AsyncLocalStorage();
|
|
26
|
+
/**
|
|
27
|
+
* Cloud Trace's own header: `TRACE_ID/SPAN_ID;o=TRACE_TRUE`.
|
|
28
|
+
* Google's load balancers and Cloud Run set this.
|
|
29
|
+
*/
|
|
30
|
+
const CLOUD_TRACE_HEADER = 'x-cloud-trace-context';
|
|
31
|
+
/**
|
|
32
|
+
* W3C Trace Context: `00-<32 hex trace>-<16 hex span>-<flags>`.
|
|
33
|
+
* What OpenTelemetry and most third-party tracers send.
|
|
34
|
+
*/
|
|
35
|
+
const TRACEPARENT_HEADER = 'traceparent';
|
|
36
|
+
const CLOUD_TRACE = /^([0-9a-fA-F]{32})(?:\/(\d+))?(?:;o=[01])?$/;
|
|
37
|
+
const TRACEPARENT = /^[0-9a-fA-F]{2}-([0-9a-fA-F]{32})-[0-9a-fA-F]{16}-[0-9a-fA-F]{2}$/;
|
|
38
|
+
function firstValue(value) {
|
|
39
|
+
if (Array.isArray(value))
|
|
40
|
+
return value[0];
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Pull a trace id out of request headers, preferring Cloud Trace's own format.
|
|
45
|
+
*
|
|
46
|
+
* Returns undefined rather than a partial id when nothing matches. A malformed
|
|
47
|
+
* header is not worth guessing at: an invalid trace resource name is rejected by
|
|
48
|
+
* Cloud Logging, which would cost the whole entry rather than just its
|
|
49
|
+
* correlation.
|
|
50
|
+
*/
|
|
51
|
+
function traceIdFromHeaders(headers) {
|
|
52
|
+
// Header names are case-insensitive, and nothing guarantees the host framework
|
|
53
|
+
// lower-cased them — Node's http does, a hand-rolled object may not.
|
|
54
|
+
const lower = {};
|
|
55
|
+
for (const [k, v] of Object.entries(headers))
|
|
56
|
+
lower[k.toLowerCase()] = v;
|
|
57
|
+
const cloud = firstValue(lower[CLOUD_TRACE_HEADER]);
|
|
58
|
+
const cloudMatch = cloud && CLOUD_TRACE.exec(cloud.trim());
|
|
59
|
+
if (cloudMatch)
|
|
60
|
+
return cloudMatch[1];
|
|
61
|
+
const parent = firstValue(lower[TRACEPARENT_HEADER]);
|
|
62
|
+
const parentMatch = parent && TRACEPARENT.exec(parent.trim());
|
|
63
|
+
if (parentMatch)
|
|
64
|
+
return parentMatch[1];
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
/** Run `fn` with `traceId` attached to every log written inside it. */
|
|
68
|
+
function runWithTrace(traceId, fn) {
|
|
69
|
+
return traceId ? traceStore.run(traceId, fn) : fn();
|
|
70
|
+
}
|
|
71
|
+
/** The current request's trace id, if one was parsed. */
|
|
72
|
+
function currentTraceId() {
|
|
73
|
+
return traceStore.getStore();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The project a trace resource name belongs to.
|
|
77
|
+
*
|
|
78
|
+
* Cloud Functions sets `GCLOUD_PROJECT`; Cloud Run sets `GOOGLE_CLOUD_PROJECT`.
|
|
79
|
+
* With neither there is no valid resource name to build, so the field is left
|
|
80
|
+
* off rather than written wrong.
|
|
81
|
+
*/
|
|
82
|
+
function traceProject() {
|
|
83
|
+
return process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT || undefined;
|
|
84
|
+
}
|
|
85
|
+
/** The full `logging.googleapis.com/trace` value, or undefined if unavailable. */
|
|
86
|
+
function traceResourceName() {
|
|
87
|
+
const traceId = currentTraceId();
|
|
88
|
+
const project = traceProject();
|
|
89
|
+
if (!traceId || !project)
|
|
90
|
+
return undefined;
|
|
91
|
+
return `projects/${project}/traces/${traceId}`;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=traceContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traceContext.js","sourceRoot":"","sources":["../../src/functions/traceContext.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;AAkCH,gDAiBC;AAGD,oCAEC;AAGD,wCAEC;AASD,oCAEC;AAGD,8CAKC;AA9ED,6CAA+C;AAE/C,MAAM,UAAU,GAAG,IAAI,+BAAiB,EAAU,CAAA;AAElD;;;GAGG;AACH,MAAM,kBAAkB,GAAG,uBAAuB,CAAA;AAElD;;;GAGG;AACH,MAAM,kBAAkB,GAAG,aAAa,CAAA;AAExC,MAAM,WAAW,GAAG,6CAA6C,CAAA;AACjE,MAAM,WAAW,GAAG,mEAAmE,CAAA;AAEvF,SAAS,UAAU,CAAC,KAAoC;IACtD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;IACzC,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,kBAAkB,CAChC,OAAsD;IAEtD,+EAA+E;IAC/E,qEAAqE;IACrE,MAAM,KAAK,GAAkD,EAAE,CAAA;IAC/D,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAA;IAExE,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAA;IACnD,MAAM,UAAU,GAAG,KAAK,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;IAC1D,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC,CAAC,CAAC,CAAA;IAEpC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAA;IACpD,MAAM,WAAW,GAAG,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;IAC7D,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC,CAAC,CAAC,CAAA;IAEtC,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,uEAAuE;AACvE,SAAgB,YAAY,CAAI,OAA2B,EAAE,EAAW;IACtE,OAAO,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;AACrD,CAAC;AAED,yDAAyD;AACzD,SAAgB,cAAc;IAC5B,OAAO,UAAU,CAAC,QAAQ,EAAE,CAAA;AAC9B,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,SAAS,CAAA;AACpF,CAAC;AAED,kFAAkF;AAClF,SAAgB,iBAAiB;IAC/B,MAAM,OAAO,GAAG,cAAc,EAAE,CAAA;IAChC,MAAM,OAAO,GAAG,YAAY,EAAE,CAAA;IAC9B,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAA;IAC1C,OAAO,YAAY,OAAO,WAAW,OAAO,EAAE,CAAA;AAChD,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every storage location this package reads or writes, defined once.
|
|
3
|
+
*
|
|
4
|
+
* These are contracts, not conveniences: each source-map path has a writer in
|
|
5
|
+
* `/tools` and a reader in `/functions`, and they used to be independent string
|
|
6
|
+
* literals in different entry points with nothing enforcing that they matched.
|
|
7
|
+
* When they disagree, symbolication does not fail — it falls through and returns
|
|
8
|
+
* the minified frames, which looks like "my maps never uploaded".
|
|
9
|
+
*
|
|
10
|
+
* #36 is what that costs: `.release` was written in three places, none of them
|
|
11
|
+
* the writer, so the release check never ran and every stack resolved against
|
|
12
|
+
* whatever happened to be embedded.
|
|
13
|
+
*
|
|
14
|
+
* `/functions` cannot import from `/tools` without a cross-entry-point
|
|
15
|
+
* dependency, which is why this lives in `shared/` beside `error.ts` and
|
|
16
|
+
* `severity.ts` rather than being exported from either side.
|
|
17
|
+
*
|
|
18
|
+
* Cloud Storage object names always use `/`; local paths are built with
|
|
19
|
+
* `path.join` by the caller. The two are kept apart on purpose — a Windows
|
|
20
|
+
* separator in a GCS object name is a different object.
|
|
21
|
+
*/
|
|
22
|
+
/** Cloud Storage prefix holding one directory per release. */
|
|
23
|
+
export declare const SOURCEMAP_PREFIX = "sourcemaps";
|
|
24
|
+
/** Cloud Storage prefix holding one directory per log entry. */
|
|
25
|
+
export declare const ATTACHMENT_PREFIX = "logAttachments";
|
|
26
|
+
/**
|
|
27
|
+
* Directory inside the deployed backend holding the current release's maps,
|
|
28
|
+
* relative to the process working directory. Checked before Cloud Storage so
|
|
29
|
+
* the common case costs no network call.
|
|
30
|
+
*/
|
|
31
|
+
export declare const EMBEDDED_DIR: string;
|
|
32
|
+
/**
|
|
33
|
+
* Names the release the embedded maps belong to.
|
|
34
|
+
*
|
|
35
|
+
* Without it the runtime cannot tell "this stack is from the deployed release"
|
|
36
|
+
* from "this stack is from an older one" — the embedded directory is keyed only
|
|
37
|
+
* by filename, so an old stack naming a bundle that still exists would be
|
|
38
|
+
* resolved with the current map, giving confidently wrong line numbers.
|
|
39
|
+
*/
|
|
40
|
+
export declare const RELEASE_MARKER = ".release";
|
|
41
|
+
/**
|
|
42
|
+
* Cloud Storage object name for one release's map of one bundle.
|
|
43
|
+
*
|
|
44
|
+
* `bundleFileName` is the bundle as it appears in a stack trace — `app-4f2a.js`,
|
|
45
|
+
* without the `.map`. The suffix belongs to the contract, not to either caller,
|
|
46
|
+
* which is what kept the writer and reader agreeing by accident before.
|
|
47
|
+
*/
|
|
48
|
+
export declare function storageMapPath(releaseId: string, bundleFileName: string, prefix?: string): string;
|
|
49
|
+
/** Cloud Storage object name for one attachment of one log entry. */
|
|
50
|
+
export declare function attachmentPath(logId: string, name: string, prefix?: string): string;
|
|
51
|
+
/** Local directory holding the embedded maps, under `baseDir`. */
|
|
52
|
+
export declare function embeddedDir(baseDir: string): string;
|
|
53
|
+
/** Local path of one embedded map, under `baseDir`. */
|
|
54
|
+
export declare function embeddedMapPath(baseDir: string, bundleFileName: string): string;
|
|
55
|
+
/** Local path of the release marker, under `baseDir`. */
|
|
56
|
+
export declare function embeddedMarkerPath(baseDir: string): string;
|
|
57
|
+
/** Strip the `.map` suffix from a map filename to get the bundle name. */
|
|
58
|
+
export declare function bundleNameOf(mapFileName: string): string;
|
|
59
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/shared/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,eAAe,CAAA;AAE5C,gEAAgE;AAChE,eAAO,MAAM,iBAAiB,mBAAmB,CAAA;AAEjD;;;;GAIG;AACH,eAAO,MAAM,YAAY,QAAyC,CAAA;AAElE;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,MAAM,GAAE,MAAyB,GAChC,MAAM,CAER;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,MAA0B,GACjC,MAAM,CAER;AAeD,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,uDAAuD;AACvD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAE/E;AAED,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAExD"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Every storage location this package reads or writes, defined once.
|
|
4
|
+
*
|
|
5
|
+
* These are contracts, not conveniences: each source-map path has a writer in
|
|
6
|
+
* `/tools` and a reader in `/functions`, and they used to be independent string
|
|
7
|
+
* literals in different entry points with nothing enforcing that they matched.
|
|
8
|
+
* When they disagree, symbolication does not fail — it falls through and returns
|
|
9
|
+
* the minified frames, which looks like "my maps never uploaded".
|
|
10
|
+
*
|
|
11
|
+
* #36 is what that costs: `.release` was written in three places, none of them
|
|
12
|
+
* the writer, so the release check never ran and every stack resolved against
|
|
13
|
+
* whatever happened to be embedded.
|
|
14
|
+
*
|
|
15
|
+
* `/functions` cannot import from `/tools` without a cross-entry-point
|
|
16
|
+
* dependency, which is why this lives in `shared/` beside `error.ts` and
|
|
17
|
+
* `severity.ts` rather than being exported from either side.
|
|
18
|
+
*
|
|
19
|
+
* Cloud Storage object names always use `/`; local paths are built with
|
|
20
|
+
* `path.join` by the caller. The two are kept apart on purpose — a Windows
|
|
21
|
+
* separator in a GCS object name is a different object.
|
|
22
|
+
*/
|
|
23
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
26
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
27
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
28
|
+
}
|
|
29
|
+
Object.defineProperty(o, k2, desc);
|
|
30
|
+
}) : (function(o, m, k, k2) {
|
|
31
|
+
if (k2 === undefined) k2 = k;
|
|
32
|
+
o[k2] = m[k];
|
|
33
|
+
}));
|
|
34
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
35
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
36
|
+
}) : function(o, v) {
|
|
37
|
+
o["default"] = v;
|
|
38
|
+
});
|
|
39
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
40
|
+
var ownKeys = function(o) {
|
|
41
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
42
|
+
var ar = [];
|
|
43
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
44
|
+
return ar;
|
|
45
|
+
};
|
|
46
|
+
return ownKeys(o);
|
|
47
|
+
};
|
|
48
|
+
return function (mod) {
|
|
49
|
+
if (mod && mod.__esModule) return mod;
|
|
50
|
+
var result = {};
|
|
51
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
52
|
+
__setModuleDefault(result, mod);
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
})();
|
|
56
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
+
exports.RELEASE_MARKER = exports.EMBEDDED_DIR = exports.ATTACHMENT_PREFIX = exports.SOURCEMAP_PREFIX = void 0;
|
|
58
|
+
exports.storageMapPath = storageMapPath;
|
|
59
|
+
exports.attachmentPath = attachmentPath;
|
|
60
|
+
exports.embeddedDir = embeddedDir;
|
|
61
|
+
exports.embeddedMapPath = embeddedMapPath;
|
|
62
|
+
exports.embeddedMarkerPath = embeddedMarkerPath;
|
|
63
|
+
exports.bundleNameOf = bundleNameOf;
|
|
64
|
+
const path = __importStar(require("path"));
|
|
65
|
+
/** Cloud Storage prefix holding one directory per release. */
|
|
66
|
+
exports.SOURCEMAP_PREFIX = 'sourcemaps';
|
|
67
|
+
/** Cloud Storage prefix holding one directory per log entry. */
|
|
68
|
+
exports.ATTACHMENT_PREFIX = 'logAttachments';
|
|
69
|
+
/**
|
|
70
|
+
* Directory inside the deployed backend holding the current release's maps,
|
|
71
|
+
* relative to the process working directory. Checked before Cloud Storage so
|
|
72
|
+
* the common case costs no network call.
|
|
73
|
+
*/
|
|
74
|
+
exports.EMBEDDED_DIR = path.join(exports.SOURCEMAP_PREFIX, 'current');
|
|
75
|
+
/**
|
|
76
|
+
* Names the release the embedded maps belong to.
|
|
77
|
+
*
|
|
78
|
+
* Without it the runtime cannot tell "this stack is from the deployed release"
|
|
79
|
+
* from "this stack is from an older one" — the embedded directory is keyed only
|
|
80
|
+
* by filename, so an old stack naming a bundle that still exists would be
|
|
81
|
+
* resolved with the current map, giving confidently wrong line numbers.
|
|
82
|
+
*/
|
|
83
|
+
exports.RELEASE_MARKER = '.release';
|
|
84
|
+
/**
|
|
85
|
+
* Cloud Storage object name for one release's map of one bundle.
|
|
86
|
+
*
|
|
87
|
+
* `bundleFileName` is the bundle as it appears in a stack trace — `app-4f2a.js`,
|
|
88
|
+
* without the `.map`. The suffix belongs to the contract, not to either caller,
|
|
89
|
+
* which is what kept the writer and reader agreeing by accident before.
|
|
90
|
+
*/
|
|
91
|
+
function storageMapPath(releaseId, bundleFileName, prefix = exports.SOURCEMAP_PREFIX) {
|
|
92
|
+
return `${trimPrefix(prefix)}/${releaseId}/${bundleFileName}.map`;
|
|
93
|
+
}
|
|
94
|
+
/** Cloud Storage object name for one attachment of one log entry. */
|
|
95
|
+
function attachmentPath(logId, name, prefix = exports.ATTACHMENT_PREFIX) {
|
|
96
|
+
return `${trimPrefix(prefix)}/${logId}/${name}`;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Normalise a caller-supplied prefix.
|
|
100
|
+
*
|
|
101
|
+
* A prefix is a directory, and people write directories with a trailing slash.
|
|
102
|
+
* Passing `'fsl/'` unnormalised yields `fsl//abc/app.js.map`, which is a
|
|
103
|
+
* *different* Storage object from `fsl/abc/app.js.map` — GCS keys are opaque
|
|
104
|
+
* strings, so the double slash is not collapsed and the reader would miss.
|
|
105
|
+
* Leading slashes are dropped for the same reason.
|
|
106
|
+
*/
|
|
107
|
+
function trimPrefix(prefix) {
|
|
108
|
+
return prefix.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
109
|
+
}
|
|
110
|
+
/** Local directory holding the embedded maps, under `baseDir`. */
|
|
111
|
+
function embeddedDir(baseDir) {
|
|
112
|
+
return path.join(baseDir, exports.EMBEDDED_DIR);
|
|
113
|
+
}
|
|
114
|
+
/** Local path of one embedded map, under `baseDir`. */
|
|
115
|
+
function embeddedMapPath(baseDir, bundleFileName) {
|
|
116
|
+
return path.join(embeddedDir(baseDir), `${bundleFileName}.map`);
|
|
117
|
+
}
|
|
118
|
+
/** Local path of the release marker, under `baseDir`. */
|
|
119
|
+
function embeddedMarkerPath(baseDir) {
|
|
120
|
+
return path.join(embeddedDir(baseDir), exports.RELEASE_MARKER);
|
|
121
|
+
}
|
|
122
|
+
/** Strip the `.map` suffix from a map filename to get the bundle name. */
|
|
123
|
+
function bundleNameOf(mapFileName) {
|
|
124
|
+
return mapFileName.replace(/\.map$/, '');
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/shared/paths.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCH,wCAMC;AAGD,wCAMC;AAgBD,kCAEC;AAGD,0CAEC;AAGD,gDAEC;AAGD,oCAEC;AAhFD,2CAA4B;AAE5B,8DAA8D;AACjD,QAAA,gBAAgB,GAAG,YAAY,CAAA;AAE5C,gEAAgE;AACnD,QAAA,iBAAiB,GAAG,gBAAgB,CAAA;AAEjD;;;;GAIG;AACU,QAAA,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,wBAAgB,EAAE,SAAS,CAAC,CAAA;AAElE;;;;;;;GAOG;AACU,QAAA,cAAc,GAAG,UAAU,CAAA;AAExC;;;;;;GAMG;AACH,SAAgB,cAAc,CAC5B,SAAiB,EACjB,cAAsB,EACtB,SAAiB,wBAAgB;IAEjC,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,SAAS,IAAI,cAAc,MAAM,CAAA;AACnE,CAAC;AAED,qEAAqE;AACrE,SAAgB,cAAc,CAC5B,KAAa,EACb,IAAY,EACZ,SAAiB,yBAAiB;IAElC,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,EAAE,CAAA;AACjD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,UAAU,CAAC,MAAc;IAChC,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;AACvD,CAAC;AAED,kEAAkE;AAClE,SAAgB,WAAW,CAAC,OAAe;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAY,CAAC,CAAA;AACzC,CAAC;AAED,uDAAuD;AACvD,SAAgB,eAAe,CAAC,OAAe,EAAE,cAAsB;IACrE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,cAAc,MAAM,CAAC,CAAA;AACjE,CAAC;AAED,yDAAyD;AACzD,SAAgB,kBAAkB,CAAC,OAAe;IAChD,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,sBAAc,CAAC,CAAA;AACxD,CAAC;AAED,0EAA0E;AAC1E,SAAgB,YAAY,CAAC,WAAmB;IAC9C,OAAO,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;AAC1C,CAAC"}
|
package/dist/tools/index.js
CHANGED
|
@@ -79,9 +79,13 @@ async function main() {
|
|
|
79
79
|
switch (command) {
|
|
80
80
|
case 'upload-sourcemaps': {
|
|
81
81
|
const bucket = args.bucket ?? process.env.VITE_FIREBASE_STORAGE_BUCKET ?? process.env.FIREBASE_STORAGE_BUCKET;
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
const embed = args['embed-sourcemaps'] === 'true';
|
|
83
|
+
// A bucket is only required when something is going to be uploaded.
|
|
84
|
+
// Embed-only is the whole flow for a backend that has no bucket — see #34.
|
|
85
|
+
if (!bucket && !embed) {
|
|
86
|
+
console.error('Usage: fsl upload-sourcemaps [--bucket=<name>] [--functions=<path>] [--embed-sourcemaps] [--release=<id>] [--dist=<path>] [--prefix=<path>]');
|
|
84
87
|
console.error('Bucket can also be set via VITE_FIREBASE_STORAGE_BUCKET or FIREBASE_STORAGE_BUCKET env var (loaded from .env.local automatically).');
|
|
88
|
+
console.error('Omit the bucket only with --embed-sourcemaps, to embed the current release without uploading.');
|
|
85
89
|
process.exit(1);
|
|
86
90
|
}
|
|
87
91
|
const result = await (0, uploadSourceMaps_1.uploadSourceMaps)({
|
|
@@ -89,7 +93,8 @@ async function main() {
|
|
|
89
93
|
release: args.release,
|
|
90
94
|
distDir: args.dist,
|
|
91
95
|
functionsDir: args.functions,
|
|
92
|
-
embedSourcemaps:
|
|
96
|
+
embedSourcemaps: embed,
|
|
97
|
+
prefix: args.prefix,
|
|
93
98
|
});
|
|
94
99
|
// Distinct code so a deploy chain can choose to continue:
|
|
95
100
|
// npx fsl upload-sourcemaps … || [ $? -eq 3 ]
|
|
@@ -106,11 +111,15 @@ async function main() {
|
|
|
106
111
|
firebase-structured-logger (fsl)
|
|
107
112
|
|
|
108
113
|
Commands:
|
|
109
|
-
fsl upload-sourcemaps [--bucket=<name>] [--functions=<path>] [--embed-sourcemaps] [--release=<id>] [--dist=<path>]
|
|
114
|
+
fsl upload-sourcemaps [--bucket=<name>] [--functions=<path>] [--embed-sourcemaps] [--release=<id>] [--dist=<path>] [--prefix=<path>]
|
|
110
115
|
Upload .map files from dist/ to Cloud Storage and delete them locally.
|
|
111
116
|
--bucket defaults to VITE_FIREBASE_STORAGE_BUCKET or FIREBASE_STORAGE_BUCKET (loaded from .env.local automatically).
|
|
112
117
|
--functions path to Cloud Functions directory (e.g. ./functions or ./backend).
|
|
113
118
|
--embed-sourcemaps copies maps to {functions}/sourcemaps/current/ for fast lookup of current release.
|
|
119
|
+
Given without --bucket, embeds only and uploads nothing — for a backend with no
|
|
120
|
+
bucket. Only the deployed release can then be symbolicated.
|
|
121
|
+
--prefix Cloud Storage prefix to upload under (default sourcemaps/). Must match
|
|
122
|
+
createClientLogHandler({ sourceMaps: { prefix } }) or maps are not found.
|
|
114
123
|
Authenticates via FIREBASE_SERVICE_ACCOUNT_PATH if set, otherwise uses ADC.
|
|
115
124
|
Release ID defaults to git rev-parse --short HEAD.
|
|
116
125
|
|
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,uCAAwB;AACxB,2CAA4B;AAC5B,yDAAsF;AACtF,mDAA+C;AAE/C,MAAM,CAAC,EAAE,AAAD,EAAG,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAA;AAE9C,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAA;QAC3C,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QAC7B,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAA;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,WAAW,CAAC,QAAgB;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAA;IACtD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAM;IACpC,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAClE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;QAC3B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAQ;QACjD,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,SAAQ;QACvB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QACvC,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QACxC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACrG,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QAC5B,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;IACjD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAA;IAE/B,2CAA2C;IAC3C,WAAW,CAAC,YAAY,CAAC,CAAA;IAEzB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,mBAAmB,CAAC,CAAC,CAAC;YACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,4BAA4B,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAA;YAC7G,IAAI,CAAC,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
|