@insightfactory.ai/insightfactory-databricks-langgraph-tracer 1.0.0-dev.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/LICENSE +5 -0
  3. package/README.md +160 -0
  4. package/THIRD_PARTY_NOTICES +26 -0
  5. package/dist/cost.d.ts +76 -0
  6. package/dist/cost.d.ts.map +1 -0
  7. package/dist/cost.js +124 -0
  8. package/dist/cost.js.map +1 -0
  9. package/dist/databricks-tracer.d.ts +235 -0
  10. package/dist/databricks-tracer.d.ts.map +1 -0
  11. package/dist/databricks-tracer.js +841 -0
  12. package/dist/databricks-tracer.js.map +1 -0
  13. package/dist/errors.d.ts +5 -0
  14. package/dist/errors.d.ts.map +1 -0
  15. package/dist/errors.js +8 -0
  16. package/dist/errors.js.map +1 -0
  17. package/dist/generated-keys.d.ts +39 -0
  18. package/dist/generated-keys.d.ts.map +1 -0
  19. package/dist/generated-keys.js +39 -0
  20. package/dist/generated-keys.js.map +1 -0
  21. package/dist/index.d.ts +65 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +130 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/pricing/model-pricing-overrides.json +28 -0
  26. package/dist/pricing/model-pricing.json +1 -0
  27. package/dist/token-aggregate.d.ts +29 -0
  28. package/dist/token-aggregate.d.ts.map +1 -0
  29. package/dist/token-aggregate.js +63 -0
  30. package/dist/token-aggregate.js.map +1 -0
  31. package/dist/trace-metadata.d.ts +14 -0
  32. package/dist/trace-metadata.d.ts.map +1 -0
  33. package/dist/trace-metadata.js +33 -0
  34. package/dist/trace-metadata.js.map +1 -0
  35. package/dist/uc-export.d.ts +48 -0
  36. package/dist/uc-export.d.ts.map +1 -0
  37. package/dist/uc-export.js +243 -0
  38. package/dist/uc-export.js.map +1 -0
  39. package/package.json +68 -0
  40. package/src/pricing/model-pricing-overrides.json +28 -0
  41. package/src/pricing/model-pricing.json +1 -0
@@ -0,0 +1,29 @@
1
+ /** Enriched 5-field trace-level token rollup (base 3 + cache-read/creation + reasoning). */
2
+ export interface EnrichedTraceTokenUsage {
3
+ input_tokens: number;
4
+ output_tokens: number;
5
+ total_tokens: number;
6
+ cache_read_input_tokens: number;
7
+ cache_creation_input_tokens: number;
8
+ reasoning_tokens: number;
9
+ }
10
+ interface SpanLike {
11
+ spanId: string;
12
+ parentId: string | null;
13
+ attributes: Record<string, unknown> | undefined;
14
+ }
15
+ /**
16
+ * Replacement for `@mlflow/core`'s `aggregateUsageFromSpans` that returns the
17
+ * enriched rollup (cache-read / cache-creation / reasoning in addition to the
18
+ * base input/output/total sums). Reads `gen_ai.usage.input_tokens.cached`,
19
+ * `gen_ai.usage.input_tokens.cache_creation`, and
20
+ * `gen_ai.usage.output_tokens.reasoning` written by the tracer on LLM child
21
+ * spans. Preserves the SDK's double-count guard that skips a span whose parent
22
+ * also carries `TOKEN_USAGE`.
23
+ *
24
+ * Returns `null` when no span has `TOKEN_USAGE` — matching the SDK contract so
25
+ * the exporter's `if (aggregatedUsage)` guard still kicks in.
26
+ */
27
+ export declare function enrichedAggregateUsageFromSpans(spans: readonly SpanLike[]): EnrichedTraceTokenUsage | null;
28
+ export {};
29
+ //# sourceMappingURL=token-aggregate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-aggregate.d.ts","sourceRoot":"","sources":["../src/token-aggregate.ts"],"names":[],"mappings":"AAoBA,4FAA4F;AAC5F,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB,EAAE,MAAM,CAAC;IAChC,2BAA2B,EAAE,MAAM,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,UAAU,QAAQ;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CACjD;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,SAAS,QAAQ,EAAE,GACzB,uBAAuB,GAAG,IAAI,CAsChC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Enriched trace-level token rollup for the `@mlflow/core` SDK aggregator.
3
+ *
4
+ * This is a TypeScript-only enrichment with no Python parallel: the Python
5
+ * package relies on MLflow's native aggregation of the reserved per-span
6
+ * `mlflow.chat.tokenUsage` (which already carries the cache slots), whereas the
7
+ * `@mlflow/core` SDK's built-in `aggregateUsageFromSpans` hard-codes a 3-field
8
+ * trace rollup (input/output/total), dropping the cache + reasoning detail. We
9
+ * replace it (see `patchMlflowAggregator` in `index.ts`) so the Databricks
10
+ * "Usage breakdown" panel renders the `(cache read)` row and so the
11
+ * cache-creation / reasoning counts are queryable on the trace.
12
+ *
13
+ * NB: the enriched trace-level `mlflow.trace.tokenUsage` key it feeds is NOT
14
+ * part of the shared cross-language schema — the schema's token keys are all
15
+ * span-level. This module only enriches the SDK's own trace rollup.
16
+ */
17
+ import { SpanAttrKey } from "./generated-keys.js";
18
+ const TOKEN_USAGE = SpanAttrKey.TOKEN_USAGE; // "mlflow.chat.tokenUsage"
19
+ function toNum(v) {
20
+ return typeof v === "number" && Number.isFinite(v) ? v : 0;
21
+ }
22
+ /**
23
+ * Replacement for `@mlflow/core`'s `aggregateUsageFromSpans` that returns the
24
+ * enriched rollup (cache-read / cache-creation / reasoning in addition to the
25
+ * base input/output/total sums). Reads `gen_ai.usage.input_tokens.cached`,
26
+ * `gen_ai.usage.input_tokens.cache_creation`, and
27
+ * `gen_ai.usage.output_tokens.reasoning` written by the tracer on LLM child
28
+ * spans. Preserves the SDK's double-count guard that skips a span whose parent
29
+ * also carries `TOKEN_USAGE`.
30
+ *
31
+ * Returns `null` when no span has `TOKEN_USAGE` — matching the SDK contract so
32
+ * the exporter's `if (aggregatedUsage)` guard still kicks in.
33
+ */
34
+ export function enrichedAggregateUsageFromSpans(spans) {
35
+ const total = {
36
+ input_tokens: 0,
37
+ output_tokens: 0,
38
+ total_tokens: 0,
39
+ cache_read_input_tokens: 0,
40
+ cache_creation_input_tokens: 0,
41
+ reasoning_tokens: 0,
42
+ };
43
+ let hasUsage = false;
44
+ for (const span of spans) {
45
+ const tokenUsage = span.attributes?.[TOKEN_USAGE];
46
+ if (!tokenUsage)
47
+ continue;
48
+ if (span.parentId) {
49
+ const parent = spans.find((s) => s.spanId === span.parentId);
50
+ if (parent?.attributes?.[TOKEN_USAGE])
51
+ continue;
52
+ }
53
+ total.input_tokens += toNum(tokenUsage.input_tokens);
54
+ total.output_tokens += toNum(tokenUsage.output_tokens);
55
+ total.total_tokens += toNum(tokenUsage.total_tokens);
56
+ total.cache_read_input_tokens += toNum(span.attributes?.[SpanAttrKey.INPUT_TOKENS_CACHED]);
57
+ total.cache_creation_input_tokens += toNum(span.attributes?.[SpanAttrKey.INPUT_TOKENS_CACHE_CREATION]);
58
+ total.reasoning_tokens += toNum(span.attributes?.[SpanAttrKey.OUTPUT_TOKENS_REASONING]);
59
+ hasUsage = true;
60
+ }
61
+ return hasUsage ? total : null;
62
+ }
63
+ //# sourceMappingURL=token-aggregate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-aggregate.js","sourceRoot":"","sources":["../src/token-aggregate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC,2BAA2B;AAkBxE,SAAS,KAAK,CAAC,CAAU;IACvB,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,+BAA+B,CAC7C,KAA0B;IAE1B,MAAM,KAAK,GAA4B;QACrC,YAAY,EAAE,CAAC;QACf,aAAa,EAAE,CAAC;QAChB,YAAY,EAAE,CAAC;QACf,uBAAuB,EAAE,CAAC;QAC1B,2BAA2B,EAAE,CAAC;QAC9B,gBAAgB,EAAE,CAAC;KACpB,CAAC;IACF,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,WAAW,CAEnC,CAAC;QACd,IAAI,CAAC,UAAU;YAAE,SAAS;QAE1B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC7D,IAAI,MAAM,EAAE,UAAU,EAAE,CAAC,WAAW,CAAC;gBAAE,SAAS;QAClD,CAAC;QAED,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;QACrD,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACvD,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;QACrD,KAAK,CAAC,uBAAuB,IAAI,KAAK,CACpC,IAAI,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,mBAAmB,CAAC,CACnD,CAAC;QACF,KAAK,CAAC,2BAA2B,IAAI,KAAK,CACxC,IAAI,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAC3D,CAAC;QACF,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAC7B,IAAI,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,uBAAuB,CAAC,CACvD,CAAC;QACF,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Writes trace-level `tags` and/or `traceMetadata` on the in-memory trace for
3
+ * `traceId`. Both objects are mutated in place via `Object.assign` — writes must
4
+ * happen before the SDK flushes the trace to the exporter (the span processor
5
+ * pops the trace from the manager synchronously when the root span ends).
6
+ *
7
+ * Failures (missing trace, unexpected shape, etc.) are swallowed: the tracer
8
+ * must never throw from this path (resilient by design).
9
+ */
10
+ export declare function writeTraceFields(traceId: string, fields: {
11
+ tags?: Record<string, string>;
12
+ metadata?: Record<string, string>;
13
+ }): void;
14
+ //# sourceMappingURL=trace-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-metadata.d.ts","sourceRoot":"","sources":["../src/trace-metadata.ts"],"names":[],"mappings":"AAUA;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC3E,IAAI,CASN"}
@@ -0,0 +1,33 @@
1
+ // Deliberate private-API wrapper around `@mlflow/core`'s `InMemoryTraceManager`.
2
+ // `updateCurrentTrace` is a no-op from `startSpan`-style tracers (it keys off the
3
+ // OTEL active span, which is not set when callers pass `parent` explicitly), so
4
+ // trace-level tag/metadata writes have to reach into the in-memory manager. This
5
+ // is the TypeScript parallel to the Python tracer's `_write_trace_fields`
6
+ // (`InMemoryTraceManager.get_trace(trace_id)` + `.info.tags`/`.info.trace_metadata`
7
+ // mutation). Centralized here so the rest of the tracer never imports from
8
+ // `@mlflow/core/dist/...` paths directly.
9
+ import { InMemoryTraceManager } from "@mlflow/core/dist/core/trace_manager.js";
10
+ /**
11
+ * Writes trace-level `tags` and/or `traceMetadata` on the in-memory trace for
12
+ * `traceId`. Both objects are mutated in place via `Object.assign` — writes must
13
+ * happen before the SDK flushes the trace to the exporter (the span processor
14
+ * pops the trace from the manager synchronously when the root span ends).
15
+ *
16
+ * Failures (missing trace, unexpected shape, etc.) are swallowed: the tracer
17
+ * must never throw from this path (resilient by design).
18
+ */
19
+ export function writeTraceFields(traceId, fields) {
20
+ try {
21
+ const trace = InMemoryTraceManager.getInstance().getTrace(traceId);
22
+ if (!trace)
23
+ return;
24
+ if (fields.tags)
25
+ Object.assign(trace.info.tags, fields.tags);
26
+ if (fields.metadata)
27
+ Object.assign(trace.info.traceMetadata, fields.metadata);
28
+ }
29
+ catch {
30
+ // never throw from a live run
31
+ }
32
+ }
33
+ //# sourceMappingURL=trace-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-metadata.js","sourceRoot":"","sources":["../src/trace-metadata.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,kFAAkF;AAClF,gFAAgF;AAChF,iFAAiF;AACjF,0EAA0E;AAC1E,oFAAoF;AACpF,2EAA2E;AAC3E,0CAA0C;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAE/E;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,MAA4E;IAE5E,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,oBAAoB,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACnE,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,MAAM,CAAC,IAAI;YAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,MAAM,CAAC,QAAQ;YAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;IAChC,CAAC;AACH,CAAC"}
@@ -0,0 +1,48 @@
1
+ /** Experiment tag carrying the UC destination (`catalog.schema.table_prefix`). */
2
+ export declare const UC_DESTINATION_TAG = "mlflow.experiment.databricksTraceDestinationPath";
3
+ /** Experiment tag naming the spans table outright (preferred over deriving). */
4
+ export declare const UC_SPANS_TABLE_TAG = "mlflow.experiment.databricksTraceSpanStorageTable";
5
+ /** Header naming the UC spans table for the OTLP ingest endpoint. */
6
+ export declare const UC_TABLE_HEADER = "X-Databricks-UC-Table-Name";
7
+ export interface UcDestination {
8
+ catalogName: string;
9
+ schemaName: string;
10
+ tablePrefix: string;
11
+ /** `catalog.schema.table_prefix` — the V4 location path segment. */
12
+ fullTablePrefix: string;
13
+ /** `catalog.schema.<prefix>_otel_spans` — the OTLP ingest header value. */
14
+ spansTableName: string;
15
+ }
16
+ /**
17
+ * Parse a `databricksTraceDestinationPath` tag value into a {@link UcDestination}.
18
+ * Throws when the value is not the expected three-part `catalog.schema.prefix`.
19
+ */
20
+ export declare function parseUcDestinationPath(path: string): UcDestination;
21
+ type HeadersProvider = () => Promise<Record<string, string>> | Record<string, string>;
22
+ /**
23
+ * Fetch the experiment and resolve its UC destination from the
24
+ * `databricksTraceDestinationPath` tag. Returns `null` for classic
25
+ * (workspace-backed) experiments. SDK/network failures raise an actionable
26
+ * configuration error rather than a generic fetch failure, mirroring the
27
+ * Python package's hardened guard.
28
+ */
29
+ export declare function resolveUcDestination(hostUrl: string, headersProvider: HeadersProvider, experimentId: string): Promise<UcDestination | null>;
30
+ /**
31
+ * Databricks' OTLP ingest rejects batches over 10 MiB ("Batch exceeds maximum
32
+ * size of 10485760 bytes"). Stay comfortably under it — protobuf framing per
33
+ * chunk adds a little over the sum of span sizes.
34
+ */
35
+ export declare const OTLP_MAX_BATCH_BYTES: number;
36
+ /** Reset patch state. For testing only. */
37
+ export declare function _resetUcExportForTests(): void;
38
+ /**
39
+ * Patch `MlflowSpanExporter.exportTraceToBackend` with a UC-aware
40
+ * implementation. The destination is resolved once (memoized promise) from
41
+ * the experiment's tags on the first export — the SDK's client (and its
42
+ * auth headers) only exists at export time — and classic experiments
43
+ * delegate to the original implementation untouched. Resolution failures
44
+ * log loudly and fall back to classic export rather than dropping traces.
45
+ */
46
+ export declare function patchExporterForUc(experimentId: string): void;
47
+ export {};
48
+ //# sourceMappingURL=uc-export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uc-export.d.ts","sourceRoot":"","sources":["../src/uc-export.ts"],"names":[],"mappings":"AAiCA,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,qDAAqD,CAAC;AAErF,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,sDAAsD,CAAC;AAEtF,qEAAqE;AACrE,eAAO,MAAM,eAAe,+BAA+B,CAAC;AAM5D,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,eAAe,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAgBlE;AAED,KAAK,eAAe,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAsCtF;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,eAAe,EAChC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA+B/B;AAOD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAAkB,CAAC;AAsGpD,2CAA2C;AAC3C,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAsD7D"}
@@ -0,0 +1,243 @@
1
+ /**
2
+ * UC table-backed span export for Databricks MLflow experiments.
3
+ *
4
+ * `@mlflow/core@0.2.0` exports traces via `StartTraceV3` + artifact-store
5
+ * upload — a path UC table-backed experiments silently ignore (the calls
6
+ * succeed but the spans never reach the `<prefix>_otel_spans` Delta table and
7
+ * V4 `search_traces` returns nothing). This module mirrors the Python
8
+ * package's UC fix (mlflow_utils.py `_resolve_uc_trace_location`) plus the
9
+ * protocol MLflow >= 3.10 Python uses natively:
10
+ *
11
+ * - Spans: OTLP `ExportTraceServiceRequest` protobuf POSTed to
12
+ * `/api/2.0/otel/v1/traces` with the `X-Databricks-UC-Table-Name` header
13
+ * naming the fully-qualified `<catalog>.<schema>.<prefix>_otel_spans` table.
14
+ * - Trace info: `CreateTraceInfo` JSON POSTed to
15
+ * `/api/4.0/mlflow/traces/<location>/<otelTraceId>/info` with a
16
+ * `UC_TABLE_PREFIX` trace location and `mlflow.trace_schema.version = "4"`.
17
+ *
18
+ * Like the aggregator patch in `index.ts`, the seam is a `createRequire`
19
+ * monkeypatch of the SDK's `MlflowSpanExporter` — the exporter pops the trace
20
+ * from `InMemoryTraceManager` synchronously inside root-span `end()`, so
21
+ * there is no public post-export hook to intercept instead.
22
+ *
23
+ * UC detection is resolved lazily (and memoized) from the experiment's
24
+ * `databricksTraceDestinationPath` tag on the first export, because the
25
+ * public `initDatabricksTracing` surface is synchronous and the SDK's
26
+ * authenticated client only exists at export time. Experiments without the
27
+ * tag fall through to the SDK's classic export path unchanged.
28
+ */
29
+ import { createRequire } from "node:module";
30
+ import { ProtobufTraceSerializer } from "@opentelemetry/otlp-transformer";
31
+ import { DatabricksTracingConfigurationError } from "./errors.js";
32
+ /** Experiment tag carrying the UC destination (`catalog.schema.table_prefix`). */
33
+ export const UC_DESTINATION_TAG = "mlflow.experiment.databricksTraceDestinationPath";
34
+ /** Experiment tag naming the spans table outright (preferred over deriving). */
35
+ export const UC_SPANS_TABLE_TAG = "mlflow.experiment.databricksTraceSpanStorageTable";
36
+ /** Header naming the UC spans table for the OTLP ingest endpoint. */
37
+ export const UC_TABLE_HEADER = "X-Databricks-UC-Table-Name";
38
+ /** V4 schema version stamped into UC trace metadata. */
39
+ const TRACE_SCHEMA_VERSION_KEY = "mlflow.trace_schema.version";
40
+ const UC_TRACE_SCHEMA_VERSION = "4";
41
+ /**
42
+ * Parse a `databricksTraceDestinationPath` tag value into a {@link UcDestination}.
43
+ * Throws when the value is not the expected three-part `catalog.schema.prefix`.
44
+ */
45
+ export function parseUcDestinationPath(path) {
46
+ const parts = path.split(".");
47
+ const [catalogName, schemaName, tablePrefix] = parts;
48
+ if (parts.length !== 3 || !catalogName || !schemaName || !tablePrefix) {
49
+ throw new DatabricksTracingConfigurationError(`Unexpected ${UC_DESTINATION_TAG} value '${path}' ` +
50
+ "(expected 'catalog.schema.table_prefix').");
51
+ }
52
+ return {
53
+ catalogName,
54
+ schemaName,
55
+ tablePrefix,
56
+ fullTablePrefix: path,
57
+ spansTableName: `${catalogName}.${schemaName}.${tablePrefix}_otel_spans`,
58
+ };
59
+ }
60
+ /**
61
+ * Fetch the experiment and resolve its UC destination from the
62
+ * `databricksTraceDestinationPath` tag. Returns `null` for classic
63
+ * (workspace-backed) experiments. SDK/network failures raise an actionable
64
+ * configuration error rather than a generic fetch failure, mirroring the
65
+ * Python package's hardened guard.
66
+ */
67
+ export async function resolveUcDestination(hostUrl, headersProvider, experimentId) {
68
+ const url = `${hostUrl.replace(/\/$/, "")}/api/2.0/mlflow/experiments/get?experiment_id=${encodeURIComponent(experimentId)}`;
69
+ let response;
70
+ try {
71
+ response = await fetch(url, { headers: await headersProvider() });
72
+ }
73
+ catch (err) {
74
+ throw new DatabricksTracingConfigurationError(`Failed to fetch experiment '${experimentId}' while resolving the UC trace ` +
75
+ `destination: ${err.message}`);
76
+ }
77
+ if (!response.ok) {
78
+ throw new DatabricksTracingConfigurationError(`Failed to fetch experiment '${experimentId}' while resolving the UC trace ` +
79
+ `destination: HTTP ${response.status}`);
80
+ }
81
+ const body = (await response.json());
82
+ const tags = body.experiment?.tags ?? [];
83
+ const destinationTag = tags.find((t) => t.key === UC_DESTINATION_TAG);
84
+ if (!destinationTag?.value)
85
+ return null;
86
+ const destination = parseUcDestinationPath(destinationTag.value);
87
+ // Prefer the explicit spans-table tag when present; the derived
88
+ // `<prefix>_otel_spans` name is the documented default fallback.
89
+ const spansTableTag = tags.find((t) => t.key === UC_SPANS_TABLE_TAG);
90
+ if (spansTableTag?.value) {
91
+ destination.spansTableName = spansTableTag.value;
92
+ }
93
+ return destination;
94
+ }
95
+ /** Strip the `tr-` prefix from an MLflow trace id, yielding the OTel hex id. */
96
+ function toOtelTraceId(mlflowTraceId) {
97
+ return mlflowTraceId.startsWith("tr-") ? mlflowTraceId.slice(3) : mlflowTraceId;
98
+ }
99
+ /**
100
+ * Databricks' OTLP ingest rejects batches over 10 MiB ("Batch exceeds maximum
101
+ * size of 10485760 bytes"). Stay comfortably under it — protobuf framing per
102
+ * chunk adds a little over the sum of span sizes.
103
+ */
104
+ export const OTLP_MAX_BATCH_BYTES = 9 * 1024 * 1024;
105
+ /**
106
+ * POST one OTLP `ExportTraceServiceRequest` to the Databricks ingest endpoint,
107
+ * addressed at the UC spans table.
108
+ */
109
+ async function postOtlpBatch(client, destination, payload) {
110
+ const url = `${client.hostUrl.replace(/\/$/, "")}/api/2.0/otel/v1/traces`;
111
+ const response = await fetch(url, {
112
+ method: "POST",
113
+ headers: {
114
+ ...(await client.headersProvider()),
115
+ "Content-Type": "application/x-protobuf",
116
+ [UC_TABLE_HEADER]: destination.spansTableName,
117
+ },
118
+ body: payload,
119
+ });
120
+ if (!response.ok) {
121
+ const text = await response.text().catch(() => "");
122
+ throw new Error(`OTLP span export failed: HTTP ${response.status} ${text.slice(0, 500)}`);
123
+ }
124
+ }
125
+ /**
126
+ * POST the trace's spans to the Databricks OTLP ingest endpoint, splitting
127
+ * into multiple requests when the serialized batch exceeds the ingest size
128
+ * cap (SQL-heavy agent turns routinely serialize past 10 MiB — one validation
129
+ * run saw a 98-span turn produce a 16.8 MB batch).
130
+ * Spans are append-only rows in the UC table, so a trace's spans may arrive
131
+ * across several requests. Binary-splits recursively (log N serializations);
132
+ * a single span that alone exceeds the cap is sent anyway and surfaces the
133
+ * server's 400 — truncating span payloads is the tracer's job, not the
134
+ * exporter's.
135
+ */
136
+ async function exportSpansToUcTable(client, destination, spans, maxBatchBytes = OTLP_MAX_BATCH_BYTES) {
137
+ if (spans.length === 0)
138
+ return;
139
+ const payload = ProtobufTraceSerializer.serializeRequest(spans);
140
+ if (!payload) {
141
+ throw new Error("OTLP serialization produced no payload");
142
+ }
143
+ if (payload.byteLength > maxBatchBytes && spans.length > 1) {
144
+ const mid = Math.ceil(spans.length / 2);
145
+ await exportSpansToUcTable(client, destination, spans.slice(0, mid), maxBatchBytes);
146
+ await exportSpansToUcTable(client, destination, spans.slice(mid), maxBatchBytes);
147
+ return;
148
+ }
149
+ await postOtlpBatch(client, destination, payload);
150
+ }
151
+ /**
152
+ * POST the trace info to the V4 `CreateTraceInfo` endpoint with a
153
+ * `UC_TABLE_PREFIX` location and V4 trace-id format
154
+ * (`trace:/<location>/<otelTraceId>`).
155
+ */
156
+ async function exportTraceInfoV4(client, destination, info) {
157
+ const otelTraceId = toOtelTraceId(info.traceId);
158
+ const body = info.toJson();
159
+ body.trace_id = `trace:/${destination.fullTablePrefix}/${otelTraceId}`;
160
+ body.trace_location = {
161
+ type: "UC_TABLE_PREFIX",
162
+ uc_table_prefix: {
163
+ catalog_name: destination.catalogName,
164
+ schema_name: destination.schemaName,
165
+ table_prefix: destination.tablePrefix,
166
+ },
167
+ };
168
+ body.trace_metadata = {
169
+ ...body.trace_metadata,
170
+ [TRACE_SCHEMA_VERSION_KEY]: UC_TRACE_SCHEMA_VERSION,
171
+ };
172
+ const url = `${client.hostUrl.replace(/\/$/, "")}/api/4.0/mlflow/traces/` +
173
+ `${destination.fullTablePrefix}/${otelTraceId}/info`;
174
+ const response = await fetch(url, {
175
+ method: "POST",
176
+ headers: {
177
+ ...(await client.headersProvider()),
178
+ "Content-Type": "application/json",
179
+ },
180
+ body: JSON.stringify(body),
181
+ });
182
+ if (!response.ok) {
183
+ const text = await response.text().catch(() => "");
184
+ throw new Error(`V4 trace-info export failed: HTTP ${response.status} ${text.slice(0, 500)}`);
185
+ }
186
+ }
187
+ let exporterPatched = false;
188
+ /** Reset patch state. For testing only. */
189
+ export function _resetUcExportForTests() {
190
+ exporterPatched = false;
191
+ }
192
+ /**
193
+ * Patch `MlflowSpanExporter.exportTraceToBackend` with a UC-aware
194
+ * implementation. The destination is resolved once (memoized promise) from
195
+ * the experiment's tags on the first export — the SDK's client (and its
196
+ * auth headers) only exists at export time — and classic experiments
197
+ * delegate to the original implementation untouched. Resolution failures
198
+ * log loudly and fall back to classic export rather than dropping traces.
199
+ */
200
+ export function patchExporterForUc(experimentId) {
201
+ if (exporterPatched)
202
+ return;
203
+ const nodeRequire = createRequire(import.meta.url);
204
+ const exporterModule = nodeRequire("@mlflow/core/dist/exporters/mlflow.js");
205
+ const proto = exporterModule.MlflowSpanExporter.prototype;
206
+ const originalExport = proto.exportTraceToBackend;
207
+ let destinationPromise = null;
208
+ const resolveOnce = (client) => {
209
+ destinationPromise ??= resolveUcDestination(client.hostUrl, client.headersProvider, experimentId).catch((err) => {
210
+ console.error("[databricks-langgraph-tracer] UC destination resolution failed:", err);
211
+ return null;
212
+ });
213
+ return destinationPromise;
214
+ };
215
+ proto.exportTraceToBackend = async function (trace) {
216
+ const destination = await resolveOnce(this._client);
217
+ if (!destination) {
218
+ return originalExport.call(this, trace);
219
+ }
220
+ // UC path: OTLP spans -> UC table; trace info -> V4 endpoint. No
221
+ // artifact upload (UC experiments do not read the artifact store).
222
+ // Span export goes first — trace info without spans renders as an
223
+ // empty trace, while spans without info are recoverable on retry.
224
+ const spans = trace.data.spans.map((s) => s._span);
225
+ try {
226
+ await exportSpansToUcTable(this._client, destination, spans);
227
+ await exportTraceInfoV4(this._client, destination, trace.info);
228
+ }
229
+ catch (err) {
230
+ console.error(`[databricks-langgraph-tracer] UC export failed for ${trace.info.traceId}, ` +
231
+ "falling back to classic export:", err);
232
+ return originalExport.call(this, trace);
233
+ }
234
+ // Mirror the SDK's `finally` cleanup: `export()` records this promise in
235
+ // `_pendingExports` and the original implementation deletes the entry on
236
+ // completion. Only the UC success path needs this here — both delegation
237
+ // paths above end in `originalExport`, whose own `finally` cleans up
238
+ // (deleting earlier would hide an in-flight fallback from `forceFlush`).
239
+ delete this._pendingExports[trace.info.traceId];
240
+ };
241
+ exporterPatched = true;
242
+ }
243
+ //# sourceMappingURL=uc-export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uc-export.js","sourceRoot":"","sources":["../src/uc-export.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@insightfactory.ai/insightfactory-databricks-langgraph-tracer",
3
+ "version": "1.0.0-dev.0",
4
+ "description": "LangGraph tracing for Databricks MLflow (TypeScript)",
5
+ "type": "module",
6
+ "packageManager": "yarn@4.12.0",
7
+ "license": "SEE LICENSE IN LICENSE",
8
+ "author": {
9
+ "name": "insightfactory.ai",
10
+ "email": "support@insightfactory.ai"
11
+ },
12
+ "homepage": "https://insightfactory.ai",
13
+ "keywords": [
14
+ "databricks",
15
+ "langchain",
16
+ "langgraph",
17
+ "mlflow",
18
+ "tracing"
19
+ ],
20
+ "engines": {
21
+ "node": ">=20"
22
+ },
23
+ "publishConfig": {
24
+ "registry": "https://registry.npmjs.org/",
25
+ "access": "public",
26
+ "provenance": true
27
+ },
28
+ "main": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "src/pricing",
39
+ "CHANGELOG.md",
40
+ "LICENSE",
41
+ "THIRD_PARTY_NOTICES",
42
+ "README.md"
43
+ ],
44
+ "scripts": {
45
+ "build": "tsc -p tsconfig.build.json && node scripts/copy-pricing.mjs",
46
+ "test": "vitest run",
47
+ "keys:generate": "tsx scripts/generate-keys.ts",
48
+ "keys:check": "tsx scripts/generate-keys.ts --check",
49
+ "pricing:update": "tsx scripts/update-pricing.ts"
50
+ },
51
+ "dependencies": {
52
+ "@opentelemetry/otlp-transformer": "^0.205.0",
53
+ "@opentelemetry/sdk-trace-base": "^2.1.0"
54
+ },
55
+ "peerDependencies": {
56
+ "@langchain/core": "^1.1.47",
57
+ "@mlflow/core": "^0.2.0"
58
+ },
59
+ "devDependencies": {
60
+ "@langchain/core": "^1.1.47",
61
+ "@langchain/langgraph": "^1.2.6",
62
+ "@mlflow/core": "^0.2.0",
63
+ "@types/node": "^25.5.0",
64
+ "tsx": "^4.21.0",
65
+ "typescript": "^6.0.2",
66
+ "vitest": "^4.1.4"
67
+ }
68
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "azure_ai/deepseek-v4-flash": {
3
+ "input_cost_per_token": 1.9e-7,
4
+ "output_cost_per_token": 5.1e-7,
5
+ "litellm_provider": "azure_ai",
6
+ "max_input_tokens": 131072,
7
+ "max_output_tokens": 131072,
8
+ "max_tokens": 131072,
9
+ "mode": "chat",
10
+ "supports_function_calling": true,
11
+ "supports_reasoning": true,
12
+ "supports_tool_choice": true,
13
+ "source": "https://techcommunity.microsoft.com/blog/azure-ai-foundry-blog/introducing-deepseek-v4-flash-and-v4-pro-in-microsoft-foundry/4515174"
14
+ },
15
+ "azure_ai/deepseek-v4-pro": {
16
+ "input_cost_per_token": 1.74e-6,
17
+ "output_cost_per_token": 3.48e-6,
18
+ "litellm_provider": "azure_ai",
19
+ "max_input_tokens": 131072,
20
+ "max_output_tokens": 131072,
21
+ "max_tokens": 131072,
22
+ "mode": "chat",
23
+ "supports_function_calling": true,
24
+ "supports_reasoning": true,
25
+ "supports_tool_choice": true,
26
+ "source": "https://techcommunity.microsoft.com/blog/azure-ai-foundry-blog/introducing-deepseek-v4-flash-and-v4-pro-in-microsoft-foundry/4515174"
27
+ }
28
+ }