@kortyx/usage-telemetry 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.0](https://github.com/kortyx-io/kortyx/compare/usage-telemetry-v0.3.0...usage-telemetry-v0.4.0) (2026-10-16)
4
+
5
+
6
+ ### Features
7
+
8
+ * **studio:** standardize tables, filters and column behavior ([#353](https://github.com/kortyx-io/kortyx/issues/353)) ([c662e59](https://github.com/kortyx-io/kortyx/commit/c662e59d814a6a9f12c709595968ee7b1ece3191))
9
+ * **telemetry:** improve failure classification and add CLI usage ([#355](https://github.com/kortyx-io/kortyx/issues/355)) ([c5fbbed](https://github.com/kortyx-io/kortyx/commit/c5fbbed3064ea7b2b3020617db7ce09d1b175db3))
10
+
3
11
  ## [0.3.0](https://github.com/kortyx-io/kortyx/compare/usage-telemetry-v0.2.0...usage-telemetry-v0.3.0) (2026-10-13)
4
12
 
5
13
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Kortyx usage telemetry
2
2
 
3
- Maintainer usage telemetry measures adoption and reliability of the SDK and OSS Studio. It is separate from customer observability in `@kortyx/telemetry` and `@kortyx/otel`. The default destination is Kortyx's EU PostHog Production project, using its public capture key. Consumers need no personal API token.
3
+ Maintainer usage telemetry measures adoption and reliability of the SDK, CLI and OSS Studio. It is separate from customer observability in `@kortyx/telemetry` and `@kortyx/otel`. The default destination is Kortyx's EU PostHog Production project, using its public capture key. Consumers need no personal API token.
4
4
 
5
5
  ## Controls
6
6
 
@@ -14,6 +14,7 @@ Set these in the SDK process or Studio deployment environment. CLI-generated Com
14
14
  | `KORTYX_USAGE_TELEMETRY_POSTHOG_HOST` | Overrides the ingestion host; defaults to `https://eu.i.posthog.com` |
15
15
  | `KORTYX_USAGE_TELEMETRY_ENDPOINT` | Replaces PostHog with a collector accepting `{ identity, records }` |
16
16
  | `KORTYX_USAGE_TELEMETRY_ENVIRONMENT=staging` | Labels maintainer staging; pair it with that project's capture key |
17
+ | `KORTYX_USAGE_TELEMETRY_TRAFFIC_SOURCE` | Explicit `internal`, `synthetic` or `external` cohort; otherwise `unknown`. CI does not imply synthetic traffic |
17
18
  | `KORTYX_USAGE_TELEMETRY_ID` | Optional random UUID for deliberate identity sharing between Node processes |
18
19
 
19
20
  Tests (`NODE_ENV=test`) disable the default Node integration. Consumer `NODE_ENV` and `CI` supply a coarse runtime mode; they do not select the maintainer project. Browser bootstrap receives only public configuration from Studio's server environment, so no `NEXT_PUBLIC_` variables are needed. Debug output contains approved dimensions and aggregate counts, never application payloads.
@@ -30,7 +31,7 @@ Records aggregate matching operations, outcomes and approved dimensions over a 6
30
31
 
31
32
  Each component client buffers at most 64 distinct groups and sends at most 120 groups per hour. A group can represent many attempts through `count`. Duration buckets are noncumulative: ≤10ms, (10,100], (100,1,000], (1,000,10,000], (10,000,60,000], >60,000ms. Query `duration_total_ms / count` for means or combine bucket counts for approximate distributions. Restrict latency queries to `usage.operation`.
32
33
 
33
- Delivery is best effort, single-flight, with a two-second transport timeout, no retries and unreferenced Node timers. SDK operations never await analytics delivery or change results because collection fails. The short-lived Studio setup CLI flushes after recording its outcome, so it can spend up to the transport timeout delivering its final batch. Browser visibility changes request a flush. Offline, disabled, terminated or short-lived processes can lose records; call the helper's `flush()` explicitly at an application-controlled shutdown boundary when appropriate. No disk event queue or crash detection is implied. `stats()` exposes local pending/dropped/delivered group counts. Budgets are per component and process, not an organization-wide spending guarantee; PostHog's $0 billing limits remain the financial control.
34
+ Delivery is best effort, single-flight, with a two-second transport timeout, no retries and unreferenced Node timers. SDK operations never await analytics delivery or change results because collection fails. The CLI flushes registered component clients after command parsing/execution, waiting at most two seconds even for a custom transport. Setup stages and command invocations are separate measurements. Browser visibility changes request a flush. Offline, disabled, terminated or short-lived processes can lose records; call the helper's `flush()` explicitly at an application-controlled shutdown boundary when appropriate. No disk event queue or crash detection is implied. `stats()` exposes local pending/dropped/delivered group counts. Budgets are per component and process, not an organization-wide spending guarantee; PostHog's $0 billing limits remain the financial control.
34
35
 
35
36
  ## Reusable boundaries
36
37
 
@@ -78,12 +79,93 @@ aggregation and failure-independent delivery apply unchanged.
78
79
 
79
80
  SDK boundaries include initialization, registry resolution, direct execution/resume, chat admission, terminal graph execution, response completion, model and tool execution, structured output, explicit response completion, prompt resolution, eval outcomes, MCP connection/discovery/close, checkpoint operations and observability export attempts. Early response completion and later graph failure are separate outcomes. An eval quality failure is distinct from an execution error.
80
81
 
81
- Studio boundaries include CLI setup, API requests/ingest, server reads and parse failures, first-use guidance and observed data, navigation, tab/trace inspection, render failures/retries, prompt actions, eval launch/read/cancel and live refresh/reconnect. Prompt and eval browser actions measure request acceptance; they do not imply background worker completion. Some preflight errors before a selected boundary remain outside this slice.
82
+ Studio boundaries include CLI setup, API requests/ingest, server reads and parse failures, first-use guidance and observed data, navigation, tab/trace inspection, render failures/retries, prompt actions, eval launch/read/cancel and live refresh/reconnect. Prompt and eval browser actions measure request acceptance. The built-in eval worker separately measures persisted terminal results; its attempt and legacy run units are described below. SDK eval configuration rejection is included with phase `configuration`.
82
83
 
83
- The [opportunity inventory](../../docs/audits/sdk-studio-usage-telemetry.md) covers remaining node/parallel/child execution, prompt cache/refresh, persistence internals, exporter queue loss, deeper filters/saved views, worker completion, reviews and upgrade phases. Reserved catalog operations are not evidence that these boundaries already emit. Feature-flag evaluation and exposure are a future addition.
84
+ The [opportunity inventory](../../docs/audits/sdk-studio-usage-telemetry.md) covers remaining node/parallel/child execution, prompt cache/refresh, persistence internals, exporter queue loss, deeper filters/saved views, deeper worker phases, reviews and upgrade phases. Reserved catalog operations are not evidence that these boundaries already emit. Feature-flag evaluation and exposure are a future addition.
84
85
 
85
86
  Use `sum(properties.count)`, rather than raw PostHog event count, to measure attempts. For a comparable component/operation cohort, failure rate is `sum(count where outcome = failed) / sum(count for completed operation outcomes)`. Decide explicitly whether cancellations, denial and suspension belong in the denominator. Compare installation reach, repeated use and failure rate by release; do not rank features solely by workload volume. PostHog funnels over aggregates give coarse observed ordering (flush windows can obscure exact ordering), not exact user-session sequences or time since npm installation.
86
87
 
88
+ ## Measurement quality (version 2)
89
+
90
+ The envelope remains `schema_version: 1`; additive approved properties carry
91
+ `measurement_version: "2"`. Historical events without it retain their old coverage.
92
+ Compare matching measurement versions, release, component, operation, origin,
93
+ action, analytics environment and runtime mode. Never add up all SDK operations
94
+ as workflow executions.
95
+
96
+ | Unit (`measurement_kind`) | Counting boundary |
97
+ | --- | --- |
98
+ | `invocation` | One CLI command parse/action outcome or SDK eval `run()` call, including rejected configuration |
99
+ | `execution` | SDK terminal graph execution; persisted legacy worker suite run |
100
+ | `attempt` | Each model/export send attempt; each claimed eval worker case/repetition attempt |
101
+ | `chunk`, `output`, `update` | Structured text deltas, final output, other updates; workload volume, not feature adoption |
102
+ | `stage` | A Studio setup phase, separate from CLI command completion |
103
+ | `poll` | Background Studio reads, including diagnostic prefetch; not deliberate inspection |
104
+ | `request`, `call` | Studio request or other SDK API call outcome |
105
+ | `feature`, `observation` | Deliberate/configured use versus server/background observation |
106
+
107
+ `runtime_mode` uses Node `CI` / `NODE_ENV`, independently of the destination
108
+ project. Node factories and Studio browser bootstrap carry the same safe context.
109
+ `traffic_source` is explicit: `unknown` is not evidence of external customer use.
110
+ Pseudonymous installation/browser/process reach is not a count of customers.
111
+
112
+ Failures always have an approved `error_code` and `error_category`. Unclassified
113
+ explicit failures use `UNCLASSIFIED_FAILURE`; inspected unknown errors use `other`.
114
+ The classifier reads at most eight objects, three links deep, following own data
115
+ fields `failure`, `cause`, and `error`. Known network codes, HTTP classes, framework
116
+ failure descriptors and optional bounded `cause_code`/`cause_category`/`retryable`
117
+ help distinguish provider, transport, validation and configuration problems. Eval
118
+ failures also project the first issue's approved `eval_phase`; multiple issues in
119
+ one run are not a complete failure census.
120
+ Messages, stacks, diagnostic IDs and exception serialization remain excluded.
121
+ Cancellation, suspension, limits, eval quality failures and ungraded outcomes stay
122
+ separate from technical failures. A known category is not proof of a product bug.
123
+
124
+ Exporter records add bucketed `batch_size`, `retry_attempt`, `retried` and
125
+ `recovered`. Recovery means a successful send after a retry, not a correlated
126
+ end-to-end delivery guarantee. Recursive split sends are separate attempts.
127
+
128
+ Each successful normal delivery may carry `usage_dropped_observations` and
129
+ `usage_failed_batches` once, as deltas since the last delivered health snapshot.
130
+ They include cardinality/budget losses and identity/transport failures; local
131
+ `stats().dropped` still counts groups. Health never bypasses budgets, creates its
132
+ own event, or persists on disk. Permanently offline, crashed, disabled or restarted
133
+ processes cannot report their lost tail. These counters expose observed loss;
134
+ they cannot reconstruct unbiased feature shares after selective group dropping.
135
+ A failed or ambiguous delivery may have reached ingestion: these counters describe
136
+ client-observed loss, not verified server loss.
137
+
138
+ ## Eval and diagnostic boundaries
139
+
140
+ Eval launch/settings requests record only booleans for explicit settings and
141
+ case/run deadline overrides. The SDK `sdk.eval` boundary reports configuration
142
+ rejections and safe execution failure codes. Neither timeout values nor judge,
143
+ suite, case, input, criteria or output identities are usage dimensions.
144
+
145
+ The built-in worker emits `studio.eval.execution` only **after** `store.finish`
146
+ persists a result. A claimed case/repetition uses `attempt`; a legacy suite run
147
+ uses `execution`. Cancellation, technical failure, quality failure, ungraded and
148
+ success are separate. Lease loss, process shutdown and a failed persistence write
149
+ do not imply completion. Retries/reclaims may execute again; no global deduplication
150
+ or evaluation-level completion funnel is promised.
151
+
152
+ A custom `EvalJobStore` keeps instrumentation ownership by default. Embedders may
153
+ supply `EvalWorkerOptions.usage` to opt in, or `false` to disable worker emission.
154
+ Choose one owner: either the existing store wrapper or this injected helper.
155
+ Use the same replacement catalog in its helper. Existing custom store adapters do
156
+ not acquire a second public emitter when upgraded. The dispatcher also accepts
157
+ `usage` / `false`; the worker forwards the chosen client or disables dispatch
158
+ collection for a custom store. Retry observations use `origin=server` and are
159
+ separate from terminal results. Standalone dispatcher defaults use component
160
+ `eval_dispatch`, correcting the formerly invalid component spelling.
161
+
162
+ Studio emits a `studio.diagnostic` feature on deliberate error-detail inspection,
163
+ and separately records background diagnostic reads and their failures. Shared table controls emit bounded
164
+ `studio.table.layout` interaction actions, including resize initiation, without
165
+ column names, sizes or saved layout content. Neither
166
+ path sends the displayed error content. Customer-authenticated diagnostic storage
167
+ continues to serve original errors independently.
168
+
87
169
  ## Proposal: replace direct capture with a Kortyx collector
88
170
 
89
171
  Keep direct EU capture for this slice. A later collector can accept the existing versioned record envelope, validate the catalog again, cap body/group/count sizes, rate-limit installations and total daily ingestion, deduplicate `event_id`, strip network metadata, and route approved releases to the intended PostHog project. Keep retention and operational logs bounded and avoid logging request bodies. Forward asynchronously with its own retry/deduplication policy.
@@ -1,16 +1,24 @@
1
- import { U as UsageTelemetry, a as UsageOptions } from './client-rVwo4XAO.js';
2
- export { c as createUsageTelemetry, s as scale } from './client-rVwo4XAO.js';
1
+ import { U as UsageTelemetry, a as UsageOptions } from './client-BPjAx5oh.js';
2
+ export { c as createUsageTelemetry, s as scale } from './client-BPjAx5oh.js';
3
3
 
4
+ /** Flush registered component replacements without adding another emitter. */
5
+ declare function flushUsageTelemetry(): Promise<void>;
4
6
  declare function createNodeUsageTelemetry(options: Pick<UsageOptions, "context"> & Partial<Omit<UsageOptions, "context">>): UsageTelemetry;
5
7
  declare function configureUsageTelemetry(component: string, client: UsageTelemetry): void;
6
8
  declare function getUsageTelemetry(component: string, version?: string, product?: string): UsageTelemetry;
7
9
  declare function usageDisabled(): boolean;
10
+ declare function runtimeUsageContext(): {
11
+ runtimeMode: "unknown";
12
+ trafficSource: "unknown";
13
+ };
8
14
  declare function publicUsageConfiguration(): {
9
15
  enabled: boolean;
16
+ runtimeMode: "unknown";
17
+ trafficSource: "unknown";
10
18
  debug: boolean;
11
19
  environment: "production";
12
20
  key: string;
13
21
  host: string;
14
22
  };
15
23
 
16
- export { UsageTelemetry, configureUsageTelemetry, createNodeUsageTelemetry, getUsageTelemetry, publicUsageConfiguration, usageDisabled };
24
+ export { UsageTelemetry, configureUsageTelemetry, createNodeUsageTelemetry, flushUsageTelemetry, getUsageTelemetry, publicUsageConfiguration, runtimeUsageContext, usageDisabled };