@vtex/api 7.5.1-beta.1 → 7.5.1-beta.2

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/CHANGELOG.md CHANGED
@@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [7.5.1-beta.1]
8
+ ## [7.5.1-beta.2]
9
9
 
10
10
  ### Added
11
11
 
@@ -18,6 +18,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
18
18
  - `io_app_cache_operations_total{cache_state="miss"}` counts misses when a read resolves, so the
19
19
  series stays monotonic for the async caches (`LRUDiskCache`, `DiskCache`)
20
20
 
21
+ ### Changed
22
+
23
+ - `@vtex/diagnostics-nodejs` pinned to `0.2.0-io`, the IO line's current tag, replacing the
24
+ `0.1.8-io-beta.4` beta
25
+
21
26
  ## [7.5.0]
22
27
 
23
28
  ### Added
@@ -3,6 +3,7 @@ import { CumulativeStats } from '../caches/typings';
3
3
  export interface TrackedCache {
4
4
  getCumulativeStats(): CumulativeStats;
5
5
  }
6
+ type ObservableMetricOptions = Pick<MetricOptions, 'description' | 'unit'>;
6
7
  /**
7
8
  * DiagnosticsMetrics provides a high-level API for recording metrics using
8
9
  * the @vtex/diagnostics-nodejs library. It completely abstracts instrument
@@ -72,6 +73,7 @@ export declare class DiagnosticsMetrics {
72
73
  * Called automatically in constructor.
73
74
  */
74
75
  private initMetricClient;
76
+ private warnPendingRegistrations;
75
77
  /**
76
78
  * Create the single shared histogram for all latency measurements.
77
79
  * Called after metric client is initialized.
@@ -132,6 +134,11 @@ export declare class DiagnosticsMetrics {
132
134
  * is owned by whichever instrument took it first: reusing it through the other API, or
133
135
  * under the other kind, is a conflict. Reusing it in place — same API, same kind — is a
134
136
  * replace, not a conflict.
137
+ *
138
+ * Disposing leaves a gap: remove() only detaches the callback, so the meter keeps the
139
+ * instrument and this check stops seeing the name. Reusing it under the other kind from
140
+ * then on would duplicate the stream, which only bites under cumulative temporality (a
141
+ * delta export drops the orphan). Re-registering the same kind after dispose is safe.
135
142
  */
136
143
  private nameConflict;
137
144
  private pushInstruments;
@@ -195,8 +202,8 @@ export declare class DiagnosticsMetrics {
195
202
  * ```
196
203
  */
197
204
  setGauge(name: string, value: number, attributes?: Attributes): void;
198
- registerObservableGauge(name: string, observe: ObservableCallback, options?: MetricOptions): () => void;
199
- registerObservableCounter(name: string, observe: ObservableCallback, options?: MetricOptions): () => void;
205
+ registerObservableGauge(name: string, observe: ObservableCallback, options?: ObservableMetricOptions): () => void;
206
+ registerObservableCounter(name: string, observe: ObservableCallback, options?: ObservableMetricOptions): () => void;
200
207
  private registerObservable;
201
208
  private syncObservables;
202
209
  private flushPendingObservables;
@@ -204,3 +211,4 @@ export declare class DiagnosticsMetrics {
204
211
  private ensureCacheInstruments;
205
212
  private observeCaches;
206
213
  }
214
+ export {};
@@ -174,10 +174,11 @@ class DiagnosticsMetrics {
174
174
  return this.clientInitPromise;
175
175
  }
176
176
  this.clientInitPromise = (async () => {
177
+ let timeoutId;
178
+ const timeoutPromise = new Promise((_, reject) => {
179
+ timeoutId = setTimeout(() => reject(new Error('Metric client initialization timeout')), constants_1.METRIC_CLIENT_INIT_TIMEOUT_MS);
180
+ });
177
181
  try {
178
- const timeoutPromise = new Promise((_, reject) => {
179
- setTimeout(() => reject(new Error('Metric client initialization timeout')), constants_1.METRIC_CLIENT_INIT_TIMEOUT_MS);
180
- });
181
182
  this.metricsClient = await Promise.race([
182
183
  (0, client_1.getMetricClient)(),
183
184
  timeoutPromise
@@ -185,17 +186,39 @@ class DiagnosticsMetrics {
185
186
  // Create the single latency histogram after client is ready
186
187
  this.createLatencyHistogram();
187
188
  // Attach any observable registrations made before the client was ready.
188
- // No-op if there are none.
189
- this.flushPendingObservables();
189
+ try {
190
+ this.flushPendingObservables();
191
+ }
192
+ catch (error) {
193
+ // The client is up; only the pending registrations failed to attach.
194
+ console.error('Failed to attach the pending observable registrations:', error);
195
+ }
190
196
  return this.metricsClient;
191
197
  }
192
198
  catch (error) {
193
199
  console.error('Failed to initialize metric client:', error);
200
+ this.warnPendingRegistrations();
194
201
  return undefined;
195
202
  }
203
+ finally {
204
+ // Promise.race leaves the loser running, so the timeout timer needs clearing.
205
+ if (timeoutId) {
206
+ clearTimeout(timeoutId);
207
+ }
208
+ }
196
209
  })();
197
210
  return this.clientInitPromise;
198
211
  }
212
+ // Registrations that never attach should be reported once, not left for an app to
213
+ // discover through a dashboard with missing series.
214
+ warnPendingRegistrations() {
215
+ const pending = this.cacheRegistry.size +
216
+ this.observableRegistrations.gauge.size +
217
+ this.observableRegistrations.counter.size;
218
+ if (pending > 0) {
219
+ console.warn(`DiagnosticsMetrics: metric client unavailable; ${pending} pending registration(s) are not being published.`);
220
+ }
221
+ }
199
222
  /**
200
223
  * Create the single shared histogram for all latency measurements.
201
224
  * Called after metric client is initialized.
@@ -294,6 +317,11 @@ class DiagnosticsMetrics {
294
317
  * is owned by whichever instrument took it first: reusing it through the other API, or
295
318
  * under the other kind, is a conflict. Reusing it in place — same API, same kind — is a
296
319
  * replace, not a conflict.
320
+ *
321
+ * Disposing leaves a gap: remove() only detaches the callback, so the meter keeps the
322
+ * instrument and this check stops seeing the name. Reusing it under the other kind from
323
+ * then on would duplicate the stream, which only bites under cumulative temporality (a
324
+ * delta export drops the orphan). Re-registering the same kind after dispose is safe.
297
325
  */
298
326
  nameConflict(name, kind, origin) {
299
327
  if (CACHE_METRIC_NAMES.has(name)) {
@@ -477,6 +505,12 @@ class DiagnosticsMetrics {
477
505
  // Replacement for the legacy MetricsAccumulator.trackCache() over the same cache
478
506
  // instances; reads getCumulativeStats(), which has no side effects. See METRICS_CATALOG.md.
479
507
  trackCache(name, cacheInstance) {
508
+ // TrackedCache is a compile-time contract only: a JS caller, or a cache built by
509
+ // another copy of @vtex/api, would otherwise throw on every collection cycle.
510
+ if (typeof (cacheInstance === null || cacheInstance === void 0 ? void 0 : cacheInstance.getCumulativeStats) !== 'function') {
511
+ console.error(`DiagnosticsMetrics: '${name}' does not implement getCumulativeStats(); ignoring the cache registration.`);
512
+ return () => undefined;
513
+ }
480
514
  const registration = { cache: cacheInstance };
481
515
  this.cacheRegistry.set(name, registration);
482
516
  this.ensureCacheInstruments();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/api",
3
- "version": "7.5.1-beta.1",
3
+ "version": "7.5.1-beta.2",
4
4
  "description": "VTEX I/O API client",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -53,7 +53,7 @@
53
53
  "@opentelemetry/instrumentation-koa": "0.47.1",
54
54
  "@types/koa": "^2.11.0",
55
55
  "@types/koa-compose": "^3.2.3",
56
- "@vtex/diagnostics-nodejs": "0.1.8-io-beta.4",
56
+ "@vtex/diagnostics-nodejs": "0.2.0-io",
57
57
  "@vtex/diagnostics-semconv": "5.5.3",
58
58
  "@vtex/node-error-report": "^0.0.3",
59
59
  "@wry/equality": "^0.1.9",