@syntrologie/runtime-sdk 2.17.0 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,40 @@
1
+ import type { CounterSignal, HealthReporterConfig, HistogramSignal, ReporterRuntimeBinding } from './types';
2
+ export declare class HealthReporter {
3
+ private readonly config;
4
+ private readonly resource;
5
+ private readonly flushIntervalMs;
6
+ private readonly counters;
7
+ private readonly histograms;
8
+ private windowStartMs;
9
+ private timer;
10
+ private pagehideHandler;
11
+ private runtime;
12
+ constructor(config: HealthReporterConfig);
13
+ /**
14
+ * Bind runtime-derived attribute resolvers. Called after the canvas/telemetry
15
+ * are fully initialized. Must never throw — resolvers are wrapped in
16
+ * null-safe access at flush time.
17
+ */
18
+ bindRuntime(binding: ReporterRuntimeBinding): void;
19
+ increment(signal: CounterSignal, by?: number): void;
20
+ /**
21
+ * @internal — exposed for test inspection only. Mid-window state is intentionally
22
+ * unstable; consumers should subscribe to flush payloads instead.
23
+ */
24
+ snapshotCounters(): Partial<Record<CounterSignal, number>>;
25
+ recordHistogram(signal: HistogramSignal, valueMs: number): void;
26
+ /**
27
+ * @internal — exposed for test inspection only. Mid-window state is intentionally
28
+ * unstable; consumers should subscribe to flush payloads instead.
29
+ */
30
+ snapshotHistograms(): Partial<Record<HistogramSignal, {
31
+ count: number;
32
+ p50: number;
33
+ p95: number;
34
+ }>>;
35
+ flush(): Promise<void>;
36
+ start(): void;
37
+ stop(): void;
38
+ }
39
+ export declare function initHealthReporter(config: HealthReporterConfig): HealthReporter;
40
+ export declare function getHealthReporter(): HealthReporter | null;
@@ -0,0 +1,3 @@
1
+ export { getHealthReporter, HealthReporter, initHealthReporter } from './healthReporter';
2
+ export { createOtlpEmitter } from './otlpEmitter';
3
+ export type { CounterSignal, FlushPayload, HealthReporterConfig, HistogramSignal, ReporterResource, } from './types';
@@ -0,0 +1,39 @@
1
+ import type { FlushPayload } from './types';
2
+ interface AnyValue {
3
+ stringValue?: string;
4
+ intValue?: number;
5
+ doubleValue?: number;
6
+ }
7
+ interface KV {
8
+ key: string;
9
+ value: AnyValue;
10
+ }
11
+ interface OtlpEnvelope {
12
+ resourceLogs: Array<{
13
+ resource: {
14
+ attributes: KV[];
15
+ };
16
+ scopeLogs: Array<{
17
+ scope: {
18
+ name: string;
19
+ };
20
+ logRecords: Array<{
21
+ timeUnixNano: string;
22
+ observedTimeUnixNano: string;
23
+ severityText: 'INFO';
24
+ body: AnyValue;
25
+ attributes: KV[];
26
+ }>;
27
+ }>;
28
+ }>;
29
+ }
30
+ /**
31
+ * @internal — exposed for unit testing only. Production code should use createOtlpEmitter.
32
+ */
33
+ export declare function buildOtlpPayload(flush: FlushPayload): OtlpEnvelope;
34
+ export interface OtlpEmitterConfig {
35
+ endpoint: string;
36
+ fetchImpl?: typeof fetch;
37
+ }
38
+ export declare function createOtlpEmitter(cfg: OtlpEmitterConfig): (p: FlushPayload) => Promise<void>;
39
+ export {};
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Names of signals the SDK emits. Add new entries as the taxonomy grows.
3
+ * Counter signals are unbounded integers; histogram signals are millisecond floats.
4
+ */
5
+ export type CounterSignal = 'bootstrap_ok' | 'bootstrap_errors' | 'flag_fetch_count' | 'flag_fetch_errors';
6
+ export type HistogramSignal = 'flag_fetch_latency_ms';
7
+ /**
8
+ * Resource attributes for the OTLP payload. The static fields are set at
9
+ * reporter init; the dynamic fields are resolved at flush time via runtime
10
+ * binding (see HealthReporter.bindRuntime).
11
+ */
12
+ export interface ReporterResource {
13
+ serviceName: 'syntro-runtime-sdk';
14
+ serviceVersion: string;
15
+ /** Customer's PostHog project SDK key. Identifies which PostHog project
16
+ * this telemetry corresponds to. The exporter joins on this. */
17
+ posthogKey: string;
18
+ /** Page origin where the SDK booted (e.g. https://customer.com). */
19
+ hostOrigin: string;
20
+ }
21
+ /**
22
+ * Runtime-derived attributes resolved at flush time. The HealthReporter
23
+ * binds resolvers via bindRuntime() once the canvas/telemetry are ready.
24
+ * Before bindRuntime is called, defaults apply.
25
+ */
26
+ export interface ReporterRuntimeBinding {
27
+ /** PostHog session ID. Returns empty string before telemetry is ready. */
28
+ getSessionId(): string;
29
+ /** Surface context snapshot. Returns null before context is ready. */
30
+ getSurface(): {
31
+ type: 'web' | 'telegram' | 'mcp-app';
32
+ host: string;
33
+ device: 'mobile' | 'tablet' | 'desktop';
34
+ mode: 'agent' | 'mobile' | 'desktop';
35
+ } | null;
36
+ }
37
+ /**
38
+ * In-memory aggregate produced at flush time. Resource is the snapshot
39
+ * of static + runtime-bound fields at flush moment.
40
+ */
41
+ export interface FlushPayload {
42
+ resource: ReporterResource & {
43
+ sessionId: string;
44
+ surfaceType: 'web' | 'telegram' | 'mcp-app' | 'unknown';
45
+ surfaceHost: string;
46
+ surfaceDevice: 'mobile' | 'tablet' | 'desktop' | 'unknown';
47
+ surfaceMode: 'agent' | 'mobile' | 'desktop' | 'unknown';
48
+ };
49
+ windowSeconds: number;
50
+ windowStartUnixMs: number;
51
+ counters: Partial<Record<CounterSignal, number>>;
52
+ /** Histograms expose count, p50, p95 — raw samples are NOT shipped. */
53
+ histograms: Partial<Record<HistogramSignal, {
54
+ count: number;
55
+ p50: number;
56
+ p95: number;
57
+ }>>;
58
+ }
59
+ /** Configuration for the reporter singleton. */
60
+ export interface HealthReporterConfig {
61
+ resource: ReporterResource;
62
+ flushIntervalMs?: number;
63
+ emit: (payload: FlushPayload) => Promise<void>;
64
+ }