@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 CHANGED
@@ -15,7 +15,10 @@
15
15
 
16
16
  Your web app crashed at `app-4f2a.js:1:98432`. This tells you it was `Checkout.tsx:42` — in your own Google Cloud project, next to your backend logs. Nothing leaves.
17
17
 
18
- Ships a client logger, a Cloud Functions logger, and the `fsl` CLI.
18
+ Ships a browser logger, a server logger, and the `fsl` CLI. Built for Firebase, but
19
+ Firebase is optional: the browser half has no Firebase dependency, and the server half
20
+ runs on Cloud Functions, Cloud Run, or any Node server on Google Cloud, where stdout goes
21
+ to Cloud Logging. What it needs is a Google Cloud project — that is where the logs live.
19
22
 
20
23
  ## One query, both halves
21
24
 
@@ -62,9 +65,12 @@ npm install @dasasian/firebase-structured-logger
62
65
 
63
66
  # Cloud Functions
64
67
  cd functions && npm install @dasasian/firebase-structured-logger
68
+
69
+ # Cloud Run, or any Node server on Google Cloud
70
+ npm install @dasasian/firebase-structured-logger
65
71
  ```
66
72
 
67
- Ships ESM with three entry points — `/client`, `/functions`, `/tools` — plus the `fsl` CLI. `firebase`, `firebase-admin`, and `firebase-functions` are optional peer dependencies (bring your own versions).
73
+ Ships ESM with three entry points — `/client`, `/functions`, `/tools` — plus the `fsl` CLI. `firebase`, `firebase-admin`, and `firebase-functions` are optional peer dependencies (bring your own versions). None of them is needed to load the package; each only switches on the part that uses it — see [Without Firebase](#without-firebase).
68
74
 
69
75
  ## Setup
70
76
 
@@ -192,7 +198,7 @@ The entry should carry `userId` without your having written it.
192
198
 
193
199
  ### If your backend is not Cloud Functions
194
200
 
195
- Cloud Run, or any Node server you already run. Two things differ from the browser
201
+ Cloud Run, or any Node server you already run on Google Cloud. Two things differ from the browser
196
202
  path above; everything else — breadcrumbs, labels, symbolication, the free fields — is
197
203
  identical, and the entries land in the same stream in the same shape.
198
204
 
@@ -218,6 +224,37 @@ app.post('/log', createHttpLogHandler({
218
224
  }))
219
225
  ```
220
226
 
227
+ The handler reads Node's request and response shapes. A framework that wraps them, like
228
+ Hono, needs a few lines of adapter:
229
+
230
+ ```ts
231
+ import { Hono } from 'hono'
232
+ import { createHttpLogHandler } from '@dasasian/firebase-structured-logger/functions'
233
+
234
+ const app = new Hono()
235
+ const logHandler = createHttpLogHandler({ authorize })
236
+
237
+ app.on(['POST', 'OPTIONS'], '/log', async (c) => {
238
+ const headers: Record<string, string> = {}
239
+ let status = 200
240
+ let body: string | undefined
241
+ await logHandler(
242
+ {
243
+ method: c.req.method,
244
+ headers: Object.fromEntries(c.req.raw.headers),
245
+ body: await c.req.json().catch(() => null),
246
+ },
247
+ {
248
+ get statusCode() { return status },
249
+ set statusCode(v: number) { status = v },
250
+ setHeader: (name, value) => { headers[name] = value },
251
+ end: (b) => { body = b },
252
+ },
253
+ )
254
+ return new Response(body ?? null, { status, headers })
255
+ })
256
+ ```
257
+
221
258
  **Point the client at it.** `logFunction` is any async function, so a `fetch` works:
222
259
 
223
260
  ```ts
@@ -238,6 +275,25 @@ initLogger({
238
275
  })
239
276
  ```
240
277
 
278
+ #### Without Firebase
279
+
280
+ Nothing here needs a Firebase project — only a Google Cloud one. What changes:
281
+
282
+ - **The server has to run on Google Cloud** — Cloud Run, GKE, App Engine, or Compute
283
+ Engine with the Ops Agent. Entries are written to stdout, and only there does stdout
284
+ reach Cloud Logging. On AWS, Vercel or your own box they print and go nowhere.
285
+ - **The browser** needs no `firebase` package. `logFunction` is the `fetch` above; send
286
+ whatever credential your app already uses.
287
+ - **`authorize`** checks your own session instead of a Firebase ID token — for example
288
+ `authorize: (req) => sessions.isValid(req.headers.cookie)`.
289
+ - **Storage** has no Firebase default bucket to fall back to. Name one with `bucketName`
290
+ (it holds source maps and attachments), and give the service's account access to it.
291
+ Or name none: embedded maps still resolve the current release, older releases stay
292
+ minified, and attachments are dropped — the log says so once.
293
+ - **`fsl upload-sourcemaps --bucket`** works with any Cloud Storage bucket.
294
+ - **`withLogging` and `createClientLogFunction`** are Cloud Functions tools. Outside
295
+ them, `logInfo` / `logError` and friends still write the same entries.
296
+
241
297
  #### `authorize` is required, and that is deliberate
242
298
 
243
299
  A callable gets Firebase's token check for free. An HTTP endpoint gets nothing, and an
@@ -262,14 +318,24 @@ A gate that throws counts as a rejection, not an opening.
262
318
  before the handler. Raise its limit if you send attachments.
263
319
  - **CORS** defaults to `*`, matching `cors: true` on the callable. Pass `allowOrigin` to
264
320
  name your origin — a browser cannot send cookies to a wildcard.
265
- - **Trace correlation works**, and needs nothing from you. The handler reads
266
- `X-Cloud-Trace-Context` or `traceparent` off the request, so a request's entries still
267
- group in Cloud Logging.
321
+ - **No `firebase-functions`? Not needed.** The entry point loads without it. Each entry is
322
+ written as one line of JSON, which Cloud Run's log agent parses into the same Cloud
323
+ Logging fields a function's would.
324
+ - **Trace correlation works**, and needs nothing from you on Cloud Run. The handler reads
325
+ `X-Cloud-Trace-Context` or `traceparent` off the request, and asks the metadata server
326
+ for the project id once, so a request's entries group with Cloud Run's own request log
327
+ in Cloud Logging. Somewhere else — GKE, a VM — set `GOOGLE_CLOUD_PROJECT`; without it
328
+ the trace id is still written, but does not join the platform's request log.
329
+ - **No `firebase-admin`? Also optional.** Storage is only needed for older releases'
330
+ source maps and for attachments. With `firebase-admin` installed, its Storage and
331
+ default bucket are used. Without it, name the bucket — `bucketName` on the handler, or
332
+ `configureAttachments({ bucket })` — and the service's own credentials are used.
268
333
  - **No Storage bucket?** You do not need one. `fsl upload-sourcemaps --embed-sourcemaps`
269
334
  without `--bucket` embeds the current release's maps into your deploy and uploads
270
335
  nothing. The catch: only the **deployed** release can be symbolicated, because older
271
336
  ones live in a bucket there isn't one of. Errors from a previous release come back
272
- minified.
337
+ minified, and attachments are dropped — the entry is still written. With neither
338
+ `firebase-admin` nor a bucket name, the log says so once at the first lookup.
273
339
  - **Response codes:** `204` written, `400` malformed payload, `401` gate refused, `405`
274
340
  not a POST, `500` something else. The client treats a non-2xx as a throw.
275
341
 
@@ -376,6 +442,12 @@ logger.error(err, { orderId })
376
442
  | resolved file and line | function | your source maps — `Checkout.tsx:42`, not `app-4f2a.js:1:98432` |
377
443
  | trace context | function | request correlation in Cloud Logging |
378
444
 
445
+ **Repeats are counted, not thrown away.** The usual answer to an error that fires 200 times
446
+ is to send the first few and drop the rest. This one sends 3 in full, counts the other 197,
447
+ and tells you when it started, when it stopped, which release and which user. Close the tab
448
+ and the count waits on the device for the next visit. See
449
+ [Repeats are counted, not dropped](#repeats-are-counted-not-dropped).
450
+
379
451
  Backend logs get the same treatment: `withLogging` attaches `functionName`, `userId` from
380
452
  the verified `request.auth.uid`, and whatever else you bind.
381
453
 
@@ -559,15 +631,33 @@ or different IAM from your source maps — none of which can be arranged with a
559
631
  Nothing expires them. Add a lifecycle rule on `logAttachments/` to delete after N days, or
560
632
  they accumulate for the life of the project.
561
633
 
634
+ ## Big entries
635
+
636
+ Cloud Functions and Cloud Run both cut a stdout/stderr log line at exactly **102,400 bytes**
637
+ (100 KiB) — measured live. Past that the entry does not arrive truncated-but-valid: it arrives
638
+ as broken plain text, with no `severity`, no labels, and nothing for Error Reporting to group.
639
+
640
+ The backend logger watches for this. An entry over 90 KiB is shortened before it is written —
641
+ breadcrumb data first, then other context, then the tail of a long stack (the top frames are
642
+ what Error Reporting groups on, so those survive longest), then long text fields, and label
643
+ values only as a last resort. `severity`, labels, the trace and `serviceContext` are never
644
+ touched.
645
+
646
+ The full, unshortened entry is saved to Cloud Storage as `fsl-overflow.json`, at the same
647
+ `logAttachments/{logId}/` path an ordinary attachment would use, whenever a bucket is
648
+ available — see [Attachments](#attachments). A shortened entry carries `labels.truncated="true"`,
649
+ and `labels.hasAttachments="true"` when the full entry was saved. With no Storage configured,
650
+ the entry is still shortened; the original is lost, and the process warns once, not per entry.
651
+
562
652
  ## Volume controls
563
653
 
564
- Three separate gates decide whether a log is written. All have defaults, and the defaults
565
- drop things — so this is worth reading before you conclude something is broken.
654
+ Several gates decide whether a log is written. All have defaults, and the defaults
655
+ hold things back — so this is worth reading before you conclude something is broken.
566
656
 
567
657
  | Gate | Default | Where |
568
658
  |---|---|---|
569
- | Session limit | **50 logs**, then the client stops sending | client, per browser session |
570
- | Duplicate limit | **3 copies** of the same error, then it stops | client, per browser session |
659
+ | Log budget | **50 logs**, refilling **1 per minute**; the last **20%** for errors only | client, per browser tab |
660
+ | Duplicates | **3** full copies of the same error, then counted and sent as a summary | client, per browser tab |
571
661
  | Client severity floor | `WARNING` in production, `DEBUG` in dev | client, `minLogLevel` |
572
662
  | Server severity floor | `WARNING` in production, `DEBUG` in the emulator | function, `minSeverity` |
573
663
  | Function concurrency | `maxInstances: 1` on `createClientLogFunction` | function |
@@ -578,21 +668,91 @@ initLogger({
578
668
  releaseId,
579
669
  logFunction,
580
670
  minLogLevel: 'INFO',
581
- rateLimitOptions: { sessionLimit: 200, duplicateLimit: 5 },
671
+ rateLimitOptions: {
672
+ sessionLimit: 50, // the budget: how many logs can go at once
673
+ refillPerMinute: 1, // how fast it comes back
674
+ errorReserve: 0.2, // share of the budget only ERROR and above may spend
675
+ duplicateLimit: 3, // full copies of one error before counting starts
676
+ summaryIntervalMinutes: 60,
677
+ summaryMaxAgeDays: 7, // how long an unsent summary waits on the device
678
+ maxPendingSummaries: 50,
679
+ },
582
680
  })
583
681
  ```
584
682
 
585
- Two errors count as duplicates when the **message and the screen both match**, so the same
586
- error on two different screens is not collapsed into one. The budget lives in
587
- `sessionStorage` and resets with the session.
683
+ The client's production default comes from `process.env.NODE_ENV`, which Vite replaces at
684
+ build time. A `define: { 'process.env': {} }` in `vite.config` — common, to quiet a library
685
+ that expects Node — replaces the whole object instead, `NODE_ENV` reads as undefined, and
686
+ the floor is silently `DEBUG` in production. If your config has that line, pass
687
+ `minLogLevel` explicitly. Stating it is the safe habit either way: it is the one default
688
+ here whose failure mode is a bill rather than a missing log.
689
+
690
+ ### The budget refills
691
+
692
+ Each browser tab starts with 50 logs. Every log spends one, and one comes back each minute,
693
+ up to 50. A reload does not reset it — the tab keeps its budget in `sessionStorage`.
694
+
695
+ So a burst at start-up is fine, and a user who works in the app all afternoon is never
696
+ silenced for long. A bug that logs in a loop is still held to about 60 entries an hour per
697
+ user: 1,000 users stuck in such a loop for a working month stays around the 50 GiB of
698
+ Cloud Logging that each project gets free.
699
+
700
+ The last 20% of the budget is reserved: warnings can spend it down to 10, and only
701
+ `ERROR` and above can spend the rest. A noisy warning cannot use up the room a crash needs.
702
+
703
+ ### Repeats are counted, not dropped
704
+
705
+ Two errors are the same when the **message and the screen both match**, so the same error
706
+ on two different screens is kept apart. The first 3 are sent in full, with their stack and
707
+ breadcrumbs. After that the browser only counts them, and sends one summary:
708
+
709
+ ```
710
+ WARNING Repeated 197 more times: cart sync failed
711
+ labels.repeatOf="<repeatKey of the first copy>" labels.repeatCount="197"
712
+ labels.firstSeen="…" labels.lastSeen="…"
713
+ ```
714
+
715
+ The same count and window are in the entry's body, under `context.repeat`, so a summary is
716
+ filed as JSON like every other entry and a search on `jsonPayload.message` finds it.
717
+
718
+ The browser never learns the server's `logId` for the first copy — `writeLog` assigns it
719
+ after the log has already left the tab. So each full copy instead carries its own
720
+ `labels.repeatKey`, a client-side id, and the summary's `repeatOf` points at that instead:
721
+ query `labels.repeatKey="…" OR labels.repeatOf="…"` to find a full copy and its summary
722
+ together.
723
+
724
+ A summary is sent once an hour, when the tab is hidden, and once at startup for anything
725
+ a previous visit left queued. It is keyed by the error, the `releaseId` and the `userId`,
726
+ so two releases or two people on one computer are never counted together. Its entry is
727
+ timestamped at `lastSeen`, not at the time it was sent.
728
+
729
+ The summary's own labels are `appId`, `releaseId`, `userId`, `screen` and `errorType` — from
730
+ the time the errors happened, not from whoever's tab eventually sends it — plus
731
+ `repeatOf`/`repeatCount`/`firstSeen`/`lastSeen`/`sentLate`. Everything else about the error —
732
+ browser, platform, breadcrumbs, the stack — is not repeated here; it is already on the full
733
+ copies `repeatOf` points back to.
734
+
735
+ Unsent summaries are kept in `localStorage`, so closing the tab does not lose them: the
736
+ next visit sends them, marked `labels.sentLate="true"`. A summary is only removed from that
737
+ queue once it has actually been sent — a failed attempt (offline, or the tab closing right
738
+ after it was queued) leaves it for the next flush or the next visit to retry, never twice.
739
+ At most 50 wait, and any older than 7 days are deleted rather than sent — they are error
740
+ messages, and may hold personal data.
741
+
742
+ A summary is a `WARNING` with no stack, so Cloud Error Reporting sees the 3 full copies and
743
+ not the summary. For the true count, add up `labels.repeatCount` in Cloud Logging.
744
+
745
+ Summaries do not spend the log budget. There is at most one per error, per release, per user,
746
+ per hour.
588
747
 
589
748
  ### What a dropped log looks like
590
749
 
591
750
  The two rate limits say so in the browser console:
592
751
 
593
752
  ```
594
- [fsl] Duplicate suppressed: TypeError: cannot read 'id'|checkout
595
- [fsl] Session log limit reached
753
+ [fsl] Duplicate counted for the next summary: TypeError: cannot read 'id' | checkout
754
+ [fsl] Log budget empty — next log in about a minute
755
+ [fsl] Log budget: only errors can use the reserve now
596
756
  ```
597
757
 
598
758
  **The severity floors are silent.** Both of them — the client's `minLogLevel` and the
@@ -627,6 +787,9 @@ Narrow it when you need to:
627
787
  | `labels.screen="checkout"` | one screen |
628
788
  | `labels.feedback="true"` | user-reported issues |
629
789
  | `labels.hasAttachments="true"` | entries with files in GCS |
790
+ | `labels.truncated="true"` | entries shortened to fit — the full copy is `fsl-overflow.json` |
791
+ | `labels.repeatKey="<key>" OR labels.repeatOf="<key>"` | one repeating error: its full copies and its summaries |
792
+ | `labels.sentLate="true"` | repeat summaries sent on a later visit |
630
793
 
631
794
  Locally, the emulator's JSONL answers the same questions. Point
632
795
  **[firebase-mcp-server](https://github.com/dasasian/firebase-mcp-server)** at either and ask
@@ -762,6 +925,9 @@ Some of what is already handled here, all of it learned the expensive way:
762
925
  disagree over a typo.
763
926
  - **Checking a rate limit and spending it as two calls double-counts**, quietly making a
764
927
  configured budget of 50 a budget of 25.
928
+ - **A fixed budget goes silent in a long session.** 50 logs per page load is spent by
929
+ mid-morning in an app someone keeps open all day, and the crash at lunch is never sent.
930
+ A budget that refills, with a share kept for errors, does not have that shape.
765
931
  - **An old stack naming a bundle that still exists** resolves against the current release's
766
932
  map, giving line numbers that are confidently wrong — worse than none, because nothing
767
933
  signals it.
@@ -46,6 +46,22 @@ export declare class Logger<AppLabels extends Record<string, string | undefined>
46
46
  */
47
47
  sendFeedback(text: string, extras?: FeedbackOptions<AppLabels>): void;
48
48
  private send;
49
+ private readonly summariesInFlight;
50
+ /** Send whatever repeat summaries are due, from this visit or an earlier one. */
51
+ sendPendingSummaries(): void;
52
+ /**
53
+ * A repeat summary: a WARNING with no stack, timestamped at `lastSeen` (see
54
+ * README, "Repeats are counted, not dropped"). It still respects the
55
+ * severity floor — only the budget and the duplicate gate are skipped, via
56
+ * `send`'s `skipBudget`.
57
+ *
58
+ * It is queued in `localStorage` precisely so a failed send does not lose
59
+ * it — offline, or the tab tearing down right after the `visibilitychange`
60
+ * that triggered this. So it is only acknowledged (removed from the queue)
61
+ * once `send` reports the entry actually reached `logFunction`; otherwise
62
+ * the next flush, or the next visit, finds it still there and retries it.
63
+ */
64
+ private sendRepeatSummary;
49
65
  }
50
66
  /**
51
67
  * Send user feedback through the configured logger.
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"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"}
@@ -9,9 +9,23 @@ const severity_1 = require("../shared/severity");
9
9
  const error_1 = require("../shared/error");
10
10
  const breadcrumbs_1 = require("./breadcrumbs");
11
11
  const rateLimiter_1 = require("./rateLimiter");
12
+ /**
13
+ * No `typeof process` guard, on purpose. Every bundler folds `process.env.NODE_ENV` to a
14
+ * string literal at build time, so the comparison is safe in a browser — but `process`
15
+ * itself does not exist there, and guarding on it meant the folded branch was never
16
+ * reached: every browser build defaulted to DEBUG in production, and the README's
17
+ * "WARNING in production" was true only under Node. Seen in a real Vite bundle as
18
+ * `typeof process<"u"?"WARNING":"DEBUG"`. A runtime with neither the fold nor
19
+ * `process` throws on the read, and that is the case the catch is for.
20
+ */
12
21
  function defaultMinLevel() {
13
- if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production')
14
- return 'WARNING';
22
+ try {
23
+ if (process.env.NODE_ENV === 'production')
24
+ return 'WARNING';
25
+ }
26
+ catch {
27
+ // Not Node and not folded: development.
28
+ }
15
29
  return 'DEBUG';
16
30
  }
17
31
  // Order matters — first match wins.
@@ -122,33 +136,51 @@ class Logger {
122
136
  // same pipe — it is rare by nature and there is nothing to throttle. The
123
137
  // exemption keys on the record being feedback, not on its severity, so a
124
138
  // NOTICE emitted for anything else still behaves normally.
125
- bypassVolumeControls = false) {
139
+ bypassVolumeControls = false,
140
+ // A repeat summary spends no budget and is never itself a duplicate — but
141
+ // it still respects the severity floor, unlike feedback above.
142
+ skipBudget = false, timestamp) {
126
143
  if (!bypassVolumeControls && severity_1.SEVERITY_ORDER[severity] > this.minLevel)
127
- return;
144
+ return false;
145
+ const allLabels = {
146
+ appId: this.config.appId,
147
+ releaseId: this.config.releaseId,
148
+ screen: (0, breadcrumbs_1.getCurrentScreen)(),
149
+ userId: this.userId,
150
+ platform: PLATFORM,
151
+ browser: BROWSER,
152
+ ...this.userLabels,
153
+ ...labels,
154
+ };
128
155
  // One gate for every severity. Passing a signature opts this log into
129
156
  // duplicate suppression; the check and the budget spend are one operation,
130
157
  // so a log can neither be counted twice nor checked without being counted.
131
- const decision = bypassVolumeControls ? { allowed: true } : (0, rateLimiter_1.allow)(signature);
158
+ // Once a signature passes `duplicateLimit`, further occurrences are
159
+ // "counted", not refused outright — the rate limiter keeps a running
160
+ // count toward the next repeat summary.
161
+ const decision = bypassVolumeControls || skipBudget
162
+ ? { allowed: true }
163
+ : (0, rateLimiter_1.allow)({ severity, signature, labels: allLabels });
132
164
  if (!decision.allowed) {
133
165
  if (decision.reason === 'duplicate') {
134
- console.warn(`[fsl] Duplicate suppressed: ${decision.signature}`);
166
+ console.warn(`[fsl] Duplicate counted for the next summary: ${(0, rateLimiter_1.describeSignature)(decision.signature ?? '')}`);
167
+ }
168
+ else if (decision.reason === 'reserve') {
169
+ console.warn('[fsl] Log budget: only errors can use the reserve now');
135
170
  }
136
171
  else {
137
- console.warn('[fsl] Session log limit reached');
172
+ console.warn('[fsl] Log budget empty — next log in about a minute');
138
173
  }
139
- return;
174
+ return false;
175
+ }
176
+ // Ties this full copy to the summary its repeats will eventually become.
177
+ // The client has no server logId to put in the summary's `repeatOf` — see
178
+ // README, "Repeats are counted, not dropped" — so this client-side id is
179
+ // the join key instead, carried by every full copy of the signature.
180
+ if ('repeatKey' in decision && decision.repeatKey) {
181
+ allLabels.repeatKey = decision.repeatKey;
140
182
  }
141
183
  try {
142
- const allLabels = {
143
- appId: this.config.appId,
144
- releaseId: this.config.releaseId,
145
- screen: (0, breadcrumbs_1.getCurrentScreen)(),
146
- userId: this.userId,
147
- platform: PLATFORM,
148
- browser: BROWSER,
149
- ...this.userLabels,
150
- ...labels,
151
- };
152
184
  // Each attachment is converted in its own try. A Blob or File can fail to
153
185
  // read — a user picks a file from <input type="file">, moves or deletes it,
154
186
  // then submits, and the browser raises NotReadableError. Previously one
@@ -186,13 +218,65 @@ class Logger {
186
218
  error,
187
219
  },
188
220
  ...(base64Attachments ? { attachments: base64Attachments } : {}),
221
+ ...(timestamp ? { timestamp } : {}),
189
222
  };
190
223
  await this.config.logFunction(payload);
224
+ return true;
191
225
  }
192
226
  catch (err) {
193
227
  console.error('[fsl] Failed to send log:', err instanceof Error ? err.message : err);
228
+ return false;
229
+ }
230
+ }
231
+ // Guards against sending the same queued summary twice when a flush is
232
+ // triggered again (interval, visibilitychange) before a previous attempt's
233
+ // `logFunction` call has resolved — `peekPendingSummaries` does not remove
234
+ // anything, so without this a slow or slow-to-fail send could be picked up
235
+ // more than once.
236
+ summariesInFlight = new Set();
237
+ /** Send whatever repeat summaries are due, from this visit or an earlier one. */
238
+ sendPendingSummaries() {
239
+ for (const summary of (0, rateLimiter_1.peekPendingSummaries)()) {
240
+ if (this.summariesInFlight.has(summary.id))
241
+ continue;
242
+ this.summariesInFlight.add(summary.id);
243
+ void this.sendRepeatSummary(summary).finally(() => this.summariesInFlight.delete(summary.id));
194
244
  }
195
245
  }
246
+ /**
247
+ * A repeat summary: a WARNING with no stack, timestamped at `lastSeen` (see
248
+ * README, "Repeats are counted, not dropped"). It still respects the
249
+ * severity floor — only the budget and the duplicate gate are skipped, via
250
+ * `send`'s `skipBudget`.
251
+ *
252
+ * It is queued in `localStorage` precisely so a failed send does not lose
253
+ * it — offline, or the tab tearing down right after the `visibilitychange`
254
+ * that triggered this. So it is only acknowledged (removed from the queue)
255
+ * once `send` reports the entry actually reached `logFunction`; otherwise
256
+ * the next flush, or the next visit, finds it still there and retries it.
257
+ */
258
+ async sendRepeatSummary(summary) {
259
+ const labels = {
260
+ appId: this.config.appId,
261
+ releaseId: summary.releaseId ?? this.config.releaseId,
262
+ userId: summary.userId,
263
+ screen: summary.screen,
264
+ errorType: summary.errorType,
265
+ repeatOf: summary.repeatOf,
266
+ repeatCount: String(summary.repeatCount),
267
+ firstSeen: summary.firstSeen,
268
+ lastSeen: summary.lastSeen,
269
+ ...(summary.sentLate ? { sentLate: 'true' } : {}),
270
+ };
271
+ const sent = await this.send(`Repeated ${summary.repeatCount} more times: ${summary.message}`, 'WARNING', labels,
272
+ // A body besides the message. With only `message` left once the timestamp
273
+ // is promoted, Cloud Logging files the entry as textPayload, and a search on
274
+ // jsonPayload.message — /query-logs, or anyone's saved query — misses every
275
+ // summary. The smoke run found it.
276
+ { repeat: { count: summary.repeatCount, firstSeen: summary.firstSeen, lastSeen: summary.lastSeen } }, undefined, undefined, undefined, false, true, summary.lastSeen);
277
+ if (sent)
278
+ (0, rateLimiter_1.acknowledgeSummary)(summary.id);
279
+ }
196
280
  }
197
281
  exports.Logger = Logger;
198
282
  /**
@@ -229,6 +313,13 @@ function triggerTestLog() {
229
313
  let instance = null;
230
314
  function initLogger(config) {
231
315
  instance = new Logger(config);
316
+ // A previous visit's queued summaries (README, "the next visit sends
317
+ // them") would otherwise wait for the first `visibilitychange: hidden` or
318
+ // the first 60s interval tick — a short delay so init itself can finish
319
+ // first, not a wait for either of those.
320
+ if (typeof setTimeout !== 'undefined') {
321
+ setTimeout(() => instance?.sendPendingSummaries(), 0);
322
+ }
232
323
  return instance;
233
324
  }
234
325
  function getClientLogger() {
@@ -236,4 +327,32 @@ function getClientLogger() {
236
327
  throw new Error('[fsl] initLogger() not called');
237
328
  return instance;
238
329
  }
330
+ /**
331
+ * Repeat summaries are sent hourly and when the tab is hidden (README,
332
+ * "Repeats are counted, not dropped"). Neither is triggered by an ordinary
333
+ * log call — `send` does not check for due summaries itself, since doing so
334
+ * with frozen-for-testing time reliably makes an interval-based check look
335
+ * due immediately (see tests/rateLimiter.ts). So there are exactly three
336
+ * triggers for a flush: `initLogger` (a previous visit's queue, once, above),
337
+ * this `visibilitychange` listener (the tab going hidden), and the interval
338
+ * below (an app that never hides its tab and rarely reloads).
339
+ *
340
+ * Neither exists in the esbuild bundle test's sandbox (no `window`/`document`
341
+ * there — see tests/browserBundle.ts), so both are guarded.
342
+ */
343
+ if (typeof document !== 'undefined') {
344
+ document.addEventListener('visibilitychange', () => {
345
+ if (document.visibilityState !== 'hidden')
346
+ return;
347
+ (0, rateLimiter_1.flushDueSummaries)(true);
348
+ instance?.sendPendingSummaries();
349
+ });
350
+ }
351
+ if (typeof window !== 'undefined') {
352
+ const interval = setInterval(() => {
353
+ (0, rateLimiter_1.flushDueSummaries)();
354
+ instance?.sendPendingSummaries();
355
+ }, 60_000);
356
+ interval.unref?.();
357
+ }
239
358
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"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"}