@jaak.ai/stamps 2.1.0-dev.9 → 2.2.0-dev.1

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 (79) hide show
  1. package/README.md +42 -9
  2. package/dist/cjs/app-globals-V2Kpy_OQ.js +8 -0
  3. package/dist/cjs/app-globals-V2Kpy_OQ.js.map +1 -0
  4. package/dist/cjs/{index-BfhtOB0D.js → index-D6NBn_qu.js} +203 -121
  5. package/dist/cjs/index-D6NBn_qu.js.map +1 -0
  6. package/dist/cjs/jaak-stamps-webcomponent.cjs.js +5 -4
  7. package/dist/cjs/jaak-stamps-webcomponent.cjs.js.map +1 -1
  8. package/dist/cjs/jaak-stamps.cjs.entry.js +20219 -420
  9. package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
  10. package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
  11. package/dist/cjs/loader.cjs.js +4 -3
  12. package/dist/cjs/loader.cjs.js.map +1 -1
  13. package/dist/collection/collection-manifest.json +1 -1
  14. package/dist/collection/components/my-component/my-component.css +83 -3
  15. package/dist/collection/components/my-component/my-component.js +521 -302
  16. package/dist/collection/components/my-component/my-component.js.map +1 -1
  17. package/dist/collection/services/CameraService.js +84 -2
  18. package/dist/collection/services/CameraService.js.map +1 -1
  19. package/dist/collection/services/DetectionService.js +7 -148
  20. package/dist/collection/services/DetectionService.js.map +1 -1
  21. package/dist/collection/services/LicenseValidationService.js +111 -0
  22. package/dist/collection/services/LicenseValidationService.js.map +1 -0
  23. package/dist/collection/services/MetricsService.js +350 -0
  24. package/dist/collection/services/MetricsService.js.map +1 -0
  25. package/dist/collection/services/ServiceContainer.js +66 -1
  26. package/dist/collection/services/ServiceContainer.js.map +1 -1
  27. package/dist/collection/services/TracingService.js +442 -0
  28. package/dist/collection/services/TracingService.js.map +1 -0
  29. package/dist/collection/services/interfaces/IDetectionService.js.map +1 -1
  30. package/dist/collection/services/interfaces/ILicenseValidationService.js +2 -0
  31. package/dist/collection/services/interfaces/ILicenseValidationService.js.map +1 -0
  32. package/dist/collection/services/interfaces/IMetricsService.js +2 -0
  33. package/dist/collection/services/interfaces/IMetricsService.js.map +1 -0
  34. package/dist/collection/services/interfaces/ITracingService.js +2 -0
  35. package/dist/collection/services/interfaces/ITracingService.js.map +1 -0
  36. package/dist/components/index.js +192 -115
  37. package/dist/components/index.js.map +1 -1
  38. package/dist/components/jaak-stamps.js +20235 -423
  39. package/dist/components/jaak-stamps.js.map +1 -1
  40. package/dist/esm/app-globals-DQuL1Twl.js +6 -0
  41. package/dist/esm/app-globals-DQuL1Twl.js.map +1 -0
  42. package/dist/esm/{index-BP1Q4KOg.js → index-BCfAsrzL.js} +204 -121
  43. package/dist/esm/index-BCfAsrzL.js.map +1 -0
  44. package/dist/esm/jaak-stamps-webcomponent.js +5 -4
  45. package/dist/esm/jaak-stamps-webcomponent.js.map +1 -1
  46. package/dist/esm/jaak-stamps.entry.js +20219 -420
  47. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  48. package/dist/esm/loader.js +4 -3
  49. package/dist/esm/loader.js.map +1 -1
  50. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  51. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js.map +1 -1
  52. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  53. package/dist/jaak-stamps-webcomponent/loader.esm.js.map +1 -1
  54. package/dist/jaak-stamps-webcomponent/p-8c49893d.entry.js +7 -0
  55. package/dist/jaak-stamps-webcomponent/p-8c49893d.entry.js.map +1 -0
  56. package/dist/jaak-stamps-webcomponent/p-BCfAsrzL.js +3 -0
  57. package/dist/jaak-stamps-webcomponent/p-BCfAsrzL.js.map +1 -0
  58. package/dist/jaak-stamps-webcomponent/p-DQuL1Twl.js +2 -0
  59. package/dist/jaak-stamps-webcomponent/p-DQuL1Twl.js.map +1 -0
  60. package/dist/types/components/my-component/my-component.d.ts +24 -27
  61. package/dist/types/components.d.ts +77 -3
  62. package/dist/types/services/CameraService.d.ts +1 -0
  63. package/dist/types/services/DetectionService.d.ts +1 -9
  64. package/dist/types/services/LicenseValidationService.d.ts +59 -0
  65. package/dist/types/services/MetricsService.d.ts +74 -0
  66. package/dist/types/services/ServiceContainer.d.ts +14 -1
  67. package/dist/types/services/TracingService.d.ts +67 -0
  68. package/dist/types/services/interfaces/IDetectionService.d.ts +0 -6
  69. package/dist/types/services/interfaces/ILicenseValidationService.d.ts +4 -0
  70. package/dist/types/services/interfaces/IMetricsService.d.ts +70 -0
  71. package/dist/types/services/interfaces/ITracingService.d.ts +59 -0
  72. package/dist/types/stencil-public-runtime.d.ts +12 -5
  73. package/package.json +20 -2
  74. package/dist/cjs/index-BfhtOB0D.js.map +0 -1
  75. package/dist/esm/index-BP1Q4KOg.js.map +0 -1
  76. package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js +0 -3
  77. package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js.map +0 -1
  78. package/dist/jaak-stamps-webcomponent/p-c115e01a.entry.js +0 -2
  79. package/dist/jaak-stamps-webcomponent/p-c115e01a.entry.js.map +0 -1
@@ -0,0 +1,350 @@
1
+ import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
2
+ import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
3
+ export class MetricsService {
4
+ meterProvider = null;
5
+ meter = null;
6
+ collectorUrl;
7
+ serviceName;
8
+ serviceVersion;
9
+ debug;
10
+ customerId;
11
+ tenantId;
12
+ environment;
13
+ exportIntervalMillis;
14
+ metricReader = null;
15
+ // Business Metrics - Counters
16
+ captureCounter = null;
17
+ errorCounter = null;
18
+ modelLoadCounter = null;
19
+ userInteractionCounter = null;
20
+ // Business Metrics - Histograms (for latencies and sizes)
21
+ captureLatencyHistogram = null;
22
+ modelLoadLatencyHistogram = null;
23
+ detectionLatencyHistogram = null;
24
+ imageSizeHistogram = null;
25
+ // Business Metrics - Gauges (for current state)
26
+ activeSessionsGauge = null;
27
+ memoryUsageGauge = null;
28
+ // State tracking
29
+ activeSessions = 0;
30
+ gaugeValues = new Map();
31
+ constructor(config = {}) {
32
+ this.collectorUrl = config.collectorUrl || 'https://collector.jaak.ai/v1/metrics';
33
+ this.serviceName = config.serviceName || 'jaak-stamps-webcomponent';
34
+ this.serviceVersion = config.serviceVersion || '2.1.0';
35
+ this.debug = config.debug || false;
36
+ this.customerId = config.customerId;
37
+ this.tenantId = config.tenantId;
38
+ this.environment = config.environment || 'production';
39
+ this.exportIntervalMillis = config.exportIntervalMillis || 60000; // Export every 60 seconds
40
+ }
41
+ initialize() {
42
+ try {
43
+ // Create OTLP metrics exporter
44
+ const exporter = new OTLPMetricExporter({
45
+ url: this.collectorUrl,
46
+ headers: {
47
+ 'Content-Type': 'application/json',
48
+ },
49
+ });
50
+ // Create periodic exporting metric reader
51
+ this.metricReader = new PeriodicExportingMetricReader({
52
+ exporter: exporter,
53
+ exportIntervalMillis: this.exportIntervalMillis,
54
+ exportTimeoutMillis: 30000,
55
+ });
56
+ // Create meter provider
57
+ this.meterProvider = new MeterProvider({
58
+ readers: [this.metricReader],
59
+ });
60
+ // Get meter
61
+ this.meter = this.meterProvider.getMeter(this.serviceName, this.serviceVersion);
62
+ // Initialize business metrics
63
+ this.initializeMetrics();
64
+ if (this.debug) {
65
+ console.log('[MetricsService] Initialized successfully', {
66
+ collectorUrl: this.collectorUrl,
67
+ serviceName: this.serviceName,
68
+ serviceVersion: this.serviceVersion,
69
+ environment: this.environment,
70
+ customerId: this.customerId,
71
+ tenantId: this.tenantId,
72
+ exportIntervalMillis: this.exportIntervalMillis,
73
+ });
74
+ }
75
+ }
76
+ catch (error) {
77
+ console.error('[MetricsService] Failed to initialize:', error);
78
+ // Don't throw - metrics should fail silently in production
79
+ }
80
+ }
81
+ initializeMetrics() {
82
+ if (!this.meter)
83
+ return;
84
+ const baseAttributes = this.getBaseAttributes();
85
+ try {
86
+ // COUNTERS - Track events and totals
87
+ // Total captures performed
88
+ this.captureCounter = this.meter.createCounter('jaak.captures.total', {
89
+ description: 'Total number of document captures',
90
+ unit: '1',
91
+ });
92
+ // Total errors
93
+ this.errorCounter = this.meter.createCounter('jaak.errors.total', {
94
+ description: 'Total number of errors',
95
+ unit: '1',
96
+ });
97
+ // Model loads
98
+ this.modelLoadCounter = this.meter.createCounter('jaak.model.loads.total', {
99
+ description: 'Total number of model loads',
100
+ unit: '1',
101
+ });
102
+ // User interactions
103
+ this.userInteractionCounter = this.meter.createCounter('jaak.user.interactions.total', {
104
+ description: 'Total user interactions (clicks, etc.)',
105
+ unit: '1',
106
+ });
107
+ // HISTOGRAMS - Track distributions of latencies and sizes
108
+ // Capture latency (time from start to completion)
109
+ this.captureLatencyHistogram = this.meter.createHistogram('jaak.capture.duration', {
110
+ description: 'Duration of capture operations',
111
+ unit: 'ms',
112
+ });
113
+ // Model load latency
114
+ this.modelLoadLatencyHistogram = this.meter.createHistogram('jaak.model.load.duration', {
115
+ description: 'Duration of model loading',
116
+ unit: 'ms',
117
+ });
118
+ // Detection latency (per frame)
119
+ this.detectionLatencyHistogram = this.meter.createHistogram('jaak.detection.duration', {
120
+ description: 'Duration of detection inference',
121
+ unit: 'ms',
122
+ });
123
+ // Image sizes
124
+ this.imageSizeHistogram = this.meter.createHistogram('jaak.image.size', {
125
+ description: 'Size of captured images',
126
+ unit: 'bytes',
127
+ });
128
+ // GAUGES - Track current state values
129
+ // Active capture sessions
130
+ this.activeSessionsGauge = this.meter.createObservableGauge('jaak.sessions.active', {
131
+ description: 'Number of active capture sessions',
132
+ unit: '1',
133
+ });
134
+ this.activeSessionsGauge.addCallback((observableResult) => {
135
+ observableResult.observe(this.activeSessions, baseAttributes);
136
+ });
137
+ // Memory usage (if available)
138
+ if ('memory' in performance) {
139
+ this.memoryUsageGauge = this.meter.createObservableGauge('jaak.memory.usage', {
140
+ description: 'JavaScript heap memory usage',
141
+ unit: 'bytes',
142
+ });
143
+ this.memoryUsageGauge.addCallback((observableResult) => {
144
+ const memInfo = performance.memory;
145
+ if (memInfo) {
146
+ observableResult.observe(memInfo.usedJSHeapSize, baseAttributes);
147
+ }
148
+ });
149
+ }
150
+ if (this.debug) {
151
+ console.log('[MetricsService] Business metrics initialized');
152
+ }
153
+ }
154
+ catch (error) {
155
+ console.error('[MetricsService] Failed to initialize metrics:', error);
156
+ }
157
+ }
158
+ getBaseAttributes() {
159
+ const attributes = {
160
+ 'service.name': this.serviceName,
161
+ 'service.version': this.serviceVersion,
162
+ 'deployment.environment': this.environment,
163
+ };
164
+ if (this.customerId) {
165
+ attributes['customer.id'] = this.customerId;
166
+ }
167
+ if (this.tenantId) {
168
+ attributes['tenant.id'] = this.tenantId;
169
+ }
170
+ return attributes;
171
+ }
172
+ incrementCounter(name, value = 1, attributes) {
173
+ try {
174
+ const baseAttrs = this.getBaseAttributes();
175
+ const allAttrs = { ...baseAttrs, ...attributes };
176
+ // Use predefined counters or create ad-hoc
177
+ switch (name) {
178
+ case 'captures':
179
+ this.captureCounter?.add(value, allAttrs);
180
+ break;
181
+ case 'errors':
182
+ this.errorCounter?.add(value, allAttrs);
183
+ break;
184
+ case 'model_loads':
185
+ this.modelLoadCounter?.add(value, allAttrs);
186
+ break;
187
+ case 'user_interactions':
188
+ this.userInteractionCounter?.add(value, allAttrs);
189
+ break;
190
+ default:
191
+ // Create ad-hoc counter if needed
192
+ if (this.meter) {
193
+ const counter = this.meter.createCounter(`jaak.${name}.total`, {
194
+ description: `Total ${name}`,
195
+ unit: '1',
196
+ });
197
+ counter.add(value, allAttrs);
198
+ }
199
+ }
200
+ if (this.debug) {
201
+ console.log(`[MetricsService] Counter incremented: ${name} += ${value}`, attributes);
202
+ }
203
+ }
204
+ catch (error) {
205
+ console.error('[MetricsService] Failed to increment counter:', error);
206
+ }
207
+ }
208
+ recordHistogram(name, value, attributes) {
209
+ try {
210
+ const baseAttrs = this.getBaseAttributes();
211
+ const allAttrs = { ...baseAttrs, ...attributes };
212
+ // Use predefined histograms
213
+ switch (name) {
214
+ case 'capture_duration':
215
+ this.captureLatencyHistogram?.record(value, allAttrs);
216
+ break;
217
+ case 'model_load_duration':
218
+ this.modelLoadLatencyHistogram?.record(value, allAttrs);
219
+ break;
220
+ case 'detection_duration':
221
+ this.detectionLatencyHistogram?.record(value, allAttrs);
222
+ break;
223
+ case 'image_size':
224
+ this.imageSizeHistogram?.record(value, allAttrs);
225
+ break;
226
+ default:
227
+ // Create ad-hoc histogram if needed
228
+ if (this.meter) {
229
+ const histogram = this.meter.createHistogram(`jaak.${name}`, {
230
+ description: `Distribution of ${name}`,
231
+ unit: 'ms',
232
+ });
233
+ histogram.record(value, allAttrs);
234
+ }
235
+ }
236
+ if (this.debug) {
237
+ console.log(`[MetricsService] Histogram recorded: ${name} = ${value}`, attributes);
238
+ }
239
+ }
240
+ catch (error) {
241
+ console.error('[MetricsService] Failed to record histogram:', error);
242
+ }
243
+ }
244
+ setGauge(name, value, attributes) {
245
+ try {
246
+ // Store gauge value for observable callbacks
247
+ this.gaugeValues.set(name, value);
248
+ // Update known gauges
249
+ if (name === 'active_sessions') {
250
+ this.activeSessions = value;
251
+ }
252
+ if (this.debug) {
253
+ console.log(`[MetricsService] Gauge set: ${name} = ${value}`, attributes);
254
+ }
255
+ }
256
+ catch (error) {
257
+ console.error('[MetricsService] Failed to set gauge:', error);
258
+ }
259
+ }
260
+ async measureDuration(name, fn, attributes) {
261
+ const startTime = performance.now();
262
+ try {
263
+ const result = await fn();
264
+ const duration = performance.now() - startTime;
265
+ this.recordHistogram(name, duration, attributes);
266
+ return result;
267
+ }
268
+ catch (error) {
269
+ const duration = performance.now() - startTime;
270
+ this.recordHistogram(name, duration, { ...attributes, error: true });
271
+ throw error;
272
+ }
273
+ }
274
+ async flush() {
275
+ try {
276
+ if (this.metricReader) {
277
+ await this.metricReader.forceFlush();
278
+ }
279
+ if (this.debug) {
280
+ console.log('[MetricsService] Metrics flushed');
281
+ }
282
+ }
283
+ catch (error) {
284
+ console.error('[MetricsService] Failed to flush metrics:', error);
285
+ }
286
+ }
287
+ async cleanup() {
288
+ try {
289
+ if (this.metricReader) {
290
+ await this.metricReader.forceFlush();
291
+ await this.metricReader.shutdown();
292
+ }
293
+ if (this.meterProvider) {
294
+ await this.meterProvider.shutdown();
295
+ }
296
+ if (this.debug) {
297
+ console.log('[MetricsService] Cleaned up successfully');
298
+ }
299
+ }
300
+ catch (error) {
301
+ console.error('[MetricsService] Failed to cleanup:', error);
302
+ }
303
+ }
304
+ // Helper methods for common business metrics
305
+ /**
306
+ * Record a successful capture
307
+ */
308
+ recordCapture(side, mode, durationMs) {
309
+ this.incrementCounter('captures', 1, { side, mode });
310
+ this.recordHistogram('capture_duration', durationMs, { side, mode });
311
+ }
312
+ /**
313
+ * Record an error
314
+ */
315
+ recordError(errorType, operation) {
316
+ this.incrementCounter('errors', 1, { error_type: errorType, operation });
317
+ }
318
+ /**
319
+ * Record model load performance
320
+ */
321
+ recordModelLoad(modelType, durationMs, cached) {
322
+ this.incrementCounter('model_loads', 1, { model_type: modelType, cached });
323
+ this.recordHistogram('model_load_duration', durationMs, { model_type: modelType, cached });
324
+ }
325
+ /**
326
+ * Record detection performance
327
+ */
328
+ recordDetection(durationMs, detectionsFound) {
329
+ this.recordHistogram('detection_duration', durationMs, { detections_found: detectionsFound });
330
+ }
331
+ /**
332
+ * Record image size
333
+ */
334
+ recordImageSize(side, sizeBytes) {
335
+ this.recordHistogram('image_size', sizeBytes, { side });
336
+ }
337
+ /**
338
+ * Update active sessions count
339
+ */
340
+ updateActiveSessions(count) {
341
+ this.setGauge('active_sessions', count);
342
+ }
343
+ /**
344
+ * Record user interaction
345
+ */
346
+ recordUserInteraction(interactionType) {
347
+ this.incrementCounter('user_interactions', 1, { interaction_type: interactionType });
348
+ }
349
+ }
350
+ //# sourceMappingURL=MetricsService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricsService.js","sourceRoot":"","sources":["../../src/services/MetricsService.ts"],"names":[],"mappings":"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","sourcesContent":["import { IMetricsService } from './interfaces/IMetricsService';\nimport { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';\nimport type { Counter, Histogram, ObservableGauge, Meter } from '@opentelemetry/api';\n\nexport interface MetricsConfig {\n collectorUrl?: string;\n serviceName?: string;\n serviceVersion?: string;\n debug?: boolean;\n customerId?: string;\n tenantId?: string;\n environment?: string;\n exportIntervalMillis?: number;\n}\n\nexport class MetricsService implements IMetricsService {\n private meterProvider: MeterProvider | null = null;\n private meter: Meter | null = null;\n private readonly collectorUrl: string;\n private readonly serviceName: string;\n private readonly serviceVersion: string;\n private readonly debug: boolean;\n private readonly customerId?: string;\n private readonly tenantId?: string;\n private readonly environment?: string;\n private readonly exportIntervalMillis: number;\n private metricReader: PeriodicExportingMetricReader | null = null;\n\n // Business Metrics - Counters\n private captureCounter: Counter | null = null;\n private errorCounter: Counter | null = null;\n private modelLoadCounter: Counter | null = null;\n private userInteractionCounter: Counter | null = null;\n\n // Business Metrics - Histograms (for latencies and sizes)\n private captureLatencyHistogram: Histogram | null = null;\n private modelLoadLatencyHistogram: Histogram | null = null;\n private detectionLatencyHistogram: Histogram | null = null;\n private imageSizeHistogram: Histogram | null = null;\n\n // Business Metrics - Gauges (for current state)\n private activeSessionsGauge: ObservableGauge | null = null;\n private memoryUsageGauge: ObservableGauge | null = null;\n\n // State tracking\n private activeSessions: number = 0;\n private gaugeValues: Map<string, number> = new Map();\n\n constructor(config: MetricsConfig = {}) {\n this.collectorUrl = config.collectorUrl || 'https://collector.jaak.ai/v1/metrics';\n this.serviceName = config.serviceName || 'jaak-stamps-webcomponent';\n this.serviceVersion = config.serviceVersion || '2.1.0';\n this.debug = config.debug || false;\n this.customerId = config.customerId;\n this.tenantId = config.tenantId;\n this.environment = config.environment || 'production';\n this.exportIntervalMillis = config.exportIntervalMillis || 60000; // Export every 60 seconds\n }\n\n initialize(): void {\n try {\n // Create OTLP metrics exporter\n const exporter = new OTLPMetricExporter({\n url: this.collectorUrl,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n // Create periodic exporting metric reader\n this.metricReader = new PeriodicExportingMetricReader({\n exporter: exporter,\n exportIntervalMillis: this.exportIntervalMillis,\n exportTimeoutMillis: 30000,\n });\n\n // Create meter provider\n this.meterProvider = new MeterProvider({\n readers: [this.metricReader],\n });\n\n // Get meter\n this.meter = this.meterProvider.getMeter(this.serviceName, this.serviceVersion);\n\n // Initialize business metrics\n this.initializeMetrics();\n\n if (this.debug) {\n console.log('[MetricsService] Initialized successfully', {\n collectorUrl: this.collectorUrl,\n serviceName: this.serviceName,\n serviceVersion: this.serviceVersion,\n environment: this.environment,\n customerId: this.customerId,\n tenantId: this.tenantId,\n exportIntervalMillis: this.exportIntervalMillis,\n });\n }\n } catch (error) {\n console.error('[MetricsService] Failed to initialize:', error);\n // Don't throw - metrics should fail silently in production\n }\n }\n\n private initializeMetrics(): void {\n if (!this.meter) return;\n\n const baseAttributes = this.getBaseAttributes();\n\n try {\n // COUNTERS - Track events and totals\n\n // Total captures performed\n this.captureCounter = this.meter.createCounter('jaak.captures.total', {\n description: 'Total number of document captures',\n unit: '1',\n });\n\n // Total errors\n this.errorCounter = this.meter.createCounter('jaak.errors.total', {\n description: 'Total number of errors',\n unit: '1',\n });\n\n // Model loads\n this.modelLoadCounter = this.meter.createCounter('jaak.model.loads.total', {\n description: 'Total number of model loads',\n unit: '1',\n });\n\n // User interactions\n this.userInteractionCounter = this.meter.createCounter('jaak.user.interactions.total', {\n description: 'Total user interactions (clicks, etc.)',\n unit: '1',\n });\n\n // HISTOGRAMS - Track distributions of latencies and sizes\n\n // Capture latency (time from start to completion)\n this.captureLatencyHistogram = this.meter.createHistogram('jaak.capture.duration', {\n description: 'Duration of capture operations',\n unit: 'ms',\n });\n\n // Model load latency\n this.modelLoadLatencyHistogram = this.meter.createHistogram('jaak.model.load.duration', {\n description: 'Duration of model loading',\n unit: 'ms',\n });\n\n // Detection latency (per frame)\n this.detectionLatencyHistogram = this.meter.createHistogram('jaak.detection.duration', {\n description: 'Duration of detection inference',\n unit: 'ms',\n });\n\n // Image sizes\n this.imageSizeHistogram = this.meter.createHistogram('jaak.image.size', {\n description: 'Size of captured images',\n unit: 'bytes',\n });\n\n // GAUGES - Track current state values\n\n // Active capture sessions\n this.activeSessionsGauge = this.meter.createObservableGauge('jaak.sessions.active', {\n description: 'Number of active capture sessions',\n unit: '1',\n });\n\n this.activeSessionsGauge.addCallback((observableResult) => {\n observableResult.observe(this.activeSessions, baseAttributes);\n });\n\n // Memory usage (if available)\n if ('memory' in performance) {\n this.memoryUsageGauge = this.meter.createObservableGauge('jaak.memory.usage', {\n description: 'JavaScript heap memory usage',\n unit: 'bytes',\n });\n\n this.memoryUsageGauge.addCallback((observableResult) => {\n const memInfo = (performance as any).memory;\n if (memInfo) {\n observableResult.observe(memInfo.usedJSHeapSize, baseAttributes);\n }\n });\n }\n\n if (this.debug) {\n console.log('[MetricsService] Business metrics initialized');\n }\n } catch (error) {\n console.error('[MetricsService] Failed to initialize metrics:', error);\n }\n }\n\n private getBaseAttributes(): Record<string, any> {\n const attributes: Record<string, any> = {\n 'service.name': this.serviceName,\n 'service.version': this.serviceVersion,\n 'deployment.environment': this.environment,\n };\n\n if (this.customerId) {\n attributes['customer.id'] = this.customerId;\n }\n\n if (this.tenantId) {\n attributes['tenant.id'] = this.tenantId;\n }\n\n return attributes;\n }\n\n incrementCounter(name: string, value: number = 1, attributes?: Record<string, any>): void {\n try {\n const baseAttrs = this.getBaseAttributes();\n const allAttrs = { ...baseAttrs, ...attributes };\n\n // Use predefined counters or create ad-hoc\n switch (name) {\n case 'captures':\n this.captureCounter?.add(value, allAttrs);\n break;\n case 'errors':\n this.errorCounter?.add(value, allAttrs);\n break;\n case 'model_loads':\n this.modelLoadCounter?.add(value, allAttrs);\n break;\n case 'user_interactions':\n this.userInteractionCounter?.add(value, allAttrs);\n break;\n default:\n // Create ad-hoc counter if needed\n if (this.meter) {\n const counter = this.meter.createCounter(`jaak.${name}.total`, {\n description: `Total ${name}`,\n unit: '1',\n });\n counter.add(value, allAttrs);\n }\n }\n\n if (this.debug) {\n console.log(`[MetricsService] Counter incremented: ${name} += ${value}`, attributes);\n }\n } catch (error) {\n console.error('[MetricsService] Failed to increment counter:', error);\n }\n }\n\n recordHistogram(name: string, value: number, attributes?: Record<string, any>): void {\n try {\n const baseAttrs = this.getBaseAttributes();\n const allAttrs = { ...baseAttrs, ...attributes };\n\n // Use predefined histograms\n switch (name) {\n case 'capture_duration':\n this.captureLatencyHistogram?.record(value, allAttrs);\n break;\n case 'model_load_duration':\n this.modelLoadLatencyHistogram?.record(value, allAttrs);\n break;\n case 'detection_duration':\n this.detectionLatencyHistogram?.record(value, allAttrs);\n break;\n case 'image_size':\n this.imageSizeHistogram?.record(value, allAttrs);\n break;\n default:\n // Create ad-hoc histogram if needed\n if (this.meter) {\n const histogram = this.meter.createHistogram(`jaak.${name}`, {\n description: `Distribution of ${name}`,\n unit: 'ms',\n });\n histogram.record(value, allAttrs);\n }\n }\n\n if (this.debug) {\n console.log(`[MetricsService] Histogram recorded: ${name} = ${value}`, attributes);\n }\n } catch (error) {\n console.error('[MetricsService] Failed to record histogram:', error);\n }\n }\n\n setGauge(name: string, value: number, attributes?: Record<string, any>): void {\n try {\n // Store gauge value for observable callbacks\n this.gaugeValues.set(name, value);\n\n // Update known gauges\n if (name === 'active_sessions') {\n this.activeSessions = value;\n }\n\n if (this.debug) {\n console.log(`[MetricsService] Gauge set: ${name} = ${value}`, attributes);\n }\n } catch (error) {\n console.error('[MetricsService] Failed to set gauge:', error);\n }\n }\n\n async measureDuration<T>(name: string, fn: () => T | Promise<T>, attributes?: Record<string, any>): Promise<T> {\n const startTime = performance.now();\n\n try {\n const result = await fn();\n const duration = performance.now() - startTime;\n\n this.recordHistogram(name, duration, attributes);\n\n return result;\n } catch (error) {\n const duration = performance.now() - startTime;\n this.recordHistogram(name, duration, { ...attributes, error: true });\n throw error;\n }\n }\n\n async flush(): Promise<void> {\n try {\n if (this.metricReader) {\n await this.metricReader.forceFlush();\n }\n\n if (this.debug) {\n console.log('[MetricsService] Metrics flushed');\n }\n } catch (error) {\n console.error('[MetricsService] Failed to flush metrics:', error);\n }\n }\n\n async cleanup(): Promise<void> {\n try {\n if (this.metricReader) {\n await this.metricReader.forceFlush();\n await this.metricReader.shutdown();\n }\n\n if (this.meterProvider) {\n await this.meterProvider.shutdown();\n }\n\n if (this.debug) {\n console.log('[MetricsService] Cleaned up successfully');\n }\n } catch (error) {\n console.error('[MetricsService] Failed to cleanup:', error);\n }\n }\n\n // Helper methods for common business metrics\n\n /**\n * Record a successful capture\n */\n recordCapture(side: 'front' | 'back', mode: 'auto' | 'manual', durationMs: number): void {\n this.incrementCounter('captures', 1, { side, mode });\n this.recordHistogram('capture_duration', durationMs, { side, mode });\n }\n\n /**\n * Record an error\n */\n recordError(errorType: string, operation: string): void {\n this.incrementCounter('errors', 1, { error_type: errorType, operation });\n }\n\n /**\n * Record model load performance\n */\n recordModelLoad(modelType: 'detection' | 'classification', durationMs: number, cached: boolean): void {\n this.incrementCounter('model_loads', 1, { model_type: modelType, cached });\n this.recordHistogram('model_load_duration', durationMs, { model_type: modelType, cached });\n }\n\n /**\n * Record detection performance\n */\n recordDetection(durationMs: number, detectionsFound: number): void {\n this.recordHistogram('detection_duration', durationMs, { detections_found: detectionsFound });\n }\n\n /**\n * Record image size\n */\n recordImageSize(side: 'front' | 'back', sizeBytes: number): void {\n this.recordHistogram('image_size', sizeBytes, { side });\n }\n\n /**\n * Update active sessions count\n */\n updateActiveSessions(count: number): void {\n this.setGauge('active_sessions', count);\n }\n\n /**\n * Record user interaction\n */\n recordUserInteraction(interactionType: string): void {\n this.incrementCounter('user_interactions', 1, { interaction_type: interactionType });\n }\n}\n"]}
@@ -2,6 +2,8 @@ import { EventBusService } from "./EventBusService";
2
2
  import { StateManagerService } from "./StateManagerService";
3
3
  import { CameraService } from "./CameraService";
4
4
  import { DetectionService } from "./DetectionService";
5
+ import { TracingService } from "./TracingService";
6
+ import { MetricsService } from "./MetricsService";
5
7
  export class ServiceContainer {
6
8
  services = new Map();
7
9
  constructor(config) {
@@ -13,11 +15,48 @@ export class ServiceContainer {
13
15
  const stateManager = new StateManagerService(eventBus);
14
16
  const cameraService = new CameraService(eventBus, config.preferredCamera);
15
17
  const detectionService = new DetectionService(config.debug, config.useDocumentClassification, config.useDocumentDetector);
18
+ // Initialize tracing service if enabled
19
+ let tracingService = null;
20
+ if (config.enableTelemetry !== false) {
21
+ tracingService = new TracingService({
22
+ collectorUrl: config.telemetryCollectorUrl || 'https://collector.jaak.ai/v1/traces',
23
+ serviceName: 'jaak-stamps-webcomponent',
24
+ serviceVersion: '2.1.0',
25
+ debug: config.debug,
26
+ customerId: config.customerId,
27
+ tenantId: config.tenantId,
28
+ environment: config.environment || 'production',
29
+ propagateTraceHeaderCorsUrls: config.propagateTraceHeaderCorsUrls || [],
30
+ enableAutoInstrumentation: true,
31
+ });
32
+ tracingService.initialize();
33
+ }
34
+ // Initialize metrics service if enabled
35
+ let metricsService = null;
36
+ if (config.enableMetrics !== false) {
37
+ metricsService = new MetricsService({
38
+ collectorUrl: config.metricsCollectorUrl || 'https://collector.jaak.ai/v1/metrics',
39
+ serviceName: 'jaak-stamps-webcomponent',
40
+ serviceVersion: '2.1.0',
41
+ debug: config.debug,
42
+ customerId: config.customerId,
43
+ tenantId: config.tenantId,
44
+ environment: config.environment || 'production',
45
+ exportIntervalMillis: config.metricsExportIntervalMillis || 60000,
46
+ });
47
+ metricsService.initialize();
48
+ }
16
49
  // Register services
17
50
  this.services.set('eventBus', eventBus);
18
51
  this.services.set('stateManager', stateManager);
19
52
  this.services.set('cameraService', cameraService);
20
53
  this.services.set('detectionService', detectionService);
54
+ if (tracingService) {
55
+ this.services.set('tracingService', tracingService);
56
+ }
57
+ if (metricsService) {
58
+ this.services.set('metricsService', metricsService);
59
+ }
21
60
  }
22
61
  get(serviceName) {
23
62
  const service = this.services.get(serviceName);
@@ -38,6 +77,22 @@ export class ServiceContainer {
38
77
  getDetectionService() {
39
78
  return this.get('detectionService');
40
79
  }
80
+ getTracingService() {
81
+ try {
82
+ return this.get('tracingService');
83
+ }
84
+ catch {
85
+ return null;
86
+ }
87
+ }
88
+ getMetricsService() {
89
+ try {
90
+ return this.get('metricsService');
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ }
41
96
  updateConfig(config) {
42
97
  // Reinitialize services that depend on configuration changes
43
98
  if (config.preferredCamera !== undefined ||
@@ -47,9 +102,19 @@ export class ServiceContainer {
47
102
  // For simplicity, this is omitted in this example
48
103
  }
49
104
  }
50
- cleanup() {
105
+ async cleanup() {
51
106
  // Cleanup services in reverse order
52
107
  this.getDetectionService().cleanup();
108
+ // Cleanup metrics service if present
109
+ const metricsService = this.getMetricsService();
110
+ if (metricsService) {
111
+ await metricsService.cleanup();
112
+ }
113
+ // Cleanup tracing service if present
114
+ const tracingService = this.getTracingService();
115
+ if (tracingService) {
116
+ await tracingService.cleanup();
117
+ }
53
118
  this.getEventBus().clear();
54
119
  this.services.clear();
55
120
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ServiceContainer.js","sourceRoot":"","sources":["../../src/services/ServiceContainer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAatD,MAAM,OAAO,gBAAgB;IACnB,QAAQ,GAAG,IAAI,GAAG,EAAe,CAAC;IAE1C,YAAY,MAAuB;QACjC,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAEO,kBAAkB,CAAC,MAAuB;QAChD,0CAA0C;QAC1C,MAAM,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;QACvC,MAAM,YAAY,GAAG,IAAI,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;QAC1E,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,CAC3C,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,yBAAyB,EAChC,MAAM,CAAC,mBAAmB,CAC3B,CAAC;QAEF,oBAAoB;QACpB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;QAChD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;QAClD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IAC1D,CAAC;IAED,GAAG,CAAI,WAAmB;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,WAAW,WAAW,YAAY,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,OAAY,CAAC;IACtB,CAAC;IAGD,WAAW;QACT,OAAO,IAAI,CAAC,GAAG,CAAY,UAAU,CAAC,CAAC;IACzC,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,GAAG,CAAgB,cAAc,CAAC,CAAC;IACjD,CAAC;IAED,gBAAgB;QACd,OAAO,IAAI,CAAC,GAAG,CAAiB,eAAe,CAAC,CAAC;IACnD,CAAC;IAED,mBAAmB;QACjB,OAAO,IAAI,CAAC,GAAG,CAAoB,kBAAkB,CAAC,CAAC;IACzD,CAAC;IAED,YAAY,CAAC,MAAgC;QAC3C,6DAA6D;QAC7D,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS;YACpC,MAAM,CAAC,yBAAyB,KAAK,SAAS;YAC9C,MAAM,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;YAC7C,+CAA+C;YAC/C,kDAAkD;QACpD,CAAC;IACH,CAAC;IAED,OAAO;QACL,oCAAoC;QACpC,IAAI,CAAC,mBAAmB,EAAE,CAAC,OAAO,EAAE,CAAC;QACrC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF","sourcesContent":["import { ICameraService } from './interfaces/ICameraService';\nimport { IDetectionService } from './interfaces/IDetectionService';\nimport { IStateManager } from './interfaces/IStateManager';\nimport { IEventBus } from './interfaces/IEventBus';\n\nimport { EventBusService } from './EventBusService';\nimport { StateManagerService } from './StateManagerService';\nimport { CameraService } from './CameraService';\nimport { DetectionService } from './DetectionService';\n\nexport interface ComponentConfig {\n debug: boolean;\n alignmentTolerance: number;\n maskSize: number;\n cropMargin: number;\n useDocumentClassification: boolean;\n useDocumentDetector: boolean;\n preferredCamera: 'auto' | 'front' | 'back';\n captureDelay: number;\n}\n\nexport class ServiceContainer {\n private services = new Map<string, any>();\n\n constructor(config: ComponentConfig) {\n this.initializeServices(config);\n }\n\n private initializeServices(config: ComponentConfig): void {\n // Initialize services in dependency order\n const eventBus = new EventBusService();\n const stateManager = new StateManagerService(eventBus);\n const cameraService = new CameraService(eventBus, config.preferredCamera);\n const detectionService = new DetectionService(\n config.debug, \n config.useDocumentClassification,\n config.useDocumentDetector\n );\n\n // Register services\n this.services.set('eventBus', eventBus);\n this.services.set('stateManager', stateManager);\n this.services.set('cameraService', cameraService);\n this.services.set('detectionService', detectionService);\n }\n\n get<T>(serviceName: string): T {\n const service = this.services.get(serviceName);\n if (!service) {\n throw new Error(`Service ${serviceName} not found`);\n }\n return service as T;\n }\n\n\n getEventBus(): IEventBus {\n return this.get<IEventBus>('eventBus');\n }\n\n getStateManager(): IStateManager {\n return this.get<IStateManager>('stateManager');\n }\n\n getCameraService(): ICameraService {\n return this.get<ICameraService>('cameraService');\n }\n\n getDetectionService(): IDetectionService {\n return this.get<IDetectionService>('detectionService');\n }\n\n updateConfig(config: Partial<ComponentConfig>): void {\n // Reinitialize services that depend on configuration changes\n if (config.preferredCamera !== undefined || \n config.useDocumentClassification !== undefined ||\n config.useDocumentDetector !== undefined) {\n // Would need to reinitialize specific services\n // For simplicity, this is omitted in this example\n }\n }\n\n cleanup(): void {\n // Cleanup services in reverse order\n this.getDetectionService().cleanup();\n this.getEventBus().clear();\n this.services.clear();\n }\n}"]}
1
+ {"version":3,"file":"ServiceContainer.js","sourceRoot":"","sources":["../../src/services/ServiceContainer.ts"],"names":[],"mappings":"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","sourcesContent":["import { ICameraService } from './interfaces/ICameraService';\nimport { IDetectionService } from './interfaces/IDetectionService';\nimport { IStateManager } from './interfaces/IStateManager';\nimport { IEventBus } from './interfaces/IEventBus';\nimport { ITracingService } from './interfaces/ITracingService';\nimport { IMetricsService } from './interfaces/IMetricsService';\n\nimport { EventBusService } from './EventBusService';\nimport { StateManagerService } from './StateManagerService';\nimport { CameraService } from './CameraService';\nimport { DetectionService } from './DetectionService';\nimport { TracingService } from './TracingService';\nimport { MetricsService } from './MetricsService';\n\nexport interface ComponentConfig {\n debug: boolean;\n alignmentTolerance: number;\n maskSize: number;\n cropMargin: number;\n useDocumentClassification: boolean;\n useDocumentDetector: boolean;\n preferredCamera: 'auto' | 'front' | 'back';\n captureDelay: number;\n telemetryCollectorUrl?: string;\n metricsCollectorUrl?: string;\n enableTelemetry?: boolean;\n enableMetrics?: boolean;\n customerId?: string;\n tenantId?: string;\n environment?: string;\n propagateTraceHeaderCorsUrls?: (string | RegExp)[];\n metricsExportIntervalMillis?: number;\n}\n\nexport class ServiceContainer {\n private services = new Map<string, any>();\n\n constructor(config: ComponentConfig) {\n this.initializeServices(config);\n }\n\n private initializeServices(config: ComponentConfig): void {\n // Initialize services in dependency order\n const eventBus = new EventBusService();\n const stateManager = new StateManagerService(eventBus);\n const cameraService = new CameraService(eventBus, config.preferredCamera);\n const detectionService = new DetectionService(\n config.debug,\n config.useDocumentClassification,\n config.useDocumentDetector\n );\n\n // Initialize tracing service if enabled\n let tracingService: ITracingService | null = null;\n if (config.enableTelemetry !== false) {\n tracingService = new TracingService({\n collectorUrl: config.telemetryCollectorUrl || 'https://collector.jaak.ai/v1/traces',\n serviceName: 'jaak-stamps-webcomponent',\n serviceVersion: '2.1.0',\n debug: config.debug,\n customerId: config.customerId,\n tenantId: config.tenantId,\n environment: config.environment || 'production',\n propagateTraceHeaderCorsUrls: config.propagateTraceHeaderCorsUrls || [],\n enableAutoInstrumentation: true,\n });\n tracingService.initialize();\n }\n\n // Initialize metrics service if enabled\n let metricsService: IMetricsService | null = null;\n if (config.enableMetrics !== false) {\n metricsService = new MetricsService({\n collectorUrl: config.metricsCollectorUrl || 'https://collector.jaak.ai/v1/metrics',\n serviceName: 'jaak-stamps-webcomponent',\n serviceVersion: '2.1.0',\n debug: config.debug,\n customerId: config.customerId,\n tenantId: config.tenantId,\n environment: config.environment || 'production',\n exportIntervalMillis: config.metricsExportIntervalMillis || 60000,\n });\n metricsService.initialize();\n }\n\n // Register services\n this.services.set('eventBus', eventBus);\n this.services.set('stateManager', stateManager);\n this.services.set('cameraService', cameraService);\n this.services.set('detectionService', detectionService);\n if (tracingService) {\n this.services.set('tracingService', tracingService);\n }\n if (metricsService) {\n this.services.set('metricsService', metricsService);\n }\n }\n\n get<T>(serviceName: string): T {\n const service = this.services.get(serviceName);\n if (!service) {\n throw new Error(`Service ${serviceName} not found`);\n }\n return service as T;\n }\n\n\n getEventBus(): IEventBus {\n return this.get<IEventBus>('eventBus');\n }\n\n getStateManager(): IStateManager {\n return this.get<IStateManager>('stateManager');\n }\n\n getCameraService(): ICameraService {\n return this.get<ICameraService>('cameraService');\n }\n\n getDetectionService(): IDetectionService {\n return this.get<IDetectionService>('detectionService');\n }\n\n getTracingService(): ITracingService | null {\n try {\n return this.get<ITracingService>('tracingService');\n } catch {\n return null;\n }\n }\n\n getMetricsService(): IMetricsService | null {\n try {\n return this.get<IMetricsService>('metricsService');\n } catch {\n return null;\n }\n }\n\n updateConfig(config: Partial<ComponentConfig>): void {\n // Reinitialize services that depend on configuration changes\n if (config.preferredCamera !== undefined || \n config.useDocumentClassification !== undefined ||\n config.useDocumentDetector !== undefined) {\n // Would need to reinitialize specific services\n // For simplicity, this is omitted in this example\n }\n }\n\n async cleanup(): Promise<void> {\n // Cleanup services in reverse order\n this.getDetectionService().cleanup();\n\n // Cleanup metrics service if present\n const metricsService = this.getMetricsService();\n if (metricsService) {\n await metricsService.cleanup();\n }\n\n // Cleanup tracing service if present\n const tracingService = this.getTracingService();\n if (tracingService) {\n await tracingService.cleanup();\n }\n\n this.getEventBus().clear();\n this.services.clear();\n }\n}"]}