@tinycloud/sdk-services 2.3.0-beta.7 → 2.3.0-beta.8

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/index.cjs CHANGED
@@ -62,6 +62,7 @@ __export(index_exports, {
62
62
  ServiceRetryEventSchema: () => ServiceRetryEventSchema,
63
63
  ServiceSessionSchema: () => ServiceSessionSchema,
64
64
  TelemetryEvents: () => TelemetryEvents,
65
+ TelemetrySpanEventSchema: () => TelemetrySpanEventSchema,
65
66
  TinyCloudQuota: () => TinyCloudQuota,
66
67
  VaultHeaders: () => VaultHeaders,
67
68
  VaultPublicSpaceKVActions: () => VaultPublicSpaceKVActions,
@@ -121,6 +122,7 @@ __export(index_exports, {
121
122
  validateServiceRequestEvent: () => validateServiceRequestEvent,
122
123
  validateServiceResponseEvent: () => validateServiceResponseEvent,
123
124
  validateServiceSession: () => validateServiceSession,
125
+ validateTelemetrySpanEvent: () => validateTelemetrySpanEvent,
124
126
  verifyDecryptResponse: () => verifyDecryptResponse,
125
127
  wrapError: () => wrapError
126
128
  });
@@ -171,6 +173,7 @@ var defaultRetryPolicy = {
171
173
  retryableErrors: [ErrorCodes.NETWORK_ERROR, ErrorCodes.TIMEOUT]
172
174
  };
173
175
  var TelemetryEvents = {
176
+ SPAN: "telemetry.span",
174
177
  SERVICE_REQUEST: "service.request",
175
178
  SERVICE_RESPONSE: "service.response",
176
179
  SERVICE_ERROR: "service.error",
@@ -248,18 +251,22 @@ var KVListResultSchema = createResultSchema(KVListResponseSchema);
248
251
  var ServiceRequestEventSchema = import_zod.z.object({
249
252
  service: import_zod.z.string(),
250
253
  action: import_zod.z.string(),
254
+ span: import_zod.z.string().optional(),
251
255
  key: import_zod.z.string().optional(),
252
256
  timestamp: import_zod.z.number()
253
257
  });
254
258
  var ServiceResponseEventSchema = import_zod.z.object({
255
259
  service: import_zod.z.string(),
256
260
  action: import_zod.z.string(),
261
+ span: import_zod.z.string().optional(),
257
262
  ok: import_zod.z.boolean(),
258
263
  duration: import_zod.z.number(),
264
+ durationMs: import_zod.z.number().optional(),
259
265
  status: import_zod.z.number().optional()
260
266
  });
261
267
  var ServiceErrorEventSchema = import_zod.z.object({
262
268
  service: import_zod.z.string(),
269
+ span: import_zod.z.string().optional(),
263
270
  error: ServiceErrorSchema
264
271
  });
265
272
  var ServiceRetryEventSchema = import_zod.z.object({
@@ -268,6 +275,15 @@ var ServiceRetryEventSchema = import_zod.z.object({
268
275
  maxAttempts: import_zod.z.number().int().positive(),
269
276
  error: ServiceErrorSchema
270
277
  });
278
+ var TelemetrySpanEventSchema = import_zod.z.object({
279
+ span: import_zod.z.string(),
280
+ ok: import_zod.z.boolean(),
281
+ durationMs: import_zod.z.number(),
282
+ service: import_zod.z.string().optional(),
283
+ action: import_zod.z.string().optional(),
284
+ status: import_zod.z.number().optional(),
285
+ error: ServiceErrorSchema.optional()
286
+ });
271
287
  var RetryPolicySchema = import_zod.z.object({
272
288
  /** Maximum number of attempts (including initial) */
273
289
  maxAttempts: import_zod.z.number().int().positive(),
@@ -399,6 +415,21 @@ function validateServiceResponseEvent(data) {
399
415
  }
400
416
  return { ok: true, data: result.data };
401
417
  }
418
+ function validateTelemetrySpanEvent(data) {
419
+ const result = TelemetrySpanEventSchema.safeParse(data);
420
+ if (!result.success) {
421
+ return {
422
+ ok: false,
423
+ error: {
424
+ code: "VALIDATION_ERROR",
425
+ message: result.error.message,
426
+ service: "telemetry",
427
+ meta: { issues: result.error.issues }
428
+ }
429
+ };
430
+ }
431
+ return { ok: true, data: result.data };
432
+ }
402
433
 
403
434
  // src/context.ts
404
435
  var ServiceContext = class {
@@ -416,6 +447,8 @@ var ServiceContext = class {
416
447
  ...defaultRetryPolicy,
417
448
  ...config.retryPolicy
418
449
  };
450
+ this._telemetryEnabled = typeof config.telemetry === "boolean" ? config.telemetry : config.telemetry?.enabled === true;
451
+ this._telemetryHandler = typeof config.telemetry === "object" ? config.telemetry.onEvent : void 0;
419
452
  }
420
453
  // ============================================================
421
454
  // Session Management
@@ -510,6 +543,13 @@ var ServiceContext = class {
510
543
  * @param data - Event data
511
544
  */
512
545
  emit(event, data) {
546
+ if (this._telemetryEnabled && this._telemetryHandler) {
547
+ try {
548
+ this._telemetryHandler(event, data);
549
+ } catch (error) {
550
+ console.error(`Error in telemetry handler for "${event}":`, error);
551
+ }
552
+ }
513
553
  const handlers = this._eventHandlers.get(event);
514
554
  if (handlers) {
515
555
  for (const handler of handlers) {
@@ -788,9 +828,11 @@ var BaseService = class {
788
828
  * @param key - Optional key/path being accessed
789
829
  */
790
830
  emitRequest(action, key) {
831
+ const service = this.getServiceName();
791
832
  this.emit(TelemetryEvents.SERVICE_REQUEST, {
792
- service: this.getServiceName(),
833
+ service,
793
834
  action,
835
+ span: this.spanName(action),
794
836
  key,
795
837
  timestamp: Date.now()
796
838
  });
@@ -804,11 +846,24 @@ var BaseService = class {
804
846
  * @param status - Optional HTTP status code
805
847
  */
806
848
  emitResponse(action, ok2, startTime, status) {
849
+ const service = this.getServiceName();
850
+ const durationMs = Date.now() - startTime;
851
+ const span = this.spanName(action);
807
852
  this.emit(TelemetryEvents.SERVICE_RESPONSE, {
808
- service: this.getServiceName(),
853
+ service,
809
854
  action,
855
+ span,
810
856
  ok: ok2,
811
- duration: Date.now() - startTime,
857
+ duration: durationMs,
858
+ durationMs,
859
+ status
860
+ });
861
+ this.emit(TelemetryEvents.SPAN, {
862
+ span,
863
+ service,
864
+ action,
865
+ ok: ok2,
866
+ durationMs,
812
867
  status
813
868
  });
814
869
  }
@@ -817,9 +872,11 @@ var BaseService = class {
817
872
  *
818
873
  * @param error - The service error
819
874
  */
820
- emitError(error) {
875
+ emitError(error, action) {
876
+ const span = action ? this.spanName(action) : void 0;
821
877
  this.emit(TelemetryEvents.SERVICE_ERROR, {
822
878
  service: this.getServiceName(),
879
+ ...span ? { span } : {},
823
880
  error
824
881
  });
825
882
  }
@@ -830,6 +887,12 @@ var BaseService = class {
830
887
  getServiceName() {
831
888
  return this.constructor.serviceName;
832
889
  }
890
+ /**
891
+ * Stable span name used by SDK telemetry sinks.
892
+ */
893
+ spanName(action) {
894
+ return `sdk.${this.getServiceName()}.${action}`;
895
+ }
833
896
  /**
834
897
  * Create a combined abort signal from multiple sources.
835
898
  *
@@ -867,13 +930,13 @@ var BaseService = class {
867
930
  this.emitResponse(action, true, startTime);
868
931
  } else {
869
932
  this.emitResponse(action, false, startTime);
870
- this.emitError(result.error);
933
+ this.emitError(result.error, action);
871
934
  }
872
935
  return result;
873
936
  } catch (error) {
874
937
  const serviceError3 = wrapError(this.getServiceName(), error);
875
938
  this.emitResponse(action, false, startTime);
876
- this.emitError(serviceError3);
939
+ this.emitError(serviceError3, action);
877
940
  return err(serviceError3);
878
941
  }
879
942
  }
@@ -5685,6 +5748,7 @@ EncryptionService.serviceName = "encryption";
5685
5748
  ServiceRetryEventSchema,
5686
5749
  ServiceSessionSchema,
5687
5750
  TelemetryEvents,
5751
+ TelemetrySpanEventSchema,
5688
5752
  TinyCloudQuota,
5689
5753
  VaultHeaders,
5690
5754
  VaultPublicSpaceKVActions,
@@ -5744,6 +5808,7 @@ EncryptionService.serviceName = "encryption";
5744
5808
  validateServiceRequestEvent,
5745
5809
  validateServiceResponseEvent,
5746
5810
  validateServiceSession,
5811
+ validateTelemetrySpanEvent,
5747
5812
  verifyDecryptResponse,
5748
5813
  wrapError
5749
5814
  });