@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.
- package/README.md +42 -9
- package/dist/cjs/app-globals-V2Kpy_OQ.js +8 -0
- package/dist/cjs/app-globals-V2Kpy_OQ.js.map +1 -0
- package/dist/cjs/{index-BfhtOB0D.js → index-D6NBn_qu.js} +203 -121
- package/dist/cjs/index-D6NBn_qu.js.map +1 -0
- package/dist/cjs/jaak-stamps-webcomponent.cjs.js +5 -4
- package/dist/cjs/jaak-stamps-webcomponent.cjs.js.map +1 -1
- package/dist/cjs/jaak-stamps.cjs.entry.js +20219 -420
- package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
- package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
- package/dist/cjs/loader.cjs.js +4 -3
- package/dist/cjs/loader.cjs.js.map +1 -1
- package/dist/collection/collection-manifest.json +1 -1
- package/dist/collection/components/my-component/my-component.css +83 -3
- package/dist/collection/components/my-component/my-component.js +521 -302
- package/dist/collection/components/my-component/my-component.js.map +1 -1
- package/dist/collection/services/CameraService.js +84 -2
- package/dist/collection/services/CameraService.js.map +1 -1
- package/dist/collection/services/DetectionService.js +7 -148
- package/dist/collection/services/DetectionService.js.map +1 -1
- package/dist/collection/services/LicenseValidationService.js +111 -0
- package/dist/collection/services/LicenseValidationService.js.map +1 -0
- package/dist/collection/services/MetricsService.js +350 -0
- package/dist/collection/services/MetricsService.js.map +1 -0
- package/dist/collection/services/ServiceContainer.js +66 -1
- package/dist/collection/services/ServiceContainer.js.map +1 -1
- package/dist/collection/services/TracingService.js +442 -0
- package/dist/collection/services/TracingService.js.map +1 -0
- package/dist/collection/services/interfaces/IDetectionService.js.map +1 -1
- package/dist/collection/services/interfaces/ILicenseValidationService.js +2 -0
- package/dist/collection/services/interfaces/ILicenseValidationService.js.map +1 -0
- package/dist/collection/services/interfaces/IMetricsService.js +2 -0
- package/dist/collection/services/interfaces/IMetricsService.js.map +1 -0
- package/dist/collection/services/interfaces/ITracingService.js +2 -0
- package/dist/collection/services/interfaces/ITracingService.js.map +1 -0
- package/dist/components/index.js +192 -115
- package/dist/components/index.js.map +1 -1
- package/dist/components/jaak-stamps.js +20235 -423
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/app-globals-DQuL1Twl.js +6 -0
- package/dist/esm/app-globals-DQuL1Twl.js.map +1 -0
- package/dist/esm/{index-BP1Q4KOg.js → index-BCfAsrzL.js} +204 -121
- package/dist/esm/index-BCfAsrzL.js.map +1 -0
- package/dist/esm/jaak-stamps-webcomponent.js +5 -4
- package/dist/esm/jaak-stamps-webcomponent.js.map +1 -1
- package/dist/esm/jaak-stamps.entry.js +20219 -420
- package/dist/esm/jaak-stamps.entry.js.map +1 -1
- package/dist/esm/loader.js +4 -3
- package/dist/esm/loader.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/loader.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/p-8c49893d.entry.js +7 -0
- package/dist/jaak-stamps-webcomponent/p-8c49893d.entry.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/p-BCfAsrzL.js +3 -0
- package/dist/jaak-stamps-webcomponent/p-BCfAsrzL.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/p-DQuL1Twl.js +2 -0
- package/dist/jaak-stamps-webcomponent/p-DQuL1Twl.js.map +1 -0
- package/dist/types/components/my-component/my-component.d.ts +24 -27
- package/dist/types/components.d.ts +77 -3
- package/dist/types/services/CameraService.d.ts +1 -0
- package/dist/types/services/DetectionService.d.ts +1 -9
- package/dist/types/services/LicenseValidationService.d.ts +59 -0
- package/dist/types/services/MetricsService.d.ts +74 -0
- package/dist/types/services/ServiceContainer.d.ts +14 -1
- package/dist/types/services/TracingService.d.ts +67 -0
- package/dist/types/services/interfaces/IDetectionService.d.ts +0 -6
- package/dist/types/services/interfaces/ILicenseValidationService.d.ts +4 -0
- package/dist/types/services/interfaces/IMetricsService.d.ts +70 -0
- package/dist/types/services/interfaces/ITracingService.d.ts +59 -0
- package/dist/types/stencil-public-runtime.d.ts +12 -5
- package/package.json +20 -2
- package/dist/cjs/index-BfhtOB0D.js.map +0 -1
- package/dist/esm/index-BP1Q4KOg.js.map +0 -1
- package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js +0 -3
- package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js.map +0 -1
- package/dist/jaak-stamps-webcomponent/p-c115e01a.entry.js +0 -2
- 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":"
|
|
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}"]}
|