@jeffjassky/telemetry 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -71,6 +71,8 @@ var newCounters = () => ({
71
71
  truncated: 0,
72
72
  rollupSkippedBy: {},
73
73
  undeclaredAttrs: {},
74
+ attrsDropped: {},
75
+ metricsDropped: {},
74
76
  subjectsLinked: 0,
75
77
  subjectLinkMisses: 0,
76
78
  subjectLinkErrors: 0,
@@ -280,6 +282,7 @@ var UsageDetailSchema = new mongoose.Schema(
280
282
  { _id: false }
281
283
  );
282
284
  function buildBaseSchema(collection, registry, counters, opts) {
285
+ const validation = opts.validation;
283
286
  const schema = new mongoose.Schema(
284
287
  {
285
288
  /** UUIDv7 — sortable, insertion-local, replaces the ObjectId */
@@ -421,13 +424,39 @@ function buildBaseSchema(collection, registry, counters, opts) {
421
424
  }
422
425
  const check = (label3, m, zschema) => {
423
426
  const obj = Object.fromEntries(m ?? []);
427
+ const dropped = label3 === "attrs" ? counters.attrsDropped : counters.metricsDropped;
428
+ const note = (key) => bumpCounterMap(dropped, `${this.name}|${key}`);
424
429
  if (!zschema) {
425
- if (Object.keys(obj).length) throw new Error(`telemetry: "${this.name}" declares no ${label3}`);
430
+ if (!Object.keys(obj).length) return;
431
+ if (validation === "strict") throw new Error(`telemetry: "${this.name}" declares no ${label3}`);
432
+ for (const key of Object.keys(obj)) {
433
+ note(key);
434
+ m?.delete(key);
435
+ }
426
436
  return;
427
437
  }
428
438
  const s = zschema.strict?.() ?? zschema;
429
439
  const r = s.safeParse(obj);
430
- if (!r.success) throw new Error(`telemetry: ${label3} invalid for "${this.name}": ${r.error.message}`);
440
+ if (r.success) return;
441
+ if (validation === "strict") {
442
+ throw new Error(`telemetry: ${label3} invalid for "${this.name}": ${r.error.message}`);
443
+ }
444
+ const bad = /* @__PURE__ */ new Set();
445
+ for (const issue of r.error.issues) {
446
+ if (issue.code === "unrecognized_keys" && Array.isArray(issue.keys)) {
447
+ for (const k of issue.keys) bad.add(String(k));
448
+ } else if (Array.isArray(issue.path) && issue.path.length) {
449
+ bad.add(String(issue.path[0]));
450
+ }
451
+ }
452
+ for (const key of bad) {
453
+ if (m?.has(key)) {
454
+ note(key);
455
+ m.delete(key);
456
+ } else {
457
+ note("(missing)");
458
+ }
459
+ }
431
460
  };
432
461
  check("attrs", this.attrs, spec.attrs);
433
462
  check("metrics", this.metrics, spec.metrics);
@@ -460,7 +489,11 @@ function buildTelemetryModels(opts) {
460
489
  )
461
490
  };
462
491
  }
463
- const base = buildBaseSchema(collection, registry, counters, { platforms, bodyMax });
492
+ const base = buildBaseSchema(collection, registry, counters, {
493
+ platforms,
494
+ bodyMax,
495
+ validation: opts.validation ?? "lenient"
496
+ });
464
497
  const TelemetryModel = connection.model(modelName, base);
465
498
  const disc = (kind, build) => TelemetryModel.discriminator(`${modelName}_${kind}`, build(), kind);
466
499
  const byKind = {
@@ -3843,7 +3876,8 @@ function createTelemetry(config) {
3843
3876
  modelName,
3844
3877
  collection,
3845
3878
  platforms: config.platforms,
3846
- bodyMax: config.bodyMax
3879
+ bodyMax: config.bodyMax,
3880
+ validation: config.validation
3847
3881
  });
3848
3882
  const RollupModel = buildRollupModel(conn, `${modelName}Rollup`, `${collection}_rollups`);
3849
3883
  const CheckpointModel = buildCheckpointModel(conn, `${modelName}Checkpoint`, `${collection}_checkpoints`);