@dasasian/firebase-structured-logger 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -513,6 +513,7 @@ logger.error(err, { orderId })
513
513
  |---|---|---|
514
514
  | `appId`, `releaseId` | client | your `initLogger` config |
515
515
  | `screen` | client | tracked as the user moves |
516
+ | `route`, `path`, `routeSource` | client | with `enableNavigation()` — the route pattern, the real path, and where the pattern came from |
516
517
  | `userId` | client | `setUser`, held for the session |
517
518
  | `platform` | client | user agent — `ios` / `android` / `macos` / `web` |
518
519
  | `browser` | client | user agent |
@@ -629,6 +630,122 @@ current screen, so `labels.screen` stays correct without a second call.
629
630
  > Record the step, not the data. Breadcrumb `data` is written to your logs verbatim — keep
630
631
  > PII, tokens and card numbers out of it, the same as you would for any label.
631
632
 
633
+ ### Navigation, automatically
634
+
635
+ ```ts
636
+ import { enableNavigation } from '@dasasian/firebase-structured-logger/client/navigation'
637
+
638
+ enableNavigation()
639
+
640
+ // or name routes the way your router does
641
+ enableNavigation({
642
+ routeFor: (path) => router.match(path)?.name, // undefined falls back to the id rule
643
+ })
644
+ ```
645
+
646
+ Its own entry point, so an app that never imports it ships none of it, whatever its
647
+ bundler — and the import says plainly that it wraps `history.pushState` and
648
+ `replaceState`, the only way to notice a single-page app changing route. Call it once,
649
+ before or after `initLogger`. It records the current page at once and every route change
650
+ after it, back and forward included, as a `nav` breadcrumb, and every entry carries three
651
+ labels:
652
+
653
+ | Label | Example | Means |
654
+ |---|---|---|
655
+ | `route` | `/orders/:id/items` | the pattern — for grouping and counting |
656
+ | `path` | `/orders/1042/items` | the real path — for "what went wrong for order 1042?" |
657
+ | `routeSource` | `router` or `pattern` | whether `route` came from your `routeFor`, or from the id rule |
658
+
659
+ `screen` keeps its meaning — the name you give with `bc.nav` or `setScreen` — and falls
660
+ back to `route` when you never set one, so an app that does nothing still gets a useful
661
+ screen.
662
+
663
+ **The id rule**, when there is no `routeFor` or it returns `undefined`: a path segment that
664
+ is all digits, a UUID, a long hex string or a ULID becomes `:id`. Anything else is kept as
665
+ written, so a slug like `/blog/my-post` stays as it is — no rule tells a slug from a page
666
+ name reliably, which is what `routeFor` is for.
667
+
668
+ **What never leaves the browser:** the query string, always — it is where tokens and
669
+ emails usually ride. The fragment too, unless it is a route: `#/orders/1042` is read as the
670
+ path, `#section-3` or `#access_token=…` is dropped. If your paths themselves can hold
671
+ personal data (`/users/jane@example.com`), clean them or switch `path` off:
672
+
673
+ ```ts
674
+ enableNavigation({ cleanPath: (path) => path.replace(/[^/]+@[^/]+/g, ':email') })
675
+ enableNavigation({ path: false })
676
+ ```
677
+
678
+ ## Timing: when something is too slow
679
+
680
+ Some failures never throw. A loading screen waits on eight pieces, one of them takes 30
681
+ seconds, and the logs say nothing — because nothing failed. Traces report exactly that
682
+ case, and only that case: something took longer than you said it should, or never
683
+ finished. A trace that finishes in time sends nothing at all.
684
+
685
+ ```ts
686
+ import { trace, startTrace } from '@dasasian/firebase-structured-logger/client/timing'
687
+
688
+ await trace('app_boot', async (boot) => {
689
+ const user = await boot.step('sign-in', () => signIn())
690
+ await Promise.all([
691
+ boot.step('products', () => loadProducts(user)),
692
+ boot.step('places', () => loadPlaces(user)),
693
+ ])
694
+ })
695
+
696
+ // A flow that spans functions — a screen that starts on mount and ends when its data is in
697
+ const open = startTrace('order_open')
698
+ await open.step('order', () => loadOrder(id))
699
+ open.end()
700
+ ```
701
+
702
+ Your code holds names only. The limits live in one place, set once at startup:
703
+
704
+ ```ts
705
+ import { configureTraces } from '@dasasian/firebase-structured-logger/client/timing'
706
+
707
+ configureTraces({
708
+ app_boot: { warnAfterMs: 8000, steps: { products: 3000 } },
709
+ order_open: { warnAfterMs: 2000 },
710
+ })
711
+ ```
712
+
713
+ A trace with no limits configured is timed but never reported. Limits are read when a run
714
+ starts, so configure before the first one.
715
+
716
+ **What gets sent.** One `WARNING` per run, the moment the first limit is crossed — the
717
+ trace's, or a step's own — while it is still running, so a step that never finishes is
718
+ reported too. Nothing more is sent for that run afterwards.
719
+
720
+ ```
721
+ WARNING app_boot slow: products passed 3000 ms, still waiting
722
+ labels.trace="app_boot" labels.run="<id>" labels.slow="step" labels.step="products"
723
+ timing: { elapsedMs: 3000, limitMs: 3000,
724
+ steps: { sign-in: 610, places: 410 }, waiting: ["products"] }
725
+ ```
726
+
727
+ `labels.slow` is `"trace"` or `"step"`. Durations are in milliseconds, always in `timing`.
728
+ `labels.run` tells two overlapping runs of the same trace apart.
729
+
730
+ **What is never judged.** A browser pauses pages it is not showing: a hidden tab, a phone
731
+ switching apps, a laptop going to sleep. Time spent paused is not your app being slow, so
732
+ a run that was hidden at any point, or that was paused — a one-second check that arrives
733
+ five or more seconds late — is not reported. Laptop sleep often fires no event at all,
734
+ which is why the late check exists.
735
+
736
+ **Underneath** each step is a standard `performance.mark` and `performance.measure`, so
737
+ it shows in the browser's Performance panel and in other tools that read them. Ours are
738
+ cleared when the run ends. A `step` after `end()`, or a second `end()`, is ignored.
739
+
740
+ **On the server**, `trace` and `startTrace` come from `/functions`, with the same entry. A
741
+ server run is judged when a step or the trace ends — there is no timer, because Cloud
742
+ Functions and Cloud Run can throttle the CPU once a response is sent. A request that hangs
743
+ outright is ended by the platform's timeout, which logs it. Inside `withLogging`, the entry
744
+ carries that request's labels like any other.
745
+
746
+ Traces explain the slow case; they do not measure what is normal. There are no
747
+ percentiles here and no sampling — if you need those, that is a monitoring tool's job.
748
+
632
749
  ## User feedback
633
750
 
634
751
  ```ts
@@ -869,11 +986,14 @@ Narrow it when you need to:
869
986
  | `labels.functionName:*` | server entries only |
870
987
  | `labels.releaseId="<sha>"` | one build |
871
988
  | `labels.screen="checkout"` | one screen |
989
+ | `labels.route="/orders/:id/items"` | one route, every id (with `enableNavigation`) |
990
+ | `labels.path="/orders/1042/items"` | one real page — that order, that user (with `enableNavigation`) |
872
991
  | `labels.feedback="true"` | user-reported issues |
873
992
  | `labels.hasAttachments="true"` | entries with files in GCS |
874
993
  | `labels.truncated="true"` | entries shortened to fit — the full copy is `fsl-overflow.json` |
875
994
  | `labels.repeatKey="<key>" OR labels.repeatOf="<key>"` | one repeating error: its full copies and its summaries |
876
995
  | `labels.sentLate="true"` | repeat summaries sent on a later visit |
996
+ | `labels.trace="app_boot"` | slow runs of one trace — `labels.slow` says whether the trace or a step was late |
877
997
 
878
998
  Locally, the emulator's JSONL answers the same questions. Point
879
999
  **[firebase-mcp-server](https://github.com/dasasian/firebase-mcp-server)** at either and ask
@@ -903,6 +1023,17 @@ logger.setUser(uid, extraLabels?)
903
1023
  logger.clearUser()
904
1024
  logger.setScreen(screen)
905
1025
  logger.addBreadcrumb(type, name, data?)
1026
+
1027
+ ```
1028
+
1029
+ Optional helpers are separate entry points, so an app ships only what it imports:
1030
+
1031
+ ```ts
1032
+ import { enableNavigation } from '@dasasian/firebase-structured-logger/client/navigation'
1033
+ enableNavigation({ routeFor?, cleanPath?, path? }) // see "Navigation, automatically"
1034
+
1035
+ import { trace, startTrace, configureTraces } from '@dasasian/firebase-structured-logger/client/timing'
1036
+ configureTraces({ name: { warnAfterMs?, steps?: { step: ms } } }) // see "Timing"
906
1037
  ```
907
1038
 
908
1039
  Also exported: `initLogger`, `getClientLogger`, `setupGlobalErrorHandler`, `handleReactError`,
@@ -937,6 +1068,8 @@ getLogger() // the current request's writer, or an anonymo
937
1068
  logError / logWarn / logInfo / logDebug (message, labels?, context?, attachments?)
938
1069
 
939
1070
  configureAttachments({ bucket?, prefix? }) // once, at module load — see Attachments
1071
+ configureTraces({ name: { warnAfterMs?, steps? } }) // once — see "Timing"
1072
+ trace(name, async (t) => { await t.step(name, fn) }) // or startTrace(name) … .end()
940
1073
 
941
1074
  // Receiving client logs. All three take the same source-map config:
942
1075
  // { bucket?, sourceMaps?: { bucket?, prefix? } }
@@ -1,4 +1,4 @@
1
- import type { BreadcrumbEntry } from '../shared/types';
1
+ import type { BreadcrumbEntry, NavigationLabels } from '../shared/types';
2
2
  /**
3
3
  * How many breadcrumbs are retained — and therefore how many are sent.
4
4
  *
@@ -15,6 +15,16 @@ import type { BreadcrumbEntry } from '../shared/types';
15
15
  export declare const MAX_BREADCRUMBS = 50;
16
16
  export declare function setCurrentScreen(screen: string): void;
17
17
  export declare function getCurrentScreen(): string | undefined;
18
+ /**
19
+ * Called by `enableNavigation()` (`client/navigation.ts`) on the current page and on
20
+ * every route change after it — never by the core itself. Mirrors `setCurrentScreen`:
21
+ * the one-way setter a helper hands data through, rather than the core reaching out to
22
+ * the helper. Adds a `nav` breadcrumb named after the real path, or the route pattern
23
+ * when `path` was omitted (`enableNavigation({ path: false })`).
24
+ */
25
+ export declare function setCurrentRoute(labels: NavigationLabels): void;
26
+ /** The current page's navigation labels, or `undefined` when `enableNavigation()` was never called. */
27
+ export declare function getCurrentRoute(): NavigationLabels | undefined;
18
28
  export declare function addBreadcrumb(type: BreadcrumbEntry['type'], name: string, data?: Record<string, unknown>): void;
19
29
  export declare function getLastBreadcrumbs(count: number): BreadcrumbEntry[];
20
30
  export declare function clearBreadcrumbs(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,KAAK,CAAA;AAMjC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAErD;AAoBD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI,CAQN;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,CAKnE;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC;AAED,eAAO,MAAM,EAAE;mBACE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBACtC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBACpC,MAAM;kBACR,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CACtD,CAAA"}
1
+ {"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAExE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,KAAK,CAAA;AAMjC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAErD;AAID;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAG9D;AAED,uGAAuG;AACvG,wBAAgB,eAAe,IAAI,gBAAgB,GAAG,SAAS,CAE9D;AAoBD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI,CAQN;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,CAKnE;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC;AAED,eAAO,MAAM,EAAE;mBACE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBACtC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBACpC,MAAM;kBACR,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CACtD,CAAA"}
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.bc = exports.MAX_BREADCRUMBS = void 0;
4
4
  exports.setCurrentScreen = setCurrentScreen;
5
5
  exports.getCurrentScreen = getCurrentScreen;
6
+ exports.setCurrentRoute = setCurrentRoute;
7
+ exports.getCurrentRoute = getCurrentRoute;
6
8
  exports.addBreadcrumb = addBreadcrumb;
7
9
  exports.getLastBreadcrumbs = getLastBreadcrumbs;
8
10
  exports.clearBreadcrumbs = clearBreadcrumbs;
@@ -30,6 +32,22 @@ function setCurrentScreen(screen) {
30
32
  function getCurrentScreen() {
31
33
  return currentScreen;
32
34
  }
35
+ let currentRoute;
36
+ /**
37
+ * Called by `enableNavigation()` (`client/navigation.ts`) on the current page and on
38
+ * every route change after it — never by the core itself. Mirrors `setCurrentScreen`:
39
+ * the one-way setter a helper hands data through, rather than the core reaching out to
40
+ * the helper. Adds a `nav` breadcrumb named after the real path, or the route pattern
41
+ * when `path` was omitted (`enableNavigation({ path: false })`).
42
+ */
43
+ function setCurrentRoute(labels) {
44
+ currentRoute = labels;
45
+ addBreadcrumb('nav', labels.path ?? labels.route, labels.path !== undefined ? { route: labels.route } : undefined);
46
+ }
47
+ /** The current page's navigation labels, or `undefined` when `enableNavigation()` was never called. */
48
+ function getCurrentRoute() {
49
+ return currentRoute;
50
+ }
33
51
  /**
34
52
  * Drop anything past the age cutoff.
35
53
  *
@@ -1 +1 @@
1
- {"version":3,"file":"breadcrumbs.js","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":";;;AAqBA,4CAGC;AAED,4CAEC;AAoBD,sCAYC;AAED,gDAKC;AAED,4CAGC;AAtED;;;;;;;;;;;;GAYG;AACU,QAAA,eAAe,GAAG,EAAE,CAAA;AACjC,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,YAAY;AAE7C,IAAI,aAAiC,CAAA;AACrC,IAAI,WAAW,GAAsB,EAAE,CAAA;AAEvC,SAAgB,gBAAgB,CAAC,MAAc;IAC7C,aAAa,GAAG,MAAM,CAAA;IACtB,aAAa,CAAC,KAAK,EAAE,YAAY,MAAM,EAAE,CAAC,CAAA;AAC5C,CAAC;AAED,SAAgB,gBAAgB;IAC9B,OAAO,aAAa,CAAA;AACtB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,SAAS,CAAC,OAA0B,EAAE,GAAW;IACxD,MAAM,MAAM,GAAG,GAAG,GAAG,UAAU,CAAA;IAC/B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,MAAM;QAAE,OAAO,OAAO,CAAA;IACzE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,GAAG,MAAM,CAAC,CAAA;AACtD,CAAC;AAED,SAAgB,aAAa,CAC3B,IAA6B,EAC7B,IAAY,EACZ,IAA8B;IAE9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,WAAW,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IACtD,WAAW,GAAG,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;IAEzC,IAAI,WAAW,CAAC,MAAM,GAAG,uBAAe,EAAE,CAAC;QACzC,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,uBAAe,CAAC,CAAA;IACvE,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAa;IAC9C,2EAA2E;IAC3E,8BAA8B;IAC9B,WAAW,GAAG,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;IAChD,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAA;AACnE,CAAC;AAED,SAAgB,gBAAgB;IAC9B,WAAW,GAAG,EAAE,CAAA;IAChB,aAAa,GAAG,SAAS,CAAA;AAC3B,CAAC;AAEY,QAAA,EAAE,GAAG;IAChB,MAAM,EAAE,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC;IAC7F,KAAK,EAAG,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;IAC5F,GAAG,EAAK,CAAC,MAAc,EAAE,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC;IACpD,KAAK,EAAG,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;CAC7F,CAAA"}
1
+ {"version":3,"file":"breadcrumbs.js","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":"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"}
@@ -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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"}
@@ -146,10 +146,19 @@ class Logger {
146
146
  skipBudget = false, timestamp) {
147
147
  if (!bypassVolumeControls && severity_1.SEVERITY_ORDER[severity] > this.minLevel)
148
148
  return false;
149
+ // Set only by enableNavigation() (@dasasian/firebase-structured-logger/client/navigation),
150
+ // through the setter it calls in breadcrumbs.ts — undefined for an app that never
151
+ // imports that entry point.
152
+ const nav = (0, breadcrumbs_1.getCurrentRoute)();
149
153
  const allLabels = {
150
154
  appId: this.config.appId,
151
155
  releaseId: this.config.releaseId,
152
- screen: (0, breadcrumbs_1.getCurrentScreen)(),
156
+ // Falls back to the route pattern so an app that never calls setScreen/bc.nav
157
+ // still gets a useful screen label once navigation is enabled.
158
+ screen: (0, breadcrumbs_1.getCurrentScreen)() ?? nav?.route,
159
+ route: nav?.route,
160
+ path: nav?.path,
161
+ routeSource: nav?.routeSource,
153
162
  userId: this.userId,
154
163
  platform: PLATFORM,
155
164
  browser: BROWSER,
@@ -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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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `@dasasian/firebase-structured-logger/client/navigation` — its own entry point
3
+ * (see CLAUDE.md, "Optional client helpers are separate entry points") so an app
4
+ * that never imports it ships none of this, whatever its bundler. Call `enableNavigation()`
5
+ * once, before or after `initLogger`. See README, "Navigation, automatically".
6
+ */
7
+ export interface NavigationOptions {
8
+ /** Names the route the way your router does. Returning `undefined` falls back to the id rule. */
9
+ routeFor?: (path: string) => string | undefined;
10
+ /**
11
+ * Runs on the real path before it is stored and before `routeFor`/the id rule sees it —
12
+ * for paths that can themselves hold personal data, e.g. `/users/jane@example.com`.
13
+ */
14
+ cleanPath?: (path: string) => string;
15
+ /** `false` omits the `path` label, and keeps the real path out of breadcrumbs too. */
16
+ path?: false;
17
+ }
18
+ /**
19
+ * The route pattern for a path: a segment counts as an id, and becomes `:id`, when it
20
+ * is all digits, a UUID, hex of 16 or more characters, or a 26-character ULID (Crockford
21
+ * base32 — digits and letters, excluding I, L, O, U). Anything else — a slug like
22
+ * `my-post`, a version segment like `v2`, a short code — is kept exactly as written:
23
+ * no rule tells those from a page name reliably, which is what `routeFor` is for.
24
+ */
25
+ export declare function routePattern(path: string): string;
26
+ /**
27
+ * Turns on automatic navigation tracking for the session. The first call wraps
28
+ * `history.pushState`/`replaceState` and listens for `popstate`, then records the
29
+ * current page; a later call only replaces `options` — the module-scoped-state rule —
30
+ * and does not wrap again. Does nothing outside a browser (Node, SSR), and touches no
31
+ * browser global until it runs, so merely importing this module is always safe.
32
+ */
33
+ export declare function enableNavigation(newOptions?: NavigationOptions): void;
34
+ //# sourceMappingURL=navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/client/navigation.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,iGAAiG;IACjG,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;IAC/C;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACpC,sFAAsF;IACtF,IAAI,CAAC,EAAE,KAAK,CAAA;CACb;AAWD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjD;AA4DD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,GAAE,iBAAsB,GAAG,IAAI,CASzE"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.routePattern = routePattern;
4
+ exports.enableNavigation = enableNavigation;
5
+ const breadcrumbs_1 = require("./breadcrumbs");
6
+ const ALL_DIGITS = /^\d+$/;
7
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
8
+ const LONG_HEX = /^[0-9a-f]{16,}$/i;
9
+ const ULID = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
10
+ function isIdSegment(segment) {
11
+ return segment !== '' && (ALL_DIGITS.test(segment) || UUID.test(segment) || LONG_HEX.test(segment) || ULID.test(segment));
12
+ }
13
+ /**
14
+ * The route pattern for a path: a segment counts as an id, and becomes `:id`, when it
15
+ * is all digits, a UUID, hex of 16 or more characters, or a 26-character ULID (Crockford
16
+ * base32 — digits and letters, excluding I, L, O, U). Anything else — a slug like
17
+ * `my-post`, a version segment like `v2`, a short code — is kept exactly as written:
18
+ * no rule tells those from a page name reliably, which is what `routeFor` is for.
19
+ */
20
+ function routePattern(path) {
21
+ return path
22
+ .split('/')
23
+ .map((segment) => (isIdSegment(segment) ? ':id' : segment))
24
+ .join('/');
25
+ }
26
+ /**
27
+ * The real path: the query string never leaves the browser, and neither does a
28
+ * fragment unless it is itself a route. `#/orders/1042` is read as the path;
29
+ * `#section-3` or `#access_token=...` is dropped.
30
+ */
31
+ function realPath(location) {
32
+ const raw = location.hash.startsWith('#/') ? location.hash.slice(1) : location.pathname;
33
+ return raw.split('?')[0] ?? raw;
34
+ }
35
+ let options = {};
36
+ let wired = false;
37
+ function labelsFor(path) {
38
+ const cleaned = options.cleanPath ? options.cleanPath(path) : path;
39
+ const fromRouter = options.routeFor?.(cleaned);
40
+ const route = fromRouter ?? routePattern(cleaned);
41
+ const routeSource = fromRouter !== undefined ? 'router' : 'pattern';
42
+ return options.path === false ? { route, routeSource } : { route, path: cleaned, routeSource };
43
+ }
44
+ function recordNavigation() {
45
+ (0, breadcrumbs_1.setCurrentRoute)(labelsFor(realPath(location)));
46
+ }
47
+ // A Symbol.for registration, not a module-local Symbol — a second copy of this module
48
+ // (two bundles on one page) must still recognize the first copy's wrapper as "ours".
49
+ const FSL_WRAPPED = Symbol.for('fsl.wrappedHistoryMethod');
50
+ /**
51
+ * Wraps `history[name]` exactly once, ever — a later call finds `FSL_WRAPPED` already
52
+ * set and leaves it alone. The wrapper calls the original with the same arguments and
53
+ * `this`, returns its result, and only then records the navigation — so it never
54
+ * disturbs a wrapper another tool installed before (captured here as "the original")
55
+ * or after (which will in turn capture this wrapper as its own "original") this one.
56
+ */
57
+ function wrapHistoryMethod(name) {
58
+ const target = history;
59
+ const original = target[name];
60
+ if (original[FSL_WRAPPED])
61
+ return;
62
+ const wrapped = function (...args) {
63
+ const result = original.apply(this, args);
64
+ recordNavigation();
65
+ return result;
66
+ };
67
+ wrapped[FSL_WRAPPED] = true;
68
+ target[name] = wrapped;
69
+ }
70
+ /**
71
+ * Turns on automatic navigation tracking for the session. The first call wraps
72
+ * `history.pushState`/`replaceState` and listens for `popstate`, then records the
73
+ * current page; a later call only replaces `options` — the module-scoped-state rule —
74
+ * and does not wrap again. Does nothing outside a browser (Node, SSR), and touches no
75
+ * browser global until it runs, so merely importing this module is always safe.
76
+ */
77
+ function enableNavigation(newOptions = {}) {
78
+ options = newOptions;
79
+ if (typeof window === 'undefined')
80
+ return;
81
+ if (wired)
82
+ return;
83
+ wired = true;
84
+ wrapHistoryMethod('pushState');
85
+ wrapHistoryMethod('replaceState');
86
+ window.addEventListener('popstate', recordNavigation);
87
+ recordNavigation();
88
+ }
89
+ //# sourceMappingURL=navigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/client/navigation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type TraceConfig } from '../shared/trace';
2
+ export type { TraceConfig, TraceLimits } from '../shared/trace';
3
+ /**
4
+ * `@dasasian/firebase-structured-logger/client/timing` — its own entry point
5
+ * (CLAUDE.md, "Optional client helpers are separate entry points"), so an app
6
+ * that never imports it ships none of this. Touches no browser global at module
7
+ * load — `performance`, `document` and the timers below are only read once a
8
+ * trace actually starts. See README, "Timing: when something is too slow".
9
+ */
10
+ export interface Trace {
11
+ step<T>(name: string, fn: () => T | Promise<T>): Promise<T>;
12
+ end(): void;
13
+ }
14
+ /** Replaces every limit. Read when a run starts, so configure before the first one. */
15
+ export declare function configureTraces(newConfig: TraceConfig): void;
16
+ /** `startTrace(name)` returns the object; call `.end()` when the flow is over. */
17
+ export declare function startTrace(name: string): Trace;
18
+ /** Runs `fn` with a trace object and ends the trace when `fn` settles, either way. */
19
+ export declare function trace<T>(name: string, fn: (t: Trace) => T | Promise<T>): Promise<T>;
20
+ //# sourceMappingURL=timing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../src/client/timing.ts"],"names":[],"mappings":"AACA,OAAO,EAAqD,KAAK,WAAW,EAAoB,MAAM,iBAAiB,CAAA;AAEvH,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAM/D;;;;;;GAMG;AACH,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC3D,GAAG,IAAI,IAAI,CAAA;CACZ;AAID,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,CAE5D;AAqHD,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAE9C;AAED,sFAAsF;AACtF,wBAAsB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOzF"}
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configureTraces = configureTraces;
4
+ exports.startTrace = startTrace;
5
+ exports.trace = trace;
6
+ const logger_1 = require("./logger");
7
+ const trace_1 = require("../shared/trace");
8
+ function newPageLocalRunId() {
9
+ return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
10
+ }
11
+ let config = {};
12
+ /** Replaces every limit. Read when a run starts, so configure before the first one. */
13
+ function configureTraces(newConfig) {
14
+ config = newConfig;
15
+ }
16
+ const WATCHDOG_INTERVAL_MS = 1000;
17
+ const LATE_THRESHOLD_MS = 5000;
18
+ const activeRuns = new Set();
19
+ let watchdogId;
20
+ let visibilityWired = false;
21
+ let lastTickAt;
22
+ function now() {
23
+ return performance.now();
24
+ }
25
+ function markName(run, step, kind) {
26
+ return `fsl:${run.name}:${run.run}:${step}:${kind}`;
27
+ }
28
+ function disqualifyActiveRuns() {
29
+ for (const active of activeRuns)
30
+ active.disqualified = true;
31
+ }
32
+ function onVisibilityChange() {
33
+ if (document.visibilityState === 'hidden')
34
+ disqualifyActiveRuns();
35
+ }
36
+ /** No-op outside a browser (Node, SSR) — nothing there can ever go hidden. */
37
+ function wireVisibility() {
38
+ if (visibilityWired)
39
+ return;
40
+ visibilityWired = true;
41
+ if (typeof document === 'undefined')
42
+ return;
43
+ document.addEventListener('visibilitychange', onVisibilityChange);
44
+ }
45
+ function reportRun(run, report) {
46
+ (0, logger_1.getClientLogger)().warning((0, trace_1.traceMessage)(run.name, report), (0, trace_1.traceLabels)(run.name, run.run, report), (0, trace_1.traceContext)(report));
47
+ }
48
+ function tick() {
49
+ const nowMs = Date.now();
50
+ const late = lastTickAt !== undefined && nowMs - lastTickAt - WATCHDOG_INTERVAL_MS >= LATE_THRESHOLD_MS;
51
+ lastTickAt = nowMs;
52
+ if (late)
53
+ disqualifyActiveRuns();
54
+ for (const active of activeRuns) {
55
+ if (active.disqualified || active.run.hasReported)
56
+ continue;
57
+ const report = active.run.check();
58
+ if (!report)
59
+ continue;
60
+ active.run.markReported();
61
+ reportRun(active.run, report);
62
+ }
63
+ }
64
+ function ensureWatchdog() {
65
+ wireVisibility();
66
+ if (watchdogId !== undefined)
67
+ return;
68
+ lastTickAt = Date.now();
69
+ watchdogId = setInterval(tick, WATCHDOG_INTERVAL_MS);
70
+ }
71
+ function stopWatchdogIfIdle() {
72
+ if (activeRuns.size > 0 || watchdogId === undefined)
73
+ return;
74
+ clearInterval(watchdogId);
75
+ watchdogId = undefined;
76
+ }
77
+ async function runStep(run, active, name, fn) {
78
+ if (run.isEnded)
79
+ return fn();
80
+ const startMark = markName(run, name, 'start');
81
+ const endMark = markName(run, name, 'end');
82
+ const measureName = markName(run, name, 'measure');
83
+ active.marks.push(startMark, endMark);
84
+ active.measures.push(measureName);
85
+ performance.mark(startMark);
86
+ run.startStep(name);
87
+ try {
88
+ return await fn();
89
+ }
90
+ finally {
91
+ run.endStep(name);
92
+ performance.mark(endMark);
93
+ performance.measure(measureName, startMark, endMark);
94
+ }
95
+ }
96
+ function endRun(run, active) {
97
+ if (run.isEnded)
98
+ return;
99
+ run.end();
100
+ for (const mark of active.marks)
101
+ performance.clearMarks(mark);
102
+ for (const measure of active.measures)
103
+ performance.clearMeasures(measure);
104
+ activeRuns.delete(active);
105
+ stopWatchdogIfIdle();
106
+ }
107
+ function startRun(name) {
108
+ const run = new trace_1.TraceRun(name, config[name], now, newPageLocalRunId());
109
+ const active = { run, disqualified: false, marks: [], measures: [] };
110
+ if (config[name]) {
111
+ activeRuns.add(active);
112
+ ensureWatchdog();
113
+ }
114
+ return {
115
+ step: (stepName, fn) => runStep(run, active, stepName, fn),
116
+ end: () => endRun(run, active),
117
+ };
118
+ }
119
+ /** `startTrace(name)` returns the object; call `.end()` when the flow is over. */
120
+ function startTrace(name) {
121
+ return startRun(name);
122
+ }
123
+ /** Runs `fn` with a trace object and ends the trace when `fn` settles, either way. */
124
+ async function trace(name, fn) {
125
+ const handle = startRun(name);
126
+ try {
127
+ return await fn(handle);
128
+ }
129
+ finally {
130
+ handle.end();
131
+ }
132
+ }
133
+ //# sourceMappingURL=timing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.js","sourceRoot":"","sources":["../../src/client/timing.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,8 @@ export { initLogger } from './logger';
3
3
  export type { LogWriter } from './logger';
4
4
  export { withLogging, getLogger } from './requestLogger';
5
5
  export { configureAttachments } from './sourceMapCache';
6
+ export { trace, startTrace, configureTraces } from './trace';
7
+ export type { Trace, TraceConfig, TraceLimits } from './trace';
6
8
  export { createClientLogHandler, createClientLogFunction, ClientLogError } from './logHandler';
7
9
  export { createHttpLogHandler } from './httpHandler';
8
10
  export type { ClientLogHandlerConfig, ClientLogRequest, LogRequest } from './logHandler';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/functions/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC9F,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpD,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACxF,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC1F,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE1E,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,KAAG,IAAkC,CAAA;AACrG,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,KAAG,IAAoC,CAAA;AACxG,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAG,IAAiC,CAAA;AAClG,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,KAAG,IAAkC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/functions/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAC5D,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC9D,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC9F,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpD,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACxF,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC1F,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE1E,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,KAAG,IAAkC,CAAA;AACrG,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,KAAG,IAAoC,CAAA;AACxG,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAG,IAAiC,CAAA;AAClG,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,KAAG,IAAkC,CAAA"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.logDebug = exports.logInfo = exports.logWarn = exports.logError = exports.createHttpLogHandler = exports.ClientLogError = exports.createClientLogFunction = exports.createClientLogHandler = exports.configureAttachments = exports.getLogger = exports.withLogging = exports.initLogger = void 0;
3
+ exports.logDebug = exports.logInfo = exports.logWarn = exports.logError = exports.createHttpLogHandler = exports.ClientLogError = exports.createClientLogFunction = exports.createClientLogHandler = exports.configureTraces = exports.startTrace = exports.trace = exports.configureAttachments = exports.getLogger = exports.withLogging = exports.initLogger = void 0;
4
4
  const requestLogger_1 = require("./requestLogger");
5
5
  var logger_1 = require("./logger");
6
6
  Object.defineProperty(exports, "initLogger", { enumerable: true, get: function () { return logger_1.initLogger; } });
@@ -9,6 +9,10 @@ Object.defineProperty(exports, "withLogging", { enumerable: true, get: function
9
9
  Object.defineProperty(exports, "getLogger", { enumerable: true, get: function () { return requestLogger_2.getLogger; } });
10
10
  var sourceMapCache_1 = require("./sourceMapCache");
11
11
  Object.defineProperty(exports, "configureAttachments", { enumerable: true, get: function () { return sourceMapCache_1.configureAttachments; } });
12
+ var trace_1 = require("./trace");
13
+ Object.defineProperty(exports, "trace", { enumerable: true, get: function () { return trace_1.trace; } });
14
+ Object.defineProperty(exports, "startTrace", { enumerable: true, get: function () { return trace_1.startTrace; } });
15
+ Object.defineProperty(exports, "configureTraces", { enumerable: true, get: function () { return trace_1.configureTraces; } });
12
16
  var logHandler_1 = require("./logHandler");
13
17
  Object.defineProperty(exports, "createClientLogHandler", { enumerable: true, get: function () { return logHandler_1.createClientLogHandler; } });
14
18
  Object.defineProperty(exports, "createClientLogFunction", { enumerable: true, get: function () { return logHandler_1.createClientLogFunction; } });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/functions/index.ts"],"names":[],"mappings":";;;AAAA,mDAA2C;AAG3C,mCAAqC;AAA5B,oGAAA,UAAU,OAAA;AAEnB,iDAAwD;AAA/C,4GAAA,WAAW,OAAA;AAAE,0GAAA,SAAS,OAAA;AAC/B,mDAAuD;AAA9C,sHAAA,oBAAoB,OAAA;AAC7B,2CAA8F;AAArF,oHAAA,sBAAsB,OAAA;AAAE,qHAAA,uBAAuB,OAAA;AAAE,4GAAA,cAAc,OAAA;AACxE,6CAAoD;AAA3C,mHAAA,oBAAoB,OAAA;AAKtB,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAoC,EAAQ,EAAE,CAAC,IAAA,yBAAS,GAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAA;AAAxF,QAAA,QAAQ,YAAgF;AAC9F,MAAM,OAAO,GAAG,CAAC,GAAG,IAAsC,EAAQ,EAAE,CAAC,IAAA,yBAAS,GAAE,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;AAA3F,QAAA,OAAO,WAAoF;AACjG,MAAM,OAAO,GAAG,CAAC,GAAG,IAAmC,EAAQ,EAAE,CAAC,IAAA,yBAAS,GAAE,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;AAArF,QAAA,OAAO,WAA8E;AAC3F,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAoC,EAAQ,EAAE,CAAC,IAAA,yBAAS,GAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAA;AAAxF,QAAA,QAAQ,YAAgF"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/functions/index.ts"],"names":[],"mappings":";;;AAAA,mDAA2C;AAG3C,mCAAqC;AAA5B,oGAAA,UAAU,OAAA;AAEnB,iDAAwD;AAA/C,4GAAA,WAAW,OAAA;AAAE,0GAAA,SAAS,OAAA;AAC/B,mDAAuD;AAA9C,sHAAA,oBAAoB,OAAA;AAC7B,iCAA4D;AAAnD,8FAAA,KAAK,OAAA;AAAE,mGAAA,UAAU,OAAA;AAAE,wGAAA,eAAe,OAAA;AAE3C,2CAA8F;AAArF,oHAAA,sBAAsB,OAAA;AAAE,qHAAA,uBAAuB,OAAA;AAAE,4GAAA,cAAc,OAAA;AACxE,6CAAoD;AAA3C,mHAAA,oBAAoB,OAAA;AAKtB,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAoC,EAAQ,EAAE,CAAC,IAAA,yBAAS,GAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAA;AAAxF,QAAA,QAAQ,YAAgF;AAC9F,MAAM,OAAO,GAAG,CAAC,GAAG,IAAsC,EAAQ,EAAE,CAAC,IAAA,yBAAS,GAAE,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;AAA3F,QAAA,OAAO,WAAoF;AACjG,MAAM,OAAO,GAAG,CAAC,GAAG,IAAmC,EAAQ,EAAE,CAAC,IAAA,yBAAS,GAAE,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;AAArF,QAAA,OAAO,WAA8E;AAC3F,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAoC,EAAQ,EAAE,CAAC,IAAA,yBAAS,GAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAA;AAAxF,QAAA,QAAQ,YAAgF"}
@@ -0,0 +1,13 @@
1
+ import { type TraceConfig } from '../shared/trace';
2
+ export type { TraceConfig, TraceLimits } from '../shared/trace';
3
+ export interface Trace {
4
+ step<T>(name: string, fn: () => T | Promise<T>): Promise<T>;
5
+ end(): void;
6
+ }
7
+ /** Replaces every limit. Read when a run starts, so configure before the first one. */
8
+ export declare function configureTraces(newConfig: TraceConfig): void;
9
+ /** `startTrace(name)` returns the object; call `.end()` when the flow is over. */
10
+ export declare function startTrace(name: string): Trace;
11
+ /** Runs `fn` with a trace object and ends the trace when `fn` settles, either way. */
12
+ export declare function trace<T>(name: string, fn: (t: Trace) => T | Promise<T>): Promise<T>;
13
+ //# sourceMappingURL=trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/functions/trace.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqD,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAErG,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE/D,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC3D,GAAG,IAAI,IAAI,CAAA;CACZ;AAID,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,CAE5D;AAyCD,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAE9C;AAED,sFAAsF;AACtF,wBAAsB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOzF"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configureTraces = configureTraces;
4
+ exports.startTrace = startTrace;
5
+ exports.trace = trace;
6
+ const ulid_1 = require("ulid");
7
+ const requestLogger_1 = require("./requestLogger");
8
+ const trace_1 = require("../shared/trace");
9
+ let config = {};
10
+ /** Replaces every limit. Read when a run starts, so configure before the first one. */
11
+ function configureTraces(newConfig) {
12
+ config = newConfig;
13
+ }
14
+ function now() {
15
+ return Date.now();
16
+ }
17
+ /**
18
+ * Judged only when a step finishes or the trace ends — no timer, since Cloud
19
+ * Functions and Cloud Run can throttle the CPU once a response is sent (see
20
+ * CLAUDE.md, "Traces report misbehaviour, nothing else"). Sent through the
21
+ * request-scoped writer, so it carries that request's labels like any other entry.
22
+ */
23
+ function report(run, found) {
24
+ if (!found)
25
+ return;
26
+ run.markReported();
27
+ (0, requestLogger_1.getLogger)().warning((0, trace_1.traceMessage)(run.name, found), (0, trace_1.traceLabels)(run.name, run.run, found), (0, trace_1.traceContext)(found));
28
+ }
29
+ function startRun(name) {
30
+ const run = new trace_1.TraceRun(name, config[name], now, (0, ulid_1.ulid)());
31
+ return {
32
+ async step(stepName, fn) {
33
+ if (run.isEnded)
34
+ return fn();
35
+ run.startStep(stepName);
36
+ try {
37
+ return await fn();
38
+ }
39
+ finally {
40
+ const ms = run.endStep(stepName);
41
+ if (ms !== undefined)
42
+ report(run, run.checkFinishedStep(stepName, ms));
43
+ report(run, run.check());
44
+ }
45
+ },
46
+ end() {
47
+ if (run.isEnded)
48
+ return;
49
+ report(run, run.check());
50
+ run.end();
51
+ },
52
+ };
53
+ }
54
+ /** `startTrace(name)` returns the object; call `.end()` when the flow is over. */
55
+ function startTrace(name) {
56
+ return startRun(name);
57
+ }
58
+ /** Runs `fn` with a trace object and ends the trace when `fn` settles, either way. */
59
+ async function trace(name, fn) {
60
+ const handle = startRun(name);
61
+ try {
62
+ return await fn(handle);
63
+ }
64
+ finally {
65
+ handle.end();
66
+ }
67
+ }
68
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/functions/trace.ts"],"names":[],"mappings":";;AAcA,0CAEC;AA0CD,gCAEC;AAGD,sBAOC;AAtED,+BAA2B;AAC3B,mDAA2C;AAC3C,2CAAqG;AASrG,IAAI,MAAM,GAAgB,EAAE,CAAA;AAE5B,uFAAuF;AACvF,SAAgB,eAAe,CAAC,SAAsB;IACpD,MAAM,GAAG,SAAS,CAAA;AACpB,CAAC;AAED,SAAS,GAAG;IACV,OAAO,IAAI,CAAC,GAAG,EAAE,CAAA;AACnB,CAAC;AAED;;;;;GAKG;AACH,SAAS,MAAM,CAAC,GAAa,EAAE,KAAoC;IACjE,IAAI,CAAC,KAAK;QAAE,OAAM;IAClB,GAAG,CAAC,YAAY,EAAE,CAAA;IAClB,IAAA,yBAAS,GAAE,CAAC,OAAO,CAAC,IAAA,oBAAY,EAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,IAAA,mBAAW,EAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,IAAA,oBAAY,EAAC,KAAK,CAAC,CAAC,CAAA;AAChH,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,GAAG,GAAG,IAAI,gBAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAA,WAAI,GAAE,CAAC,CAAA;IAEzD,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;YACrB,IAAI,GAAG,CAAC,OAAO;gBAAE,OAAO,EAAE,EAAE,CAAA;YAC5B,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;YACvB,IAAI,CAAC;gBACH,OAAO,MAAM,EAAE,EAAE,CAAA;YACnB,CAAC;oBAAS,CAAC;gBACT,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;gBAChC,IAAI,EAAE,KAAK,SAAS;oBAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,iBAAiB,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAA;gBACtE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAA;YAC1B,CAAC;QACH,CAAC;QACD,GAAG;YACD,IAAI,GAAG,CAAC,OAAO;gBAAE,OAAM;YACvB,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAA;YACxB,GAAG,CAAC,GAAG,EAAE,CAAA;QACX,CAAC;KACF,CAAA;AACH,CAAC;AAED,kFAAkF;AAClF,SAAgB,UAAU,CAAC,IAAY;IACrC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAA;AACvB,CAAC;AAED,sFAAsF;AAC/E,KAAK,UAAU,KAAK,CAAI,IAAY,EAAE,EAAgC;IAC3E,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC7B,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,MAAM,CAAC,CAAA;IACzB,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,GAAG,EAAE,CAAA;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The pure bookkeeping behind `/client/timing` and `/functions`' `trace`/`startTrace` —
3
+ * which steps are finished (with their ms) and which are still running, checked
4
+ * against configured limits through an injected monotonic clock so tests never wait
5
+ * for real time. The two entry points differ only in how often they call `check()`
6
+ * (a watchdog tick in the browser, a step/trace boundary on the server, per
7
+ * CLAUDE.md "Traces report misbehaviour, nothing else") and in what they do with
8
+ * the `TraceReport` it returns.
9
+ */
10
+ export interface TraceLimits {
11
+ warnAfterMs?: number;
12
+ steps?: Record<string, number>;
13
+ }
14
+ /** `configureTraces({ name: { warnAfterMs?, steps? } })` — see README, "Timing". */
15
+ export type TraceConfig = Record<string, TraceLimits>;
16
+ export interface TraceReport {
17
+ slow: 'trace' | 'step';
18
+ step?: string;
19
+ elapsedMs: number;
20
+ limitMs: number;
21
+ steps: Record<string, number>;
22
+ waiting: string[];
23
+ }
24
+ export declare class TraceRun {
25
+ readonly name: string;
26
+ private readonly limits;
27
+ private readonly clock;
28
+ readonly run: string;
29
+ private readonly startedAt;
30
+ private readonly finishedSteps;
31
+ private readonly runningSteps;
32
+ private reported;
33
+ private ended;
34
+ constructor(name: string, limits: TraceLimits | undefined, clock: () => number, runId: string);
35
+ get isEnded(): boolean;
36
+ get hasReported(): boolean;
37
+ startStep(name: string): void;
38
+ endStep(name: string): number | undefined;
39
+ end(): void;
40
+ /**
41
+ * The first limit crossed right now, or undefined. Does not itself mark the
42
+ * run as reported — callers do that only once they have actually sent it.
43
+ */
44
+ check(): TraceReport | undefined;
45
+ /**
46
+ * The server's counterpart to `check()`'s step loop: a step that has already
47
+ * been moved into `finishedSteps` (so `endStep` has already run for it) is no
48
+ * longer in `runningSteps` for `check()` to see, yet the instant it finished
49
+ * is the only one the server — with no timer — gets to judge it against its
50
+ * own limit. `ms` is the duration `endStep` just returned for it.
51
+ */
52
+ checkFinishedStep(name: string, ms: number): TraceReport | undefined;
53
+ markReported(): void;
54
+ }
55
+ /** The message README, "Timing" shows: `"app_boot slow: products passed 3000 ms, still waiting"`. */
56
+ export declare function traceMessage(name: string, report: TraceReport): string;
57
+ export declare function traceLabels(name: string, run: string, report: TraceReport): Record<string, string>;
58
+ export declare function traceContext(report: TraceReport): Record<string, unknown>;
59
+ //# sourceMappingURL=trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/shared/trace.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B;AAED,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;AAErD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,qBAAa,QAAQ;IASjB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAVxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA4B;IACzD,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,KAAK,CAAQ;gBAGV,IAAI,EAAE,MAAM,EACJ,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,KAAK,EAAE,MAAM,MAAM,EACpC,KAAK,EAAE,MAAM;IAMf,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK7B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IASzC,GAAG,IAAI,IAAI;IAIX;;;OAGG;IACH,KAAK,IAAI,WAAW,GAAG,SAAS;IAkChC;;;;;;OAMG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAcpE,YAAY,IAAI,IAAI;CAGrB;AAED,qGAAqG;AACrG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAGtE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIlG;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzE"}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TraceRun = void 0;
4
+ exports.traceMessage = traceMessage;
5
+ exports.traceLabels = traceLabels;
6
+ exports.traceContext = traceContext;
7
+ class TraceRun {
8
+ name;
9
+ limits;
10
+ clock;
11
+ run;
12
+ startedAt;
13
+ finishedSteps = {};
14
+ runningSteps = new Map();
15
+ reported = false;
16
+ ended = false;
17
+ constructor(name, limits, clock, runId) {
18
+ this.name = name;
19
+ this.limits = limits;
20
+ this.clock = clock;
21
+ this.run = runId;
22
+ this.startedAt = clock();
23
+ }
24
+ get isEnded() {
25
+ return this.ended;
26
+ }
27
+ get hasReported() {
28
+ return this.reported;
29
+ }
30
+ startStep(name) {
31
+ if (this.ended)
32
+ return;
33
+ this.runningSteps.set(name, this.clock());
34
+ }
35
+ endStep(name) {
36
+ const startedAt = this.runningSteps.get(name);
37
+ if (startedAt === undefined)
38
+ return undefined;
39
+ this.runningSteps.delete(name);
40
+ const ms = this.clock() - startedAt;
41
+ this.finishedSteps[name] = ms;
42
+ return ms;
43
+ }
44
+ end() {
45
+ this.ended = true;
46
+ }
47
+ /**
48
+ * The first limit crossed right now, or undefined. Does not itself mark the
49
+ * run as reported — callers do that only once they have actually sent it.
50
+ */
51
+ check() {
52
+ if (this.reported || !this.limits)
53
+ return undefined;
54
+ const limits = this.limits;
55
+ const elapsedMs = this.clock() - this.startedAt;
56
+ if (limits.warnAfterMs !== undefined && elapsedMs >= limits.warnAfterMs) {
57
+ return {
58
+ slow: 'trace',
59
+ elapsedMs,
60
+ limitMs: limits.warnAfterMs,
61
+ steps: { ...this.finishedSteps },
62
+ waiting: [...this.runningSteps.keys()],
63
+ };
64
+ }
65
+ for (const [stepName, startedAt] of this.runningSteps) {
66
+ const limitMs = limits.steps?.[stepName];
67
+ if (limitMs === undefined)
68
+ continue;
69
+ const stepElapsedMs = this.clock() - startedAt;
70
+ if (stepElapsedMs >= limitMs) {
71
+ return {
72
+ slow: 'step',
73
+ step: stepName,
74
+ elapsedMs: stepElapsedMs,
75
+ limitMs,
76
+ steps: { ...this.finishedSteps },
77
+ waiting: [...this.runningSteps.keys()],
78
+ };
79
+ }
80
+ }
81
+ return undefined;
82
+ }
83
+ /**
84
+ * The server's counterpart to `check()`'s step loop: a step that has already
85
+ * been moved into `finishedSteps` (so `endStep` has already run for it) is no
86
+ * longer in `runningSteps` for `check()` to see, yet the instant it finished
87
+ * is the only one the server — with no timer — gets to judge it against its
88
+ * own limit. `ms` is the duration `endStep` just returned for it.
89
+ */
90
+ checkFinishedStep(name, ms) {
91
+ if (this.reported || !this.limits)
92
+ return undefined;
93
+ const limitMs = this.limits.steps?.[name];
94
+ if (limitMs === undefined || ms < limitMs)
95
+ return undefined;
96
+ return {
97
+ slow: 'step',
98
+ step: name,
99
+ elapsedMs: ms,
100
+ limitMs,
101
+ steps: { ...this.finishedSteps },
102
+ waiting: [...this.runningSteps.keys()],
103
+ };
104
+ }
105
+ markReported() {
106
+ this.reported = true;
107
+ }
108
+ }
109
+ exports.TraceRun = TraceRun;
110
+ /** The message README, "Timing" shows: `"app_boot slow: products passed 3000 ms, still waiting"`. */
111
+ function traceMessage(name, report) {
112
+ const subject = report.slow === 'step' ? `${report.step} ` : '';
113
+ return `${name} slow: ${subject}passed ${report.limitMs} ms, still waiting`;
114
+ }
115
+ function traceLabels(name, run, report) {
116
+ const labels = { trace: name, run, slow: report.slow };
117
+ if (report.step !== undefined)
118
+ labels.step = report.step;
119
+ return labels;
120
+ }
121
+ function traceContext(report) {
122
+ return {
123
+ timing: {
124
+ elapsedMs: report.elapsedMs,
125
+ limitMs: report.limitMs,
126
+ steps: report.steps,
127
+ waiting: report.waiting,
128
+ },
129
+ };
130
+ }
131
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/shared/trace.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,23 @@ export interface BaseLabels {
8
8
  releaseId?: string;
9
9
  errorType?: string;
10
10
  errorCategory?: string;
11
+ /** The route pattern, e.g. `/orders/:id/items`. Set by `enableNavigation()`. */
12
+ route?: string;
13
+ /** The real path, e.g. `/orders/1042/items`. Omitted when `enableNavigation({ path: false })`. */
14
+ path?: string;
15
+ /** Whether `route` came from `routeFor` or the id rule. Set by `enableNavigation()`. */
16
+ routeSource?: 'router' | 'pattern';
17
+ }
18
+ /**
19
+ * What `enableNavigation()` (`@dasasian/firebase-structured-logger/client/navigation`)
20
+ * hands to the core logger for the current page, through `setCurrentRoute` in
21
+ * `client/breadcrumbs.ts`. `path` is absent exactly when `enableNavigation` was
22
+ * given `{ path: false }`.
23
+ */
24
+ export interface NavigationLabels {
25
+ route: string;
26
+ path?: string;
27
+ routeSource: 'router' | 'pattern';
11
28
  }
12
29
  export interface ErrorPayload {
13
30
  message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;AAE3E,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,WAAW,CAAA;IACrB,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACvD,WAAW,CAAC,EAAE;QACZ,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;QAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjC,KAAK,CAAC,EAAE,YAAY,CAAA;KACrB,CAAA;IACD,2GAA2G;IAC3G,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAA;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;AAE3E,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kGAAkG;IAClG,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,wFAAwF;IACxF,WAAW,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAA;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,QAAQ,GAAG,SAAS,CAAA;CAClC;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,WAAW,CAAA;IACrB,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACvD,WAAW,CAAC,EAAE;QACZ,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;QAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjC,KAAK,CAAC,EAAE,YAAY,CAAA;KACrB,CAAA;IACD,2GAA2G;IAC3G,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAA;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dasasian/firebase-structured-logger",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Structured logging for Firebase and Google Cloud web apps — browser, backend, and tools",
5
5
  "license": "MIT",
6
6
  "author": "Dasasian",
@@ -34,6 +34,14 @@
34
34
  "types": "./dist/client/index.d.ts",
35
35
  "default": "./dist/client/index.js"
36
36
  },
37
+ "./client/navigation": {
38
+ "types": "./dist/client/navigation.d.ts",
39
+ "default": "./dist/client/navigation.js"
40
+ },
41
+ "./client/timing": {
42
+ "types": "./dist/client/timing.d.ts",
43
+ "default": "./dist/client/timing.js"
44
+ },
37
45
  "./functions": {
38
46
  "types": "./dist/functions/index.d.ts",
39
47
  "default": "./dist/functions/index.js"
@@ -48,6 +56,12 @@
48
56
  "client": [
49
57
  "dist/client/index.d.ts"
50
58
  ],
59
+ "client/navigation": [
60
+ "dist/client/navigation.d.ts"
61
+ ],
62
+ "client/timing": [
63
+ "dist/client/timing.d.ts"
64
+ ],
51
65
  "functions": [
52
66
  "dist/functions/index.d.ts"
53
67
  ],
@@ -57,7 +71,7 @@
57
71
  }
58
72
  },
59
73
  "bin": {
60
- "fsl": "./dist/tools/index.js"
74
+ "fsl": "dist/tools/index.js"
61
75
  },
62
76
  "files": [
63
77
  "dist",
@@ -68,7 +82,7 @@
68
82
  "build:watch": "tsc --watch",
69
83
  "clean": "rm -rf dist",
70
84
  "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.check.json",
71
- "test": "tsx tests/logger.ts && tsx tests/browserBundle.ts && tsx tests/breadcrumbs.ts && tsx tests/rateLimiter.ts && tsx tests/errorHandler.ts && tsx tests/attachments.ts && tsx tests/feedback.ts && tsx tests/paths.ts && tsx tests/loadsWithoutOptionalPeers.ts && tsx tests/sourceMapStripping.ts && FUNCTIONS_EMULATOR=true tsx tests/errorPayload.ts && FUNCTIONS_EMULATOR=true tsx tests/requestLogger.ts && FUNCTIONS_EMULATOR=true tsx tests/handler.ts && FUNCTIONS_EMULATOR=true tsx tests/httpHandler.ts && FUNCTIONS_EMULATOR=true tsx tests/symbolication.ts && FUNCTIONS_EMULATOR=true tsx tests/publicApi.ts && FUNCTIONS_EMULATOR=true tsx tests/configureTwice.ts && FUNCTIONS_EMULATOR=true tsx tests/deprecatedNames.ts && tsx tests/productionOutput.ts && tsx tests/storageChain.ts && tsx tests/entrySize.ts && tsx tests/handlerSymbolication.ts && tsx tests/releaseResolution.ts && tsx tests/sourceMapCacheBounds.ts && tsx tests/doctor.ts && tsx tests/doctorProcess.ts && tsx tests/uploadSourcemapsBackend.ts",
85
+ "test": "tsx tests/logger.ts && tsx tests/browserBundle.ts && tsx tests/breadcrumbs.ts && tsx tests/navigation.ts && tsx tests/timing.ts && tsx tests/rateLimiter.ts && tsx tests/errorHandler.ts && tsx tests/attachments.ts && tsx tests/feedback.ts && tsx tests/paths.ts && tsx tests/loadsWithoutOptionalPeers.ts && tsx tests/sourceMapStripping.ts && FUNCTIONS_EMULATOR=true tsx tests/errorPayload.ts && FUNCTIONS_EMULATOR=true tsx tests/requestLogger.ts && FUNCTIONS_EMULATOR=true tsx tests/serverTrace.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 && FUNCTIONS_EMULATOR=true tsx tests/deprecatedNames.ts && tsx tests/productionOutput.ts && tsx tests/storageChain.ts && tsx tests/entrySize.ts && tsx tests/handlerSymbolication.ts && tsx tests/releaseResolution.ts && tsx tests/sourceMapCacheBounds.ts && tsx tests/doctor.ts && tsx tests/doctorProcess.ts && tsx tests/uploadSourcemapsBackend.ts",
72
86
  "prepublishOnly": "npm run clean && npm run build",
73
87
  "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)",
74
88
  "smoke:deploy:run": "bash smoke/cloudrun/deploy.sh",
@@ -170,6 +170,16 @@ bc.nav(screen: string): void // on navigation
170
170
  bc.error(type: string, data?: Record<string, unknown>): void // on errors
171
171
  ```
172
172
 
173
+ Import `enableNavigation` from `firebase-structured-logger/client/navigation`:
174
+ ```ts
175
+ enableNavigation(options?: { routeFor?: (path: string) => string | undefined; cleanPath?: (path: string) => string; path?: false }): void
176
+ ```
177
+ - Call once at startup. Every route change becomes a `nav` breadcrumb, and every entry
178
+ gets `route` (the pattern, `/orders/:id`), `path` (the real path) and `routeSource`.
179
+ - When an app has called it, do not flag a missing `bc.nav` on route changes — it is
180
+ automatic. Suggest it for a single-page app that hand-writes `bc.nav` everywhere.
181
+ - A separate import on purpose: apps that do not use it ship none of it.
182
+
173
183
  Import `sendFeedback` from `firebase-structured-logger/client`:
174
184
  ```ts
175
185
  sendFeedback(text: string, extras?: { labels?: Partial<AppLabels>; attachments?: Record<string, Blob | File | string> }): void
@@ -30,7 +30,14 @@ All entries written by firebase-structured-logger include these labels:
30
30
  |-------|-------------|
31
31
  | `appId` | Application identifier (e.g. `acme`, `store`) |
32
32
  | `userId` | Firebase Auth UID |
33
- | `screen` | Current screen name |
33
+ | `screen` | Current screen name (falls back to `route` when the app never set one) |
34
+ | `route` | Route pattern, e.g. `/orders/:id/items` — group by this (apps using `enableNavigation`) |
35
+ | `path` | Real path, e.g. `/orders/1042/items` — one specific page or record; query string never stored |
36
+ | `routeSource` | `router` (the app named the route) or `pattern` (ids replaced by rule) |
37
+ | `trace` | On a slow-trace WARNING: the trace's name, e.g. `app_boot` |
38
+ | `run` | On a slow-trace WARNING: tells overlapping runs of one trace apart |
39
+ | `slow` | `trace` (the whole run passed its limit) or `step` (one step passed its own) |
40
+ | `step` | When `slow="step"`: the step that was late. `jsonPayload.timing` has every step's ms and what was still waiting |
34
41
  | `releaseId` | Git short hash or explicit release ID |
35
42
  | `platform` | `ios`, `android`, `macos`, `windows`, `web` |
36
43
  | `browser` | `chrome`, `firefox`, `safari`, `edge` |