@saguiitay/eventhouse-ai-observability 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +125 -18
- package/dist/adapters/openai.d.ts +25 -0
- package/dist/adapters/vercel.d.ts +25 -0
- package/dist/{chunk-XQFUPGYU.js → chunk-XGCHW72B.js} +11 -55
- package/dist/{chunk-XQFUPGYU.js.map → chunk-XGCHW72B.js.map} +1 -1
- package/dist/copilot.js +5 -3
- package/dist/copilot.js.map +1 -1
- package/dist/index.d.ts +1 -6
- package/dist/index.js +3 -11
- package/dist/openai.d.ts +12 -0
- package/dist/openai.js +408 -0
- package/dist/openai.js.map +1 -0
- package/dist/validate.d.ts +2 -0
- package/dist/validate.js +237 -0
- package/dist/validate.js.map +1 -0
- package/dist/validation/fabric.d.ts +29 -0
- package/dist/vercel.d.ts +15 -0
- package/dist/vercel.js +369 -0
- package/dist/vercel.js.map +1 -0
- package/docs/architecture.md +19 -3
- package/docs/copilot-adapter.md +1 -1
- package/docs/extending.md +45 -1
- package/docs/fabric-setup.md +24 -0
- package/docs/implementation-report.md +62 -18
- package/docs/openai-adapter.md +137 -0
- package/docs/quickstart.md +75 -6
- package/docs/research-eventstream.md +8 -6
- package/docs/research.md +1 -1
- package/docs/security.md +1 -1
- package/docs/telemetry-schema.md +18 -0
- package/docs/vercel-adapter.md +201 -0
- package/examples/README.md +75 -6
- package/examples/copilot-basic/package.json +1 -1
- package/examples/openai-basic/env.example +8 -0
- package/examples/openai-basic/index.ts +46 -0
- package/examples/shared.ts +3 -62
- package/examples/telemetry.ts +124 -0
- package/examples/vercel-basic/env.example +8 -0
- package/examples/vercel-basic/index.ts +60 -0
- package/fabric-setup.zip +0 -0
- package/package.json +39 -5
|
@@ -3,18 +3,21 @@
|
|
|
3
3
|
## Delivered
|
|
4
4
|
|
|
5
5
|
A single TypeScript ESM npm package, `@saguiitay/eventhouse-ai-observability`
|
|
6
|
-
(personal project; 0.1.1 published
|
|
7
|
-
|
|
6
|
+
(personal project; 0.1.1 published and registry-verified on GitHub Packages,
|
|
7
|
+
0.1.2 published and registry-verified on npmjs, **0.2.0 prepared but not
|
|
8
|
+
published** in this checkout), with root, `/copilot`, `/openai`, and `/vercel` exports and ordinary internal modules in `src`.
|
|
8
9
|
The former private workspace packages, OTLP wrapper, custom batching queue, and
|
|
9
10
|
declaration-rewriting build step have been removed. OpenTelemetry's
|
|
10
|
-
`BatchSpanProcessor
|
|
11
|
-
|
|
11
|
+
`BatchSpanProcessor` and the standard `SpanExporter` interface replace that
|
|
12
|
+
plumbing. Fabric is the only built-in transport; applications can supply the
|
|
13
|
+
official `OTLPTraceExporter` or another standard exporter themselves.
|
|
12
14
|
|
|
13
|
-
The implementation includes bounded asynchronous batching, parent-based sampling, explicit/ambient trace context, resource attributes, privacy filtering/redaction hooks, diagnostic counters, idempotent flush/shutdown, actual SDK event integration, three
|
|
15
|
+
The implementation includes bounded asynchronous batching, parent-based sampling, explicit/ambient trace context, resource attributes, privacy filtering/redaction hooks, diagnostic counters, idempotent flush/shutdown, actual SDK event integration, five runnable examples (three Copilot, one OpenAI, one Vercel), Fabric schema/mapping/retention assets, analytics queries, native dashboard definitions, provisioning, local receiver tests, benchmarks, and CI.
|
|
14
16
|
|
|
15
17
|
## Install and configure
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
Install the published npmjs package, or build/pack this checkout and install its
|
|
20
|
+
root tarball to evaluate unreleased 0.2.0. The one-call entry point is:
|
|
18
21
|
|
|
19
22
|
```typescript
|
|
20
23
|
const observer = observeCopilot(existingSession, {
|
|
@@ -24,20 +27,33 @@ const observer = observeCopilot(existingSession, {
|
|
|
24
27
|
|
|
25
28
|
Only supply `entityName` if the Fabric source's connection string omits `EntityPath`. Metadata-only capture is the default. Shutdown the observer explicitly without transferring ownership of the session/client. See the [quickstart](quickstart.md) for all options.
|
|
26
29
|
|
|
27
|
-
The repository routes `@saguiitay` packages to GitHub Packages.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
The repository routes `@saguiitay` packages to GitHub Packages. Consumer
|
|
31
|
+
dependency registries remain organization-controlled; private registry
|
|
32
|
+
configuration must not be copied into tracked files or distributed assets.
|
|
33
|
+
Tokens belong in user-level configuration or CI secrets.
|
|
30
34
|
The earlier Azure Artifacts authentication blocker is historical: frozen installs
|
|
31
35
|
and package smoke checks subsequently passed on Node 22/24 and Windows/Linux CI,
|
|
32
36
|
and the operator successfully installed the published package from GitHub Packages
|
|
33
37
|
into the basic example. Packed-artifact smoke tests still reuse project runtime
|
|
34
38
|
dependencies and are not themselves a clean registry install.
|
|
35
39
|
|
|
40
|
+
The prepared 0.2.0 npm tarball includes exactly one generated
|
|
41
|
+
`fabric-setup.zip`, not raw tenant-bound Fabric source files. Install first,
|
|
42
|
+
resolve it beneath `npm root`, and extract its `README.md`, `manifest.json`,
|
|
43
|
+
and `fabric\` tree using the [README commands](../README.md#fabric-setup-bundle-and-ingestion-check).
|
|
44
|
+
Its manifest matches the npm version and records schema/version/hash metadata.
|
|
45
|
+
Public setup distribution uses npm because the source repository stays private;
|
|
46
|
+
GitHub Release ZIPs and Actions artifacts remain collaborator-only alternatives.
|
|
47
|
+
This policy permits only this project's authored generic public-API templates
|
|
48
|
+
and synthetic samples, not Microsoft-private code/docs/configuration, tenant
|
|
49
|
+
content, credentials, real telemetry, or copied external-repository files.
|
|
50
|
+
Fresh neutral generation is required but does not replace provenance review.
|
|
51
|
+
|
|
36
52
|
## Protocol and framework evidence
|
|
37
53
|
|
|
38
54
|
Fabric ingestion uses the **Custom endpoint source's Event Hub producer interface**, through the official Azure Event Hubs client over AMQP/TLS. This is the documented direct-ingestion path and requires neither a separate Event Hubs resource nor a Collector. It is not Eventstream accepting OTLP, nor an outbound custom endpoint destination.
|
|
39
55
|
|
|
40
|
-
The transport emits versioned framework-neutral JSON derived from standard OpenTelemetry spans.
|
|
56
|
+
The transport emits versioned framework-neutral JSON derived from standard OpenTelemetry spans. OTLP support is provided by a caller-supplied official HTTP exporter, not built into this package. See the [producer research](research-eventstream.md), [Copilot event research](research-copilot.md), and [Fabric provisioning/dashboard research](research-fabric.md) for source references.
|
|
41
57
|
|
|
42
58
|
Supported Copilot events are `session.start`/`session.resume`, `assistant.turn_start`/`assistant.turn_end`, `tool.execution_start`/`tool.execution_complete`, `subagent.started`/`subagent.completed`/`subagent.failed`, `assistant.usage`, `model.call_failure`, `user.message`/`assistant.message` (opt-in content), and `abort`/`session.error`/`session.idle`/`session.shutdown`. Request usage remains request-scoped; separate subagent aggregate usage is not added to request totals. Correlation is explicit-only and bounded; unsupported or missing metadata is not invented.
|
|
43
59
|
|
|
@@ -47,12 +63,28 @@ Fabric assets include a schema-validated native **version-75 KQLDashboard** defi
|
|
|
47
63
|
|
|
48
64
|
SDK, adapter, exporter, and Fabric asset tests run in Vitest. The Fabric checks preserve the original fixture analytics, all twenty query contracts, complete native dashboard schema validation, and source/destination routing checks using Ajv. PowerShell handles provisioning/updates and twenty mocked REST scenarios (twelve provisioning, eight updates). See [actual benchmark results](performance.md) for event handling, serialization, memory, throughput, burst pressure, and sustained queue behavior.
|
|
49
65
|
|
|
50
|
-
|
|
51
|
-
including
|
|
66
|
+
The completed local validation passed **194 Vitest tests across 15 files**,
|
|
67
|
+
including SDK adapters and Fabric asset regression suites. The installed development
|
|
52
68
|
dependencies are AJV 8.18.0 and fast-uri 3.1.9, resolving the reported dependency
|
|
53
|
-
advisories.
|
|
54
|
-
|
|
55
|
-
|
|
69
|
+
advisories. Strict typechecking, Prettier, eight Fabric contract tests, and twenty
|
|
70
|
+
mocked REST scenarios (twelve provisioning, eight updates) passed. npm and pnpm
|
|
71
|
+
root build/pack checks, ESM/declaration/CLI smoke checks, optional-peer isolation,
|
|
72
|
+
privacy smoke checks, and neutral versioned standalone ZIP generation also
|
|
73
|
+
passed locally. Repeated real root pnpm and npm packs regenerated identical
|
|
74
|
+
setup ZIP bytes; packed inventory, bindings, synthetic samples, version, and
|
|
75
|
+
per-file SHA-256 checks passed on both tarballs. The standalone ZIP matched the
|
|
76
|
+
package archive byte-for-byte. These completed checks are offline evidence, not a fresh online
|
|
77
|
+
consumer install, public/latest CI, real provider requests, or latest live Fabric.
|
|
78
|
+
The npm-embedded ZIP change additionally passed fifteen focused bundle tests,
|
|
79
|
+
including three repeated isolated fixture npm packs, stale ZIP exclusion,
|
|
80
|
+
neutral bindings, per-file hashes, safe paths, manual no-overwrite behavior,
|
|
81
|
+
and fail-closed content/source checks. The complete generator, three provisioning
|
|
82
|
+
scripts, and bundle README were reviewed: project-authored source, public Fabric
|
|
83
|
+
API/schema references, placeholder endpoints, and synthetic samples only; no
|
|
84
|
+
foreign source was imported. The fixture checks supplement, rather than replace,
|
|
85
|
+
the completed real root npm/pnpm pack and package-smoke validation. Content
|
|
86
|
+
checks cannot independently certify source provenance.
|
|
87
|
+
The original silent-export-failure reproduction rejects
|
|
56
88
|
after full cleanup, reports a sanitized authentication category and failed-export
|
|
57
89
|
counts, and exposes no raw input. The earlier in-memory benchmark completed;
|
|
58
90
|
its deliberate overload cases retain bounded queues and report drops, not
|
|
@@ -64,6 +96,13 @@ guaranteed network throughput.
|
|
|
64
96
|
- Fabric offline checks validate schemas, fixture contracts, query assets, and mocked REST provisioning, including polling and orchestration. These are **not KQL engine execution or dashboard service rendering**.
|
|
65
97
|
- The package builds with tsup plus ordinary TypeScript 7 CLI declaration emission. There are no workspace imports or custom declaration-rewriting steps.
|
|
66
98
|
|
|
99
|
+
Latest observed CI run **43727442386** failed on 287 registry-specific lockfile
|
|
100
|
+
tarball URLs. Those routes were removed without changing versions or integrity
|
|
101
|
+
hashes. A registry-agnostic pnpm hook prevents their regeneration while preserving
|
|
102
|
+
explicit URL dependencies, custom archives, and signed routes. Frozen offline
|
|
103
|
+
installation and three hook regression tests passed. This report does not claim
|
|
104
|
+
that the failing run or subsequent CI has passed.
|
|
105
|
+
|
|
67
106
|
**Live Fabric compatibility: verified for the operator's 0.1.0 deployment on
|
|
68
107
|
2026-11-12.** The operator installed the published package, ran the basic Copilot
|
|
69
108
|
example with Eventstream transport, and reported three generated/acknowledged
|
|
@@ -73,8 +112,9 @@ operator-reported, not a live run performed by the offline suite.
|
|
|
73
112
|
|
|
74
113
|
`tools/live-fabric.ts` remains an explicit opt-in test of producer acceptance,
|
|
75
114
|
ingestion, KQL lookup, and parent-child preservation; its execution has not been
|
|
76
|
-
reported. Automated provisioning, update APIs, all
|
|
77
|
-
assertions, performance at scale, and
|
|
115
|
+
reported. Automated provisioning, update APIs, all five examples as a complete
|
|
116
|
+
set, parent-child assertions, performance at scale, and live runs of 0.1.1,
|
|
117
|
+
0.1.2, and the prepared 0.2.0 remain unverified.
|
|
78
118
|
|
|
79
119
|
## Reliability and limitations
|
|
80
120
|
|
|
@@ -94,8 +134,12 @@ Pattern redaction is defense in depth, not a general PII/secret detector. Conten
|
|
|
94
134
|
|
|
95
135
|
## Required external validation
|
|
96
136
|
|
|
97
|
-
Run CI on Node 22.15+ and 24 for each release. After publishing 0.
|
|
137
|
+
Run CI on Node 22.15+ and 24 for each release. After publishing 0.2.0, reinstall
|
|
98
138
|
the basic example's pinned dependency and repeat live ingestion/dashboard checks.
|
|
139
|
+
Before publication, observe a passing CI run after lockfile remediation and
|
|
140
|
+
complete a fresh consumer installation through an approved registry.
|
|
141
|
+
Publication, uploads, and source-repository visibility changes are outside this
|
|
142
|
+
documentation update.
|
|
99
143
|
Run the opt-in parent-child validation and the remaining examples, and validate
|
|
100
144
|
automated provisioning/updates and interactive KQL performance before claiming
|
|
101
145
|
those additional capabilities as service-verified.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# OpenAI Node SDK adapter
|
|
2
|
+
|
|
3
|
+
The `/openai` entry point observes the official `openai` Node SDK's direct
|
|
4
|
+
`client.chat.completions.create()` and `client.responses.create()` calls.
|
|
5
|
+
The compatibility target is **OpenAI SDK 7.53.0**, Node.js 22.15 or later.
|
|
6
|
+
It uses public SDK APIs, not provider-wide request hooks or application-global
|
|
7
|
+
OpenTelemetry configuration.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import OpenAI from "openai";
|
|
11
|
+
import { observeOpenAI } from "@saguiitay/eventhouse-ai-observability/openai";
|
|
12
|
+
|
|
13
|
+
const sdk = new OpenAI(); // Configure authentication in the application.
|
|
14
|
+
const observer = observeOpenAI(sdk, {
|
|
15
|
+
connectionString: process.env.FABRIC_EVENTSTREAM_CONNECTION_STRING!,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const response = await observer.client.responses.create({
|
|
20
|
+
model: "gpt-4.1-mini",
|
|
21
|
+
input: "Hello",
|
|
22
|
+
});
|
|
23
|
+
console.log(response.output_text);
|
|
24
|
+
} finally {
|
|
25
|
+
await observer.shutdown();
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use the returned `client`. The original client remains uninstrumented and
|
|
30
|
+
unmodified. Endpoint overloads and the client type are preserved; SDK results and
|
|
31
|
+
raw SDK exceptions reach the caller. `then`, `catch`, `finally`, `withResponse`
|
|
32
|
+
and `asResponse` remain available. SDK retries, authentication, request options
|
|
33
|
+
and abort signals are unchanged. Observation never retries requests.
|
|
34
|
+
|
|
35
|
+
## Scope and telemetry
|
|
36
|
+
|
|
37
|
+
Each supported call produces one client span, with `gen_ai.operation.name:
|
|
38
|
+
"chat"` for both APIs, `gen_ai.provider.name: "openai"`, requested/returned model,
|
|
39
|
+
response ID, finite nonnegative input/output token usage when available, finish
|
|
40
|
+
reasons for Chat Completions, and SDK-call-to-completion duration.
|
|
41
|
+
`openai.api` distinguishes `chat.completions` from `responses`.
|
|
42
|
+
|
|
43
|
+
Errors use fixed `error.type` categories and a numeric HTTP status when available.
|
|
44
|
+
Raw exception messages, headers, credentials and endpoint URLs are not captured.
|
|
45
|
+
Failed/incomplete Responses results are returned unchanged and marked as errors.
|
|
46
|
+
Completed request/response failures are failed spans, not incomplete observations.
|
|
47
|
+
`observability.incomplete` is reserved for unfinished work, cancellation/abort,
|
|
48
|
+
incomplete responses/streams, unsupported results, and observer shutdown.
|
|
49
|
+
Background responses that are still queued/in progress are marked incomplete;
|
|
50
|
+
the adapter does not poll them.
|
|
51
|
+
|
|
52
|
+
Other endpoints and SDK helpers (`parse`, `stream`, `runTools`, retrieval,
|
|
53
|
+
pagination, realtime, embeddings, audio, batches, files, and helpers on `beta`)
|
|
54
|
+
are **not intercepted**. A client produced by `withOptions()` must be observed
|
|
55
|
+
separately. Tool execution is not traced. Only direct calls through the returned
|
|
56
|
+
client's two supported `create` methods are observed.
|
|
57
|
+
|
|
58
|
+
## Streaming and promise consumption
|
|
59
|
+
|
|
60
|
+
Supported `create({ stream: true })` calls remain lazy: no background consumer or
|
|
61
|
+
extra tee is created. The public SDK Stream constructor decorates iteration
|
|
62
|
+
without changing the original stream. Async iteration, `controller.abort()`,
|
|
63
|
+
`tee()` and `toReadableStream()` retain SDK behavior. Chunks and SDK errors are
|
|
64
|
+
returned unchanged. The SDK's own `_request_id` property descriptor is preserved
|
|
65
|
+
on decorated streams. Usage is taken from observed chunks/terminal Responses
|
|
66
|
+
events, never estimated. For Chat Completions, request
|
|
67
|
+
`stream_options: { include_usage: true }` if token reporting is needed; the
|
|
68
|
+
adapter does not change request parameters.
|
|
69
|
+
|
|
70
|
+
Stream spans finish once on exhaustion, error, early return, abort or observer
|
|
71
|
+
shutdown. Missing terminal events/finish reasons are marked incomplete.
|
|
72
|
+
Chat streams require every requested choice index to finish, not just the first
|
|
73
|
+
choice. Tracking is bounded to `n` values from 1 to 32; higher/invalid counts
|
|
74
|
+
remain usable but cannot be certified complete and are marked incomplete.
|
|
75
|
+
Duplicate, invalid and out-of-range choice indices do not satisfy completion.
|
|
76
|
+
`flush()` exports ended spans, without consuming or ending live streams.
|
|
77
|
+
`tee()` uses the SDK's own buffers; callers must consume/cancel both branches
|
|
78
|
+
responsibly. The adapter adds no chunk queue.
|
|
79
|
+
|
|
80
|
+
Promises are not eagerly parsed: that would consume bodies intended for
|
|
81
|
+
`asResponse()`. Await or consume a supported promise to observe its result.
|
|
82
|
+
`asResponse()` finishes an HTTP-only observation without reading/cloning its
|
|
83
|
+
body, so token/content telemetry is unavailable on that path. If mixed with
|
|
84
|
+
parsed consumption, the first terminal observation wins. Unconsumed promises
|
|
85
|
+
and streams stay tracked until observer shutdown; they are then marked
|
|
86
|
+
`observability.incomplete` and `openai.lifecycle: "observer_shutdown"`.
|
|
87
|
+
Shutdown does **not** abort application requests/streams, and late results
|
|
88
|
+
continue to reach the caller without reopening spans.
|
|
89
|
+
|
|
90
|
+
## Privacy and bounds
|
|
91
|
+
|
|
92
|
+
Metadata-only is the default. With an engine configured for `captureContent:
|
|
93
|
+
true`, the adapter captures text-only input/output using `gen_ai.input.messages`
|
|
94
|
+
and `gen_ai.output.messages`. The engine sanitizer/redactor applies before any
|
|
95
|
+
exporter sees content. Images, audio, tool arguments/results and arbitrary object
|
|
96
|
+
serialization are excluded. Chat output capture is limited to the first choice.
|
|
97
|
+
Structured text traversal is bounded to 32 entries per array and three levels.
|
|
98
|
+
|
|
99
|
+
`maxContentChars` defaults to 4096 (range 1–4096), independently bounding input and
|
|
100
|
+
output text, including streaming text accumulation. This is truncated text, not
|
|
101
|
+
a complete conversation transcript. `maxTrackedRequests` defaults to 1024 (range
|
|
102
|
+
1–65536) and is capped by the engine's active-span limit. At capacity, new calls
|
|
103
|
+
pass through unchanged/unobserved; `requestsSkipped` reports adapter admissions
|
|
104
|
+
skipped. `trackedRequests` includes unconsumed SDK promises/streams.
|
|
105
|
+
|
|
106
|
+
## Shared engines and lifecycle
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { createObservability } from "@saguiitay/eventhouse-ai-observability";
|
|
110
|
+
import { attachOpenAI } from "@saguiitay/eventhouse-ai-observability/openai";
|
|
111
|
+
|
|
112
|
+
const engine = createObservability({ exporter: myExporter });
|
|
113
|
+
const observer = attachOpenAI(sdk, engine); // External ownership by default.
|
|
114
|
+
// Equivalent: observeOpenAI(sdk, { engine })
|
|
115
|
+
try {
|
|
116
|
+
await observer.client.chat.completions.create({
|
|
117
|
+
model: "gpt-4.1-mini",
|
|
118
|
+
messages: [{ role: "user", content: "Hello" }],
|
|
119
|
+
});
|
|
120
|
+
} finally {
|
|
121
|
+
await observer.shutdown(); // End adapter work and flush, keep engine alive.
|
|
122
|
+
await engine.shutdown(); // Once, after every shared adapter shuts down.
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`observeOpenAI` owns engines it creates and shuts them down by default.
|
|
127
|
+
Supplied engines are externally owned by default. `shutdownEngine: true` explicitly
|
|
128
|
+
takes ownership of a supplied engine; do not set it to true on independently shutting-down adapters
|
|
129
|
+
that share an engine. Shutdown is awaited and idempotent. The SDK client is never
|
|
130
|
+
closed. `shutdownEngine: false` requires an external engine so newly constructed
|
|
131
|
+
engines cannot be left without an owner. Engine diagnostics are returned alongside
|
|
132
|
+
the two adapter counters.
|
|
133
|
+
|
|
134
|
+
Public SDK references:
|
|
135
|
+
[7.53.0 README](https://github.com/openai/openai-node/blob/v7.53.0/README.md),
|
|
136
|
+
[APIPromise](https://github.com/openai/openai-node/blob/v7.53.0/src/core/api-promise.ts),
|
|
137
|
+
[Stream](https://github.com/openai/openai-node/blob/v7.53.0/src/core/streaming.ts).
|
package/docs/quickstart.md
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
# Quickstart
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Install the package first, then follow [Fabric setup](fabric-setup.md).
|
|
4
|
+
There is no Collector or Azure Event Hubs resource to deploy.
|
|
5
|
+
|
|
6
|
+
## Install a published version
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install @saguiitay/eventhouse-ai-observability
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
npmjs **0.1.2** and GitHub Packages **0.1.1** are published and registry-verified.
|
|
13
|
+
This checkout's **0.2.0 is prepared, not published**. Its generated
|
|
14
|
+
`fabric-setup.zip` will be available from the installed package root, without
|
|
15
|
+
access to this private source repository; see the
|
|
16
|
+
[PowerShell extraction instructions](../README.md#fabric-setup-bundle-and-ingestion-check).
|
|
17
|
+
The earlier published versions do not include it; use manual Fabric setup for
|
|
18
|
+
those versions. GitHub Packages additionally requires
|
|
19
|
+
[registry authentication](../README.md#installation-from-github-packages).
|
|
4
20
|
|
|
5
21
|
## Build and install locally
|
|
6
22
|
|
|
@@ -10,9 +26,13 @@ pnpm build
|
|
|
10
26
|
pnpm pack
|
|
11
27
|
```
|
|
12
28
|
|
|
13
|
-
Install the resulting tarball into an existing Node ESM application using `npm install <tarball>`.
|
|
29
|
+
Install the resulting tarball into an existing Node ESM application using `npm install <tarball>`.
|
|
30
|
+
The prepared package includes the generated setup ZIP; extract it after installing.
|
|
31
|
+
Keep your existing Copilot session creation, permissions, model configuration, and execution unchanged; attach `observeCopilot` immediately after creating the session and before sending the first prompt.
|
|
14
32
|
|
|
15
|
-
`pnpm test:package` checks
|
|
33
|
+
`pnpm test:package` checks all packed SDK exports, the validator CLI, disposal,
|
|
34
|
+
parent-child IDs, and public TypeScript declarations. It reuses already-installed
|
|
35
|
+
project runtime dependencies and does not claim a fresh online install.
|
|
16
36
|
|
|
17
37
|
```typescript
|
|
18
38
|
import { observeCopilot } from "@saguiitay/eventhouse-ai-observability/copilot";
|
|
@@ -38,6 +58,7 @@ Shutdown closes the observer, **not your application-owned Copilot session/clien
|
|
|
38
58
|
| ---------------------- | ------------------------------------------------------------------------- |
|
|
39
59
|
| `connectionString` | `FABRIC_EVENTSTREAM_CONNECTION_STRING` |
|
|
40
60
|
| `entityName` | Needed only if `EntityPath` is absent; `FABRIC_EVENTSTREAM_ENTITY_NAME` |
|
|
61
|
+
| `exporter` | Optional standard `SpanExporter`; replaces built-in Fabric export |
|
|
41
62
|
| `serviceName` | `OTEL_SERVICE_NAME`, then `ai-application` |
|
|
42
63
|
| `serviceVersion` | `OTEL_SERVICE_VERSION` |
|
|
43
64
|
| `environment` | `DEPLOYMENT_ENVIRONMENT` |
|
|
@@ -79,14 +100,62 @@ into the application. Unknown third-party error codes remain `unknown`.
|
|
|
79
100
|
|
|
80
101
|
Native OTel batches wait for a concurrency slot within the existing queue admission budget and callback deadline, so healthy flush backlogs drain without saturation drops. There is no second span queue. New admissions beyond `maxQueueSize` and batches exceeding their deadline are dropped. Third-party exporters remain standard OTel `SpanExporter`s; a callback deadline cannot forcibly stop their I/O, so a hung call keeps its slot until actual completion. Engine shutdown still releases local context within its deadline even if exporter cleanup hangs. Eventstream cancels Azure operations with abort signals and separately bounds pending transport calls. Known acknowledged spans count as exported; oversized, unsent, or uncertain spans count as dropped. See [transport failure semantics](eventstream-transport.md#failure-semantics).
|
|
81
102
|
|
|
82
|
-
|
|
103
|
+
Fabric is the only built-in transport. Without a Fabric connection string or
|
|
104
|
+
an explicit `exporter`, configuration fails early. The root package does not
|
|
105
|
+
read OTLP environment variables.
|
|
106
|
+
|
|
107
|
+
For an existing OTLP service, install
|
|
108
|
+
`@opentelemetry/exporter-trace-otlp-http` separately:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import { createObservability } from "@saguiitay/eventhouse-ai-observability";
|
|
112
|
+
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
113
|
+
|
|
114
|
+
const observer = createObservability({
|
|
115
|
+
exporter: new OTLPTraceExporter({
|
|
116
|
+
url: "https://your-collector.example/v1/traces",
|
|
117
|
+
headers: { authorization: `Bearer ${process.env.COLLECTOR_TOKEN}` },
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Endpoint, header, and standard OTLP environment handling belong to that exporter.
|
|
123
|
+
Use HTTPS outside local development. The engine still sanitizes spans and owns
|
|
124
|
+
the supplied exporter's flush/shutdown lifecycle.
|
|
125
|
+
|
|
126
|
+
In 0.2.0, remove `transport`, `endpoint`, and `headers` from observability options
|
|
127
|
+
and stop importing `OTLPTraceExporter` from this package. Use `exporter` as above.
|
|
83
128
|
|
|
84
129
|
## Live Fabric validation
|
|
85
130
|
|
|
86
131
|
Set `FABRIC_EVENTSTREAM_CONNECTION_STRING`, optionally `FABRIC_EVENTSTREAM_ENTITY_NAME`, `FABRIC_KQL_QUERY_ENDPOINT` (database query URI, HTTPS), `FABRIC_KQL_DATABASE`, and `FABRIC_KQL_ACCESS_TOKEN` (a short-lived, authorized Kusto query token for that URI).
|
|
87
132
|
|
|
133
|
+
Run the CLI from the application where this SDK is installed; no source checkout
|
|
134
|
+
or separate CLI package is needed:
|
|
135
|
+
|
|
88
136
|
```sh
|
|
89
|
-
|
|
137
|
+
npx --no-install eventhouse-ai-observability-validate
|
|
90
138
|
```
|
|
91
139
|
|
|
92
|
-
|
|
140
|
+
From a checkout, run `pnpm build` then `pnpm validate:ingestion`.
|
|
141
|
+
`pnpm exec tsx tools/live-fabric.ts` remains a compatible source command.
|
|
142
|
+
`--help` performs no network I/O. No other arguments are accepted; keep
|
|
143
|
+
credentials out of command-line arguments, shell history, and committed files.
|
|
144
|
+
|
|
145
|
+
The producer needs Eventstream source Send credentials. The separate query token
|
|
146
|
+
needs Kusto database read permission and the correct Kusto audience; the
|
|
147
|
+
`FABRIC_ACCESS_TOKEN` used by provisioning is not a substitute.
|
|
148
|
+
|
|
149
|
+
The opt-in check reports producer acknowledgement, Eventhouse ingestion, and
|
|
150
|
+
trace/parent-child correlation separately. It sends two metadata-only spans and
|
|
151
|
+
queries `AIObservabilityTraces` until both appear. The polling timeout defaults
|
|
152
|
+
to three minutes after producer cleanup; set `FABRIC_VALIDATION_TIMEOUT_MS` to
|
|
153
|
+
a positive integer up to `900000` to change it. Export and query requests have
|
|
154
|
+
bounded deadlines. Query authorization failures, producer failures, ingestion
|
|
155
|
+
timeouts, and mapping/correlation failures use distinct safe error messages and
|
|
156
|
+
exit code 1; successful verification exits 0. No endpoint, token, query response
|
|
157
|
+
body, or raw SDK error is printed.
|
|
158
|
+
|
|
159
|
+
This writes real telemetry and can incur Fabric ingestion/query charges. It
|
|
160
|
+
neither provisions resources, acquires tokens, nor calls an AI provider. A
|
|
161
|
+
producer acknowledgement alone is not a successful validation.
|
|
@@ -162,15 +162,17 @@ or schema-registry headers.
|
|
|
162
162
|
|
|
163
163
|
[Official OTel exporter documentation][otel] identifies
|
|
164
164
|
`@opentelemetry/exporter-trace-otlp-http` as **HTTP/JSON**, not HTTP/protobuf
|
|
165
|
-
(`exporter-trace-otlp-proto`).
|
|
166
|
-
`OTLPTraceExporter` directly through
|
|
167
|
-
|
|
165
|
+
(`exporter-trace-otlp-proto`). Applications can supply the official
|
|
166
|
+
`OTLPTraceExporter` directly through the standard `exporter` option, without
|
|
167
|
+
a separate transport wrapper or private package. It is not a runtime
|
|
168
|
+
dependency or public export of this package.
|
|
168
169
|
The [official implementation][otlp-source] supplies the serializer, HTTP sender,
|
|
169
170
|
and exporter lifecycle.
|
|
170
171
|
|
|
171
|
-
`
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
The exporter's `url`, if supplied, is the full traces URL, normally ending in
|
|
173
|
+
`/v1/traces`. The official exporter owns environment/default resolution and
|
|
174
|
+
header configuration. The observability engine sanitizes exported spans and
|
|
175
|
+
diagnostic errors, not arbitrary transport configuration.
|
|
174
176
|
Use HTTPS outside trusted local development. This is an optional external OTLP
|
|
175
177
|
destination, **not an assertion that Fabric Eventstream accepts OTLP**.
|
|
176
178
|
|
package/docs/research.md
CHANGED
|
@@ -31,6 +31,6 @@ on 2026-11-12.** The published package was installed and the basic Copilot examp
|
|
|
31
31
|
ran successfully, with three acknowledged spans and no drops/failures. The
|
|
32
32
|
operator confirmed rows in `AIObservabilityTraces` and dashboard visibility.
|
|
33
33
|
This is not automated validation of all tenants, provisioning APIs, all examples,
|
|
34
|
-
or 0.1.1. The opt-in live validation script's execution and parent-child assertions
|
|
34
|
+
or 0.1.1, 0.1.2, or the prepared unpublished 0.2.0. The opt-in live validation script's execution and parent-child assertions
|
|
35
35
|
have not been reported; it requires a real Custom endpoint source, Eventhouse
|
|
36
36
|
destination, KQL query URI/database, and a user-supplied query access token.
|
package/docs/security.md
CHANGED
|
@@ -19,7 +19,7 @@ Use the Fabric Custom endpoint source's producer credential with **Send** capabi
|
|
|
19
19
|
|
|
20
20
|
Rotate using Fabric's supported source key regeneration/credential controls: update the application secret, replace the observer/transport, verify ingestion, then revoke the old key. Existing clients retain their original credential; changing an environment variable does not rotate a running producer. No credential is embedded in the provisioned dashboard or sample data.
|
|
21
21
|
|
|
22
|
-
AMQP uses TLS through the official Azure SDK. OTLP
|
|
22
|
+
AMQP uses TLS through the official Azure SDK. For a caller-supplied OTLP exporter, configure HTTPS except localhost/loopback for local tests; endpoint/header security belongs to the application and its exporter. The SDK does not register global logging or print raw exporter errors. Diagnostics contain aggregate counts and an optional latest failure with an allowlisted category and fixed troubleshooting hint, never the original exception. `onDiagnostic` and opt-in `debug` logging expose only those safe fields.
|
|
23
23
|
|
|
24
24
|
## Access and retention
|
|
25
25
|
|
package/docs/telemetry-schema.md
CHANGED
|
@@ -26,6 +26,24 @@ Copilot correlation uses the `copilot.*` namespace, including `copilot.session.i
|
|
|
26
26
|
|
|
27
27
|
`copilot.span.type` distinguishes `session`, `turn`, `tool`, `subagent`, and `model_request`. Execution metrics count turns, not the enclosing session observation or the separate subagent lifecycle span. Generic `invoke_agent` spans without Copilot-specific types remain supported. Agent identity is preserved as `copilot.agent.id`; names are added only when explicitly correlated metadata is available.
|
|
28
28
|
|
|
29
|
+
## Request token details
|
|
30
|
+
|
|
31
|
+
SDK adapters normalize explicitly reported request usage into:
|
|
32
|
+
|
|
33
|
+
| Attribute | Meaning |
|
|
34
|
+
| ------------------------------------------ | --------------------------------------------------- |
|
|
35
|
+
| `gen_ai.usage.cache_read.input_tokens` | Input tokens read from the provider's prompt cache |
|
|
36
|
+
| `gen_ai.usage.cache_creation.input_tokens` | Input tokens written to the provider's prompt cache |
|
|
37
|
+
| `gen_ai.usage.reasoning.output_tokens` | Reasoning tokens within the reported output total |
|
|
38
|
+
|
|
39
|
+
These are breakdowns, not additional totals: do not add reasoning tokens to `gen_ai.usage.output_tokens` or cached tokens to `gen_ai.usage.input_tokens`. Missing details remain absent; explicitly reported zero remains zero. Counts must be nonnegative safe integers. Adapters do not estimate, split totals, infer cache writes from reads, or copy aggregate turn/session usage onto requests.
|
|
40
|
+
|
|
41
|
+
OpenAI Chat Completions uses `prompt_tokens_details.cached_tokens`, `prompt_tokens_details.cache_write_tokens`, and `completion_tokens_details.reasoning_tokens`. Responses uses `input_tokens_details.cached_tokens`, `input_tokens_details.cache_write_tokens`, and `output_tokens_details.reasoning_tokens`. Normal and terminal streaming usage follow the same mapping; cache creation is recorded only if the provider reports it.
|
|
42
|
+
|
|
43
|
+
Vercel AI SDK 7 uses each `onLanguageModelCallEnd` event's `usage.inputTokenDetails.cacheReadTokens`, `cacheWriteTokens`, and `usage.outputTokenDetails.reasoningTokens` on its native model-request span. Native cache attributes and optional supplemental reasoning attributes normalize to the same keys. This also works when native supplemental usage recording is disabled; step/root aggregate usage is not duplicated.
|
|
44
|
+
|
|
45
|
+
Copilot `assistant.usage` uses `cacheReadTokens`, `cacheWriteTokens`, and `reasoningTokens`. The compatibility attribute `copilot.usage.reasoning_tokens` remains alongside the standard reasoning key. Session shutdown metrics and subagent aggregates are not converted into request token details.
|
|
46
|
+
|
|
29
47
|
## Privacy and evolution
|
|
30
48
|
|
|
31
49
|
Content is disabled by default. Sanitized resources, span attributes, events, and links are bounded before export. A custom transport receives the same privacy-filtered model. Error status remains available without exposing raw error text.
|