@tetrascience-npm/tetrascience-react-ui 1.0.0-beta.135.1 → 1.0.0-beta.136.1
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/dist/telemetry/context.cjs +2 -0
- package/dist/telemetry/context.cjs.map +1 -0
- package/dist/telemetry/context.d.ts +6 -0
- package/dist/telemetry/context.js +6 -0
- package/dist/telemetry/context.js.map +1 -0
- package/dist/telemetry/error-boundary.cjs +2 -0
- package/dist/telemetry/error-boundary.cjs.map +1 -0
- package/dist/telemetry/error-boundary.d.ts +39 -0
- package/dist/telemetry/error-boundary.js +33 -0
- package/dist/telemetry/error-boundary.js.map +1 -0
- package/dist/telemetry/events.cjs +2 -0
- package/dist/telemetry/events.cjs.map +1 -0
- package/dist/telemetry/events.d.ts +15 -0
- package/dist/telemetry/events.js +13 -0
- package/dist/telemetry/events.js.map +1 -0
- package/dist/telemetry/facade.cjs +2 -0
- package/dist/telemetry/facade.cjs.map +1 -0
- package/dist/telemetry/facade.d.ts +15 -0
- package/dist/telemetry/facade.js +86 -0
- package/dist/telemetry/facade.js.map +1 -0
- package/dist/telemetry/global-handlers.cjs +2 -0
- package/dist/telemetry/global-handlers.cjs.map +1 -0
- package/dist/telemetry/global-handlers.d.ts +25 -0
- package/dist/telemetry/global-handlers.js +31 -0
- package/dist/telemetry/global-handlers.js.map +1 -0
- package/dist/telemetry/index.d.ts +27 -0
- package/dist/telemetry/telemetry-provider.cjs +2 -0
- package/dist/telemetry/telemetry-provider.cjs.map +1 -0
- package/dist/telemetry/telemetry-provider.d.ts +36 -0
- package/dist/telemetry/telemetry-provider.js +65 -0
- package/dist/telemetry/telemetry-provider.js.map +1 -0
- package/dist/telemetry/types.d.ts +140 -0
- package/dist/telemetry/use-tetra-events.cjs +2 -0
- package/dist/telemetry/use-tetra-events.cjs.map +1 -0
- package/dist/telemetry/use-tetra-events.d.ts +19 -0
- package/dist/telemetry/use-tetra-events.js +55 -0
- package/dist/telemetry/use-tetra-events.js.map +1 -0
- package/dist/telemetry.cjs +2 -0
- package/dist/telemetry.cjs.map +1 -0
- package/dist/telemetry.js +24 -0
- package/dist/telemetry.js.map +1 -0
- package/package.json +19 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.cjs","sources":["../../src/telemetry/context.ts"],"sourcesContent":["import {createContext} from \"react\";\n\nimport type {Telemetry} from \"@tetrascience-npm/request/telemetry\";\n\n/**\n * `null` outside a {@link TelemetryProvider} — consumers no-op rather than\n * throw (telemetry never breaks the app; see `use-tetra-events.ts`).\n */\nexport const TelemetryContext = createContext<Telemetry | null>(null);\n"],"names":["TelemetryContext","createContext"],"mappings":"yGAQaA,EAAmBC,EAAAA,cAAgC,IAAI"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Telemetry } from '@tetrascience-npm/request/telemetry';
|
|
2
|
+
/**
|
|
3
|
+
* `null` outside a {@link TelemetryProvider} — consumers no-op rather than
|
|
4
|
+
* throw (telemetry never breaks the app; see `use-tetra-events.ts`).
|
|
5
|
+
*/
|
|
6
|
+
export declare const TelemetryContext: import('react').Context<Telemetry | null>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sources":["../../src/telemetry/context.ts"],"sourcesContent":["import {createContext} from \"react\";\n\nimport type {Telemetry} from \"@tetrascience-npm/request/telemetry\";\n\n/**\n * `null` outside a {@link TelemetryProvider} — consumers no-op rather than\n * throw (telemetry never breaks the app; see `use-tetra-events.ts`).\n */\nexport const TelemetryContext = createContext<Telemetry | null>(null);\n"],"names":["TelemetryContext","createContext"],"mappings":";AAQO,MAAMA,IAAmBC,EAAgC,IAAI;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react"),s=require("./context.cjs"),r=require("./events.cjs");class n extends o.Component{static contextType=s.TelemetryContext;state={error:null};static getDerivedStateFromError(t){return{error:t}}componentDidCatch(t,e){this.context?.trackError(t,{name:this.props.eventName??r.TelemetryEvent.ReactError,attributes:{...this.props.attributes,"error.source":"react","react.component_stack":(e.componentStack??"").slice(0,r.MAX_COMPONENT_STACK_LENGTH)}}),this.props.onError?.(t,e)}reset=()=>{this.setState({error:null})};render(){const{error:t}=this.state;if(!t)return this.props.children;const{fallback:e}=this.props;return typeof e=="function"?e(t,this.reset):e??null}}exports.TSErrorBoundary=n;
|
|
2
|
+
//# sourceMappingURL=error-boundary.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-boundary.cjs","sources":["../../src/telemetry/error-boundary.tsx"],"sourcesContent":["import {Component, type ContextType, type ErrorInfo, type ReactNode} from \"react\";\n\nimport {TelemetryContext} from \"./context\";\nimport {MAX_COMPONENT_STACK_LENGTH, TelemetryEvent} from \"./events\";\n\n/** Props for {@link TSErrorBoundary}. */\nexport interface TSErrorBoundaryProps {\n\tchildren?: ReactNode;\n\t/**\n\t * Rendered instead of the children once a render error is caught. A\n\t * function receives the error and a `reset` callback for retry UI.\n\t */\n\tfallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n\t/** Event name override. Default: `App:Error:React`. */\n\teventName?: string;\n\t/** Extra attributes merged into the emitted event. */\n\tattributes?: Record<string, unknown>;\n\t/** Escape hatch for app-side handling (logging, resetting state). */\n\tonError?: (error: Error, info: ErrorInfo) => void;\n}\n\ninterface State {\n\terror: Error | null;\n}\n\n/**\n * React error boundary that records render errors as a stable-named product\n * event with the component stack attached, then renders `fallback`.\n *\n * Boundaries only catch errors thrown during render/lifecycle. Async\n * callbacks and promise rejections need {@link installGlobalErrorHandlers}.\n * The exception message is truncated by the core emitter; the component stack\n * is truncated here.\n */\nexport class TSErrorBoundary extends Component<TSErrorBoundaryProps, State> {\n\tstatic contextType = TelemetryContext;\n\tdeclare context: ContextType<typeof TelemetryContext>;\n\n\tstate: State = {error: null};\n\n\tstatic getDerivedStateFromError(error: Error): State {\n\t\treturn {error};\n\t}\n\n\tcomponentDidCatch(error: Error, info: ErrorInfo): void {\n\t\tthis.context?.trackError(error, {\n\t\t\tname: this.props.eventName ?? TelemetryEvent.ReactError,\n\t\t\tattributes: {\n\t\t\t\t...this.props.attributes,\n\t\t\t\t\"error.source\": \"react\",\n\t\t\t\t\"react.component_stack\": (info.componentStack ?? \"\").slice(0, MAX_COMPONENT_STACK_LENGTH),\n\t\t\t},\n\t\t});\n\t\tthis.props.onError?.(error, info);\n\t}\n\n\tprivate readonly reset = (): void => {\n\t\tthis.setState({error: null});\n\t};\n\n\trender(): ReactNode {\n\t\tconst {error} = this.state;\n\t\tif (!error) return this.props.children;\n\t\tconst {fallback} = this.props;\n\t\treturn typeof fallback === \"function\" ? fallback(error, this.reset) : (fallback ?? null);\n\t}\n}\n"],"names":["TSErrorBoundary","Component","TelemetryContext","error","info","TelemetryEvent","MAX_COMPONENT_STACK_LENGTH","fallback"],"mappings":"8JAkCO,MAAMA,UAAwBC,EAAAA,SAAuC,CAC3E,OAAO,YAAcC,EAAAA,iBAGrB,MAAe,CAAC,MAAO,IAAA,EAEvB,OAAO,yBAAyBC,EAAqB,CACpD,MAAO,CAAC,MAAAA,CAAA,CACT,CAEA,kBAAkBA,EAAcC,EAAuB,CACtD,KAAK,SAAS,WAAWD,EAAO,CAC/B,KAAM,KAAK,MAAM,WAAaE,EAAAA,eAAe,WAC7C,WAAY,CACX,GAAG,KAAK,MAAM,WACd,eAAgB,QAChB,yBAA0BD,EAAK,gBAAkB,IAAI,MAAM,EAAGE,EAAAA,0BAA0B,CAAA,CACzF,CACA,EACD,KAAK,MAAM,UAAUH,EAAOC,CAAI,CACjC,CAEiB,MAAQ,IAAY,CACpC,KAAK,SAAS,CAAC,MAAO,IAAA,CAAK,CAC5B,EAEA,QAAoB,CACnB,KAAM,CAAC,MAAAD,GAAS,KAAK,MACrB,GAAI,CAACA,EAAO,OAAO,KAAK,MAAM,SAC9B,KAAM,CAAC,SAAAI,GAAY,KAAK,MACxB,OAAO,OAAOA,GAAa,WAAaA,EAASJ,EAAO,KAAK,KAAK,EAAKI,GAAY,IACpF,CACD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Component, ContextType, ErrorInfo, ReactNode } from 'react';
|
|
2
|
+
import { TelemetryContext } from './context';
|
|
3
|
+
/** Props for {@link TSErrorBoundary}. */
|
|
4
|
+
export interface TSErrorBoundaryProps {
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* Rendered instead of the children once a render error is caught. A
|
|
8
|
+
* function receives the error and a `reset` callback for retry UI.
|
|
9
|
+
*/
|
|
10
|
+
fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
|
|
11
|
+
/** Event name override. Default: `App:Error:React`. */
|
|
12
|
+
eventName?: string;
|
|
13
|
+
/** Extra attributes merged into the emitted event. */
|
|
14
|
+
attributes?: Record<string, unknown>;
|
|
15
|
+
/** Escape hatch for app-side handling (logging, resetting state). */
|
|
16
|
+
onError?: (error: Error, info: ErrorInfo) => void;
|
|
17
|
+
}
|
|
18
|
+
interface State {
|
|
19
|
+
error: Error | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* React error boundary that records render errors as a stable-named product
|
|
23
|
+
* event with the component stack attached, then renders `fallback`.
|
|
24
|
+
*
|
|
25
|
+
* Boundaries only catch errors thrown during render/lifecycle. Async
|
|
26
|
+
* callbacks and promise rejections need {@link installGlobalErrorHandlers}.
|
|
27
|
+
* The exception message is truncated by the core emitter; the component stack
|
|
28
|
+
* is truncated here.
|
|
29
|
+
*/
|
|
30
|
+
export declare class TSErrorBoundary extends Component<TSErrorBoundaryProps, State> {
|
|
31
|
+
static contextType: import('react').Context<import('@tetrascience-npm/request/telemetry').Telemetry | null>;
|
|
32
|
+
context: ContextType<typeof TelemetryContext>;
|
|
33
|
+
state: State;
|
|
34
|
+
static getDerivedStateFromError(error: Error): State;
|
|
35
|
+
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
36
|
+
private readonly reset;
|
|
37
|
+
render(): ReactNode;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Component as e } from "react";
|
|
2
|
+
import { TelemetryContext as o } from "./context.js";
|
|
3
|
+
import { TelemetryEvent as s, MAX_COMPONENT_STACK_LENGTH as n } from "./events.js";
|
|
4
|
+
class m extends e {
|
|
5
|
+
static contextType = o;
|
|
6
|
+
state = { error: null };
|
|
7
|
+
static getDerivedStateFromError(t) {
|
|
8
|
+
return { error: t };
|
|
9
|
+
}
|
|
10
|
+
componentDidCatch(t, r) {
|
|
11
|
+
this.context?.trackError(t, {
|
|
12
|
+
name: this.props.eventName ?? s.ReactError,
|
|
13
|
+
attributes: {
|
|
14
|
+
...this.props.attributes,
|
|
15
|
+
"error.source": "react",
|
|
16
|
+
"react.component_stack": (r.componentStack ?? "").slice(0, n)
|
|
17
|
+
}
|
|
18
|
+
}), this.props.onError?.(t, r);
|
|
19
|
+
}
|
|
20
|
+
reset = () => {
|
|
21
|
+
this.setState({ error: null });
|
|
22
|
+
};
|
|
23
|
+
render() {
|
|
24
|
+
const { error: t } = this.state;
|
|
25
|
+
if (!t) return this.props.children;
|
|
26
|
+
const { fallback: r } = this.props;
|
|
27
|
+
return typeof r == "function" ? r(t, this.reset) : r ?? null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
m as TSErrorBoundary
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=error-boundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-boundary.js","sources":["../../src/telemetry/error-boundary.tsx"],"sourcesContent":["import {Component, type ContextType, type ErrorInfo, type ReactNode} from \"react\";\n\nimport {TelemetryContext} from \"./context\";\nimport {MAX_COMPONENT_STACK_LENGTH, TelemetryEvent} from \"./events\";\n\n/** Props for {@link TSErrorBoundary}. */\nexport interface TSErrorBoundaryProps {\n\tchildren?: ReactNode;\n\t/**\n\t * Rendered instead of the children once a render error is caught. A\n\t * function receives the error and a `reset` callback for retry UI.\n\t */\n\tfallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n\t/** Event name override. Default: `App:Error:React`. */\n\teventName?: string;\n\t/** Extra attributes merged into the emitted event. */\n\tattributes?: Record<string, unknown>;\n\t/** Escape hatch for app-side handling (logging, resetting state). */\n\tonError?: (error: Error, info: ErrorInfo) => void;\n}\n\ninterface State {\n\terror: Error | null;\n}\n\n/**\n * React error boundary that records render errors as a stable-named product\n * event with the component stack attached, then renders `fallback`.\n *\n * Boundaries only catch errors thrown during render/lifecycle. Async\n * callbacks and promise rejections need {@link installGlobalErrorHandlers}.\n * The exception message is truncated by the core emitter; the component stack\n * is truncated here.\n */\nexport class TSErrorBoundary extends Component<TSErrorBoundaryProps, State> {\n\tstatic contextType = TelemetryContext;\n\tdeclare context: ContextType<typeof TelemetryContext>;\n\n\tstate: State = {error: null};\n\n\tstatic getDerivedStateFromError(error: Error): State {\n\t\treturn {error};\n\t}\n\n\tcomponentDidCatch(error: Error, info: ErrorInfo): void {\n\t\tthis.context?.trackError(error, {\n\t\t\tname: this.props.eventName ?? TelemetryEvent.ReactError,\n\t\t\tattributes: {\n\t\t\t\t...this.props.attributes,\n\t\t\t\t\"error.source\": \"react\",\n\t\t\t\t\"react.component_stack\": (info.componentStack ?? \"\").slice(0, MAX_COMPONENT_STACK_LENGTH),\n\t\t\t},\n\t\t});\n\t\tthis.props.onError?.(error, info);\n\t}\n\n\tprivate readonly reset = (): void => {\n\t\tthis.setState({error: null});\n\t};\n\n\trender(): ReactNode {\n\t\tconst {error} = this.state;\n\t\tif (!error) return this.props.children;\n\t\tconst {fallback} = this.props;\n\t\treturn typeof fallback === \"function\" ? fallback(error, this.reset) : (fallback ?? null);\n\t}\n}\n"],"names":["TSErrorBoundary","Component","TelemetryContext","error","info","TelemetryEvent","MAX_COMPONENT_STACK_LENGTH","fallback"],"mappings":";;;AAkCO,MAAMA,UAAwBC,EAAuC;AAAA,EAC3E,OAAO,cAAcC;AAAA,EAGrB,QAAe,EAAC,OAAO,KAAA;AAAA,EAEvB,OAAO,yBAAyBC,GAAqB;AACpD,WAAO,EAAC,OAAAA,EAAA;AAAA,EACT;AAAA,EAEA,kBAAkBA,GAAcC,GAAuB;AACtD,SAAK,SAAS,WAAWD,GAAO;AAAA,MAC/B,MAAM,KAAK,MAAM,aAAaE,EAAe;AAAA,MAC7C,YAAY;AAAA,QACX,GAAG,KAAK,MAAM;AAAA,QACd,gBAAgB;AAAA,QAChB,0BAA0BD,EAAK,kBAAkB,IAAI,MAAM,GAAGE,CAA0B;AAAA,MAAA;AAAA,IACzF,CACA,GACD,KAAK,MAAM,UAAUH,GAAOC,CAAI;AAAA,EACjC;AAAA,EAEiB,QAAQ,MAAY;AACpC,SAAK,SAAS,EAAC,OAAO,KAAA,CAAK;AAAA,EAC5B;AAAA,EAEA,SAAoB;AACnB,UAAM,EAAC,OAAAD,MAAS,KAAK;AACrB,QAAI,CAACA,EAAO,QAAO,KAAK,MAAM;AAC9B,UAAM,EAAC,UAAAI,MAAY,KAAK;AACxB,WAAO,OAAOA,KAAa,aAAaA,EAASJ,GAAO,KAAK,KAAK,IAAKI,KAAY;AAAA,EACpF;AACD;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e={ReactError:"App:Error:React",WindowError:"App:Error:Window",UnhandledRejection:"App:Error:UnhandledRejection"},r=4e3;exports.MAX_COMPONENT_STACK_LENGTH=r;exports.TelemetryEvent=e;
|
|
2
|
+
//# sourceMappingURL=events.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.cjs","sources":["../../src/telemetry/events.ts"],"sourcesContent":["/**\n * Stable event names emitted by the bindings themselves. Apps keep their own\n * `App[:Page][:Object]:Action` names for product events; these three exist so\n * error volume is queryable across every app without per-app naming drift.\n */\nexport const TelemetryEvent = {\n\t/** React render error caught by `TSErrorBoundary`. */\n\tReactError: \"App:Error:React\",\n\t/** Uncaught exception seen by `window.onerror`. */\n\tWindowError: \"App:Error:Window\",\n\t/** Promise rejection with no handler. */\n\tUnhandledRejection: \"App:Error:UnhandledRejection\",\n} as const;\n\n/** Max length of the React component stack attribute. */\nexport const MAX_COMPONENT_STACK_LENGTH = 4000;\n"],"names":["TelemetryEvent","MAX_COMPONENT_STACK_LENGTH"],"mappings":"gFAKO,MAAMA,EAAiB,CAE7B,WAAY,kBAEZ,YAAa,mBAEb,mBAAoB,8BACrB,EAGaC,EAA6B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable event names emitted by the bindings themselves. Apps keep their own
|
|
3
|
+
* `App[:Page][:Object]:Action` names for product events; these three exist so
|
|
4
|
+
* error volume is queryable across every app without per-app naming drift.
|
|
5
|
+
*/
|
|
6
|
+
export declare const TelemetryEvent: {
|
|
7
|
+
/** React render error caught by `TSErrorBoundary`. */
|
|
8
|
+
readonly ReactError: "App:Error:React";
|
|
9
|
+
/** Uncaught exception seen by `window.onerror`. */
|
|
10
|
+
readonly WindowError: "App:Error:Window";
|
|
11
|
+
/** Promise rejection with no handler. */
|
|
12
|
+
readonly UnhandledRejection: "App:Error:UnhandledRejection";
|
|
13
|
+
};
|
|
14
|
+
/** Max length of the React component stack attribute. */
|
|
15
|
+
export declare const MAX_COMPONENT_STACK_LENGTH = 4000;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const r = {
|
|
2
|
+
/** React render error caught by `TSErrorBoundary`. */
|
|
3
|
+
ReactError: "App:Error:React",
|
|
4
|
+
/** Uncaught exception seen by `window.onerror`. */
|
|
5
|
+
WindowError: "App:Error:Window",
|
|
6
|
+
/** Promise rejection with no handler. */
|
|
7
|
+
UnhandledRejection: "App:Error:UnhandledRejection"
|
|
8
|
+
}, e = 4e3;
|
|
9
|
+
export {
|
|
10
|
+
e as MAX_COMPONENT_STACK_LENGTH,
|
|
11
|
+
r as TelemetryEvent
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sources":["../../src/telemetry/events.ts"],"sourcesContent":["/**\n * Stable event names emitted by the bindings themselves. Apps keep their own\n * `App[:Page][:Object]:Action` names for product events; these three exist so\n * error volume is queryable across every app without per-app naming drift.\n */\nexport const TelemetryEvent = {\n\t/** React render error caught by `TSErrorBoundary`. */\n\tReactError: \"App:Error:React\",\n\t/** Uncaught exception seen by `window.onerror`. */\n\tWindowError: \"App:Error:Window\",\n\t/** Promise rejection with no handler. */\n\tUnhandledRejection: \"App:Error:UnhandledRejection\",\n} as const;\n\n/** Max length of the React component stack attribute. */\nexport const MAX_COMPONENT_STACK_LENGTH = 4000;\n"],"names":["TelemetryEvent","MAX_COMPONENT_STACK_LENGTH"],"mappings":"AAKO,MAAMA,IAAiB;AAAA;AAAA,EAE7B,YAAY;AAAA;AAAA,EAEZ,aAAa;AAAA;AAAA,EAEb,oBAAoB;AACrB,GAGaC,IAA6B;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("@tetrascience-npm/request/telemetry"),s={trackEvent(){},trackError(){},startSpan:()=>o.NOOP_SPAN,withSpan:(a,n)=>n(o.NOOP_SPAN),counter(){},gauge(){},histogram(){},upDownCounter(){},async flush(){},async shutdown(){}},u=50;function i(){let a,n=[];const c=t=>{n.length<u&&n.push(t)};return{trackEvent(t,e,r){a?a.trackEvent(t,e,r):c({kind:"event",name:t,attributes:e,body:r})},trackError(t,e){a?a.trackError(t,e):c({kind:"error",error:t,context:e})},startSpan(t,e){return a?a.startSpan(t,e):o.NOOP_SPAN},counter(t,e,r){a?.counter(t,e,r)},gauge(t,e,r){a?.gauge(t,e,r)},histogram(t,e,r){a?.histogram(t,e,r)},upDownCounter(t,e,r){a?.upDownCounter(t,e,r)},withSpan(t,e,r){return a?a.withSpan(t,e,r):e(o.NOOP_SPAN)},async flush(){await a?.flush()},async shutdown(){await a?.shutdown()},attach(t){a=t;const e=n;n=[];for(const r of e)r.kind==="event"?t.trackEvent(r.name,r.attributes,r.body):t.trackError(r.error,r.context)},detach(t){a===t&&(a=void 0)}}}exports.NOOP_TELEMETRY=s;exports.createTelemetryFacade=i;
|
|
2
|
+
//# sourceMappingURL=facade.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facade.cjs","sources":["../../src/telemetry/facade.ts"],"sourcesContent":["import {NOOP_SPAN} from \"@tetrascience-npm/request/telemetry\";\n\nimport type {TelemetryFacade} from \"./types\";\nimport type {Telemetry, TrackErrorContext} from \"@tetrascience-npm/request/telemetry\";\n\n/** A client that accepts and drops everything (`enabled={false}`, no provider). */\nexport const NOOP_TELEMETRY: Telemetry = {\n\ttrackEvent() {\n\t\t// disabled: nothing is recorded, nothing is buffered\n\t},\n\ttrackError() {\n\t\t// disabled: nothing is recorded, nothing is buffered\n\t},\n\tstartSpan: () => NOOP_SPAN,\n\t// Still RUNS the callback: withSpan wraps application work, so skipping it\n\t// when telemetry is off would make disabling telemetry change what the app\n\t// does. Only the measurement is dropped.\n\twithSpan: (_name, fn) => fn(NOOP_SPAN),\n\tcounter() {\n\t\t// disabled: nothing is recorded\n\t},\n\tgauge() {\n\t\t// disabled: nothing is recorded\n\t},\n\thistogram() {\n\t\t// disabled: nothing is recorded\n\t},\n\tupDownCounter() {\n\t\t// disabled: nothing is recorded\n\t},\n\tasync flush() {\n\t\t// nothing to flush\n\t},\n\tasync shutdown() {\n\t\t// nothing to tear down\n\t},\n};\n\n/** Records emitted before the provider's effect attaches a client. */\nconst MAX_PENDING = 50;\n\ntype Pending =\n\t| {kind: \"event\"; name: string; attributes?: Record<string, unknown>; body?: unknown}\n\t| {kind: \"error\"; error: unknown; context?: TrackErrorContext};\n\n/**\n * Stable context value that forwards to the currently attached client.\n *\n * The real client is built in an effect (so React StrictMode's mount →\n * unmount → mount cycle disposes it cleanly instead of leaving a shut-down\n * provider behind), but child effects run *before* the provider's effect —\n * so records emitted in that window are held here (bounded) and replayed on\n * attach. The buffer is drained exactly once, so a StrictMode re-attach\n * cannot re-emit it.\n */\nexport function createTelemetryFacade(): TelemetryFacade {\n\tlet target: Telemetry | undefined;\n\tlet pending: Pending[] = [];\n\n\tconst buffer = (record: Pending): void => {\n\t\tif (pending.length < MAX_PENDING) pending.push(record);\n\t};\n\n\treturn {\n\t\ttrackEvent(name, attributes, body) {\n\t\t\tif (target) target.trackEvent(name, attributes, body);\n\t\t\telse buffer({kind: \"event\", name, attributes, body});\n\t\t},\n\t\ttrackError(error, context) {\n\t\t\tif (target) target.trackError(error, context);\n\t\t\telse buffer({kind: \"error\", error, context});\n\t\t},\n\t\t// Spans are NOT buffered, unlike the two above. A span carries a live\n\t\t// start and end, so replaying one after attach would invent a duration\n\t\t// that never happened — worse than not recording it. Work that runs\n\t\t// before the provider's effect attaches a client is simply untraced.\n\t\tstartSpan(name, options) {\n\t\t\treturn target ? target.startSpan(name, options) : NOOP_SPAN;\n\t\t},\n\t\t// Metric recordings before attach are DROPPED, not buffered. A gauge is a\n\t\t// point-in-time reading and a histogram observation is timestamped by the\n\t\t// SDK on record, so replaying either after attach would date it to the\n\t\t// wrong moment. Events buffer because a product event is a fact that\n\t\t// happened, not a sample of a moving value.\n\t\tcounter(name, delta, attributes) {\n\t\t\ttarget?.counter(name, delta, attributes);\n\t\t},\n\t\tgauge(name, value, attributes) {\n\t\t\ttarget?.gauge(name, value, attributes);\n\t\t},\n\t\thistogram(name, value, attributes) {\n\t\t\ttarget?.histogram(name, value, attributes);\n\t\t},\n\t\tupDownCounter(name, delta, attributes) {\n\t\t\ttarget?.upDownCounter(name, delta, attributes);\n\t\t},\n\t\twithSpan(name, fn, options) {\n\t\t\treturn target ? target.withSpan(name, fn, options) : fn(NOOP_SPAN);\n\t\t},\n\t\tasync flush() {\n\t\t\tawait target?.flush();\n\t\t},\n\t\tasync shutdown() {\n\t\t\tawait target?.shutdown();\n\t\t},\n\t\tattach(client) {\n\t\t\ttarget = client;\n\t\t\tconst replay = pending;\n\t\t\tpending = [];\n\t\t\tfor (const record of replay) {\n\t\t\t\tif (record.kind === \"event\") client.trackEvent(record.name, record.attributes, record.body);\n\t\t\t\telse client.trackError(record.error, record.context);\n\t\t\t}\n\t\t},\n\t\tdetach(client) {\n\t\t\t// Guard against an out-of-order cleanup detaching a newer client.\n\t\t\tif (target === client) target = undefined;\n\t\t},\n\t};\n}\n"],"names":["NOOP_TELEMETRY","NOOP_SPAN","_name","fn","MAX_PENDING","createTelemetryFacade","target","pending","buffer","record","name","attributes","body","error","context","options","delta","value","client","replay"],"mappings":"uIAMaA,EAA4B,CACxC,YAAa,CAEb,EACA,YAAa,CAEb,EACA,UAAW,IAAMC,EAAAA,UAIjB,SAAU,CAACC,EAAOC,IAAOA,EAAGF,EAAAA,SAAS,EACrC,SAAU,CAEV,EACA,OAAQ,CAER,EACA,WAAY,CAEZ,EACA,eAAgB,CAEhB,EACA,MAAM,OAAQ,CAEd,EACA,MAAM,UAAW,CAEjB,CACD,EAGMG,EAAc,GAgBb,SAASC,GAAyC,CACxD,IAAIC,EACAC,EAAqB,CAAA,EAEzB,MAAMC,EAAUC,GAA0B,CACrCF,EAAQ,OAASH,GAAaG,EAAQ,KAAKE,CAAM,CACtD,EAEA,MAAO,CACN,WAAWC,EAAMC,EAAYC,EAAM,CAC9BN,EAAQA,EAAO,WAAWI,EAAMC,EAAYC,CAAI,IACxC,CAAC,KAAM,QAAS,KAAAF,EAAM,WAAAC,EAAY,KAAAC,EAAK,CACpD,EACA,WAAWC,EAAOC,EAAS,CACtBR,EAAQA,EAAO,WAAWO,EAAOC,CAAO,IAChC,CAAC,KAAM,QAAS,MAAAD,EAAO,QAAAC,EAAQ,CAC5C,EAKA,UAAUJ,EAAMK,EAAS,CACxB,OAAOT,EAASA,EAAO,UAAUI,EAAMK,CAAO,EAAId,EAAAA,SACnD,EAMA,QAAQS,EAAMM,EAAOL,EAAY,CAChCL,GAAQ,QAAQI,EAAMM,EAAOL,CAAU,CACxC,EACA,MAAMD,EAAMO,EAAON,EAAY,CAC9BL,GAAQ,MAAMI,EAAMO,EAAON,CAAU,CACtC,EACA,UAAUD,EAAMO,EAAON,EAAY,CAClCL,GAAQ,UAAUI,EAAMO,EAAON,CAAU,CAC1C,EACA,cAAcD,EAAMM,EAAOL,EAAY,CACtCL,GAAQ,cAAcI,EAAMM,EAAOL,CAAU,CAC9C,EACA,SAASD,EAAMP,EAAIY,EAAS,CAC3B,OAAOT,EAASA,EAAO,SAASI,EAAMP,EAAIY,CAAO,EAAIZ,EAAGF,WAAS,CAClE,EACA,MAAM,OAAQ,CACb,MAAMK,GAAQ,MAAA,CACf,EACA,MAAM,UAAW,CAChB,MAAMA,GAAQ,SAAA,CACf,EACA,OAAOY,EAAQ,CACdZ,EAASY,EACT,MAAMC,EAASZ,EACfA,EAAU,CAAA,EACV,UAAWE,KAAUU,EAChBV,EAAO,OAAS,QAASS,EAAO,WAAWT,EAAO,KAAMA,EAAO,WAAYA,EAAO,IAAI,EACrFS,EAAO,WAAWT,EAAO,MAAOA,EAAO,OAAO,CAErD,EACA,OAAOS,EAAQ,CAEVZ,IAAWY,IAAQZ,EAAS,OACjC,CAAA,CAEF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { TelemetryFacade } from './types';
|
|
2
|
+
import { Telemetry } from '@tetrascience-npm/request/telemetry';
|
|
3
|
+
/** A client that accepts and drops everything (`enabled={false}`, no provider). */
|
|
4
|
+
export declare const NOOP_TELEMETRY: Telemetry;
|
|
5
|
+
/**
|
|
6
|
+
* Stable context value that forwards to the currently attached client.
|
|
7
|
+
*
|
|
8
|
+
* The real client is built in an effect (so React StrictMode's mount →
|
|
9
|
+
* unmount → mount cycle disposes it cleanly instead of leaving a shut-down
|
|
10
|
+
* provider behind), but child effects run *before* the provider's effect —
|
|
11
|
+
* so records emitted in that window are held here (bounded) and replayed on
|
|
12
|
+
* attach. The buffer is drained exactly once, so a StrictMode re-attach
|
|
13
|
+
* cannot re-emit it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createTelemetryFacade(): TelemetryFacade;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { NOOP_SPAN as o } from "@tetrascience-npm/request/telemetry";
|
|
2
|
+
const i = {
|
|
3
|
+
trackEvent() {
|
|
4
|
+
},
|
|
5
|
+
trackError() {
|
|
6
|
+
},
|
|
7
|
+
startSpan: () => o,
|
|
8
|
+
// Still RUNS the callback: withSpan wraps application work, so skipping it
|
|
9
|
+
// when telemetry is off would make disabling telemetry change what the app
|
|
10
|
+
// does. Only the measurement is dropped.
|
|
11
|
+
withSpan: (n, a) => a(o),
|
|
12
|
+
counter() {
|
|
13
|
+
},
|
|
14
|
+
gauge() {
|
|
15
|
+
},
|
|
16
|
+
histogram() {
|
|
17
|
+
},
|
|
18
|
+
upDownCounter() {
|
|
19
|
+
},
|
|
20
|
+
async flush() {
|
|
21
|
+
},
|
|
22
|
+
async shutdown() {
|
|
23
|
+
}
|
|
24
|
+
}, c = 50;
|
|
25
|
+
function h() {
|
|
26
|
+
let n, a = [];
|
|
27
|
+
const s = (t) => {
|
|
28
|
+
a.length < c && a.push(t);
|
|
29
|
+
};
|
|
30
|
+
return {
|
|
31
|
+
trackEvent(t, r, e) {
|
|
32
|
+
n ? n.trackEvent(t, r, e) : s({ kind: "event", name: t, attributes: r, body: e });
|
|
33
|
+
},
|
|
34
|
+
trackError(t, r) {
|
|
35
|
+
n ? n.trackError(t, r) : s({ kind: "error", error: t, context: r });
|
|
36
|
+
},
|
|
37
|
+
// Spans are NOT buffered, unlike the two above. A span carries a live
|
|
38
|
+
// start and end, so replaying one after attach would invent a duration
|
|
39
|
+
// that never happened — worse than not recording it. Work that runs
|
|
40
|
+
// before the provider's effect attaches a client is simply untraced.
|
|
41
|
+
startSpan(t, r) {
|
|
42
|
+
return n ? n.startSpan(t, r) : o;
|
|
43
|
+
},
|
|
44
|
+
// Metric recordings before attach are DROPPED, not buffered. A gauge is a
|
|
45
|
+
// point-in-time reading and a histogram observation is timestamped by the
|
|
46
|
+
// SDK on record, so replaying either after attach would date it to the
|
|
47
|
+
// wrong moment. Events buffer because a product event is a fact that
|
|
48
|
+
// happened, not a sample of a moving value.
|
|
49
|
+
counter(t, r, e) {
|
|
50
|
+
n?.counter(t, r, e);
|
|
51
|
+
},
|
|
52
|
+
gauge(t, r, e) {
|
|
53
|
+
n?.gauge(t, r, e);
|
|
54
|
+
},
|
|
55
|
+
histogram(t, r, e) {
|
|
56
|
+
n?.histogram(t, r, e);
|
|
57
|
+
},
|
|
58
|
+
upDownCounter(t, r, e) {
|
|
59
|
+
n?.upDownCounter(t, r, e);
|
|
60
|
+
},
|
|
61
|
+
withSpan(t, r, e) {
|
|
62
|
+
return n ? n.withSpan(t, r, e) : r(o);
|
|
63
|
+
},
|
|
64
|
+
async flush() {
|
|
65
|
+
await n?.flush();
|
|
66
|
+
},
|
|
67
|
+
async shutdown() {
|
|
68
|
+
await n?.shutdown();
|
|
69
|
+
},
|
|
70
|
+
attach(t) {
|
|
71
|
+
n = t;
|
|
72
|
+
const r = a;
|
|
73
|
+
a = [];
|
|
74
|
+
for (const e of r)
|
|
75
|
+
e.kind === "event" ? t.trackEvent(e.name, e.attributes, e.body) : t.trackError(e.error, e.context);
|
|
76
|
+
},
|
|
77
|
+
detach(t) {
|
|
78
|
+
n === t && (n = void 0);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export {
|
|
83
|
+
i as NOOP_TELEMETRY,
|
|
84
|
+
h as createTelemetryFacade
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=facade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facade.js","sources":["../../src/telemetry/facade.ts"],"sourcesContent":["import {NOOP_SPAN} from \"@tetrascience-npm/request/telemetry\";\n\nimport type {TelemetryFacade} from \"./types\";\nimport type {Telemetry, TrackErrorContext} from \"@tetrascience-npm/request/telemetry\";\n\n/** A client that accepts and drops everything (`enabled={false}`, no provider). */\nexport const NOOP_TELEMETRY: Telemetry = {\n\ttrackEvent() {\n\t\t// disabled: nothing is recorded, nothing is buffered\n\t},\n\ttrackError() {\n\t\t// disabled: nothing is recorded, nothing is buffered\n\t},\n\tstartSpan: () => NOOP_SPAN,\n\t// Still RUNS the callback: withSpan wraps application work, so skipping it\n\t// when telemetry is off would make disabling telemetry change what the app\n\t// does. Only the measurement is dropped.\n\twithSpan: (_name, fn) => fn(NOOP_SPAN),\n\tcounter() {\n\t\t// disabled: nothing is recorded\n\t},\n\tgauge() {\n\t\t// disabled: nothing is recorded\n\t},\n\thistogram() {\n\t\t// disabled: nothing is recorded\n\t},\n\tupDownCounter() {\n\t\t// disabled: nothing is recorded\n\t},\n\tasync flush() {\n\t\t// nothing to flush\n\t},\n\tasync shutdown() {\n\t\t// nothing to tear down\n\t},\n};\n\n/** Records emitted before the provider's effect attaches a client. */\nconst MAX_PENDING = 50;\n\ntype Pending =\n\t| {kind: \"event\"; name: string; attributes?: Record<string, unknown>; body?: unknown}\n\t| {kind: \"error\"; error: unknown; context?: TrackErrorContext};\n\n/**\n * Stable context value that forwards to the currently attached client.\n *\n * The real client is built in an effect (so React StrictMode's mount →\n * unmount → mount cycle disposes it cleanly instead of leaving a shut-down\n * provider behind), but child effects run *before* the provider's effect —\n * so records emitted in that window are held here (bounded) and replayed on\n * attach. The buffer is drained exactly once, so a StrictMode re-attach\n * cannot re-emit it.\n */\nexport function createTelemetryFacade(): TelemetryFacade {\n\tlet target: Telemetry | undefined;\n\tlet pending: Pending[] = [];\n\n\tconst buffer = (record: Pending): void => {\n\t\tif (pending.length < MAX_PENDING) pending.push(record);\n\t};\n\n\treturn {\n\t\ttrackEvent(name, attributes, body) {\n\t\t\tif (target) target.trackEvent(name, attributes, body);\n\t\t\telse buffer({kind: \"event\", name, attributes, body});\n\t\t},\n\t\ttrackError(error, context) {\n\t\t\tif (target) target.trackError(error, context);\n\t\t\telse buffer({kind: \"error\", error, context});\n\t\t},\n\t\t// Spans are NOT buffered, unlike the two above. A span carries a live\n\t\t// start and end, so replaying one after attach would invent a duration\n\t\t// that never happened — worse than not recording it. Work that runs\n\t\t// before the provider's effect attaches a client is simply untraced.\n\t\tstartSpan(name, options) {\n\t\t\treturn target ? target.startSpan(name, options) : NOOP_SPAN;\n\t\t},\n\t\t// Metric recordings before attach are DROPPED, not buffered. A gauge is a\n\t\t// point-in-time reading and a histogram observation is timestamped by the\n\t\t// SDK on record, so replaying either after attach would date it to the\n\t\t// wrong moment. Events buffer because a product event is a fact that\n\t\t// happened, not a sample of a moving value.\n\t\tcounter(name, delta, attributes) {\n\t\t\ttarget?.counter(name, delta, attributes);\n\t\t},\n\t\tgauge(name, value, attributes) {\n\t\t\ttarget?.gauge(name, value, attributes);\n\t\t},\n\t\thistogram(name, value, attributes) {\n\t\t\ttarget?.histogram(name, value, attributes);\n\t\t},\n\t\tupDownCounter(name, delta, attributes) {\n\t\t\ttarget?.upDownCounter(name, delta, attributes);\n\t\t},\n\t\twithSpan(name, fn, options) {\n\t\t\treturn target ? target.withSpan(name, fn, options) : fn(NOOP_SPAN);\n\t\t},\n\t\tasync flush() {\n\t\t\tawait target?.flush();\n\t\t},\n\t\tasync shutdown() {\n\t\t\tawait target?.shutdown();\n\t\t},\n\t\tattach(client) {\n\t\t\ttarget = client;\n\t\t\tconst replay = pending;\n\t\t\tpending = [];\n\t\t\tfor (const record of replay) {\n\t\t\t\tif (record.kind === \"event\") client.trackEvent(record.name, record.attributes, record.body);\n\t\t\t\telse client.trackError(record.error, record.context);\n\t\t\t}\n\t\t},\n\t\tdetach(client) {\n\t\t\t// Guard against an out-of-order cleanup detaching a newer client.\n\t\t\tif (target === client) target = undefined;\n\t\t},\n\t};\n}\n"],"names":["NOOP_TELEMETRY","NOOP_SPAN","_name","fn","MAX_PENDING","createTelemetryFacade","target","pending","buffer","record","name","attributes","body","error","context","options","delta","value","client","replay"],"mappings":";AAMO,MAAMA,IAA4B;AAAA,EACxC,aAAa;AAAA,EAEb;AAAA,EACA,aAAa;AAAA,EAEb;AAAA,EACA,WAAW,MAAMC;AAAA;AAAA;AAAA;AAAA,EAIjB,UAAU,CAACC,GAAOC,MAAOA,EAAGF,CAAS;AAAA,EACrC,UAAU;AAAA,EAEV;AAAA,EACA,QAAQ;AAAA,EAER;AAAA,EACA,YAAY;AAAA,EAEZ;AAAA,EACA,gBAAgB;AAAA,EAEhB;AAAA,EACA,MAAM,QAAQ;AAAA,EAEd;AAAA,EACA,MAAM,WAAW;AAAA,EAEjB;AACD,GAGMG,IAAc;AAgBb,SAASC,IAAyC;AACxD,MAAIC,GACAC,IAAqB,CAAA;AAEzB,QAAMC,IAAS,CAACC,MAA0B;AACzC,IAAIF,EAAQ,SAASH,KAAaG,EAAQ,KAAKE,CAAM;AAAA,EACtD;AAEA,SAAO;AAAA,IACN,WAAWC,GAAMC,GAAYC,GAAM;AAClC,MAAIN,IAAQA,EAAO,WAAWI,GAAMC,GAAYC,CAAI,MACxC,EAAC,MAAM,SAAS,MAAAF,GAAM,YAAAC,GAAY,MAAAC,GAAK;AAAA,IACpD;AAAA,IACA,WAAWC,GAAOC,GAAS;AAC1B,MAAIR,IAAQA,EAAO,WAAWO,GAAOC,CAAO,MAChC,EAAC,MAAM,SAAS,OAAAD,GAAO,SAAAC,GAAQ;AAAA,IAC5C;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,UAAUJ,GAAMK,GAAS;AACxB,aAAOT,IAASA,EAAO,UAAUI,GAAMK,CAAO,IAAId;AAAA,IACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,QAAQS,GAAMM,GAAOL,GAAY;AAChC,MAAAL,GAAQ,QAAQI,GAAMM,GAAOL,CAAU;AAAA,IACxC;AAAA,IACA,MAAMD,GAAMO,GAAON,GAAY;AAC9B,MAAAL,GAAQ,MAAMI,GAAMO,GAAON,CAAU;AAAA,IACtC;AAAA,IACA,UAAUD,GAAMO,GAAON,GAAY;AAClC,MAAAL,GAAQ,UAAUI,GAAMO,GAAON,CAAU;AAAA,IAC1C;AAAA,IACA,cAAcD,GAAMM,GAAOL,GAAY;AACtC,MAAAL,GAAQ,cAAcI,GAAMM,GAAOL,CAAU;AAAA,IAC9C;AAAA,IACA,SAASD,GAAMP,GAAIY,GAAS;AAC3B,aAAOT,IAASA,EAAO,SAASI,GAAMP,GAAIY,CAAO,IAAIZ,EAAGF,CAAS;AAAA,IAClE;AAAA,IACA,MAAM,QAAQ;AACb,YAAMK,GAAQ,MAAA;AAAA,IACf;AAAA,IACA,MAAM,WAAW;AAChB,YAAMA,GAAQ,SAAA;AAAA,IACf;AAAA,IACA,OAAOY,GAAQ;AACd,MAAAZ,IAASY;AACT,YAAMC,IAASZ;AACf,MAAAA,IAAU,CAAA;AACV,iBAAWE,KAAUU;AACpB,QAAIV,EAAO,SAAS,UAASS,EAAO,WAAWT,EAAO,MAAMA,EAAO,YAAYA,EAAO,IAAI,IACrFS,EAAO,WAAWT,EAAO,OAAOA,EAAO,OAAO;AAAA,IAErD;AAAA,IACA,OAAOS,GAAQ;AAEd,MAAIZ,MAAWY,MAAQZ,IAAS;AAAA,IACjC;AAAA,EAAA;AAEF;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./events.cjs"),n=new WeakMap;function u(e,t={}){const a=n.get(e);if(a)return a;if(typeof window>"u"){const r=()=>{};return n.set(e,r),r}const d=r=>{e.trackError(r.error??r.message,{name:t.windowErrorEventName??i.TelemetryEvent.WindowError,attributes:{...t.attributes,"error.source":"window"}})},s=r=>{e.trackError(r.reason,{name:t.unhandledRejectionEventName??i.TelemetryEvent.UnhandledRejection,attributes:{...t.attributes,"error.source":"unhandledrejection"}})};window.addEventListener("error",d),window.addEventListener("unhandledrejection",s);const o=()=>{n.get(e)===o&&(n.delete(e),window.removeEventListener("error",d),window.removeEventListener("unhandledrejection",s))};return n.set(e,o),o}exports.installGlobalErrorHandlers=u;
|
|
2
|
+
//# sourceMappingURL=global-handlers.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-handlers.cjs","sources":["../../src/telemetry/global-handlers.ts"],"sourcesContent":["import {TelemetryEvent} from \"./events\";\n\nimport type {Telemetry} from \"@tetrascience-npm/request/telemetry\";\n\n/** Options for {@link installGlobalErrorHandlers}. */\nexport interface GlobalErrorHandlerOptions {\n\t/** Event name for `window.onerror`. Default: `App:Error:Window`. */\n\twindowErrorEventName?: string;\n\t/** Event name for unhandled promise rejections. Default: `App:Error:UnhandledRejection`. */\n\tunhandledRejectionEventName?: string;\n\t/** Extra attributes merged into both events. */\n\tattributes?: Record<string, unknown>;\n}\n\n// Keyed by client so two federated apps can each install their own handlers,\n// while a repeated install for the same client (StrictMode, hot reload) is a\n// no-op that returns the original uninstall.\nconst installed = new WeakMap<Telemetry, () => void>();\n\n/**\n * Explicit opt-in: capture uncaught errors and unhandled promise rejections\n * for `client`. Never installed automatically by the provider — global\n * listeners are a host-level decision, and under Module Federation several\n * apps share `window`.\n *\n * Idempotent per client; returns an uninstall function (also idempotent).\n *\n * @example\n * ```tsx\n * const client = useTelemetryClient();\n * useEffect(() => installGlobalErrorHandlers(client), [client]);\n * ```\n */\nexport function installGlobalErrorHandlers(client: Telemetry, options: GlobalErrorHandlerOptions = {}): () => void {\n\tconst existing = installed.get(client);\n\tif (existing) return existing;\n\tif (typeof window === \"undefined\") {\n\t\t// Recorded in the map like any other install, so the documented\n\t\t// once-per-client contract holds here too: without this, every call in an\n\t\t// SSR/non-browser runtime handed back a different uninstall function.\n\t\tconst noop = (): void => {\n\t\t\t// nothing was installed (SSR / non-browser runtime)\n\t\t};\n\t\tinstalled.set(client, noop);\n\t\treturn noop;\n\t}\n\n\tconst onError = (event: ErrorEvent): void => {\n\t\tclient.trackError(event.error ?? event.message, {\n\t\t\tname: options.windowErrorEventName ?? TelemetryEvent.WindowError,\n\t\t\tattributes: {...options.attributes, \"error.source\": \"window\"},\n\t\t});\n\t};\n\tconst onRejection = (event: PromiseRejectionEvent): void => {\n\t\tclient.trackError(event.reason, {\n\t\t\tname: options.unhandledRejectionEventName ?? TelemetryEvent.UnhandledRejection,\n\t\t\tattributes: {...options.attributes, \"error.source\": \"unhandledrejection\"},\n\t\t});\n\t};\n\n\twindow.addEventListener(\"error\", onError);\n\twindow.addEventListener(\"unhandledrejection\", onRejection);\n\n\tconst uninstall = (): void => {\n\t\tif (installed.get(client) !== uninstall) return;\n\t\tinstalled.delete(client);\n\t\twindow.removeEventListener(\"error\", onError);\n\t\twindow.removeEventListener(\"unhandledrejection\", onRejection);\n\t};\n\tinstalled.set(client, uninstall);\n\treturn uninstall;\n}\n"],"names":["installed","installGlobalErrorHandlers","client","options","existing","noop","onError","event","TelemetryEvent","onRejection","uninstall"],"mappings":"gHAiBMA,MAAgB,QAgBf,SAASC,EAA2BC,EAAmBC,EAAqC,GAAgB,CAClH,MAAMC,EAAWJ,EAAU,IAAIE,CAAM,EACrC,GAAIE,EAAU,OAAOA,EACrB,GAAI,OAAO,OAAW,IAAa,CAIlC,MAAMC,EAAO,IAAY,CAEzB,EACA,OAAAL,EAAU,IAAIE,EAAQG,CAAI,EACnBA,CACR,CAEA,MAAMC,EAAWC,GAA4B,CAC5CL,EAAO,WAAWK,EAAM,OAASA,EAAM,QAAS,CAC/C,KAAMJ,EAAQ,sBAAwBK,EAAAA,eAAe,YACrD,WAAY,CAAC,GAAGL,EAAQ,WAAY,eAAgB,QAAA,CAAQ,CAC5D,CACF,EACMM,EAAeF,GAAuC,CAC3DL,EAAO,WAAWK,EAAM,OAAQ,CAC/B,KAAMJ,EAAQ,6BAA+BK,EAAAA,eAAe,mBAC5D,WAAY,CAAC,GAAGL,EAAQ,WAAY,eAAgB,oBAAA,CAAoB,CACxE,CACF,EAEA,OAAO,iBAAiB,QAASG,CAAO,EACxC,OAAO,iBAAiB,qBAAsBG,CAAW,EAEzD,MAAMC,EAAY,IAAY,CACzBV,EAAU,IAAIE,CAAM,IAAMQ,IAC9BV,EAAU,OAAOE,CAAM,EACvB,OAAO,oBAAoB,QAASI,CAAO,EAC3C,OAAO,oBAAoB,qBAAsBG,CAAW,EAC7D,EACA,OAAAT,EAAU,IAAIE,EAAQQ,CAAS,EACxBA,CACR"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Telemetry } from '@tetrascience-npm/request/telemetry';
|
|
2
|
+
/** Options for {@link installGlobalErrorHandlers}. */
|
|
3
|
+
export interface GlobalErrorHandlerOptions {
|
|
4
|
+
/** Event name for `window.onerror`. Default: `App:Error:Window`. */
|
|
5
|
+
windowErrorEventName?: string;
|
|
6
|
+
/** Event name for unhandled promise rejections. Default: `App:Error:UnhandledRejection`. */
|
|
7
|
+
unhandledRejectionEventName?: string;
|
|
8
|
+
/** Extra attributes merged into both events. */
|
|
9
|
+
attributes?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Explicit opt-in: capture uncaught errors and unhandled promise rejections
|
|
13
|
+
* for `client`. Never installed automatically by the provider — global
|
|
14
|
+
* listeners are a host-level decision, and under Module Federation several
|
|
15
|
+
* apps share `window`.
|
|
16
|
+
*
|
|
17
|
+
* Idempotent per client; returns an uninstall function (also idempotent).
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* const client = useTelemetryClient();
|
|
22
|
+
* useEffect(() => installGlobalErrorHandlers(client), [client]);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function installGlobalErrorHandlers(client: Telemetry, options?: GlobalErrorHandlerOptions): () => void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { TelemetryEvent as s } from "./events.js";
|
|
2
|
+
const n = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
function w(e, t = {}) {
|
|
4
|
+
const d = n.get(e);
|
|
5
|
+
if (d) return d;
|
|
6
|
+
if (typeof window > "u") {
|
|
7
|
+
const r = () => {
|
|
8
|
+
};
|
|
9
|
+
return n.set(e, r), r;
|
|
10
|
+
}
|
|
11
|
+
const a = (r) => {
|
|
12
|
+
e.trackError(r.error ?? r.message, {
|
|
13
|
+
name: t.windowErrorEventName ?? s.WindowError,
|
|
14
|
+
attributes: { ...t.attributes, "error.source": "window" }
|
|
15
|
+
});
|
|
16
|
+
}, i = (r) => {
|
|
17
|
+
e.trackError(r.reason, {
|
|
18
|
+
name: t.unhandledRejectionEventName ?? s.UnhandledRejection,
|
|
19
|
+
attributes: { ...t.attributes, "error.source": "unhandledrejection" }
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
window.addEventListener("error", a), window.addEventListener("unhandledrejection", i);
|
|
23
|
+
const o = () => {
|
|
24
|
+
n.get(e) === o && (n.delete(e), window.removeEventListener("error", a), window.removeEventListener("unhandledrejection", i));
|
|
25
|
+
};
|
|
26
|
+
return n.set(e, o), o;
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
w as installGlobalErrorHandlers
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=global-handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-handlers.js","sources":["../../src/telemetry/global-handlers.ts"],"sourcesContent":["import {TelemetryEvent} from \"./events\";\n\nimport type {Telemetry} from \"@tetrascience-npm/request/telemetry\";\n\n/** Options for {@link installGlobalErrorHandlers}. */\nexport interface GlobalErrorHandlerOptions {\n\t/** Event name for `window.onerror`. Default: `App:Error:Window`. */\n\twindowErrorEventName?: string;\n\t/** Event name for unhandled promise rejections. Default: `App:Error:UnhandledRejection`. */\n\tunhandledRejectionEventName?: string;\n\t/** Extra attributes merged into both events. */\n\tattributes?: Record<string, unknown>;\n}\n\n// Keyed by client so two federated apps can each install their own handlers,\n// while a repeated install for the same client (StrictMode, hot reload) is a\n// no-op that returns the original uninstall.\nconst installed = new WeakMap<Telemetry, () => void>();\n\n/**\n * Explicit opt-in: capture uncaught errors and unhandled promise rejections\n * for `client`. Never installed automatically by the provider — global\n * listeners are a host-level decision, and under Module Federation several\n * apps share `window`.\n *\n * Idempotent per client; returns an uninstall function (also idempotent).\n *\n * @example\n * ```tsx\n * const client = useTelemetryClient();\n * useEffect(() => installGlobalErrorHandlers(client), [client]);\n * ```\n */\nexport function installGlobalErrorHandlers(client: Telemetry, options: GlobalErrorHandlerOptions = {}): () => void {\n\tconst existing = installed.get(client);\n\tif (existing) return existing;\n\tif (typeof window === \"undefined\") {\n\t\t// Recorded in the map like any other install, so the documented\n\t\t// once-per-client contract holds here too: without this, every call in an\n\t\t// SSR/non-browser runtime handed back a different uninstall function.\n\t\tconst noop = (): void => {\n\t\t\t// nothing was installed (SSR / non-browser runtime)\n\t\t};\n\t\tinstalled.set(client, noop);\n\t\treturn noop;\n\t}\n\n\tconst onError = (event: ErrorEvent): void => {\n\t\tclient.trackError(event.error ?? event.message, {\n\t\t\tname: options.windowErrorEventName ?? TelemetryEvent.WindowError,\n\t\t\tattributes: {...options.attributes, \"error.source\": \"window\"},\n\t\t});\n\t};\n\tconst onRejection = (event: PromiseRejectionEvent): void => {\n\t\tclient.trackError(event.reason, {\n\t\t\tname: options.unhandledRejectionEventName ?? TelemetryEvent.UnhandledRejection,\n\t\t\tattributes: {...options.attributes, \"error.source\": \"unhandledrejection\"},\n\t\t});\n\t};\n\n\twindow.addEventListener(\"error\", onError);\n\twindow.addEventListener(\"unhandledrejection\", onRejection);\n\n\tconst uninstall = (): void => {\n\t\tif (installed.get(client) !== uninstall) return;\n\t\tinstalled.delete(client);\n\t\twindow.removeEventListener(\"error\", onError);\n\t\twindow.removeEventListener(\"unhandledrejection\", onRejection);\n\t};\n\tinstalled.set(client, uninstall);\n\treturn uninstall;\n}\n"],"names":["installed","installGlobalErrorHandlers","client","options","existing","noop","onError","event","TelemetryEvent","onRejection","uninstall"],"mappings":";AAiBA,MAAMA,wBAAgB,QAAA;AAgBf,SAASC,EAA2BC,GAAmBC,IAAqC,IAAgB;AAClH,QAAMC,IAAWJ,EAAU,IAAIE,CAAM;AACrC,MAAIE,EAAU,QAAOA;AACrB,MAAI,OAAO,SAAW,KAAa;AAIlC,UAAMC,IAAO,MAAY;AAAA,IAEzB;AACA,WAAAL,EAAU,IAAIE,GAAQG,CAAI,GACnBA;AAAA,EACR;AAEA,QAAMC,IAAU,CAACC,MAA4B;AAC5C,IAAAL,EAAO,WAAWK,EAAM,SAASA,EAAM,SAAS;AAAA,MAC/C,MAAMJ,EAAQ,wBAAwBK,EAAe;AAAA,MACrD,YAAY,EAAC,GAAGL,EAAQ,YAAY,gBAAgB,SAAA;AAAA,IAAQ,CAC5D;AAAA,EACF,GACMM,IAAc,CAACF,MAAuC;AAC3D,IAAAL,EAAO,WAAWK,EAAM,QAAQ;AAAA,MAC/B,MAAMJ,EAAQ,+BAA+BK,EAAe;AAAA,MAC5D,YAAY,EAAC,GAAGL,EAAQ,YAAY,gBAAgB,qBAAA;AAAA,IAAoB,CACxE;AAAA,EACF;AAEA,SAAO,iBAAiB,SAASG,CAAO,GACxC,OAAO,iBAAiB,sBAAsBG,CAAW;AAEzD,QAAMC,IAAY,MAAY;AAC7B,IAAIV,EAAU,IAAIE,CAAM,MAAMQ,MAC9BV,EAAU,OAAOE,CAAM,GACvB,OAAO,oBAAoB,SAASI,CAAO,GAC3C,OAAO,oBAAoB,sBAAsBG,CAAW;AAAA,EAC7D;AACA,SAAAT,EAAU,IAAIE,GAAQQ,CAAS,GACxBA;AACR;"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React bindings for the product-event telemetry distro (SW-2322).
|
|
3
|
+
*
|
|
4
|
+
* One provider mount and one import is the whole integration:
|
|
5
|
+
*
|
|
6
|
+
* ```tsx
|
|
7
|
+
* import {TelemetryProvider, TSErrorBoundary, useTetraEvents} from '@tetrascience-npm/tetrascience-react-ui/telemetry';
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* This entry IS the React layer — it exports a provider, a hook and an error
|
|
11
|
+
* boundary — so importing it pulls React in, and `react` is a required peer of
|
|
12
|
+
* this package (it carries no `peerDependenciesMeta.optional`).
|
|
13
|
+
*
|
|
14
|
+
* If you want telemetry without React, import the framework-agnostic core
|
|
15
|
+
* directly: `@tetrascience-npm/request/telemetry`. That is what these bindings
|
|
16
|
+
* wrap, and it is re-exported below so a consumer never needs both imports.
|
|
17
|
+
*/
|
|
18
|
+
export * from './types';
|
|
19
|
+
export * from './events';
|
|
20
|
+
export * from './context';
|
|
21
|
+
export * from './facade';
|
|
22
|
+
export * from './telemetry-provider';
|
|
23
|
+
export * from './use-tetra-events';
|
|
24
|
+
export * from './error-boundary';
|
|
25
|
+
export * from './global-handlers';
|
|
26
|
+
export * from '@tetrascience-npm/request/telemetry';
|
|
27
|
+
export type { ArtifactIdentity } from '@tetrascience-npm/request/telemetry';
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("react/jsx-runtime"),T=require("@tetrascience-npm/request/telemetry"),u=require("react"),v=require("./context.cjs"),d=require("./facade.cjs");function s(t){if(typeof window>"u")return;const e=window.env?.[t];if(typeof e=="boolean")return e;if(typeof e=="string"){if(/^(true|1|yes)$/i.test(e))return!0;if(/^(false|0|no)$/i.test(e))return!1}}function f(t,e,r="data-app"){const l=t?.namespace??e?.namespace,i=t?.slug??e?.slug,n=t?.version??e?.version,c=t?.type??e?.type??r;return l&&i&&n?{namespace:l,slug:i,version:n,type:c}:void 0}function E({children:t,...e}){const r=e.enabled??s("TELEMETRY_ENABLED")??!0,l=e.debug??s("TELEMETRY_DEBUG")??!1,i=f(e.artifact,e.manifest,e.artifactType),[n]=u.useState(d.createTelemetryFacade),c=u.useRef(e.getAuthToken);c.current=e.getAuthToken;const a={artifact:i,orgSlug:e.orgSlug,logsUrl:e.logsUrl,debug:l,flushTimeoutMillis:e.flushTimeoutMillis,processors:e.processors,logger:e.logger,tracing:e.tracing,metrics:e.metrics,getAuthToken:()=>c.current?.()},g=u.useRef(a);g.current=a;const m=JSON.stringify([r,l,e.logsUrl??null,e.orgSlug??null,i??null,e.tracing?.enabled??null,e.tracing?.tracesUrl??null,e.tracing?.sampleRatio??null,(e.tracing?.spanProcessors?.length??0)>0,e.metrics?.enabled??null,e.metrics?.metricsUrl??null,e.metrics?.exportIntervalMillis??null,(e.metrics?.readers?.length??0)>0]);return u.useEffect(()=>{const o=r?T.createTelemetry(g.current):d.NOOP_TELEMETRY;return n.attach(o),()=>{n.detach(o),o.shutdown()}},[n,m,r]),y.jsx(v.TelemetryContext.Provider,{value:n,children:t})}exports.TelemetryProvider=E;exports.readHostFlag=s;exports.resolveArtifact=f;
|
|
2
|
+
//# sourceMappingURL=telemetry-provider.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-provider.cjs","sources":["../../src/telemetry/telemetry-provider.tsx"],"sourcesContent":["import {\n\tcreateTelemetry,\n\ttype ArtifactType,\n\ttype TelemetryArtifact,\n\ttype TelemetryOptions,\n} from \"@tetrascience-npm/request/telemetry\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { TelemetryContext } from \"./context\";\nimport { NOOP_TELEMETRY, createTelemetryFacade } from \"./facade\";\n\nimport type { TelemetryProviderProps } from \"./types\";\n\n/**\n * Read a boolean flag from the host-provided browser config (`window.env`) —\n * the same seam the core uses for `API_URI`. Accepts real booleans and the\n * string forms hosts inject through templated config.\n */\nexport function readHostFlag(key: string): boolean | undefined {\n if (typeof window === \"undefined\") return undefined;\n const value = (window as { env?: Record<string, unknown> }).env?.[key];\n if (typeof value === \"boolean\") return value;\n if (typeof value === \"string\") {\n if (/^(true|1|yes)$/i.test(value)) return true;\n if (/^(false|0|no)$/i.test(value)) return false;\n }\n return undefined;\n}\n\n/**\n * Merge host mount props with the manifest fallback, field by field. Returns\n * undefined when identity is still incomplete — the core then emits without\n * artifact identity rather than with placeholder values.\n */\nexport function resolveArtifact(\n artifact: Partial<TelemetryArtifact> | undefined,\n manifest: Partial<TelemetryArtifact> | undefined,\n artifactType: ArtifactType = \"data-app\",\n): TelemetryArtifact | undefined {\n const namespace = artifact?.namespace ?? manifest?.namespace;\n const slug = artifact?.slug ?? manifest?.slug;\n const version = artifact?.version ?? manifest?.version;\n const type = artifact?.type ?? manifest?.type ?? artifactType;\n return namespace && slug && version ? { namespace, slug, version, type } : undefined;\n}\n\n/**\n * Mount once, near the app root: builds a PER-INSTANCE telemetry client from\n * the app's identity and exposes it to `useTetraEvents` / `TSErrorBoundary`.\n *\n * The client is never module-global — federated apps share `globalThis` with\n * the host and siblings, so a global client would cross-attribute events.\n * It is built inside an effect and shut down (which flushes) on unmount, so\n * StrictMode's mount → unmount → mount cycle disposes the first client\n * cleanly instead of leaving a dead provider attached. The context value is a\n * stable façade, so hook callback identities never change.\n *\n * No user identity is ever attached client-side: `user.id` is stamped\n * server-side at the gateway from the authenticated principal.\n *\n * @example\n * ```tsx\n * <TelemetryProvider artifact={hostProps.artifact} manifest={manifest} orgSlug={org?.slug}>\n * <App />\n * </TelemetryProvider>\n * ```\n */\nexport function TelemetryProvider({ children, ...props }: TelemetryProviderProps) {\n const enabled = props.enabled ?? readHostFlag(\"TELEMETRY_ENABLED\") ?? true;\n const debug = props.debug ?? readHostFlag(\"TELEMETRY_DEBUG\") ?? false;\n const artifact = resolveArtifact(props.artifact, props.manifest, props.artifactType);\n\n const [facade] = useState(createTelemetryFacade);\n\n // Options are read at construction time; only identity-shaped changes\n // rebuild the client (a new `processors`/`logger` object per render must not).\n // The client is built ONCE per identity change, but the token resolver has to\n // track re-renders: an app writing `getAuthToken={() => token}` produces a new\n // closure each render, and the client would otherwise keep calling the first\n // one — capturing whatever token existed at mount. That fails silently and\n // late, as 401s appearing only after the first token rotation. Holding the\n // prop in a ref and calling through it means the client always invokes the\n // CURRENT closure without being rebuilt.\n const getAuthTokenRef = useRef(props.getAuthToken);\n getAuthTokenRef.current = props.getAuthToken;\n\n const options: TelemetryOptions = {\n artifact,\n orgSlug: props.orgSlug,\n logsUrl: props.logsUrl,\n debug,\n flushTimeoutMillis: props.flushTimeoutMillis,\n processors: props.processors,\n logger: props.logger,\n tracing: props.tracing,\n metrics: props.metrics,\n getAuthToken: () => getAuthTokenRef.current?.(),\n };\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // `tracing` is part of the identity: without it, flipping tracing on (or\n // changing the sample ratio) would not rebuild the client, so the change\n // would silently take effect only when some UNRELATED identity field\n // happened to change. Read field-by-field rather than by reference so an\n // inline `tracing={{enabled: true}}` object literal does not rebuild every\n // render.\n // Only SCALARS go in the key. `tracing.spanProcessors` and `metrics.readers`\n // hold live SDK instances — serialising those would make the key depend on\n // an exporter's internal state (spurious rebuilds), and a processor with a\n // circular reference would throw here and take the whole provider down on\n // render. Their PRESENCE is part of the identity; their contents are not.\n const identityKey = JSON.stringify([\n enabled,\n debug,\n props.logsUrl ?? null,\n props.orgSlug ?? null,\n artifact ?? null,\n props.tracing?.enabled ?? null,\n props.tracing?.tracesUrl ?? null,\n props.tracing?.sampleRatio ?? null,\n (props.tracing?.spanProcessors?.length ?? 0) > 0,\n // Same argument as `tracing`: without metrics in the identity, flipping\n // it on would not rebuild the client, so the change would take effect\n // only when some UNRELATED identity field happened to change.\n props.metrics?.enabled ?? null,\n props.metrics?.metricsUrl ?? null,\n props.metrics?.exportIntervalMillis ?? null,\n (props.metrics?.readers?.length ?? 0) > 0,\n ]);\n\n useEffect(() => {\n const client = enabled ? createTelemetry(optionsRef.current) : NOOP_TELEMETRY;\n facade.attach(client);\n return () => {\n facade.detach(client);\n // shutdown() flushes what is buffered, then tears the pipeline down.\n void client.shutdown();\n };\n // `enabled` is encoded in identityKey; optionsRef is intentionally not a dep.\n }, [facade, identityKey, enabled]);\n\n return <TelemetryContext.Provider value={facade}>{children}</TelemetryContext.Provider>;\n}\n"],"names":["readHostFlag","key","value","resolveArtifact","artifact","manifest","artifactType","namespace","slug","version","type","TelemetryProvider","children","props","enabled","debug","facade","useState","createTelemetryFacade","getAuthTokenRef","useRef","options","optionsRef","identityKey","useEffect","client","createTelemetry","NOOP_TELEMETRY","TelemetryContext"],"mappings":"8OAkBO,SAASA,EAAaC,EAAkC,CAC7D,GAAI,OAAO,OAAW,IAAa,OACnC,MAAMC,EAAS,OAA6C,MAAMD,CAAG,EACrE,GAAI,OAAOC,GAAU,UAAW,OAAOA,EACvC,GAAI,OAAOA,GAAU,SAAU,CAC7B,GAAI,kBAAkB,KAAKA,CAAK,EAAG,MAAO,GAC1C,GAAI,kBAAkB,KAAKA,CAAK,EAAG,MAAO,EAC5C,CAEF,CAOO,SAASC,EACdC,EACAC,EACAC,EAA6B,WACE,CAC/B,MAAMC,EAAYH,GAAU,WAAaC,GAAU,UAC7CG,EAAOJ,GAAU,MAAQC,GAAU,KACnCI,EAAUL,GAAU,SAAWC,GAAU,QACzCK,EAAON,GAAU,MAAQC,GAAU,MAAQC,EACjD,OAAOC,GAAaC,GAAQC,EAAU,CAAE,UAAAF,EAAW,KAAAC,EAAM,QAAAC,EAAS,KAAAC,GAAS,MAC7E,CAuBO,SAASC,EAAkB,CAAE,SAAAC,EAAU,GAAGC,GAAiC,CAChF,MAAMC,EAAUD,EAAM,SAAWb,EAAa,mBAAmB,GAAK,GAChEe,EAAQF,EAAM,OAASb,EAAa,iBAAiB,GAAK,GAC1DI,EAAWD,EAAgBU,EAAM,SAAUA,EAAM,SAAUA,EAAM,YAAY,EAE7E,CAACG,CAAM,EAAIC,EAAAA,SAASC,uBAAqB,EAWzCC,EAAkBC,EAAAA,OAAOP,EAAM,YAAY,EACjDM,EAAgB,QAAUN,EAAM,aAEhC,MAAMQ,EAA4B,CAChC,SAAAjB,EACA,QAASS,EAAM,QACf,QAASA,EAAM,QACf,MAAAE,EACA,mBAAoBF,EAAM,mBAC1B,WAAYA,EAAM,WAClB,OAAQA,EAAM,OACd,QAASA,EAAM,QACf,QAASA,EAAM,QACf,aAAc,IAAMM,EAAgB,UAAA,CAAU,EAE1CG,EAAaF,EAAAA,OAAOC,CAAO,EACjCC,EAAW,QAAUD,EAarB,MAAME,EAAc,KAAK,UAAU,CACjCT,EACAC,EACAF,EAAM,SAAW,KACjBA,EAAM,SAAW,KACjBT,GAAY,KACZS,EAAM,SAAS,SAAW,KAC1BA,EAAM,SAAS,WAAa,KAC5BA,EAAM,SAAS,aAAe,MAC7BA,EAAM,SAAS,gBAAgB,QAAU,GAAK,EAI/CA,EAAM,SAAS,SAAW,KAC1BA,EAAM,SAAS,YAAc,KAC7BA,EAAM,SAAS,sBAAwB,MACtCA,EAAM,SAAS,SAAS,QAAU,GAAK,CAAA,CACzC,EAEDW,OAAAA,EAAAA,UAAU,IAAM,CACd,MAAMC,EAASX,EAAUY,EAAAA,gBAAgBJ,EAAW,OAAO,EAAIK,EAAAA,eAC/DX,OAAAA,EAAO,OAAOS,CAAM,EACb,IAAM,CACXT,EAAO,OAAOS,CAAM,EAEfA,EAAO,SAAA,CACd,CAEF,EAAG,CAACT,EAAQO,EAAaT,CAAO,CAAC,QAEzBc,EAAAA,iBAAiB,SAAjB,CAA0B,MAAOZ,EAAS,SAAAJ,EAAS,CAC7D"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ArtifactType, TelemetryArtifact } from '@tetrascience-npm/request/telemetry';
|
|
2
|
+
import { TelemetryProviderProps } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Read a boolean flag from the host-provided browser config (`window.env`) —
|
|
5
|
+
* the same seam the core uses for `API_URI`. Accepts real booleans and the
|
|
6
|
+
* string forms hosts inject through templated config.
|
|
7
|
+
*/
|
|
8
|
+
export declare function readHostFlag(key: string): boolean | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Merge host mount props with the manifest fallback, field by field. Returns
|
|
11
|
+
* undefined when identity is still incomplete — the core then emits without
|
|
12
|
+
* artifact identity rather than with placeholder values.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveArtifact(artifact: Partial<TelemetryArtifact> | undefined, manifest: Partial<TelemetryArtifact> | undefined, artifactType?: ArtifactType): TelemetryArtifact | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Mount once, near the app root: builds a PER-INSTANCE telemetry client from
|
|
17
|
+
* the app's identity and exposes it to `useTetraEvents` / `TSErrorBoundary`.
|
|
18
|
+
*
|
|
19
|
+
* The client is never module-global — federated apps share `globalThis` with
|
|
20
|
+
* the host and siblings, so a global client would cross-attribute events.
|
|
21
|
+
* It is built inside an effect and shut down (which flushes) on unmount, so
|
|
22
|
+
* StrictMode's mount → unmount → mount cycle disposes the first client
|
|
23
|
+
* cleanly instead of leaving a dead provider attached. The context value is a
|
|
24
|
+
* stable façade, so hook callback identities never change.
|
|
25
|
+
*
|
|
26
|
+
* No user identity is ever attached client-side: `user.id` is stamped
|
|
27
|
+
* server-side at the gateway from the authenticated principal.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* <TelemetryProvider artifact={hostProps.artifact} manifest={manifest} orgSlug={org?.slug}>
|
|
32
|
+
* <App />
|
|
33
|
+
* </TelemetryProvider>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function TelemetryProvider({ children, ...props }: TelemetryProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jsx as m } from "react/jsx-runtime";
|
|
2
|
+
import { createTelemetry as d } from "@tetrascience-npm/request/telemetry";
|
|
3
|
+
import { useState as T, useRef as a, useEffect as y } from "react";
|
|
4
|
+
import { TelemetryContext as v } from "./context.js";
|
|
5
|
+
import { createTelemetryFacade as E, NOOP_TELEMETRY as h } from "./facade.js";
|
|
6
|
+
function g(t) {
|
|
7
|
+
if (typeof window > "u") return;
|
|
8
|
+
const e = window.env?.[t];
|
|
9
|
+
if (typeof e == "boolean") return e;
|
|
10
|
+
if (typeof e == "string") {
|
|
11
|
+
if (/^(true|1|yes)$/i.test(e)) return !0;
|
|
12
|
+
if (/^(false|0|no)$/i.test(e)) return !1;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function b(t, e, r = "data-app") {
|
|
16
|
+
const l = t?.namespace ?? e?.namespace, i = t?.slug ?? e?.slug, n = t?.version ?? e?.version, o = t?.type ?? e?.type ?? r;
|
|
17
|
+
return l && i && n ? { namespace: l, slug: i, version: n, type: o } : void 0;
|
|
18
|
+
}
|
|
19
|
+
function S({ children: t, ...e }) {
|
|
20
|
+
const r = e.enabled ?? g("TELEMETRY_ENABLED") ?? !0, l = e.debug ?? g("TELEMETRY_DEBUG") ?? !1, i = b(e.artifact, e.manifest, e.artifactType), [n] = T(E), o = a(e.getAuthToken);
|
|
21
|
+
o.current = e.getAuthToken;
|
|
22
|
+
const u = {
|
|
23
|
+
artifact: i,
|
|
24
|
+
orgSlug: e.orgSlug,
|
|
25
|
+
logsUrl: e.logsUrl,
|
|
26
|
+
debug: l,
|
|
27
|
+
flushTimeoutMillis: e.flushTimeoutMillis,
|
|
28
|
+
processors: e.processors,
|
|
29
|
+
logger: e.logger,
|
|
30
|
+
tracing: e.tracing,
|
|
31
|
+
metrics: e.metrics,
|
|
32
|
+
getAuthToken: () => o.current?.()
|
|
33
|
+
}, s = a(u);
|
|
34
|
+
s.current = u;
|
|
35
|
+
const f = JSON.stringify([
|
|
36
|
+
r,
|
|
37
|
+
l,
|
|
38
|
+
e.logsUrl ?? null,
|
|
39
|
+
e.orgSlug ?? null,
|
|
40
|
+
i ?? null,
|
|
41
|
+
e.tracing?.enabled ?? null,
|
|
42
|
+
e.tracing?.tracesUrl ?? null,
|
|
43
|
+
e.tracing?.sampleRatio ?? null,
|
|
44
|
+
(e.tracing?.spanProcessors?.length ?? 0) > 0,
|
|
45
|
+
// Same argument as `tracing`: without metrics in the identity, flipping
|
|
46
|
+
// it on would not rebuild the client, so the change would take effect
|
|
47
|
+
// only when some UNRELATED identity field happened to change.
|
|
48
|
+
e.metrics?.enabled ?? null,
|
|
49
|
+
e.metrics?.metricsUrl ?? null,
|
|
50
|
+
e.metrics?.exportIntervalMillis ?? null,
|
|
51
|
+
(e.metrics?.readers?.length ?? 0) > 0
|
|
52
|
+
]);
|
|
53
|
+
return y(() => {
|
|
54
|
+
const c = r ? d(s.current) : h;
|
|
55
|
+
return n.attach(c), () => {
|
|
56
|
+
n.detach(c), c.shutdown();
|
|
57
|
+
};
|
|
58
|
+
}, [n, f, r]), /* @__PURE__ */ m(v.Provider, { value: n, children: t });
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
S as TelemetryProvider,
|
|
62
|
+
g as readHostFlag,
|
|
63
|
+
b as resolveArtifact
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=telemetry-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-provider.js","sources":["../../src/telemetry/telemetry-provider.tsx"],"sourcesContent":["import {\n\tcreateTelemetry,\n\ttype ArtifactType,\n\ttype TelemetryArtifact,\n\ttype TelemetryOptions,\n} from \"@tetrascience-npm/request/telemetry\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { TelemetryContext } from \"./context\";\nimport { NOOP_TELEMETRY, createTelemetryFacade } from \"./facade\";\n\nimport type { TelemetryProviderProps } from \"./types\";\n\n/**\n * Read a boolean flag from the host-provided browser config (`window.env`) —\n * the same seam the core uses for `API_URI`. Accepts real booleans and the\n * string forms hosts inject through templated config.\n */\nexport function readHostFlag(key: string): boolean | undefined {\n if (typeof window === \"undefined\") return undefined;\n const value = (window as { env?: Record<string, unknown> }).env?.[key];\n if (typeof value === \"boolean\") return value;\n if (typeof value === \"string\") {\n if (/^(true|1|yes)$/i.test(value)) return true;\n if (/^(false|0|no)$/i.test(value)) return false;\n }\n return undefined;\n}\n\n/**\n * Merge host mount props with the manifest fallback, field by field. Returns\n * undefined when identity is still incomplete — the core then emits without\n * artifact identity rather than with placeholder values.\n */\nexport function resolveArtifact(\n artifact: Partial<TelemetryArtifact> | undefined,\n manifest: Partial<TelemetryArtifact> | undefined,\n artifactType: ArtifactType = \"data-app\",\n): TelemetryArtifact | undefined {\n const namespace = artifact?.namespace ?? manifest?.namespace;\n const slug = artifact?.slug ?? manifest?.slug;\n const version = artifact?.version ?? manifest?.version;\n const type = artifact?.type ?? manifest?.type ?? artifactType;\n return namespace && slug && version ? { namespace, slug, version, type } : undefined;\n}\n\n/**\n * Mount once, near the app root: builds a PER-INSTANCE telemetry client from\n * the app's identity and exposes it to `useTetraEvents` / `TSErrorBoundary`.\n *\n * The client is never module-global — federated apps share `globalThis` with\n * the host and siblings, so a global client would cross-attribute events.\n * It is built inside an effect and shut down (which flushes) on unmount, so\n * StrictMode's mount → unmount → mount cycle disposes the first client\n * cleanly instead of leaving a dead provider attached. The context value is a\n * stable façade, so hook callback identities never change.\n *\n * No user identity is ever attached client-side: `user.id` is stamped\n * server-side at the gateway from the authenticated principal.\n *\n * @example\n * ```tsx\n * <TelemetryProvider artifact={hostProps.artifact} manifest={manifest} orgSlug={org?.slug}>\n * <App />\n * </TelemetryProvider>\n * ```\n */\nexport function TelemetryProvider({ children, ...props }: TelemetryProviderProps) {\n const enabled = props.enabled ?? readHostFlag(\"TELEMETRY_ENABLED\") ?? true;\n const debug = props.debug ?? readHostFlag(\"TELEMETRY_DEBUG\") ?? false;\n const artifact = resolveArtifact(props.artifact, props.manifest, props.artifactType);\n\n const [facade] = useState(createTelemetryFacade);\n\n // Options are read at construction time; only identity-shaped changes\n // rebuild the client (a new `processors`/`logger` object per render must not).\n // The client is built ONCE per identity change, but the token resolver has to\n // track re-renders: an app writing `getAuthToken={() => token}` produces a new\n // closure each render, and the client would otherwise keep calling the first\n // one — capturing whatever token existed at mount. That fails silently and\n // late, as 401s appearing only after the first token rotation. Holding the\n // prop in a ref and calling through it means the client always invokes the\n // CURRENT closure without being rebuilt.\n const getAuthTokenRef = useRef(props.getAuthToken);\n getAuthTokenRef.current = props.getAuthToken;\n\n const options: TelemetryOptions = {\n artifact,\n orgSlug: props.orgSlug,\n logsUrl: props.logsUrl,\n debug,\n flushTimeoutMillis: props.flushTimeoutMillis,\n processors: props.processors,\n logger: props.logger,\n tracing: props.tracing,\n metrics: props.metrics,\n getAuthToken: () => getAuthTokenRef.current?.(),\n };\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // `tracing` is part of the identity: without it, flipping tracing on (or\n // changing the sample ratio) would not rebuild the client, so the change\n // would silently take effect only when some UNRELATED identity field\n // happened to change. Read field-by-field rather than by reference so an\n // inline `tracing={{enabled: true}}` object literal does not rebuild every\n // render.\n // Only SCALARS go in the key. `tracing.spanProcessors` and `metrics.readers`\n // hold live SDK instances — serialising those would make the key depend on\n // an exporter's internal state (spurious rebuilds), and a processor with a\n // circular reference would throw here and take the whole provider down on\n // render. Their PRESENCE is part of the identity; their contents are not.\n const identityKey = JSON.stringify([\n enabled,\n debug,\n props.logsUrl ?? null,\n props.orgSlug ?? null,\n artifact ?? null,\n props.tracing?.enabled ?? null,\n props.tracing?.tracesUrl ?? null,\n props.tracing?.sampleRatio ?? null,\n (props.tracing?.spanProcessors?.length ?? 0) > 0,\n // Same argument as `tracing`: without metrics in the identity, flipping\n // it on would not rebuild the client, so the change would take effect\n // only when some UNRELATED identity field happened to change.\n props.metrics?.enabled ?? null,\n props.metrics?.metricsUrl ?? null,\n props.metrics?.exportIntervalMillis ?? null,\n (props.metrics?.readers?.length ?? 0) > 0,\n ]);\n\n useEffect(() => {\n const client = enabled ? createTelemetry(optionsRef.current) : NOOP_TELEMETRY;\n facade.attach(client);\n return () => {\n facade.detach(client);\n // shutdown() flushes what is buffered, then tears the pipeline down.\n void client.shutdown();\n };\n // `enabled` is encoded in identityKey; optionsRef is intentionally not a dep.\n }, [facade, identityKey, enabled]);\n\n return <TelemetryContext.Provider value={facade}>{children}</TelemetryContext.Provider>;\n}\n"],"names":["readHostFlag","key","value","resolveArtifact","artifact","manifest","artifactType","namespace","slug","version","type","TelemetryProvider","children","props","enabled","debug","facade","useState","createTelemetryFacade","getAuthTokenRef","useRef","options","optionsRef","identityKey","useEffect","client","createTelemetry","NOOP_TELEMETRY","TelemetryContext"],"mappings":";;;;;AAkBO,SAASA,EAAaC,GAAkC;AAC7D,MAAI,OAAO,SAAW,IAAa;AACnC,QAAMC,IAAS,OAA6C,MAAMD,CAAG;AACrE,MAAI,OAAOC,KAAU,UAAW,QAAOA;AACvC,MAAI,OAAOA,KAAU,UAAU;AAC7B,QAAI,kBAAkB,KAAKA,CAAK,EAAG,QAAO;AAC1C,QAAI,kBAAkB,KAAKA,CAAK,EAAG,QAAO;AAAA,EAC5C;AAEF;AAOO,SAASC,EACdC,GACAC,GACAC,IAA6B,YACE;AAC/B,QAAMC,IAAYH,GAAU,aAAaC,GAAU,WAC7CG,IAAOJ,GAAU,QAAQC,GAAU,MACnCI,IAAUL,GAAU,WAAWC,GAAU,SACzCK,IAAON,GAAU,QAAQC,GAAU,QAAQC;AACjD,SAAOC,KAAaC,KAAQC,IAAU,EAAE,WAAAF,GAAW,MAAAC,GAAM,SAAAC,GAAS,MAAAC,MAAS;AAC7E;AAuBO,SAASC,EAAkB,EAAE,UAAAC,GAAU,GAAGC,KAAiC;AAChF,QAAMC,IAAUD,EAAM,WAAWb,EAAa,mBAAmB,KAAK,IAChEe,IAAQF,EAAM,SAASb,EAAa,iBAAiB,KAAK,IAC1DI,IAAWD,EAAgBU,EAAM,UAAUA,EAAM,UAAUA,EAAM,YAAY,GAE7E,CAACG,CAAM,IAAIC,EAASC,CAAqB,GAWzCC,IAAkBC,EAAOP,EAAM,YAAY;AACjD,EAAAM,EAAgB,UAAUN,EAAM;AAEhC,QAAMQ,IAA4B;AAAA,IAChC,UAAAjB;AAAA,IACA,SAASS,EAAM;AAAA,IACf,SAASA,EAAM;AAAA,IACf,OAAAE;AAAA,IACA,oBAAoBF,EAAM;AAAA,IAC1B,YAAYA,EAAM;AAAA,IAClB,QAAQA,EAAM;AAAA,IACd,SAASA,EAAM;AAAA,IACf,SAASA,EAAM;AAAA,IACf,cAAc,MAAMM,EAAgB,UAAA;AAAA,EAAU,GAE1CG,IAAaF,EAAOC,CAAO;AACjC,EAAAC,EAAW,UAAUD;AAarB,QAAME,IAAc,KAAK,UAAU;AAAA,IACjCT;AAAA,IACAC;AAAA,IACAF,EAAM,WAAW;AAAA,IACjBA,EAAM,WAAW;AAAA,IACjBT,KAAY;AAAA,IACZS,EAAM,SAAS,WAAW;AAAA,IAC1BA,EAAM,SAAS,aAAa;AAAA,IAC5BA,EAAM,SAAS,eAAe;AAAA,KAC7BA,EAAM,SAAS,gBAAgB,UAAU,KAAK;AAAA;AAAA;AAAA;AAAA,IAI/CA,EAAM,SAAS,WAAW;AAAA,IAC1BA,EAAM,SAAS,cAAc;AAAA,IAC7BA,EAAM,SAAS,wBAAwB;AAAA,KACtCA,EAAM,SAAS,SAAS,UAAU,KAAK;AAAA,EAAA,CACzC;AAED,SAAAW,EAAU,MAAM;AACd,UAAMC,IAASX,IAAUY,EAAgBJ,EAAW,OAAO,IAAIK;AAC/D,WAAAX,EAAO,OAAOS,CAAM,GACb,MAAM;AACX,MAAAT,EAAO,OAAOS,CAAM,GAEfA,EAAO,SAAA;AAAA,IACd;AAAA,EAEF,GAAG,CAACT,GAAQO,GAAaT,CAAO,CAAC,qBAEzBc,EAAiB,UAAjB,EAA0B,OAAOZ,GAAS,UAAAJ,GAAS;AAC7D;"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { LogRecordProcessor } from '@opentelemetry/sdk-logs';
|
|
2
|
+
import { RequestTrackingLogger } from '@tetrascience-npm/request';
|
|
3
|
+
import { ArtifactType, MetricsOptions, StartSpanOptions, Telemetry, TelemetryArtifact, TelemetryTracingOptions, TetraSpan, TrackErrorContext } from '@tetrascience-npm/request/telemetry';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
/** Props for {@link TelemetryProvider}. */
|
|
6
|
+
export interface TelemetryProviderProps {
|
|
7
|
+
/**
|
|
8
|
+
* Artifact identity from the host mount props (`hostProps.artifact`).
|
|
9
|
+
* Fields missing here fall back to {@link TelemetryProviderProps.manifest}.
|
|
10
|
+
*/
|
|
11
|
+
artifact?: Partial<TelemetryArtifact>;
|
|
12
|
+
/**
|
|
13
|
+
* Manifest fallback for standalone dev, e.g. `import manifest from './manifest.json'`.
|
|
14
|
+
* Used field-by-field wherever `artifact` is incomplete.
|
|
15
|
+
*/
|
|
16
|
+
manifest?: Partial<TelemetryArtifact>;
|
|
17
|
+
/**
|
|
18
|
+
* What KIND of artifact is mounting this — `"data-app"` unless stated.
|
|
19
|
+
*
|
|
20
|
+
* The core distro refuses to guess this (it serves data apps and connectors
|
|
21
|
+
* alike, and mislabelling one as the other is worse than emitting no kind at
|
|
22
|
+
* all). This kit can: it is React bindings for a browser mount, and on this
|
|
23
|
+
* platform that is a data app. The default is a DECLARATION by a component
|
|
24
|
+
* only data apps mount, not a fallback for producers that do not know what
|
|
25
|
+
* they are — and anything else mounting it says so here.
|
|
26
|
+
*
|
|
27
|
+
* `artifact.type` / `manifest.type` win over this when present.
|
|
28
|
+
*/
|
|
29
|
+
artifactType?: ArtifactType;
|
|
30
|
+
/**
|
|
31
|
+
* Org slug hint. Producer-asserted only — the gateway stamps the
|
|
32
|
+
* authenticated org server-side and that value wins (SW-2319).
|
|
33
|
+
*/
|
|
34
|
+
orgSlug?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the current user's auth token for the `ts-auth-token` header.
|
|
37
|
+
*
|
|
38
|
+
* REQUIRED for a browser data app to deliver anything. The gateway reads
|
|
39
|
+
* credentials from headers only, and its CORS config (`origin: ['*']`, no
|
|
40
|
+
* `credentials`) means a browser cannot send a session cookie — so without
|
|
41
|
+
* this every batch 401s and the app emits into the void.
|
|
42
|
+
*
|
|
43
|
+
* Called on every export, so pass a function that reads the host's CURRENT
|
|
44
|
+
* token rather than a captured string: a data app outlives any single
|
|
45
|
+
* short-lived token.
|
|
46
|
+
*/
|
|
47
|
+
getAuthToken?: () => string | undefined | Promise<string | undefined>;
|
|
48
|
+
/** OTLP/HTTP logs URL override. Default: the core's endpoint resolution. */
|
|
49
|
+
logsUrl?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Master switch. Default: `window.env.TELEMETRY_ENABLED` when the host
|
|
52
|
+
* provides it, otherwise `true`. When disabled the context client is a
|
|
53
|
+
* no-op — no OTel provider, no exporter, no network, no buffers.
|
|
54
|
+
*/
|
|
55
|
+
enabled?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Route records to the stock console exporter in addition to OTLP, so
|
|
58
|
+
* authors see the exact pre-gateway payload. Default:
|
|
59
|
+
* `window.env.TELEMETRY_DEBUG` when the host provides it, otherwise `false`.
|
|
60
|
+
*/
|
|
61
|
+
debug?: boolean;
|
|
62
|
+
/** Log record processors override (tests, custom pipelines). */
|
|
63
|
+
processors?: LogRecordProcessor[];
|
|
64
|
+
/**
|
|
65
|
+
* Distributed tracing (SW-2478). Off unless `tracing.enabled` is true —
|
|
66
|
+
* tracing adds a second exporter and a per-span network cost, so an app
|
|
67
|
+
* opts in rather than acquiring it by upgrading the library.
|
|
68
|
+
*/
|
|
69
|
+
tracing?: TelemetryTracingOptions;
|
|
70
|
+
/**
|
|
71
|
+
* OTel metrics (SW-2478). Off unless `metrics.enabled` is true, for the same
|
|
72
|
+
* reason tracing is: a metrics reader is a recurring timer and a recurring
|
|
73
|
+
* export.
|
|
74
|
+
*
|
|
75
|
+
* Forwarded here rather than left to the core's defaults because apps build
|
|
76
|
+
* their client through THIS provider — an option the provider does not pass
|
|
77
|
+
* through is one no React data app can ever set, which is how
|
|
78
|
+
* `gauge()`/`histogram()` came to be callable but permanently inert.
|
|
79
|
+
*/
|
|
80
|
+
metrics?: MetricsOptions;
|
|
81
|
+
/**
|
|
82
|
+
* Cap on how long `flush()` and `shutdown()` wait for the exporter, in ms.
|
|
83
|
+
* Forwarded to the core, which defaults to 5000. Worth setting when the
|
|
84
|
+
* host unmounts on a route change and cannot afford a 5s teardown.
|
|
85
|
+
*/
|
|
86
|
+
flushTimeoutMillis?: number;
|
|
87
|
+
/** Logger for setup failures and stripped attributes. */
|
|
88
|
+
logger?: RequestTrackingLogger;
|
|
89
|
+
children?: ReactNode;
|
|
90
|
+
}
|
|
91
|
+
/** Bound emitters returned by {@link useTetraEvents}. */
|
|
92
|
+
export interface TetraEvents {
|
|
93
|
+
/** Record a product event (`App[:Page][:Object]:Action`). */
|
|
94
|
+
trackEvent(name: string, attributes?: Record<string, unknown>, body?: unknown): void;
|
|
95
|
+
/** Record an error event with `exception.*` attributes. */
|
|
96
|
+
trackError(error: unknown, context?: TrackErrorContext): void;
|
|
97
|
+
/**
|
|
98
|
+
* Start a span (SW-2478). No-op unless the provider was given
|
|
99
|
+
* `tracing.enabled`. The caller must `end()` it — prefer `withSpan`.
|
|
100
|
+
*/
|
|
101
|
+
startSpan(name: string, options?: StartSpanOptions): TetraSpan;
|
|
102
|
+
/**
|
|
103
|
+
* Run `fn` inside a span, ending it when the work settles (promises
|
|
104
|
+
* included) and on the error path. Errors are recorded and re-thrown.
|
|
105
|
+
*/
|
|
106
|
+
withSpan<T>(name: string, fn: (span: TetraSpan) => T, options?: StartSpanOptions): T;
|
|
107
|
+
/**
|
|
108
|
+
* Add to a running total that only ever goes up (SW-2478). No-op unless the
|
|
109
|
+
* provider was given `metrics.enabled`.
|
|
110
|
+
*
|
|
111
|
+
* The core client and the Python distro have both exposed this from the
|
|
112
|
+
* start; the React bindings did not, so a data app could reach `gauge`,
|
|
113
|
+
* `histogram` and `upDownCounter` but not the most basic instrument of the
|
|
114
|
+
* four. Found by the bindings' own e2e — `events.counter is not a function`.
|
|
115
|
+
*/
|
|
116
|
+
counter(name: string, delta?: number, attributes?: Record<string, unknown>): void;
|
|
117
|
+
/**
|
|
118
|
+
* Record the current value of something (SW-2478). No-op unless the
|
|
119
|
+
* provider was given `metrics.enabled`.
|
|
120
|
+
*
|
|
121
|
+
* Unlike {@link TetraEvents.trackEvent}, this carries a VALUE — counting is
|
|
122
|
+
* one-record-one-increment and cannot express "the reading right now".
|
|
123
|
+
*/
|
|
124
|
+
gauge(name: string, value: number, attributes?: Record<string, unknown>): void;
|
|
125
|
+
/** Record a distribution sample — a duration, a size. Same opt-in as `gauge`. */
|
|
126
|
+
histogram(name: string, value: number, attributes?: Record<string, unknown>): void;
|
|
127
|
+
/** Add to a running total that can go both ways. Same opt-in as `gauge`. */
|
|
128
|
+
upDownCounter(name: string, delta: number, attributes?: Record<string, unknown>): void;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The context client: a stable façade whose underlying per-instance client is
|
|
132
|
+
* attached by {@link TelemetryProvider} in an effect. Identity is stable for
|
|
133
|
+
* the provider's lifetime, so hook callbacks never change identity.
|
|
134
|
+
*/
|
|
135
|
+
export type TelemetryFacade = Telemetry & {
|
|
136
|
+
/** @internal */
|
|
137
|
+
attach(client: Telemetry): void;
|
|
138
|
+
/** @internal */
|
|
139
|
+
detach(client: Telemetry): void;
|
|
140
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react"),d=require("./context.cjs"),k=require("./facade.cjs");let a=!1;function E(){a||(a=!0,!(typeof process<"u"&&process.env?.NODE_ENV==="production")&&console.warn("[telemetry] useTetraEvents() called outside <TelemetryProvider> — events are dropped."))}function m(){a=!1}function p(){const e=s.useContext(d.TelemetryContext);return e||E(),e??k.NOOP_TELEMETRY}function b(){const e=p(),o=s.useCallback((t,n,r)=>{e.trackEvent(t,n,r)},[e]),c=s.useCallback((t,n)=>{e.trackError(t,n)},[e]),u=s.useCallback((t,n)=>e.startSpan(t,n),[e]),l=s.useCallback((t,n,r)=>e.counter(t,n,r),[e]),i=s.useCallback((t,n,r)=>e.gauge(t,n,r),[e]),C=s.useCallback((t,n,r)=>e.histogram(t,n,r),[e]),T=s.useCallback((t,n,r)=>e.upDownCounter(t,n,r),[e]),f=s.useCallback((t,n,r)=>e.withSpan(t,n,r),[e]);return s.useMemo(()=>({trackEvent:o,trackError:c,startSpan:u,withSpan:f,counter:l,gauge:i,histogram:C,upDownCounter:T}),[o,c,u,f,l,i,C,T])}exports.__resetTelemetryWarningForTests=m;exports.useTelemetryClient=p;exports.useTetraEvents=b;
|
|
2
|
+
//# sourceMappingURL=use-tetra-events.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-tetra-events.cjs","sources":["../../src/telemetry/use-tetra-events.ts"],"sourcesContent":["import { useCallback, useContext, useMemo } from \"react\";\n\nimport { TelemetryContext } from \"./context\";\nimport { NOOP_TELEMETRY } from \"./facade\";\n\nimport type { TetraEvents } from \"./types\";\nimport type { StartSpanOptions, Telemetry, TetraSpan, TrackErrorContext } from \"@tetrascience-npm/request/telemetry\";\n\nlet warned = false;\n\n/**\n * Outside a provider the hook no-ops with one development warning rather than\n * throwing. Rationale: the core's contract is that telemetry never throws into\n * application code — a missing provider is an instrumentation defect, and\n * crashing a customer's app over it inverts the risk. The warning (dev only,\n * once per module instance) keeps the mistake visible during development and\n * is asserted in tests.\n */\nfunction warnOnce(): void {\n if (warned) return;\n warned = true;\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\") return;\n\n console.warn(\"[telemetry] useTetraEvents() called outside <TelemetryProvider> — events are dropped.\");\n}\n\n/** @internal test seam: reset the once-per-module warning latch. */\nexport function __resetTelemetryWarningForTests(): void {\n warned = false;\n}\n\n/** Access the raw context client — e.g. to wire {@link installGlobalErrorHandlers}. */\nexport function useTelemetryClient(): Telemetry {\n const client = useContext(TelemetryContext);\n if (!client) warnOnce();\n return client ?? NOOP_TELEMETRY;\n}\n\n/**\n * The app-facing emitters, bound to the provider's client.\n *\n * Identities are stable for the provider's lifetime (the context value is a\n * stable façade), so these are safe as effect dependencies.\n *\n * @example\n * ```tsx\n * const {trackEvent} = useTetraEvents();\n * trackEvent('Sandbox:Chat:Submit', {model});\n * ```\n */\nexport function useTetraEvents(): TetraEvents {\n const client = useTelemetryClient();\n\n const trackEvent = useCallback(\n (name: string, attributes?: Record<string, unknown>, body?: unknown) => {\n client.trackEvent(name, attributes, body);\n },\n [client],\n );\n\n const trackError = useCallback(\n (error: unknown, context?: TrackErrorContext) => {\n client.trackError(error, context);\n },\n [client],\n );\n\n // SW-2478. Every method here delegates to the core rather than\n // re-implementing anything, so React and non-React consumers cannot drift.\n const startSpan = useCallback(\n (name: string, options?: StartSpanOptions) => client.startSpan(name, options),\n [client],\n );\n\n // SW-2478 metrics. Same delegation rule as startSpan: the\n // instrument caching, the value guards and the publishable-name warning all\n // live in the core client, so re-implementing any of it here would give\n // React apps different behaviour from Node ones for the same call.\n const counter = useCallback(\n (name: string, delta?: number, attributes?: Record<string, unknown>) => client.counter(name, delta, attributes),\n [client],\n );\n\n const gauge = useCallback(\n (name: string, value: number, attributes?: Record<string, unknown>) => client.gauge(name, value, attributes),\n [client],\n );\n\n const histogram = useCallback(\n (name: string, value: number, attributes?: Record<string, unknown>) => client.histogram(name, value, attributes),\n [client],\n );\n\n const upDownCounter = useCallback(\n (name: string, delta: number, attributes?: Record<string, unknown>) =>\n client.upDownCounter(name, delta, attributes),\n [client],\n );\n\n const withSpan = useCallback(\n <T>(name: string, fn: (span: TetraSpan) => T, options?: StartSpanOptions) => client.withSpan(name, fn, options),\n [client],\n );\n\n return useMemo(\n () => ({ trackEvent, trackError, startSpan, withSpan, counter, gauge, histogram, upDownCounter }),\n [trackEvent, trackError, startSpan, withSpan, counter, gauge, histogram, upDownCounter],\n );\n}\n"],"names":["warned","warnOnce","__resetTelemetryWarningForTests","useTelemetryClient","client","useContext","TelemetryContext","NOOP_TELEMETRY","useTetraEvents","trackEvent","useCallback","name","attributes","body","trackError","error","context","startSpan","options","counter","delta","gauge","value","histogram","upDownCounter","withSpan","fn","useMemo"],"mappings":"8JAQA,IAAIA,EAAS,GAUb,SAASC,GAAiB,CACpBD,IACJA,EAAS,GACL,SAAO,QAAY,KAAe,QAAQ,KAAK,WAAa,eAEhE,QAAQ,KAAK,uFAAuF,EACtG,CAGO,SAASE,GAAwC,CACtDF,EAAS,EACX,CAGO,SAASG,GAAgC,CAC9C,MAAMC,EAASC,EAAAA,WAAWC,kBAAgB,EAC1C,OAAKF,GAAQH,EAAA,EACNG,GAAUG,EAAAA,cACnB,CAcO,SAASC,GAA8B,CAC5C,MAAMJ,EAASD,EAAA,EAETM,EAAaC,EAAAA,YACjB,CAACC,EAAcC,EAAsCC,IAAmB,CACtET,EAAO,WAAWO,EAAMC,EAAYC,CAAI,CAC1C,EACA,CAACT,CAAM,CAAA,EAGHU,EAAaJ,EAAAA,YACjB,CAACK,EAAgBC,IAAgC,CAC/CZ,EAAO,WAAWW,EAAOC,CAAO,CAClC,EACA,CAACZ,CAAM,CAAA,EAKHa,EAAYP,EAAAA,YAChB,CAACC,EAAcO,IAA+Bd,EAAO,UAAUO,EAAMO,CAAO,EAC5E,CAACd,CAAM,CAAA,EAOHe,EAAUT,EAAAA,YACd,CAACC,EAAcS,EAAgBR,IAAyCR,EAAO,QAAQO,EAAMS,EAAOR,CAAU,EAC9G,CAACR,CAAM,CAAA,EAGHiB,EAAQX,EAAAA,YACZ,CAACC,EAAcW,EAAeV,IAAyCR,EAAO,MAAMO,EAAMW,EAAOV,CAAU,EAC3G,CAACR,CAAM,CAAA,EAGHmB,EAAYb,EAAAA,YAChB,CAACC,EAAcW,EAAeV,IAAyCR,EAAO,UAAUO,EAAMW,EAAOV,CAAU,EAC/G,CAACR,CAAM,CAAA,EAGHoB,EAAgBd,EAAAA,YACpB,CAACC,EAAcS,EAAeR,IAC5BR,EAAO,cAAcO,EAAMS,EAAOR,CAAU,EAC9C,CAACR,CAAM,CAAA,EAGHqB,EAAWf,EAAAA,YACf,CAAIC,EAAce,EAA4BR,IAA+Bd,EAAO,SAASO,EAAMe,EAAIR,CAAO,EAC9G,CAACd,CAAM,CAAA,EAGT,OAAOuB,EAAAA,QACL,KAAO,CAAE,WAAAlB,EAAY,WAAAK,EAAY,UAAAG,EAAW,SAAAQ,EAAU,QAAAN,EAAS,MAAAE,EAAO,UAAAE,EAAW,cAAAC,IACjF,CAACf,EAAYK,EAAYG,EAAWQ,EAAUN,EAASE,EAAOE,EAAWC,CAAa,CAAA,CAE1F"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { TetraEvents } from './types';
|
|
2
|
+
import { Telemetry } from '@tetrascience-npm/request/telemetry';
|
|
3
|
+
/** @internal test seam: reset the once-per-module warning latch. */
|
|
4
|
+
export declare function __resetTelemetryWarningForTests(): void;
|
|
5
|
+
/** Access the raw context client — e.g. to wire {@link installGlobalErrorHandlers}. */
|
|
6
|
+
export declare function useTelemetryClient(): Telemetry;
|
|
7
|
+
/**
|
|
8
|
+
* The app-facing emitters, bound to the provider's client.
|
|
9
|
+
*
|
|
10
|
+
* Identities are stable for the provider's lifetime (the context value is a
|
|
11
|
+
* stable façade), so these are safe as effect dependencies.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const {trackEvent} = useTetraEvents();
|
|
16
|
+
* trackEvent('Sandbox:Chat:Submit', {model});
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function useTetraEvents(): TetraEvents;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useContext as E, useCallback as o, useMemo as d } from "react";
|
|
2
|
+
import { TelemetryContext as T } from "./context.js";
|
|
3
|
+
import { NOOP_TELEMETRY as g } from "./facade.js";
|
|
4
|
+
let s = !1;
|
|
5
|
+
function v() {
|
|
6
|
+
s || (s = !0, !(typeof process < "u" && process.env?.NODE_ENV === "production") && console.warn("[telemetry] useTetraEvents() called outside <TelemetryProvider> — events are dropped."));
|
|
7
|
+
}
|
|
8
|
+
function h() {
|
|
9
|
+
s = !1;
|
|
10
|
+
}
|
|
11
|
+
function w() {
|
|
12
|
+
const e = E(T);
|
|
13
|
+
return e || v(), e ?? g;
|
|
14
|
+
}
|
|
15
|
+
function O() {
|
|
16
|
+
const e = w(), c = o(
|
|
17
|
+
(t, r, n) => {
|
|
18
|
+
e.trackEvent(t, r, n);
|
|
19
|
+
},
|
|
20
|
+
[e]
|
|
21
|
+
), a = o(
|
|
22
|
+
(t, r) => {
|
|
23
|
+
e.trackError(t, r);
|
|
24
|
+
},
|
|
25
|
+
[e]
|
|
26
|
+
), u = o(
|
|
27
|
+
(t, r) => e.startSpan(t, r),
|
|
28
|
+
[e]
|
|
29
|
+
), i = o(
|
|
30
|
+
(t, r, n) => e.counter(t, r, n),
|
|
31
|
+
[e]
|
|
32
|
+
), l = o(
|
|
33
|
+
(t, r, n) => e.gauge(t, r, n),
|
|
34
|
+
[e]
|
|
35
|
+
), p = o(
|
|
36
|
+
(t, r, n) => e.histogram(t, r, n),
|
|
37
|
+
[e]
|
|
38
|
+
), f = o(
|
|
39
|
+
(t, r, n) => e.upDownCounter(t, r, n),
|
|
40
|
+
[e]
|
|
41
|
+
), m = o(
|
|
42
|
+
(t, r, n) => e.withSpan(t, r, n),
|
|
43
|
+
[e]
|
|
44
|
+
);
|
|
45
|
+
return d(
|
|
46
|
+
() => ({ trackEvent: c, trackError: a, startSpan: u, withSpan: m, counter: i, gauge: l, histogram: p, upDownCounter: f }),
|
|
47
|
+
[c, a, u, m, i, l, p, f]
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
h as __resetTelemetryWarningForTests,
|
|
52
|
+
w as useTelemetryClient,
|
|
53
|
+
O as useTetraEvents
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=use-tetra-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-tetra-events.js","sources":["../../src/telemetry/use-tetra-events.ts"],"sourcesContent":["import { useCallback, useContext, useMemo } from \"react\";\n\nimport { TelemetryContext } from \"./context\";\nimport { NOOP_TELEMETRY } from \"./facade\";\n\nimport type { TetraEvents } from \"./types\";\nimport type { StartSpanOptions, Telemetry, TetraSpan, TrackErrorContext } from \"@tetrascience-npm/request/telemetry\";\n\nlet warned = false;\n\n/**\n * Outside a provider the hook no-ops with one development warning rather than\n * throwing. Rationale: the core's contract is that telemetry never throws into\n * application code — a missing provider is an instrumentation defect, and\n * crashing a customer's app over it inverts the risk. The warning (dev only,\n * once per module instance) keeps the mistake visible during development and\n * is asserted in tests.\n */\nfunction warnOnce(): void {\n if (warned) return;\n warned = true;\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\") return;\n\n console.warn(\"[telemetry] useTetraEvents() called outside <TelemetryProvider> — events are dropped.\");\n}\n\n/** @internal test seam: reset the once-per-module warning latch. */\nexport function __resetTelemetryWarningForTests(): void {\n warned = false;\n}\n\n/** Access the raw context client — e.g. to wire {@link installGlobalErrorHandlers}. */\nexport function useTelemetryClient(): Telemetry {\n const client = useContext(TelemetryContext);\n if (!client) warnOnce();\n return client ?? NOOP_TELEMETRY;\n}\n\n/**\n * The app-facing emitters, bound to the provider's client.\n *\n * Identities are stable for the provider's lifetime (the context value is a\n * stable façade), so these are safe as effect dependencies.\n *\n * @example\n * ```tsx\n * const {trackEvent} = useTetraEvents();\n * trackEvent('Sandbox:Chat:Submit', {model});\n * ```\n */\nexport function useTetraEvents(): TetraEvents {\n const client = useTelemetryClient();\n\n const trackEvent = useCallback(\n (name: string, attributes?: Record<string, unknown>, body?: unknown) => {\n client.trackEvent(name, attributes, body);\n },\n [client],\n );\n\n const trackError = useCallback(\n (error: unknown, context?: TrackErrorContext) => {\n client.trackError(error, context);\n },\n [client],\n );\n\n // SW-2478. Every method here delegates to the core rather than\n // re-implementing anything, so React and non-React consumers cannot drift.\n const startSpan = useCallback(\n (name: string, options?: StartSpanOptions) => client.startSpan(name, options),\n [client],\n );\n\n // SW-2478 metrics. Same delegation rule as startSpan: the\n // instrument caching, the value guards and the publishable-name warning all\n // live in the core client, so re-implementing any of it here would give\n // React apps different behaviour from Node ones for the same call.\n const counter = useCallback(\n (name: string, delta?: number, attributes?: Record<string, unknown>) => client.counter(name, delta, attributes),\n [client],\n );\n\n const gauge = useCallback(\n (name: string, value: number, attributes?: Record<string, unknown>) => client.gauge(name, value, attributes),\n [client],\n );\n\n const histogram = useCallback(\n (name: string, value: number, attributes?: Record<string, unknown>) => client.histogram(name, value, attributes),\n [client],\n );\n\n const upDownCounter = useCallback(\n (name: string, delta: number, attributes?: Record<string, unknown>) =>\n client.upDownCounter(name, delta, attributes),\n [client],\n );\n\n const withSpan = useCallback(\n <T>(name: string, fn: (span: TetraSpan) => T, options?: StartSpanOptions) => client.withSpan(name, fn, options),\n [client],\n );\n\n return useMemo(\n () => ({ trackEvent, trackError, startSpan, withSpan, counter, gauge, histogram, upDownCounter }),\n [trackEvent, trackError, startSpan, withSpan, counter, gauge, histogram, upDownCounter],\n );\n}\n"],"names":["warned","warnOnce","__resetTelemetryWarningForTests","useTelemetryClient","client","useContext","TelemetryContext","NOOP_TELEMETRY","useTetraEvents","trackEvent","useCallback","name","attributes","body","trackError","error","context","startSpan","options","counter","delta","gauge","value","histogram","upDownCounter","withSpan","fn","useMemo"],"mappings":";;;AAQA,IAAIA,IAAS;AAUb,SAASC,IAAiB;AACxB,EAAID,MACJA,IAAS,IACL,SAAO,UAAY,OAAe,QAAQ,KAAK,aAAa,iBAEhE,QAAQ,KAAK,uFAAuF;AACtG;AAGO,SAASE,IAAwC;AACtD,EAAAF,IAAS;AACX;AAGO,SAASG,IAAgC;AAC9C,QAAMC,IAASC,EAAWC,CAAgB;AAC1C,SAAKF,KAAQH,EAAA,GACNG,KAAUG;AACnB;AAcO,SAASC,IAA8B;AAC5C,QAAMJ,IAASD,EAAA,GAETM,IAAaC;AAAA,IACjB,CAACC,GAAcC,GAAsCC,MAAmB;AACtE,MAAAT,EAAO,WAAWO,GAAMC,GAAYC,CAAI;AAAA,IAC1C;AAAA,IACA,CAACT,CAAM;AAAA,EAAA,GAGHU,IAAaJ;AAAA,IACjB,CAACK,GAAgBC,MAAgC;AAC/C,MAAAZ,EAAO,WAAWW,GAAOC,CAAO;AAAA,IAClC;AAAA,IACA,CAACZ,CAAM;AAAA,EAAA,GAKHa,IAAYP;AAAA,IAChB,CAACC,GAAcO,MAA+Bd,EAAO,UAAUO,GAAMO,CAAO;AAAA,IAC5E,CAACd,CAAM;AAAA,EAAA,GAOHe,IAAUT;AAAA,IACd,CAACC,GAAcS,GAAgBR,MAAyCR,EAAO,QAAQO,GAAMS,GAAOR,CAAU;AAAA,IAC9G,CAACR,CAAM;AAAA,EAAA,GAGHiB,IAAQX;AAAA,IACZ,CAACC,GAAcW,GAAeV,MAAyCR,EAAO,MAAMO,GAAMW,GAAOV,CAAU;AAAA,IAC3G,CAACR,CAAM;AAAA,EAAA,GAGHmB,IAAYb;AAAA,IAChB,CAACC,GAAcW,GAAeV,MAAyCR,EAAO,UAAUO,GAAMW,GAAOV,CAAU;AAAA,IAC/G,CAACR,CAAM;AAAA,EAAA,GAGHoB,IAAgBd;AAAA,IACpB,CAACC,GAAcS,GAAeR,MAC5BR,EAAO,cAAcO,GAAMS,GAAOR,CAAU;AAAA,IAC9C,CAACR,CAAM;AAAA,EAAA,GAGHqB,IAAWf;AAAA,IACf,CAAIC,GAAce,GAA4BR,MAA+Bd,EAAO,SAASO,GAAMe,GAAIR,CAAO;AAAA,IAC9G,CAACd,CAAM;AAAA,EAAA;AAGT,SAAOuB;AAAA,IACL,OAAO,EAAE,YAAAlB,GAAY,YAAAK,GAAY,WAAAG,GAAW,UAAAQ,GAAU,SAAAN,GAAS,OAAAE,GAAO,WAAAE,GAAW,eAAAC;IACjF,CAACf,GAAYK,GAAYG,GAAWQ,GAAUN,GAASE,GAAOE,GAAWC,CAAa;AAAA,EAAA;AAE1F;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./telemetry/events.cjs"),n=require("./telemetry/context.cjs"),a=require("./telemetry/facade.cjs"),r=require("./telemetry/telemetry-provider.cjs"),t=require("./telemetry/use-tetra-events.cjs"),s=require("./telemetry/error-boundary.cjs"),T=require("./telemetry/global-handlers.cjs"),l=require("@tetrascience-npm/request/telemetry");exports.MAX_COMPONENT_STACK_LENGTH=o.MAX_COMPONENT_STACK_LENGTH;exports.TelemetryEvent=o.TelemetryEvent;exports.TelemetryContext=n.TelemetryContext;exports.NOOP_TELEMETRY=a.NOOP_TELEMETRY;exports.createTelemetryFacade=a.createTelemetryFacade;exports.TelemetryProvider=r.TelemetryProvider;exports.readHostFlag=r.readHostFlag;exports.resolveArtifact=r.resolveArtifact;exports.__resetTelemetryWarningForTests=t.__resetTelemetryWarningForTests;exports.useTelemetryClient=t.useTelemetryClient;exports.useTetraEvents=t.useTetraEvents;exports.TSErrorBoundary=s.TSErrorBoundary;exports.installGlobalErrorHandlers=T.installGlobalErrorHandlers;Object.keys(l).forEach(e=>{e!=="default"&&!Object.prototype.hasOwnProperty.call(exports,e)&&Object.defineProperty(exports,e,{enumerable:!0,get:()=>l[e]})});
|
|
2
|
+
//# sourceMappingURL=telemetry.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { MAX_COMPONENT_STACK_LENGTH as t, TelemetryEvent as o } from "./telemetry/events.js";
|
|
2
|
+
import { TelemetryContext as m } from "./telemetry/context.js";
|
|
3
|
+
import { NOOP_TELEMETRY as a, createTelemetryFacade as s } from "./telemetry/facade.js";
|
|
4
|
+
import { TelemetryProvider as n, readHostFlag as x, resolveArtifact as E } from "./telemetry/telemetry-provider.js";
|
|
5
|
+
import { __resetTelemetryWarningForTests as y, useTelemetryClient as _, useTetraEvents as d } from "./telemetry/use-tetra-events.js";
|
|
6
|
+
import { TSErrorBoundary as v } from "./telemetry/error-boundary.js";
|
|
7
|
+
import { installGlobalErrorHandlers as N } from "./telemetry/global-handlers.js";
|
|
8
|
+
export * from "@tetrascience-npm/request/telemetry";
|
|
9
|
+
export {
|
|
10
|
+
t as MAX_COMPONENT_STACK_LENGTH,
|
|
11
|
+
a as NOOP_TELEMETRY,
|
|
12
|
+
v as TSErrorBoundary,
|
|
13
|
+
m as TelemetryContext,
|
|
14
|
+
o as TelemetryEvent,
|
|
15
|
+
n as TelemetryProvider,
|
|
16
|
+
y as __resetTelemetryWarningForTests,
|
|
17
|
+
s as createTelemetryFacade,
|
|
18
|
+
N as installGlobalErrorHandlers,
|
|
19
|
+
x as readHostFlag,
|
|
20
|
+
E as resolveArtifact,
|
|
21
|
+
_ as useTelemetryClient,
|
|
22
|
+
d as useTetraEvents
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tetrascience-npm/tetrascience-react-ui",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.136.1",
|
|
4
4
|
"description": "TetraScience React UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "TetraScience",
|
|
@@ -30,6 +30,16 @@
|
|
|
30
30
|
"default": "./dist/index.cjs"
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
|
+
"./telemetry": {
|
|
34
|
+
"import": {
|
|
35
|
+
"types": "./dist/telemetry/index.d.ts",
|
|
36
|
+
"default": "./dist/telemetry.js"
|
|
37
|
+
},
|
|
38
|
+
"require": {
|
|
39
|
+
"types": "./dist/telemetry/index.d.ts",
|
|
40
|
+
"default": "./dist/telemetry.cjs"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
33
43
|
"./server": {
|
|
34
44
|
"import": {
|
|
35
45
|
"types": "./dist/server/index.d.ts",
|
|
@@ -200,7 +210,9 @@
|
|
|
200
210
|
"lint:fix": "eslint . --fix --max-warnings 0",
|
|
201
211
|
"typecheck": "tsc --noEmit",
|
|
202
212
|
"format": "prettier --write .",
|
|
203
|
-
"format:check": "prettier --check ."
|
|
213
|
+
"format:check": "prettier --check .",
|
|
214
|
+
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
215
|
+
"typecheck:e2e": "tsc --noEmit -p tsconfig.e2e.json"
|
|
204
216
|
},
|
|
205
217
|
"dependencies": {
|
|
206
218
|
"@aws-sdk/client-cloudwatch-logs": ">=3.0.0 <4.0.0",
|
|
@@ -250,6 +262,7 @@
|
|
|
250
262
|
"@rdkit/rdkit": "2025.3.4-1.0.0",
|
|
251
263
|
"@streamdown/math": "^1.0.2",
|
|
252
264
|
"@streamdown/mermaid": "^1.0.2",
|
|
265
|
+
"@tetrascience-npm/request": ">=0.4.0",
|
|
253
266
|
"plotly.js-dist": "^2.35.2",
|
|
254
267
|
"react": "^19.0.0",
|
|
255
268
|
"react-dom": "^19.0.0",
|
|
@@ -280,6 +293,9 @@
|
|
|
280
293
|
},
|
|
281
294
|
"devDependencies": {
|
|
282
295
|
"@aws-sdk/client-athena": "^3.975.0",
|
|
296
|
+
"@aws-sdk/client-cloudwatch": "^3.699.0",
|
|
297
|
+
"@aws-sdk/client-cloudwatch-logs": "^3.699.0",
|
|
298
|
+
"@aws-sdk/client-ssm": "^3.699.0",
|
|
283
299
|
"@commitlint/cli": "^20.5.0",
|
|
284
300
|
"@commitlint/config-conventional": "^20.5.0",
|
|
285
301
|
"@databricks/sql": "^1.12.0",
|
|
@@ -303,6 +319,7 @@
|
|
|
303
319
|
"@streamdown/math": "^1.0.2",
|
|
304
320
|
"@streamdown/mermaid": "^1.0.2",
|
|
305
321
|
"@tailwindcss/vite": "^4.2.2",
|
|
322
|
+
"@tetrascience-npm/request": "0.4.0",
|
|
306
323
|
"@types/eslint-plugin-jsx-a11y": "^6",
|
|
307
324
|
"@types/jsdom": "^27",
|
|
308
325
|
"@types/node": "^25.3.3",
|