@dasasian/firebase-structured-logger 0.5.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.
Files changed (63) hide show
  1. package/README.md +652 -91
  2. package/dist/client/breadcrumbs.d.ts +14 -2
  3. package/dist/client/breadcrumbs.d.ts.map +1 -1
  4. package/dist/client/breadcrumbs.js +39 -21
  5. package/dist/client/breadcrumbs.js.map +1 -1
  6. package/dist/client/index.d.ts +3 -3
  7. package/dist/client/index.d.ts.map +1 -1
  8. package/dist/client/index.js +2 -2
  9. package/dist/client/index.js.map +1 -1
  10. package/dist/client/logger.d.ts +29 -0
  11. package/dist/client/logger.d.ts.map +1 -1
  12. package/dist/client/logger.js +39 -5
  13. package/dist/client/logger.js.map +1 -1
  14. package/dist/client/rateLimiter.d.ts +8 -3
  15. package/dist/client/rateLimiter.d.ts.map +1 -1
  16. package/dist/client/rateLimiter.js +9 -4
  17. package/dist/client/rateLimiter.js.map +1 -1
  18. package/dist/functions/httpHandler.d.ts +89 -0
  19. package/dist/functions/httpHandler.d.ts.map +1 -0
  20. package/dist/functions/httpHandler.js +112 -0
  21. package/dist/functions/httpHandler.js.map +1 -0
  22. package/dist/functions/index.d.ts +6 -3
  23. package/dist/functions/index.d.ts.map +1 -1
  24. package/dist/functions/index.js +6 -2
  25. package/dist/functions/index.js.map +1 -1
  26. package/dist/functions/logHandler.d.ts +53 -2
  27. package/dist/functions/logHandler.d.ts.map +1 -1
  28. package/dist/functions/logHandler.js +38 -7
  29. package/dist/functions/logHandler.js.map +1 -1
  30. package/dist/functions/logger.d.ts.map +1 -1
  31. package/dist/functions/logger.js +95 -7
  32. package/dist/functions/logger.js.map +1 -1
  33. package/dist/functions/requestLogger.d.ts +2 -20
  34. package/dist/functions/requestLogger.d.ts.map +1 -1
  35. package/dist/functions/requestLogger.js +2 -39
  36. package/dist/functions/requestLogger.js.map +1 -1
  37. package/dist/functions/sourceMapCache.d.ts +27 -1
  38. package/dist/functions/sourceMapCache.d.ts.map +1 -1
  39. package/dist/functions/sourceMapCache.js +84 -9
  40. package/dist/functions/sourceMapCache.js.map +1 -1
  41. package/dist/functions/traceContext.d.ts +40 -0
  42. package/dist/functions/traceContext.d.ts.map +1 -0
  43. package/dist/functions/traceContext.js +93 -0
  44. package/dist/functions/traceContext.js.map +1 -0
  45. package/dist/shared/paths.d.ts +59 -0
  46. package/dist/shared/paths.d.ts.map +1 -0
  47. package/dist/shared/paths.js +126 -0
  48. package/dist/shared/paths.js.map +1 -0
  49. package/dist/shared/severity.d.ts +21 -0
  50. package/dist/shared/severity.d.ts.map +1 -1
  51. package/dist/shared/severity.js +31 -3
  52. package/dist/shared/severity.js.map +1 -1
  53. package/dist/shared/types.d.ts +1 -2
  54. package/dist/shared/types.d.ts.map +1 -1
  55. package/dist/tools/index.js +13 -4
  56. package/dist/tools/index.js.map +1 -1
  57. package/dist/tools/uploadSourceMaps.d.ts +24 -1
  58. package/dist/tools/uploadSourceMaps.d.ts.map +1 -1
  59. package/dist/tools/uploadSourceMaps.js +31 -4
  60. package/dist/tools/uploadSourceMaps.js.map +1 -1
  61. package/package.json +4 -4
  62. package/skills/logs/SKILL.md +32 -9
  63. package/skills/query-logs/SKILL.md +14 -1
@@ -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
- if (!bucket) {
83
- console.error('Usage: fsl upload-sourcemaps [--bucket=<name>] [--functions=<path>] [--embed-sourcemaps] [--release=<id>] [--dist=<path>]');
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: args['embed-sourcemaps'] === 'true',
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
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
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,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,MAAM,CAAA;YACjD,oEAAoE;YACpE,2EAA2E;YAC3E,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;gBACtB,OAAO,CAAC,KAAK,CAAC,6IAA6I,CAAC,CAAA;gBAC5J,OAAO,CAAC,KAAK,CAAC,oIAAoI,CAAC,CAAA;gBACnJ,OAAO,CAAC,KAAK,CAAC,+FAA+F,CAAC,CAAA;gBAC9G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAA,mCAAgB,EAAC;gBACpC,MAAM;gBACN,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,OAAO,EAAE,IAAI,CAAC,IAAI;gBAClB,YAAY,EAAE,IAAI,CAAC,SAAS;gBAC5B,eAAe,EAAE,KAAK;gBACtB,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAA;YACF,0DAA0D;YAC1D,gDAAgD;YAChD,IAAI,CAAC,MAAM,CAAC,QAAQ;gBAAE,OAAO,CAAC,IAAI,CAAC,kDAA+B,CAAC,CAAA;YACnE,MAAK;QACP,CAAC;QAED,KAAK,gBAAgB,CAAC,CAAC,CAAC;YACtB,MAAM,IAAA,6BAAa,EAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC,CAAA;YACrF,MAAK;QACP,CAAC;QAED,OAAO,CAAC,CAAC,CAAC;YACR,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;CAqBjB,CAAC,CAAA;YACI,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAA;gBAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -17,11 +17,34 @@ export declare const EXIT_UPLOAD_FAILED_BUT_EMBEDDED = 3;
17
17
  */
18
18
  export declare const EMBEDDED_RELEASE_MARKER = ".release";
19
19
  export interface UploadOptions {
20
- bucket: string;
20
+ /**
21
+ * Cloud Storage bucket to upload to. Resolved by the caller — the CLI falls
22
+ * back to env vars.
23
+ *
24
+ * Optional, but only alongside `embedSourcemaps`: a run that neither uploads
25
+ * nor embeds does nothing except delete maps, which is not a thing to let
26
+ * someone ask for by accident. Omitting it is how a backend with no bucket —
27
+ * Cloud Run, say — gets the embedded copy without inventing a bucket name to
28
+ * satisfy the tool (#34).
29
+ */
30
+ bucket?: string;
21
31
  release?: string;
22
32
  distDir?: string;
23
33
  functionsDir?: string;
24
34
  embedSourcemaps?: boolean;
35
+ /**
36
+ * Cloud Storage prefix to upload under. Defaults to `sourcemaps/`.
37
+ *
38
+ * The reader must be told the same value, via
39
+ * `createClientLogHandler({ sourceMaps: { prefix } })`. These are the two ends
40
+ * of one contract and nothing checks them against each other — when they
41
+ * disagree the maps are simply not found and stacks stay minified, which
42
+ * looks identical to never having uploaded them (#35).
43
+ *
44
+ * Does not affect the embedded copy: that directory ships inside the deploy
45
+ * artifact and nothing outside reads it, so it stays fixed.
46
+ */
47
+ prefix?: string;
25
48
  }
26
49
  /**
27
50
  * Drop `sourcesContent` from a source map, returning the JSON to store.
@@ -1 +1 @@
1
- {"version":3,"file":"uploadSourceMaps.d.ts","sourceRoot":"","sources":["../../src/tools/uploadSourceMaps.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,IAAI,CAAA;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,aAAa,CAAA;AAEjD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CASpF;AA8BD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAmF7F"}
1
+ {"version":3,"file":"uploadSourceMaps.d.ts","sourceRoot":"","sources":["../../src/tools/uploadSourceMaps.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,IAAI,CAAA;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,aAAiB,CAAA;AAErD,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CASpF;AA8BD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAkH7F"}
@@ -39,6 +39,7 @@ exports.uploadSourceMaps = uploadSourceMaps;
39
39
  const fs = __importStar(require("fs"));
40
40
  const path = __importStar(require("path"));
41
41
  const storage_1 = require("@google-cloud/storage");
42
+ const paths_js_1 = require("../shared/paths.js");
42
43
  /**
43
44
  * Exit code used when maps were embedded but the Storage upload failed.
44
45
  *
@@ -56,7 +57,7 @@ exports.EXIT_UPLOAD_FAILED_BUT_EMBEDDED = 3;
56
57
  * by filename, so an old stack naming a bundle that still exists would be
57
58
  * resolved with the current map, giving confidently wrong line numbers.
58
59
  */
59
- exports.EMBEDDED_RELEASE_MARKER = '.release';
60
+ exports.EMBEDDED_RELEASE_MARKER = paths_js_1.RELEASE_MARKER;
60
61
  /**
61
62
  * Drop `sourcesContent` from a source map, returning the JSON to store.
62
63
  *
@@ -118,14 +119,19 @@ async function uploadSourceMaps(options) {
118
119
  }
119
120
  const distDir = options.distDir ?? path.join(process.cwd(), 'dist');
120
121
  const mapFiles = findMapFiles(distDir);
122
+ if (!options.bucket && !options.embedSourcemaps) {
123
+ throw new Error('[fsl] Nothing to do: no --bucket to upload to and no --embed-sourcemaps. ' +
124
+ 'Running would only delete the maps from dist/.');
125
+ }
121
126
  if (mapFiles.length === 0) {
122
127
  console.log('[fsl] No .map files found in', distDir);
123
128
  return { uploaded: true };
124
129
  }
125
- console.log(`[fsl] Uploading ${mapFiles.length} source map(s) for release ${releaseId}...`);
130
+ const verb = options.bucket ? 'Uploading' : 'Embedding';
131
+ console.log(`[fsl] ${verb} ${mapFiles.length} source map(s) for release ${releaseId}...`);
126
132
  // Embed maps into functions directory before uploading (for fast lookup of current release)
127
133
  if (options.embedSourcemaps && options.functionsDir) {
128
- const embedDir = path.join(process.cwd(), options.functionsDir, 'sourcemaps', 'current');
134
+ const embedDir = (0, paths_js_1.embeddedDir)(path.join(process.cwd(), options.functionsDir));
129
135
  fs.mkdirSync(embedDir, { recursive: true });
130
136
  for (const f of fs.readdirSync(embedDir)) {
131
137
  fs.unlinkSync(path.join(embedDir, f));
@@ -139,6 +145,27 @@ async function uploadSourceMaps(options) {
139
145
  const saved = before > after ? ` (${kb(before)} → ${kb(after)})` : '';
140
146
  console.log(` ✓ embedded ${path.basename(localPath)} → ${options.functionsDir}/sourcemaps/current/${saved}`);
141
147
  }
148
+ // Record which release these maps are for. Without it the runtime cannot tell
149
+ // a stack from the deployed release from a stack from an older one, and
150
+ // resolves both with whatever is embedded — see the marker's own doc above.
151
+ // Written after the loop, which has already cleared any stale marker.
152
+ fs.writeFileSync(path.join(embedDir, paths_js_1.RELEASE_MARKER), releaseId);
153
+ console.log(` ✓ marked ${options.functionsDir}/sourcemaps/current/ as release ${releaseId}`);
154
+ }
155
+ // Embed-only: nothing to authenticate against, so do not construct a client.
156
+ // The maps still leave dist/ — they are embedded, and leaving them behind
157
+ // would serve source maps to browsers, which is the worse outcome.
158
+ if (!options.bucket) {
159
+ for (const localPath of mapFiles) {
160
+ if (fs.existsSync(localPath)) {
161
+ fs.unlinkSync(localPath);
162
+ console.log(` ✗ deleted ${path.relative(process.cwd(), localPath)}`);
163
+ }
164
+ }
165
+ console.log('[fsl] Embedded only — no bucket given, nothing uploaded.');
166
+ console.log(`[fsl] Stacks from ${releaseId} symbolicate while it is the deployed release.`);
167
+ console.log('[fsl] Older releases cannot be symbolicated without a bucket to read from.');
168
+ return { uploaded: true };
142
169
  }
143
170
  // Authenticate via service account key if available, otherwise fall back to ADC
144
171
  const serviceAccountPath = process.env.FIREBASE_SERVICE_ACCOUNT_PATH;
@@ -150,7 +177,7 @@ async function uploadSourceMaps(options) {
150
177
  try {
151
178
  for (const localPath of mapFiles) {
152
179
  const fileName = path.basename(localPath);
153
- const destination = `sourcemaps/${releaseId}/${fileName}`;
180
+ const destination = (0, paths_js_1.storageMapPath)(releaseId, (0, paths_js_1.bundleNameOf)(fileName), options.prefix);
154
181
  const { json, before, after } = readStrippedMap(localPath);
155
182
  await bucket.file(destination).save(json, { contentType: 'application/json' });
156
183
  const saved = before > after ? ` (${kb(before)} → ${kb(after)}, -${Math.round(100 - (after / before) * 100)}%)` : '';
@@ -1 +1 @@
1
- {"version":3,"file":"uploadSourceMaps.js","sourceRoot":"","sources":["../../src/tools/uploadSourceMaps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"uploadSourceMaps.js","sourceRoot":"","sources":["../../src/tools/uploadSourceMaps.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dasasian/firebase-structured-logger",
3
- "version": "0.5.0",
4
- "description": "Structured logging for Firebase apps \u2014 client, functions, and tools",
3
+ "version": "0.7.0",
4
+ "description": "Structured logging for Firebase apps client, functions, and tools",
5
5
  "license": "MIT",
6
6
  "author": "Dasasian",
7
7
  "keywords": [
@@ -64,8 +64,8 @@
64
64
  "build": "tsc",
65
65
  "build:watch": "tsc --watch",
66
66
  "clean": "rm -rf dist",
67
- "typecheck": "tsc --noEmit",
68
- "test": "tsx tests/logger.ts && tsx tests/breadcrumbs.ts && tsx tests/rateLimiter.ts && tsx tests/errorHandler.ts && tsx tests/attachments.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/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",
67
+ "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",
69
69
  "prepublishOnly": "npm run clean && npm run build",
70
70
  "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
71
  "smoke": "tsx smoke/run.ts"
@@ -9,7 +9,7 @@ Validate frontend and backend logging implementation for a given file.
9
9
  Identify whether the target file is frontend or backend:
10
10
 
11
11
  **Frontend:** path starts with `src/`, imports from `firebase-structured-logger/client`, uses `logError/logWarn/logInfo/logDebug` or `bc.*`
12
- **Backend:** path starts with `functions/src/`, imports from `firebase-structured-logger/functions`, uses `initRequestLogger/getLogger/logError/logWarn/logInfo/logDebug`
12
+ **Backend:** path starts with `functions/src/`, imports from `firebase-structured-logger/functions`, uses `withLogging/getLogger/logError/logWarn/logInfo/logDebug`
13
13
 
14
14
  ---
15
15
 
@@ -96,11 +96,16 @@ API:
96
96
  - Must import from `firebase-structured-logger/functions`
97
97
  - Use `logError/logWarn/logInfo/logDebug` — never `console.log/console.error` directly
98
98
 
99
- **`initRequestLogger` — mandatory at function entry**
100
- - Every `onCall` handler must call `initRequestLogger<AppLabels>(request, { functionName, labels })` as the first line
99
+ **`withLogging` — mandatory wrapper on every handler**
100
+ - Every `onCall` handler must be wrapped: `onCall(withLogging<AppLabels>({ functionName, labels }, handler))`
101
101
  - Auto-seeds `userId` and `functionName` — do not pass these manually in labels
102
- - Any `AppLabels` fields present in `request.data` or function params should be passed in `labels`
103
- - Flag missing `initRequestLogger` as a critical violation
102
+ - Any `AppLabels` fields present in `request.data` need the callback form, which is evaluated per request: `withLogging<AppLabels>((request) => ({ functionName, labels: { orgId: request.data.orgId } }), handler)`
103
+ - Flag an unwrapped handler as a critical violation
104
+ - Flag `initRequestLogger` as a critical violation — it was removed in 0.6.0. It bound the
105
+ scope with `enterWith()`, which never unwinds, so a request's labels outlived the request
106
+ and any later handler that did *not* call it inherited whichever user last touched the
107
+ warm instance. `withLogging` uses `run()`, which restores the previous scope when the
108
+ handler settles.
104
109
 
105
110
  **Error paths**
106
111
  - Every `catch` block must call `logError`
@@ -109,7 +114,7 @@ API:
109
114
 
110
115
  **Label completeness**
111
116
  - For each log call, check which `AppLabels` fields are in scope
112
- - Fields already seeded via `initRequestLogger` labels do not need repeating
117
+ - Fields already seeded via `withLogging` labels do not need repeating
113
118
  - Flag any in-scope fields not seeded at entry or passed on the log call
114
119
 
115
120
  **PII**
@@ -165,11 +170,28 @@ bc.nav(screen: string): void // on navigation
165
170
  bc.error(type: string, data?: Record<string, unknown>): void // on errors
166
171
  ```
167
172
 
173
+ Import `sendFeedback` from `firebase-structured-logger/client`:
174
+ ```ts
175
+ sendFeedback(text: string, extras?: { labels?: Partial<AppLabels>; attachments?: Record<string, Blob | File | string> }): void
176
+ ```
177
+ - For what a user reports, not what the code catches — a wrong total, a button that did
178
+ nothing. Wire it to a feedback form, never to a `catch` block.
179
+ - Writes at `NOTICE` with `labels.feedback="true"`, and carries the current breadcrumbs,
180
+ screen and user labels automatically.
181
+ - Exempt from the severity floor and the rate limiter. Returns nothing — tell the user
182
+ thanks; if the app needs correlation, pass its own id in `labels`.
183
+
168
184
  ### Backend
169
185
  Import from `firebase-structured-logger/functions`:
170
186
  ```ts
171
- // Call first in every onCall handler — auto-seeds userId and functionName
172
- initRequestLogger<AppLabels>(request, { functionName: 'myFunc', labels: { organizationId: request.data.organizationId } })
187
+ // Wrap every onCall handler — auto-seeds userId and functionName, and unwinds
188
+ // the scope when the handler settles
189
+ export const myFunc = onCall(
190
+ withLogging<AppLabels>(
191
+ (request) => ({ functionName: 'myFunc', labels: { organizationId: request.data.organizationId } }),
192
+ async (request) => { /* logError/logWarn/logInfo/logDebug work in here */ },
193
+ ),
194
+ )
173
195
 
174
196
  logError(raw: unknown, labels?: Record<string, string | undefined>, context?: Record<string, unknown>, attachments?: Record<string, string | Buffer>): void
175
197
  logWarn(message: string, labels?: Record<string, string | undefined>, context?: Record<string, unknown>, attachments?: Record<string, string | Buffer>): void
@@ -180,6 +202,7 @@ logDebug(message: string, labels?: Record<string, string | undefined>, context?:
180
202
  ### Key behaviours
181
203
  - `logError` auto-derives `errorType` from `error.name` — only pass explicitly to override (e.g. `{ errorType: 'DatabaseError' }`)
182
204
  - `logError` accepts `unknown` — never cast with `as Error`
183
- - `initRequestLogger` auto-seeds `userId` (from `request.auth.uid`) and `functionName` — do not pass these in labels
205
+ - `withLogging` auto-seeds `userId` (from `request.auth.uid`) and `functionName` — do not pass these in labels
206
+ - `getLogger()` outside a wrapped handler returns an anonymous writer, not stale labels
184
207
  - Every log entry includes `labels.logId` (ULID) — if `attachments` are passed, they are uploaded to GCS at `logAttachments/{logId}/{name}` fire-and-forget; upload failure never blocks the log entry
185
208
  - When catching an error, check if there are attachments in scope (images, file snapshots, captured data) that would help reproduce or diagnose it — if so, pass them via `attachments`
@@ -30,7 +30,20 @@ App-specific labels are defined in each app's `AppLabels` type.
30
30
 
31
31
  ## Common Queries
32
32
 
33
- ### All errors for a user
33
+ ### Everything one user did, in order
34
+ ```
35
+ labels.userId="<uid>"
36
+ ```
37
+ No severity filter. Frontend and backend entries share the `userId` label, so this
38
+ returns both halves interleaved in time order — the clicks and screen changes that
39
+ led up to a failure, the backend call that failed, and the error the browser saw.
40
+ Filtering to `severity=ERROR` keeps the crash and throws away the story; reach for
41
+ it only when you already know what you are looking for.
42
+
43
+ Add `labels.platform:*` for client entries only, or `labels.functionName:*` for
44
+ server entries only.
45
+
46
+ ### Only the errors for a user
34
47
  ```
35
48
  labels.userId="<uid>" severity=ERROR
36
49
  ```