@elsium-ai/observe 0.2.2 → 0.3.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/dist/audit.d.ts CHANGED
@@ -44,6 +44,8 @@ export interface AuditTrail {
44
44
  actor?: string;
45
45
  traceId?: string;
46
46
  }): void;
47
+ /** Resolves once async initialization (e.g. getLastHash) has completed. */
48
+ ready(): Promise<void>;
47
49
  query(filter: AuditQueryFilter): Promise<AuditEvent[]>;
48
50
  verifyIntegrity(): Promise<AuditIntegrityResult>;
49
51
  readonly count: number;
@@ -1 +1 @@
1
- {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,iBAAiB,CAAA;AAEpF,MAAM,MAAM,cAAc,GACvB,UAAU,GACV,gBAAgB,GAChB,oBAAoB,GACpB,cAAc,GACd,kBAAkB,GAClB,YAAY,GACZ,kBAAkB,GAClB,mBAAmB,GACnB,eAAe,CAAA;AAElB,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,cAAc,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,mBAAmB;IACnC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,KAAK,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IACrE,KAAK,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACjC,eAAe,IAAI,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACvE,WAAW,CAAC,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACxC;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,cAAc,GAAG,cAAc,EAAE,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,OAAO,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,CAAC,EAAE,mBAAmB,GAAG,QAAQ,CAAA;IACxC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;CAClC;AAED,MAAM,WAAW,UAAU;IAC1B,GAAG,CACF,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC5C,IAAI,CAAA;IACP,KAAK,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IACtD,eAAe,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACtB;AAyFD,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,UAAU,CAuEtE;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CA0ClE"}
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,iBAAiB,CAAA;AAEpF,MAAM,MAAM,cAAc,GACvB,UAAU,GACV,gBAAgB,GAChB,oBAAoB,GACpB,cAAc,GACd,kBAAkB,GAClB,YAAY,GACZ,kBAAkB,GAClB,mBAAmB,GACnB,eAAe,CAAA;AAElB,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,cAAc,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,mBAAmB;IACnC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,KAAK,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IACrE,KAAK,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACjC,eAAe,IAAI,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACvE,WAAW,CAAC,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACxC;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,cAAc,GAAG,cAAc,EAAE,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,OAAO,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,CAAC,EAAE,mBAAmB,GAAG,QAAQ,CAAA;IACxC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;CAClC;AAED,MAAM,WAAW,UAAU;IAC1B,GAAG,CACF,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC5C,IAAI,CAAA;IACP,2EAA2E;IAC3E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,KAAK,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IACtD,eAAe,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACtB;AAyFD,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,UAAU,CAqGtE;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CA0ClE"}
@@ -0,0 +1,28 @@
1
+ export interface ExperimentVariant {
2
+ name: string;
3
+ weight: number;
4
+ config: Record<string, unknown>;
5
+ }
6
+ export interface ExperimentResults {
7
+ name: string;
8
+ totalAssignments: number;
9
+ variants: Record<string, {
10
+ assignments: number;
11
+ metrics: Record<string, {
12
+ sum: number;
13
+ count: number;
14
+ avg: number;
15
+ }>;
16
+ }>;
17
+ }
18
+ export interface Experiment {
19
+ assign(userId?: string): ExperimentVariant;
20
+ record(variant: string, metrics: Record<string, number>): void;
21
+ results(): ExperimentResults;
22
+ }
23
+ export interface ExperimentConfig {
24
+ name: string;
25
+ variants: ExperimentVariant[];
26
+ }
27
+ export declare function createExperiment(config: ExperimentConfig): Experiment;
28
+ //# sourceMappingURL=experiment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"experiment.d.ts","sourceRoot":"","sources":["../src/experiment.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,gBAAgB,EAAE,MAAM,CAAA;IACxB,QAAQ,EAAE,MAAM,CACf,MAAM,EACN;QACC,WAAW,EAAE,MAAM,CAAA;QACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KACpE,CACD,CAAA;CACD;AAED,MAAM,WAAW,UAAU;IAC1B,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAA;IAC1C,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;IAC9D,OAAO,IAAI,iBAAiB,CAAA;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,iBAAiB,EAAE,CAAA;CAC7B;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CA0FrE"}
package/dist/index.d.ts CHANGED
@@ -10,6 +10,8 @@ export { createAuditTrail, auditMiddleware } from './audit';
10
10
  export type { AuditEventType, AuditEvent, AuditStorageAdapter, AuditQueryFilter, AuditIntegrityResult, AuditTrailConfig, AuditTrail, } from './audit';
11
11
  export { createProvenanceTracker } from './provenance';
12
12
  export type { ProvenanceRecord, ProvenanceTracker } from './provenance';
13
+ export { createExperiment } from './experiment';
14
+ export type { Experiment, ExperimentConfig, ExperimentVariant, ExperimentResults, } from './experiment';
13
15
  export { toOTelSpan, toOTelExportRequest, toTraceparent, parseTraceparent, injectTraceContext, extractTraceContext, createOTLPExporter, } from './otel';
14
16
  export type { OTelSpan, OTelSpanKind, OTelStatusCode, OTelAttribute, OTelAttributeValue, OTelEvent, OTelResource, OTelExportRequest, TraceContext, OTLPExporterConfig, } from './otel';
15
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAG1F,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACnE,YAAY,EACX,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,SAAS,EACT,aAAa,EACb,sBAAsB,EACtB,eAAe,EACf,cAAc,GACd,MAAM,eAAe,CAAA;AAGtB,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAClC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAG9F,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG9D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAC3D,YAAY,EACX,cAAc,EACd,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,GACV,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AACtD,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAGvE,OAAO,EACN,UAAU,EACV,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,QAAQ,CAAA;AACf,YAAY,EACX,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,GAClB,MAAM,QAAQ,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAG1F,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACnE,YAAY,EACX,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,SAAS,EACT,aAAa,EACb,sBAAsB,EACtB,eAAe,EACf,cAAc,GACd,MAAM,eAAe,CAAA;AAGtB,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAClC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAG9F,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG9D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAC3D,YAAY,EACX,cAAc,EACd,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,GACV,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AACtD,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAGvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,YAAY,EACX,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GACjB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACN,UAAU,EACV,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,QAAQ,CAAA;AACf,YAAY,EACX,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,GAClB,MAAM,QAAQ,CAAA"}
package/dist/index.js CHANGED
@@ -140,6 +140,11 @@ function createLogger(options = {}) {
140
140
  }
141
141
  };
142
142
  }
143
+ // ../core/src/schema.ts
144
+ var log = createLogger();
145
+ // ../core/src/registry.ts
146
+ var log2 = createLogger();
147
+ var BLOCKED_KEYS = new Set(["__proto__", "constructor", "prototype"]);
143
148
  // src/span.ts
144
149
  function createSpan(name, options = {}) {
145
150
  const id = generateId("spn");
@@ -491,7 +496,8 @@ function createCostEngine(config = {}) {
491
496
  };
492
497
  }
493
498
  // src/tracer.ts
494
- var log = createLogger();
499
+ import { writeFileSync } from "node:fs";
500
+ var log3 = createLogger();
495
501
  function observe(config = {}) {
496
502
  const {
497
503
  output = ["console"],
@@ -506,7 +512,21 @@ function observe(config = {}) {
506
512
  for (const out of output) {
507
513
  if (out === "console") {
508
514
  handlers.push(consoleHandler);
509
- } else if (out === "json-file") {} else {
515
+ } else if (out === "json-file") {
516
+ exporters.push({
517
+ name: "json-file",
518
+ export(spansToExport) {
519
+ const filename = `.elsium/traces-${Date.now()}.json`;
520
+ try {
521
+ writeFileSync(filename, JSON.stringify(spansToExport, null, 2));
522
+ } catch (err2) {
523
+ log3.error("Failed to write trace file", {
524
+ error: err2 instanceof Error ? err2.message : String(err2)
525
+ });
526
+ }
527
+ }
528
+ });
529
+ } else {
510
530
  exporters.push(out);
511
531
  }
512
532
  }
@@ -575,7 +595,7 @@ function observe(config = {}) {
575
595
  function consoleHandler(span) {
576
596
  const duration = span.durationMs !== undefined ? `${span.durationMs}ms` : "running";
577
597
  const status = span.status === "error" ? "[ERROR]" : span.status === "ok" ? "[OK]" : "[...]";
578
- log.info("span", {
598
+ log3.info("span", {
579
599
  trace: span.traceId,
580
600
  span: span.name,
581
601
  kind: span.kind,
@@ -757,41 +777,55 @@ function createAuditTrail(config) {
757
777
  let sequenceId = 0;
758
778
  let idCounter = 0;
759
779
  let previousHash = "0".repeat(64);
780
+ let isReady = true;
781
+ let readyPromise = Promise.resolve();
760
782
  if (useHashChain && storage.getLastHash) {
761
783
  const lastHash = storage.getLastHash();
762
784
  if (typeof lastHash === "string") {
763
785
  previousHash = lastHash;
764
- } else if (lastHash && typeof lastHash.then === "function") {
765
- lastHash.then((hash) => {
786
+ } else {
787
+ isReady = false;
788
+ readyPromise = lastHash.then((hash) => {
766
789
  if (typeof hash === "string")
767
790
  previousHash = hash;
791
+ isReady = true;
768
792
  });
769
793
  }
770
794
  }
795
+ function appendEntry(type, data, options) {
796
+ sequenceId++;
797
+ idCounter++;
798
+ const event = {
799
+ id: `audit_${idCounter.toString(36)}_${Date.now().toString(36)}`,
800
+ sequenceId,
801
+ type,
802
+ timestamp: Date.now(),
803
+ actor: options?.actor,
804
+ traceId: options?.traceId,
805
+ data,
806
+ previousHash: useHashChain ? previousHash : "0".repeat(64)
807
+ };
808
+ const hash = useHashChain ? computeEventHash(event, event.previousHash) : createHash("sha256").update(JSON.stringify(event)).digest("hex");
809
+ const finalEvent = { ...event, hash };
810
+ if (useHashChain) {
811
+ previousHash = hash;
812
+ }
813
+ const result = storage.append(finalEvent);
814
+ if (result && typeof result.catch === "function") {
815
+ result.catch((err2) => config?.onError?.(err2));
816
+ }
817
+ }
771
818
  return {
772
819
  log(type, data, options) {
773
- sequenceId++;
774
- idCounter++;
775
- const event = {
776
- id: `audit_${idCounter.toString(36)}_${Date.now().toString(36)}`,
777
- sequenceId,
778
- type,
779
- timestamp: Date.now(),
780
- actor: options?.actor,
781
- traceId: options?.traceId,
782
- data,
783
- previousHash: useHashChain ? previousHash : "0".repeat(64)
784
- };
785
- const hash = useHashChain ? computeEventHash(event, event.previousHash) : createHash("sha256").update(JSON.stringify(event)).digest("hex");
786
- const finalEvent = { ...event, hash };
787
- if (useHashChain) {
788
- previousHash = hash;
789
- }
790
- const result = storage.append(finalEvent);
791
- if (result && typeof result.catch === "function") {
792
- result.catch((err2) => config?.onError?.(err2));
820
+ if (isReady) {
821
+ appendEntry(type, data, options);
822
+ } else {
823
+ readyPromise = readyPromise.then(() => appendEntry(type, data, options));
793
824
  }
794
825
  },
826
+ ready() {
827
+ return readyPromise;
828
+ },
795
829
  async query(filter) {
796
830
  return storage.query(filter);
797
831
  },
@@ -891,8 +925,86 @@ function createProvenanceTracker(options) {
891
925
  }
892
926
  };
893
927
  }
928
+ // src/experiment.ts
929
+ import { createHash as createHash3 } from "node:crypto";
930
+ var log4 = createLogger();
931
+ function createExperiment(config) {
932
+ const { name, variants } = config;
933
+ if (variants.length === 0) {
934
+ throw new Error("Experiment must have at least one variant");
935
+ }
936
+ const totalWeight = variants.reduce((sum, v) => sum + v.weight, 0);
937
+ const stats = {};
938
+ for (const v of variants) {
939
+ stats[v.name] = { assignments: 0, metrics: {} };
940
+ }
941
+ function hashAssign(userId) {
942
+ const hash = createHash3("sha256").update(`${name}:${userId}`).digest();
943
+ const value = hash.readUInt32BE(0) % 1e4 / 1e4;
944
+ return pickVariant(value);
945
+ }
946
+ function randomAssign() {
947
+ const value = Math.random();
948
+ return pickVariant(value);
949
+ }
950
+ function pickVariant(value) {
951
+ let cumulative = 0;
952
+ for (const v of variants) {
953
+ cumulative += v.weight / totalWeight;
954
+ if (value < cumulative)
955
+ return v;
956
+ }
957
+ return variants[variants.length - 1];
958
+ }
959
+ return {
960
+ assign(userId) {
961
+ const variant = userId ? hashAssign(userId) : randomAssign();
962
+ const s = stats[variant.name];
963
+ if (s)
964
+ s.assignments++;
965
+ log4.debug("Experiment assignment", {
966
+ experiment: name,
967
+ variant: variant.name,
968
+ userId
969
+ });
970
+ return variant;
971
+ },
972
+ record(variant, metrics) {
973
+ const s = stats[variant];
974
+ if (!s)
975
+ return;
976
+ for (const [key, value] of Object.entries(metrics)) {
977
+ if (!s.metrics[key]) {
978
+ s.metrics[key] = { sum: 0, count: 0 };
979
+ }
980
+ s.metrics[key].sum += value;
981
+ s.metrics[key].count++;
982
+ }
983
+ },
984
+ results() {
985
+ let totalAssignments = 0;
986
+ const variantResults = {};
987
+ for (const [vName, s] of Object.entries(stats)) {
988
+ totalAssignments += s.assignments;
989
+ const metricsResult = {};
990
+ for (const [key, m] of Object.entries(s.metrics)) {
991
+ metricsResult[key] = {
992
+ sum: m.sum,
993
+ count: m.count,
994
+ avg: m.count > 0 ? m.sum / m.count : 0
995
+ };
996
+ }
997
+ variantResults[vName] = {
998
+ assignments: s.assignments,
999
+ metrics: metricsResult
1000
+ };
1001
+ }
1002
+ return { name, totalAssignments, variants: variantResults };
1003
+ }
1004
+ };
1005
+ }
894
1006
  // src/otel.ts
895
- var log2 = createLogger();
1007
+ var log5 = createLogger();
896
1008
  var SPAN_KIND_MAP = {
897
1009
  llm: 3,
898
1010
  tool: 1,
@@ -1033,10 +1145,10 @@ function createOTLPExporter(config) {
1033
1145
  body: JSON.stringify(payload)
1034
1146
  });
1035
1147
  if (!response.ok) {
1036
- log2.error(`OTLP export failed: ${response.status} ${response.statusText}`);
1148
+ log5.error(`OTLP export failed: ${response.status} ${response.statusText}`);
1037
1149
  }
1038
1150
  } catch (err2) {
1039
- log2.error("OTLP export error", { error: err2 instanceof Error ? err2.message : String(err2) });
1151
+ log5.error("OTLP export error", { error: err2 instanceof Error ? err2.message : String(err2) });
1040
1152
  }
1041
1153
  }
1042
1154
  function startAutoFlush() {
@@ -1059,6 +1171,16 @@ function createOTLPExporter(config) {
1059
1171
  } else {
1060
1172
  startAutoFlush();
1061
1173
  }
1174
+ },
1175
+ async shutdown() {
1176
+ if (flushTimer) {
1177
+ clearInterval(flushTimer);
1178
+ flushTimer = null;
1179
+ }
1180
+ if (buffer.length > 0) {
1181
+ const batch = buffer.splice(0, buffer.length);
1182
+ await sendBatch(batch);
1183
+ }
1062
1184
  }
1063
1185
  };
1064
1186
  }
@@ -1075,6 +1197,7 @@ export {
1075
1197
  createProvenanceTracker,
1076
1198
  createOTLPExporter,
1077
1199
  createMetrics,
1200
+ createExperiment,
1078
1201
  createCostEngine,
1079
1202
  createAuditTrail,
1080
1203
  auditMiddleware
@@ -1 +1 @@
1
- {"version":3,"file":"otel.d.ts","sourceRoot":"","sources":["../src/otel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"otel.d.ts","sourceRoot":"","sources":["../src/otel.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,QAAQ,CAAA;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAM9C,MAAM,WAAW,QAAQ;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,YAAY,CAAA;IAClB,iBAAiB,EAAE,MAAM,CAAA;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,aAAa,EAAE,CAAA;IAC3B,MAAM,EAAE,SAAS,EAAE,CAAA;IACnB,MAAM,EAAE;QACP,IAAI,EAAE,cAAc,CAAA;QACpB,OAAO,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACD;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAGhD,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAGtC,MAAM,WAAW,aAAa;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,kBAAkB,CAAA;CACzB;AAED,MAAM,WAAW,kBAAkB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE;QAAE,MAAM,EAAE,kBAAkB,EAAE,CAAA;KAAE,CAAA;CAC7C;AAED,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,aAAa,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,YAAY;IAC5B,UAAU,EAAE,aAAa,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,iBAAiB;IACjC,aAAa,EAAE,KAAK,CAAC;QACpB,QAAQ,EAAE,YAAY,CAAA;QACtB,UAAU,EAAE,KAAK,CAAC;YACjB,KAAK,EAAE;gBACN,IAAI,EAAE,MAAM,CAAA;gBACZ,OAAO,EAAE,MAAM,CAAA;aACf,CAAA;YACD,KAAK,EAAE,QAAQ,EAAE,CAAA;SACjB,CAAC,CAAA;KACF,CAAC,CAAA;CACF;AA+BD;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CA6BnD;AAgBD;;GAEG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,QAAQ,EAAE,EACjB,OAAO,GAAE;IACR,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;CAClB,GACJ,iBAAiB,CA0BnB;AAID,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAMpD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAapE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,QAAQ,EACd,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAClC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKxB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACzC,YAAY,GAAG,IAAI,CAIrB;AAID,MAAM,WAAW,kBAAkB;IAClC,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAA;IAChB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sBAAsB;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2BAA2B;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,cAAc,CAuE7E"}
package/dist/tracer.d.ts CHANGED
@@ -9,6 +9,7 @@ export type TracerOutput = 'console' | 'json-file' | TracerExporter;
9
9
  export interface TracerExporter {
10
10
  name: string;
11
11
  export(spans: SpanData[]): void | Promise<void>;
12
+ shutdown?(): void | Promise<void>;
12
13
  }
13
14
  export interface CostReport {
14
15
  totalCost: number;
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../src/tracer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAe,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAGnE,MAAM,WAAW,YAAY;IAC5B,MAAM,CAAC,EAAE,YAAY,EAAE,CAAA;IACvB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,CAAA;AAEnE,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/C;AAED,MAAM,WAAW,UAAU;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CACd,MAAM,EACN;QACC,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,KAAK,EAAE,MAAM,CAAA;KACb,CACD,CAAA;CACD;AAED,MAAM,WAAW,MAAM;IACtB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC9C,QAAQ,IAAI,QAAQ,EAAE,CAAA;IACtB,aAAa,IAAI,UAAU,CAAA;IAC3B,YAAY,CAAC,IAAI,EAAE;QAClB,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,EAAE,MAAM,CAAA;QACpB,IAAI,EAAE,MAAM,CAAA;QACZ,SAAS,EAAE,MAAM,CAAA;KACjB,GAAG,IAAI,CAAA;IACR,KAAK,IAAI,IAAI,CAAA;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAED,wBAAgB,OAAO,CAAC,MAAM,GAAE,YAAiB,GAAG,MAAM,CAkGzD"}
1
+ {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../src/tracer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAe,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAGnE,MAAM,WAAW,YAAY;IAC5B,MAAM,CAAC,EAAE,YAAY,EAAE,CAAA;IACvB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,CAAA;AAEnE,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,QAAQ,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACjC;AAED,MAAM,WAAW,UAAU;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CACd,MAAM,EACN;QACC,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,KAAK,EAAE,MAAM,CAAA;KACb,CACD,CAAA;CACD;AAED,MAAM,WAAW,MAAM;IACtB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC9C,QAAQ,IAAI,QAAQ,EAAE,CAAA;IACtB,aAAa,IAAI,UAAU,CAAA;IAC3B,YAAY,CAAC,IAAI,EAAE;QAClB,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,EAAE,MAAM,CAAA;QACpB,IAAI,EAAE,MAAM,CAAA;QACZ,SAAS,EAAE,MAAM,CAAA;KACjB,GAAG,IAAI,CAAA;IACR,KAAK,IAAI,IAAI,CAAA;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAED,wBAAgB,OAAO,CAAC,MAAM,GAAE,YAAiB,GAAG,MAAM,CA8GzD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elsium-ai/observe",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Observability, tracing, and cost tracking for ElsiumAI",
5
5
  "license": "MIT",
6
6
  "author": "Eric Utrera <ebutrera9103@gmail.com>",
@@ -26,7 +26,7 @@
26
26
  "dev": "bun --watch src/index.ts"
27
27
  },
28
28
  "dependencies": {
29
- "@elsium-ai/core": "^0.2.2"
29
+ "@elsium-ai/core": "^0.3.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "typescript": "^5.7.0"