@blamejs/core 0.7.18 → 0.7.19
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 +425 -423
- package/README.md +150 -150
- package/bin/blamejs.js +0 -0
- package/index.js +310 -308
- package/lib/api-key.js +660 -660
- package/lib/api-snapshot.js +338 -338
- package/lib/app-shutdown.js +385 -385
- package/lib/app.js +365 -365
- package/lib/archive.js +250 -250
- package/lib/atomic-file.js +544 -544
- package/lib/audit-chain.js +177 -177
- package/lib/audit-sign.js +344 -344
- package/lib/audit-tools.js +677 -677
- package/lib/audit.js +766 -766
- package/lib/auth/jwt-external.js +365 -0
- package/lib/auth/jwt.js +337 -311
- package/lib/auth/lockout.js +436 -436
- package/lib/auth/oauth.js +721 -721
- package/lib/auth/passkey.js +181 -181
- package/lib/auth/password.js +628 -594
- package/lib/backup/bundle.js +217 -217
- package/lib/backup/crypto.js +176 -176
- package/lib/backup/index.js +515 -515
- package/lib/backup/manifest.js +282 -282
- package/lib/break-glass.js +1338 -1338
- package/lib/bundler.js +441 -441
- package/lib/cache-redis.js +256 -256
- package/lib/cache.js +1206 -1206
- package/lib/canonical-json.js +115 -115
- package/lib/chain-writer.js +234 -234
- package/lib/cli-helpers.js +206 -206
- package/lib/cli.js +2334 -2334
- package/lib/cluster-provider-db.js +317 -317
- package/lib/cluster-storage.js +226 -226
- package/lib/cluster.js +703 -703
- package/lib/config-drift.js +301 -301
- package/lib/consent.js +222 -222
- package/lib/constants.js +191 -191
- package/lib/cookies.js +315 -315
- package/lib/credential-hash.js +322 -322
- package/lib/crypto.js +266 -266
- package/lib/csv.js +275 -275
- package/lib/db-declare-row-policy.js +267 -267
- package/lib/db-declare-view.js +420 -420
- package/lib/db-query.js +406 -406
- package/lib/db-schema.js +319 -319
- package/lib/db.js +1288 -1288
- package/lib/deprecate.js +222 -222
- package/lib/dev.js +335 -335
- package/lib/dual-control.js +473 -473
- package/lib/error-page.js +420 -420
- package/lib/external-db-migrate.js +441 -441
- package/lib/external-db.js +1061 -1061
- package/lib/file-type.js +273 -273
- package/lib/forms.js +422 -422
- package/lib/framework-error.js +293 -293
- package/lib/framework-schema.js +717 -717
- package/lib/handlers.js +350 -350
- package/lib/http-client-cookie-jar.js +508 -508
- package/lib/http-client.js +1195 -1195
- package/lib/i18n.js +878 -878
- package/lib/jobs.js +185 -185
- package/lib/log-stream-cloudwatch.js +369 -369
- package/lib/log-stream-local.js +146 -146
- package/lib/log-stream-otlp-grpc.js +410 -410
- package/lib/log-stream-otlp.js +286 -286
- package/lib/log-stream-syslog.js +302 -302
- package/lib/log-stream-webhook.js +199 -199
- package/lib/log-stream.js +330 -330
- package/lib/log.js +500 -500
- package/lib/mail-bounce.js +528 -528
- package/lib/mail-dkim.js +369 -369
- package/lib/mail.js +981 -981
- package/lib/metrics.js +683 -683
- package/lib/middleware/api-encrypt.js +936 -936
- package/lib/middleware/attach-user.js +157 -157
- package/lib/middleware/bearer-auth.js +152 -0
- package/lib/middleware/body-parser.js +1170 -1170
- package/lib/middleware/bot-guard.js +178 -178
- package/lib/middleware/compression.js +452 -452
- package/lib/middleware/cors.js +314 -314
- package/lib/middleware/csp-nonce.js +348 -348
- package/lib/middleware/csrf-protect.js +316 -316
- package/lib/middleware/db-role-for.js +264 -264
- package/lib/middleware/health.js +392 -392
- package/lib/middleware/index.js +82 -79
- package/lib/middleware/rate-limit.js +358 -358
- package/lib/middleware/request-id.js +61 -61
- package/lib/middleware/request-log.js +168 -168
- package/lib/middleware/require-auth.js +104 -104
- package/lib/middleware/security-headers.js +116 -116
- package/lib/middleware/sse.js +166 -166
- package/lib/migrations.js +383 -383
- package/lib/mtls-ca.js +518 -518
- package/lib/mtls-engine-default.js +481 -481
- package/lib/network-dns.js +632 -632
- package/lib/network-heartbeat.js +290 -290
- package/lib/network-nts.js +574 -574
- package/lib/network-proxy.js +265 -265
- package/lib/network-tls.js +328 -328
- package/lib/network.js +233 -233
- package/lib/notify.js +612 -612
- package/lib/ntp-check.js +229 -229
- package/lib/numeric-bounds.js +111 -111
- package/lib/object-store/azure-blob-bucket-ops.js +349 -349
- package/lib/object-store/azure-blob.js +488 -488
- package/lib/object-store/gcs-bucket-ops.js +351 -351
- package/lib/object-store/gcs.js +519 -519
- package/lib/object-store/http-put.js +153 -153
- package/lib/object-store/index.js +197 -197
- package/lib/object-store/sigv4-bucket-ops.js +1092 -1092
- package/lib/object-store/sigv4.js +903 -903
- package/lib/observability.js +151 -151
- package/lib/otel-export.js +269 -269
- package/lib/pagination.js +464 -464
- package/lib/parsers/index.js +80 -80
- package/lib/parsers/safe-env.js +642 -642
- package/lib/parsers/safe-ini.js +292 -292
- package/lib/parsers/safe-toml.js +784 -784
- package/lib/parsers/safe-xml.js +390 -390
- package/lib/parsers/safe-yaml.js +1015 -1015
- package/lib/permissions.js +708 -708
- package/lib/pqc-agent.js +87 -87
- package/lib/pqc-gate.js +279 -279
- package/lib/protobuf-encoder.js +190 -190
- package/lib/protocol-dispatcher.js +161 -161
- package/lib/pubsub-redis.js +167 -167
- package/lib/pubsub.js +429 -429
- package/lib/queue-local.js +476 -476
- package/lib/queue-redis.js +745 -745
- package/lib/queue-sqs.js +319 -319
- package/lib/queue.js +695 -695
- package/lib/redis-client.js +519 -519
- package/lib/request-helpers.js +340 -340
- package/lib/restore-bundle.js +237 -237
- package/lib/restore-rollback.js +259 -259
- package/lib/restore.js +409 -409
- package/lib/retry.js +376 -376
- package/lib/router.js +748 -748
- package/lib/safe-async.js +735 -735
- package/lib/safe-buffer.js +237 -237
- package/lib/safe-json.js +541 -541
- package/lib/safe-schema.js +1266 -1266
- package/lib/safe-url.js +159 -159
- package/lib/scheduler.js +706 -706
- package/lib/security-assert.js +373 -373
- package/lib/seeders.js +618 -618
- package/lib/session.js +535 -478
- package/lib/slug.js +269 -269
- package/lib/ssrf-guard.js +401 -401
- package/lib/storage.js +471 -471
- package/lib/subject.js +281 -281
- package/lib/template.js +791 -791
- package/lib/testing.js +798 -798
- package/lib/time.js +310 -310
- package/lib/totp.js +302 -302
- package/lib/tracing.js +494 -494
- package/lib/uuid.js +132 -132
- package/lib/validate-opts.js +340 -340
- package/lib/vault/index.js +308 -308
- package/lib/vault/rotate.js +784 -784
- package/lib/vault/wrap.js +296 -296
- package/lib/vendor/noble-ciphers.cjs +9 -9
- package/lib/webhook.js +595 -595
- package/lib/websocket.js +1048 -1048
- package/package.json +77 -77
- package/sbom.cyclonedx.json +7 -7
package/lib/observability.js
CHANGED
|
@@ -1,151 +1,151 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* observability — combined metrics + tracing tap surface.
|
|
4
|
-
*
|
|
5
|
-
* Framework hot paths previously called metrics.tap + tracing.tap
|
|
6
|
-
* separately, with each module repeating the lazy-require + try/catch
|
|
7
|
-
* boilerplate. This primitive folds the two into one helper:
|
|
8
|
-
*
|
|
9
|
-
* var obs = require("./observability");
|
|
10
|
-
* return obs.tap("audit.record",
|
|
11
|
-
* { action: event.action, outcome: event.outcome },
|
|
12
|
-
* async function (span) {
|
|
13
|
-
* // ... operation body ...
|
|
14
|
-
* return result;
|
|
15
|
-
* });
|
|
16
|
-
*
|
|
17
|
-
* Behavior:
|
|
18
|
-
* - tracing.tap wraps fn in a span (spec 9.8). Pass-through is
|
|
19
|
-
* fn(null) when no tracing registry is active — zero overhead.
|
|
20
|
-
* - After fn settles (either branch), metrics.tap fires once with
|
|
21
|
-
* the same name + the same attrs reused as labels. Existing
|
|
22
|
-
* metrics _tapHandler dispatches still work unchanged because
|
|
23
|
-
* the labels are the same shape modules previously passed.
|
|
24
|
-
* - If fn throws (sync) or rejects (async), metrics still fire
|
|
25
|
-
* before the throw propagates. Operators get the counter bump
|
|
26
|
-
* even on the failure path — the existing pattern across audit /
|
|
27
|
-
* vault / queue did the same.
|
|
28
|
-
*
|
|
29
|
-
* Why combine: every framework module that wanted both a span AND a
|
|
30
|
-
* counter previously wrote nested tap wrappers + try/catch. Centralizing
|
|
31
|
-
* keeps the call sites readable, eliminates boot-order drift each
|
|
32
|
-
* module had to reason about, and lets us change tap semantics
|
|
33
|
-
* (e.g. add a third sink) in one place.
|
|
34
|
-
*
|
|
35
|
-
* For fire-and-forget value-noting where wrapping fn doesn't fit —
|
|
36
|
-
* incrementing a counter on a side-effect deep inside an existing
|
|
37
|
-
* function — use `event(name, value, labels)`. Same shape as the
|
|
38
|
-
* legacy metrics.tap call; routes through metrics only (no span).
|
|
39
|
-
*
|
|
40
|
-
* Public API:
|
|
41
|
-
* observability.tap(name, attrs, fn) → fn's return value
|
|
42
|
-
* observability.tap(name, fn) → fn's return value (no attrs)
|
|
43
|
-
* observability.event(name, value, labels) → undefined
|
|
44
|
-
*
|
|
45
|
-
* Tests live in test/layer-0-primitives/observability.test.js.
|
|
46
|
-
*
|
|
47
|
-
* Parameters:
|
|
48
|
-
* name: string — used as both the span name AND the metrics tap
|
|
49
|
-
* name. Convention: dotted lowercase ("audit.record", "queue.enqueue").
|
|
50
|
-
* attrs: object | null — passed verbatim to tracing.tap as span
|
|
51
|
-
* attributes AND to metrics.tap as labels. Modules previously
|
|
52
|
-
* passing two slightly-different objects to the two sinks should
|
|
53
|
-
* pass one unified shape.
|
|
54
|
-
* fn: function — sync or async. Return propagates; throws propagate
|
|
55
|
-
* after metrics fire.
|
|
56
|
-
*/
|
|
57
|
-
var lazyRequire = require("./lazy-require");
|
|
58
|
-
|
|
59
|
-
var tracing = lazyRequire(function () { return require("./tracing"); });
|
|
60
|
-
var metrics = lazyRequire(function () { return require("./metrics"); });
|
|
61
|
-
|
|
62
|
-
// Operator-installed tap handler — wired via setTap(). When non-null,
|
|
63
|
-
// every observability event/tap dispatch routes here in addition to
|
|
64
|
-
// the framework's metrics module. Used by b.otelExport.create() so an
|
|
65
|
-
// OTLP/HTTP exporter receives the same hot-path counters the framework
|
|
66
|
-
// emits internally.
|
|
67
|
-
var _externalTap = null;
|
|
68
|
-
|
|
69
|
-
function _safeMetricsTap(name, value, labels) {
|
|
70
|
-
try { metrics().tap(name, value, labels); }
|
|
71
|
-
catch (_e) { /* boot-order tolerance — metrics may not be loaded */ }
|
|
72
|
-
if (_externalTap !== null) {
|
|
73
|
-
try { _externalTap(name, value, labels); }
|
|
74
|
-
catch (_e) { /* operator-installed handler — drop-silent on its throws */ }
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// setTap — install an external tap handler. Operators wire this from
|
|
79
|
-
// `b.otelExport.create({...}).tapHandler` so every framework counter
|
|
80
|
-
// also lands in the operator's metrics pipeline.
|
|
81
|
-
//
|
|
82
|
-
// The handler signature mirrors metrics.tap: (name, value, labels).
|
|
83
|
-
// Pass null to remove the previously-installed handler.
|
|
84
|
-
function setTap(handler) {
|
|
85
|
-
if (handler !== null && typeof handler !== "function") {
|
|
86
|
-
throw new TypeError("observability.setTap: handler must be a function or null, got " +
|
|
87
|
-
typeof handler);
|
|
88
|
-
}
|
|
89
|
-
_externalTap = handler;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function tap(name, attrs, fn) {
|
|
93
|
-
if (typeof attrs === "function") { fn = attrs; attrs = null; }
|
|
94
|
-
// Throw on bad input: tap is called from many call sites and a typo
|
|
95
|
-
// in the name (e.g. variable holding undefined) silently corrupts
|
|
96
|
-
// both the span tree AND the metrics counter route, with no obvious
|
|
97
|
-
// symptom until somebody opens a dashboard. Throw at first call so
|
|
98
|
-
// the operator catches it.
|
|
99
|
-
if (typeof name !== "string" || name.length === 0) {
|
|
100
|
-
throw new TypeError("observability.tap: name must be a non-empty string, got " +
|
|
101
|
-
(typeof name) + " " + JSON.stringify(name));
|
|
102
|
-
}
|
|
103
|
-
if (typeof fn !== "function") {
|
|
104
|
-
throw new TypeError("observability.tap: fn must be a function, got " + (typeof fn));
|
|
105
|
-
}
|
|
106
|
-
return tracing().tap(name, attrs, function (span) {
|
|
107
|
-
var ret;
|
|
108
|
-
try {
|
|
109
|
-
ret = fn(span);
|
|
110
|
-
} catch (e) {
|
|
111
|
-
_safeMetricsTap(name, 1, attrs);
|
|
112
|
-
throw e;
|
|
113
|
-
}
|
|
114
|
-
if (ret && typeof ret.then === "function") {
|
|
115
|
-
return ret.then(
|
|
116
|
-
function (v) { _safeMetricsTap(name, 1, attrs); return v; },
|
|
117
|
-
function (e) { _safeMetricsTap(name, 1, attrs); throw e; }
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
_safeMetricsTap(name, 1, attrs);
|
|
121
|
-
return ret;
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Drop-silent on bad input by design: event is the fire-and-forget
|
|
126
|
-
// shape called from hot paths where throwing would crash the request
|
|
127
|
-
// that triggered it. Operators with a misnamed event see the missing
|
|
128
|
-
// counter, not a 500. metrics.tap performs its own label-name regex
|
|
129
|
-
// validation; an invalid call surfaces in the metrics module log, not
|
|
130
|
-
// via a thrown exception.
|
|
131
|
-
function event(name, value, labels) {
|
|
132
|
-
if (typeof name !== "string" || name.length === 0) return;
|
|
133
|
-
_safeMetricsTap(name, value, labels);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// safeEvent — wraps `event` in a try/catch so callers on hot paths
|
|
137
|
-
// (per-request observability emits) can't crash the request that
|
|
138
|
-
// triggered them when the metrics registry has a misconfigured
|
|
139
|
-
// counter or label name. Replaces the per-file `_emitEvent` helper
|
|
140
|
-
// that 7+ modules previously duplicated.
|
|
141
|
-
function safeEvent(name, value, labels) {
|
|
142
|
-
try { event(name, value, labels); }
|
|
143
|
-
catch (_e) { /* hot-path observability sink — drops silent on internal throws */ }
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
module.exports = {
|
|
147
|
-
tap: tap,
|
|
148
|
-
event: event,
|
|
149
|
-
safeEvent: safeEvent,
|
|
150
|
-
setTap: setTap,
|
|
151
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* observability — combined metrics + tracing tap surface.
|
|
4
|
+
*
|
|
5
|
+
* Framework hot paths previously called metrics.tap + tracing.tap
|
|
6
|
+
* separately, with each module repeating the lazy-require + try/catch
|
|
7
|
+
* boilerplate. This primitive folds the two into one helper:
|
|
8
|
+
*
|
|
9
|
+
* var obs = require("./observability");
|
|
10
|
+
* return obs.tap("audit.record",
|
|
11
|
+
* { action: event.action, outcome: event.outcome },
|
|
12
|
+
* async function (span) {
|
|
13
|
+
* // ... operation body ...
|
|
14
|
+
* return result;
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* Behavior:
|
|
18
|
+
* - tracing.tap wraps fn in a span (spec 9.8). Pass-through is
|
|
19
|
+
* fn(null) when no tracing registry is active — zero overhead.
|
|
20
|
+
* - After fn settles (either branch), metrics.tap fires once with
|
|
21
|
+
* the same name + the same attrs reused as labels. Existing
|
|
22
|
+
* metrics _tapHandler dispatches still work unchanged because
|
|
23
|
+
* the labels are the same shape modules previously passed.
|
|
24
|
+
* - If fn throws (sync) or rejects (async), metrics still fire
|
|
25
|
+
* before the throw propagates. Operators get the counter bump
|
|
26
|
+
* even on the failure path — the existing pattern across audit /
|
|
27
|
+
* vault / queue did the same.
|
|
28
|
+
*
|
|
29
|
+
* Why combine: every framework module that wanted both a span AND a
|
|
30
|
+
* counter previously wrote nested tap wrappers + try/catch. Centralizing
|
|
31
|
+
* keeps the call sites readable, eliminates boot-order drift each
|
|
32
|
+
* module had to reason about, and lets us change tap semantics
|
|
33
|
+
* (e.g. add a third sink) in one place.
|
|
34
|
+
*
|
|
35
|
+
* For fire-and-forget value-noting where wrapping fn doesn't fit —
|
|
36
|
+
* incrementing a counter on a side-effect deep inside an existing
|
|
37
|
+
* function — use `event(name, value, labels)`. Same shape as the
|
|
38
|
+
* legacy metrics.tap call; routes through metrics only (no span).
|
|
39
|
+
*
|
|
40
|
+
* Public API:
|
|
41
|
+
* observability.tap(name, attrs, fn) → fn's return value
|
|
42
|
+
* observability.tap(name, fn) → fn's return value (no attrs)
|
|
43
|
+
* observability.event(name, value, labels) → undefined
|
|
44
|
+
*
|
|
45
|
+
* Tests live in test/layer-0-primitives/observability.test.js.
|
|
46
|
+
*
|
|
47
|
+
* Parameters:
|
|
48
|
+
* name: string — used as both the span name AND the metrics tap
|
|
49
|
+
* name. Convention: dotted lowercase ("audit.record", "queue.enqueue").
|
|
50
|
+
* attrs: object | null — passed verbatim to tracing.tap as span
|
|
51
|
+
* attributes AND to metrics.tap as labels. Modules previously
|
|
52
|
+
* passing two slightly-different objects to the two sinks should
|
|
53
|
+
* pass one unified shape.
|
|
54
|
+
* fn: function — sync or async. Return propagates; throws propagate
|
|
55
|
+
* after metrics fire.
|
|
56
|
+
*/
|
|
57
|
+
var lazyRequire = require("./lazy-require");
|
|
58
|
+
|
|
59
|
+
var tracing = lazyRequire(function () { return require("./tracing"); });
|
|
60
|
+
var metrics = lazyRequire(function () { return require("./metrics"); });
|
|
61
|
+
|
|
62
|
+
// Operator-installed tap handler — wired via setTap(). When non-null,
|
|
63
|
+
// every observability event/tap dispatch routes here in addition to
|
|
64
|
+
// the framework's metrics module. Used by b.otelExport.create() so an
|
|
65
|
+
// OTLP/HTTP exporter receives the same hot-path counters the framework
|
|
66
|
+
// emits internally.
|
|
67
|
+
var _externalTap = null;
|
|
68
|
+
|
|
69
|
+
function _safeMetricsTap(name, value, labels) {
|
|
70
|
+
try { metrics().tap(name, value, labels); }
|
|
71
|
+
catch (_e) { /* boot-order tolerance — metrics may not be loaded */ }
|
|
72
|
+
if (_externalTap !== null) {
|
|
73
|
+
try { _externalTap(name, value, labels); }
|
|
74
|
+
catch (_e) { /* operator-installed handler — drop-silent on its throws */ }
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// setTap — install an external tap handler. Operators wire this from
|
|
79
|
+
// `b.otelExport.create({...}).tapHandler` so every framework counter
|
|
80
|
+
// also lands in the operator's metrics pipeline.
|
|
81
|
+
//
|
|
82
|
+
// The handler signature mirrors metrics.tap: (name, value, labels).
|
|
83
|
+
// Pass null to remove the previously-installed handler.
|
|
84
|
+
function setTap(handler) {
|
|
85
|
+
if (handler !== null && typeof handler !== "function") {
|
|
86
|
+
throw new TypeError("observability.setTap: handler must be a function or null, got " +
|
|
87
|
+
typeof handler);
|
|
88
|
+
}
|
|
89
|
+
_externalTap = handler;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function tap(name, attrs, fn) {
|
|
93
|
+
if (typeof attrs === "function") { fn = attrs; attrs = null; }
|
|
94
|
+
// Throw on bad input: tap is called from many call sites and a typo
|
|
95
|
+
// in the name (e.g. variable holding undefined) silently corrupts
|
|
96
|
+
// both the span tree AND the metrics counter route, with no obvious
|
|
97
|
+
// symptom until somebody opens a dashboard. Throw at first call so
|
|
98
|
+
// the operator catches it.
|
|
99
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
100
|
+
throw new TypeError("observability.tap: name must be a non-empty string, got " +
|
|
101
|
+
(typeof name) + " " + JSON.stringify(name));
|
|
102
|
+
}
|
|
103
|
+
if (typeof fn !== "function") {
|
|
104
|
+
throw new TypeError("observability.tap: fn must be a function, got " + (typeof fn));
|
|
105
|
+
}
|
|
106
|
+
return tracing().tap(name, attrs, function (span) {
|
|
107
|
+
var ret;
|
|
108
|
+
try {
|
|
109
|
+
ret = fn(span);
|
|
110
|
+
} catch (e) {
|
|
111
|
+
_safeMetricsTap(name, 1, attrs);
|
|
112
|
+
throw e;
|
|
113
|
+
}
|
|
114
|
+
if (ret && typeof ret.then === "function") {
|
|
115
|
+
return ret.then(
|
|
116
|
+
function (v) { _safeMetricsTap(name, 1, attrs); return v; },
|
|
117
|
+
function (e) { _safeMetricsTap(name, 1, attrs); throw e; }
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
_safeMetricsTap(name, 1, attrs);
|
|
121
|
+
return ret;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Drop-silent on bad input by design: event is the fire-and-forget
|
|
126
|
+
// shape called from hot paths where throwing would crash the request
|
|
127
|
+
// that triggered it. Operators with a misnamed event see the missing
|
|
128
|
+
// counter, not a 500. metrics.tap performs its own label-name regex
|
|
129
|
+
// validation; an invalid call surfaces in the metrics module log, not
|
|
130
|
+
// via a thrown exception.
|
|
131
|
+
function event(name, value, labels) {
|
|
132
|
+
if (typeof name !== "string" || name.length === 0) return;
|
|
133
|
+
_safeMetricsTap(name, value, labels);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// safeEvent — wraps `event` in a try/catch so callers on hot paths
|
|
137
|
+
// (per-request observability emits) can't crash the request that
|
|
138
|
+
// triggered them when the metrics registry has a misconfigured
|
|
139
|
+
// counter or label name. Replaces the per-file `_emitEvent` helper
|
|
140
|
+
// that 7+ modules previously duplicated.
|
|
141
|
+
function safeEvent(name, value, labels) {
|
|
142
|
+
try { event(name, value, labels); }
|
|
143
|
+
catch (_e) { /* hot-path observability sink — drops silent on internal throws */ }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = {
|
|
147
|
+
tap: tap,
|
|
148
|
+
event: event,
|
|
149
|
+
safeEvent: safeEvent,
|
|
150
|
+
setTap: setTap,
|
|
151
|
+
};
|