@fedify/fedify 2.3.0-dev.1119 → 2.3.0-dev.1137
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 +3 -0
- package/dist/{assert-DikXweDx.mjs → assert-OguE97r2.mjs} +1 -1
- package/dist/{assert_instance_of-C4Ri6VuN.mjs → assert_instance_of-DBC5X09g.mjs} +1 -1
- package/dist/{assert_not_equals--wG9hV7u.mjs → assert_not_equals-DkVK8oqV.mjs} +1 -1
- package/dist/{assert_rejects-DQP-q39h.mjs → assert_rejects-DN60FHPX.mjs} +2 -2
- package/dist/{assert_strict_equals-Dmjbg-bA.mjs → assert_strict_equals-XEgZAlrj.mjs} +1 -1
- package/dist/{assert_throws-4NwKEy2q.mjs → assert_throws-BOkhLGYc.mjs} +1 -1
- package/dist/{builder-Ond_h57y.mjs → builder-BCkBXxky.mjs} +60 -41
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/outgoing-jsonld.test.mjs +3 -3
- package/dist/compat/public-audience.test.mjs +3 -3
- package/dist/compat/transformers.test.mjs +5 -5
- package/dist/{context-cSUMk2da.d.ts → context-DCtsSHDv.d.ts} +4 -293
- package/dist/{context-Ch-ZLyTQ.d.cts → context-DI2gRbyN.d.cts} +3 -294
- package/dist/{context-BAE7AKLA.mjs → context-DVoTs_wM.mjs} +1 -1
- package/dist/{deno-DVsHS7rA.mjs → deno-B_9yJW3w.mjs} +1 -1
- package/dist/{docloader-WsWfKaE5.mjs → docloader-BT89tyFr.mjs} +3 -3
- package/dist/federation/builder.test.mjs +138 -10
- package/dist/federation/collection.test.mjs +3 -3
- package/dist/federation/handler.test.mjs +12 -12
- package/dist/federation/idempotency.test.mjs +6 -6
- package/dist/federation/inbox.test.mjs +3 -3
- package/dist/federation/keycache.test.mjs +5 -5
- package/dist/federation/kv.test.mjs +3 -3
- package/dist/federation/metrics.test.mjs +231 -3
- package/dist/federation/middleware.test.mjs +88 -18
- package/dist/federation/mod.cjs +155 -3
- package/dist/federation/mod.d.cts +3 -2
- package/dist/federation/mod.d.ts +3 -2
- package/dist/federation/mod.js +153 -1
- package/dist/federation/mq.test.mjs +5 -5
- package/dist/federation/negotiation.test.mjs +4 -4
- package/dist/federation/retry.test.mjs +3 -3
- package/dist/federation/router.test.mjs +190 -9
- package/dist/federation/send.test.mjs +16 -16
- package/dist/federation/webfinger.test.mjs +5 -5
- package/dist/{getMachineId-bsd-BY01PL1n.mjs → getMachineId-bsd-etIyxDet.mjs} +1 -1
- package/dist/{getMachineId-darwin-Dr1gkBkp.mjs → getMachineId-darwin-D23zTf4g.mjs} +1 -1
- package/dist/{getMachineId-win-QEYwcJiy.mjs → getMachineId-win-Dpap6v5i.mjs} +1 -1
- package/dist/{http-CouJSFVK.js → http-CToqG5ap.js} +252 -20
- package/dist/{http-CubOB9wq.cjs → http-CWoeyogl.cjs} +263 -19
- package/dist/{http-DUV8ysti.mjs → http-Cyx5SNuu.mjs} +8 -6
- package/dist/{http-D6LP89UO.d.ts → http-VyDTd4G3.d.cts} +8 -1
- package/dist/{http-D6aw3j2U.d.cts → http-lf8Hsd91.d.ts} +8 -1
- package/dist/{key-BoWaYRHm.mjs → key-CkkMJBjF.mjs} +42 -17
- package/dist/{kv-cache-DBNpsneh.js → kv-cache-CuCn2xvM.js} +19 -2
- package/dist/{kv-cache-Dz31ATUT.cjs → kv-cache-DuEwFYcN.cjs} +19 -2
- package/dist/{kv-cache-DihufyAQ.mjs → kv-cache-VHFP42vY.mjs} +19 -1
- package/dist/{ld-B5K1mSuG.mjs → ld-k8yqD2a-.mjs} +3 -3
- package/dist/{metrics-C4attqv0.mjs → metrics-iRBg8jTk.mjs} +209 -2
- package/dist/{middleware-CmsDtIHI.cjs → middleware-BWLUrbS9.cjs} +137 -210
- package/dist/{middleware-BDKFRjue.mjs → middleware-CztxpARM.mjs} +1 -1
- package/dist/{middleware-Dtjz-hSk.js → middleware-D7FrhN9q.js} +101 -162
- package/dist/{middleware-t0jC8I99.mjs → middleware-DQEgdr83.mjs} +64 -36
- package/dist/{mod-BDhgfjP7.d.cts → mod-B0hW12_O.d.cts} +1 -1
- package/dist/mod-C504qevA.d.cts +173 -0
- package/dist/{mod-B-Lin9Sy.d.ts → mod-COIAjwRS.d.ts} +1 -1
- package/dist/{mod-DLrRb0dx.d.ts → mod-DFvNJcNb.d.ts} +54 -3
- package/dist/mod-wYfuXeDE.d.ts +173 -0
- package/dist/{mod-BR_BB0bh.d.cts → mod-yvIXFAEi.d.cts} +54 -3
- package/dist/mod.cjs +6 -6
- package/dist/mod.d.cts +6 -5
- package/dist/mod.d.ts +6 -5
- package/dist/mod.js +5 -5
- package/dist/mq-D-nlpY04.d.ts +208 -0
- package/dist/mq-D8uSFzxe.d.cts +208 -0
- package/dist/nodeinfo/client.test.mjs +4 -4
- package/dist/nodeinfo/handler.test.mjs +5 -5
- package/dist/nodeinfo/types.test.mjs +4 -4
- package/dist/otel/exporter.test.mjs +3 -3
- package/dist/{outgoing-jsonld-BNL8AC14.mjs → outgoing-jsonld-BgFLCJQ_.mjs} +1 -1
- package/dist/{owner-hDxI0ufu.mjs → owner-nmXdvXpc.mjs} +2 -2
- package/dist/{proof-BUWfVr6Q.cjs → proof-CcsIJLTn.cjs} +1 -1
- package/dist/{proof-DhVuz4bc.mjs → proof-DpwO1T4S.mjs} +5 -5
- package/dist/{proof-n60t8o9P.js → proof-NRmtrTDu.js} +1 -1
- package/dist/{send-BPhyR5Oo.mjs → send-DvX2tYyZ.mjs} +3 -3
- package/dist/sig/accept.test.mjs +1 -1
- package/dist/sig/http.test.mjs +13 -9
- package/dist/sig/key.test.mjs +104 -7
- package/dist/sig/ld.test.mjs +7 -7
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.d.cts +2 -2
- package/dist/sig/mod.d.ts +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +6 -6
- package/dist/sig/proof.test.mjs +8 -8
- package/dist/{std__assert-BTEgfoJo.mjs → std__assert-BBjXFNOb.mjs} +4 -4
- package/dist/testing/mod.d.mts +1 -0
- package/dist/testing/mod.mjs +1 -1
- package/dist/utils/docloader.test.mjs +7 -7
- package/dist/utils/kv-cache.test.mjs +67 -2
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.d.cts +1 -1
- package/dist/utils/mod.d.ts +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +6 -7
- package/dist/mod-C6E8rkcz.d.ts +0 -63
- package/dist/mod-P9tE2WmM.d.cts +0 -63
- package/dist/router-BT_F5748.mjs +0 -114
- /package/dist/{accept-CgDcxvjV.mjs → accept-CceiKpCy.mjs} +0 -0
- /package/dist/{activity-listener-BeTGV3wc.mjs → activity-listener-tztVvlNb.mjs} +0 -0
- /package/dist/{assert_equals-Ew3jOFa3.mjs → assert_equals-C-ZRDbaf.mjs} +0 -0
- /package/dist/{client-Bneh_DYR.mjs → client-B_A6mfn3.mjs} +0 -0
- /package/dist/{collection-Cc3DVAhE.mjs → collection-CA3V5zyK.mjs} +0 -0
- /package/dist/{esm-sdtqOUPu.mjs → esm-BQRw925N.mjs} +0 -0
- /package/dist/{execAsync-Dxb7rNf3.mjs → execAsync-DCBrgFiV.mjs} +0 -0
- /package/dist/{getMachineId-linux-Bbhofx-s.mjs → getMachineId-linux-ObI47Hql.mjs} +0 -0
- /package/dist/{getMachineId-unsupported-dIOte2Ct.mjs → getMachineId-unsupported-Ddu-PFeh.mjs} +0 -0
- /package/dist/{keycache-BeU0LCII.mjs → keycache-BYMd8q7F.mjs} +0 -0
- /package/dist/{keys-CSYsOMFG.mjs → keys-C3kae-6B.mjs} +0 -0
- /package/dist/{kv-QHE0oeM3.mjs → kv-x2IvBUyq.mjs} +0 -0
- /package/dist/{negotiation-DDstyBvc.mjs → negotiation-CDW-_gUU.mjs} +0 -0
- /package/dist/{public-audience-c9zmYKgA.mjs → public-audience-N3pyOx2p.mjs} +0 -0
- /package/dist/{retry-_VvV0h9f.mjs → retry-v_sGLH1d.mjs} +0 -0
- /package/dist/{types-D09GN0uZ.mjs → types-BFowWFTT.mjs} +0 -0
|
@@ -11,7 +11,7 @@ let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conve
|
|
|
11
11
|
let byte_encodings_base64 = require("byte-encodings/base64");
|
|
12
12
|
//#region deno.json
|
|
13
13
|
var name = "@fedify/fedify";
|
|
14
|
-
var version = "2.3.0-dev.
|
|
14
|
+
var version = "2.3.0-dev.1137+53a1f26d";
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/sig/accept.ts
|
|
17
17
|
/**
|
|
@@ -172,6 +172,11 @@ var FederationMetrics = class {
|
|
|
172
172
|
fanoutRecipients;
|
|
173
173
|
inboxActivity;
|
|
174
174
|
outboxActivity;
|
|
175
|
+
keyLookup;
|
|
176
|
+
keyLookupDuration;
|
|
177
|
+
documentFetch;
|
|
178
|
+
documentFetchDuration;
|
|
179
|
+
documentCache;
|
|
175
180
|
constructor(meterProvider) {
|
|
176
181
|
const meter = meterProvider.getMeter(name, version);
|
|
177
182
|
this.deliverySent = meter.createCounter("activitypub.delivery.sent", {
|
|
@@ -278,6 +283,58 @@ var FederationMetrics = class {
|
|
|
278
283
|
description: "ActivityPub activities observed at the outbox lifecycle level: queued, retried, or abandoned. Per-recipient delivery counters live on `activitypub.delivery.*`.",
|
|
279
284
|
unit: "{activity}"
|
|
280
285
|
});
|
|
286
|
+
this.keyLookup = meter.createCounter("activitypub.key.lookup", {
|
|
287
|
+
description: "Public-key lookup attempts performed by Fedify, including both cache hits and remote fetches.",
|
|
288
|
+
unit: "{lookup}"
|
|
289
|
+
});
|
|
290
|
+
this.keyLookupDuration = meter.createHistogram("activitypub.key.lookup.duration", {
|
|
291
|
+
description: "Duration of public-key lookups performed by Fedify, including any remote fetch.",
|
|
292
|
+
unit: "ms",
|
|
293
|
+
advice: { explicitBucketBoundaries: [
|
|
294
|
+
5,
|
|
295
|
+
10,
|
|
296
|
+
25,
|
|
297
|
+
50,
|
|
298
|
+
75,
|
|
299
|
+
100,
|
|
300
|
+
250,
|
|
301
|
+
500,
|
|
302
|
+
750,
|
|
303
|
+
1e3,
|
|
304
|
+
2500,
|
|
305
|
+
5e3,
|
|
306
|
+
7500,
|
|
307
|
+
1e4
|
|
308
|
+
] }
|
|
309
|
+
});
|
|
310
|
+
this.documentFetch = meter.createCounter("activitypub.document.fetch", {
|
|
311
|
+
description: "Remote JSON-LD document loader invocations made by Fedify-wrapped loaders.",
|
|
312
|
+
unit: "{fetch}"
|
|
313
|
+
});
|
|
314
|
+
this.documentFetchDuration = meter.createHistogram("activitypub.document.fetch.duration", {
|
|
315
|
+
description: "Duration of remote JSON-LD document loader invocations made by Fedify-wrapped loaders.",
|
|
316
|
+
unit: "ms",
|
|
317
|
+
advice: { explicitBucketBoundaries: [
|
|
318
|
+
5,
|
|
319
|
+
10,
|
|
320
|
+
25,
|
|
321
|
+
50,
|
|
322
|
+
75,
|
|
323
|
+
100,
|
|
324
|
+
250,
|
|
325
|
+
500,
|
|
326
|
+
750,
|
|
327
|
+
1e3,
|
|
328
|
+
2500,
|
|
329
|
+
5e3,
|
|
330
|
+
7500,
|
|
331
|
+
1e4
|
|
332
|
+
] }
|
|
333
|
+
});
|
|
334
|
+
this.documentCache = meter.createCounter("activitypub.document.cache", {
|
|
335
|
+
description: "KV-backed document loader cache lookups, with `hit` or `miss` classification.",
|
|
336
|
+
unit: "{lookup}"
|
|
337
|
+
});
|
|
281
338
|
}
|
|
282
339
|
recordDelivery(inbox, durationMs, success, activityType) {
|
|
283
340
|
const deliveryAttributes = {
|
|
@@ -361,6 +418,36 @@ var FederationMetrics = class {
|
|
|
361
418
|
recordOutboxActivity(result, activityType) {
|
|
362
419
|
this.outboxActivity.add(1, buildActivityLifecycleAttributes(result, activityType));
|
|
363
420
|
}
|
|
421
|
+
recordKeyLookup(attrs) {
|
|
422
|
+
const attributes = {
|
|
423
|
+
"activitypub.lookup.kind": "public_key",
|
|
424
|
+
"activitypub.lookup.result": attrs.result,
|
|
425
|
+
"activitypub.cache.enabled": attrs.cacheEnabled
|
|
426
|
+
};
|
|
427
|
+
if (attrs.remoteUrl != null) attributes["activitypub.remote.host"] = getRemoteHost(attrs.remoteUrl);
|
|
428
|
+
if (attrs.statusCode != null) attributes["http.response.status_code"] = attrs.statusCode;
|
|
429
|
+
this.keyLookup.add(1, attributes);
|
|
430
|
+
this.keyLookupDuration.record(attrs.durationMs, attributes);
|
|
431
|
+
}
|
|
432
|
+
recordDocumentFetch(attrs) {
|
|
433
|
+
const attributes = {
|
|
434
|
+
"activitypub.lookup.kind": attrs.kind,
|
|
435
|
+
"activitypub.lookup.result": attrs.result
|
|
436
|
+
};
|
|
437
|
+
if (attrs.remoteUrl != null) attributes["activitypub.remote.host"] = getRemoteHost(attrs.remoteUrl);
|
|
438
|
+
if (attrs.cacheEnabled != null) attributes["activitypub.cache.enabled"] = attrs.cacheEnabled;
|
|
439
|
+
if (attrs.statusCode != null) attributes["http.response.status_code"] = attrs.statusCode;
|
|
440
|
+
this.documentFetch.add(1, attributes);
|
|
441
|
+
this.documentFetchDuration.record(attrs.durationMs, attributes);
|
|
442
|
+
}
|
|
443
|
+
recordDocumentCache(attrs) {
|
|
444
|
+
const attributes = {
|
|
445
|
+
"activitypub.lookup.kind": attrs.kind,
|
|
446
|
+
"activitypub.lookup.result": attrs.result
|
|
447
|
+
};
|
|
448
|
+
if (attrs.remoteUrl != null) attributes["activitypub.remote.host"] = getRemoteHost(attrs.remoteUrl);
|
|
449
|
+
this.documentCache.add(1, attributes);
|
|
450
|
+
}
|
|
364
451
|
};
|
|
365
452
|
function buildActivityLifecycleAttributes(result, activityType) {
|
|
366
453
|
const attributes = { "activitypub.processing.result": result };
|
|
@@ -449,6 +536,125 @@ function recordOutboxActivity(meterProvider, result, activityType) {
|
|
|
449
536
|
getFederationMetrics(meterProvider).recordOutboxActivity(result, activityType);
|
|
450
537
|
}
|
|
451
538
|
/**
|
|
539
|
+
* Records one measurement on `activitypub.key.lookup` (counter) and
|
|
540
|
+
* `activitypub.key.lookup.duration` (histogram) for a public-key lookup.
|
|
541
|
+
*
|
|
542
|
+
* `activitypub.lookup.kind` is always recorded as `public_key`; the result
|
|
543
|
+
* classification, remote host, HTTP status code (when an HTTP response was
|
|
544
|
+
* received), and `activitypub.cache.enabled` are recorded as attributes on
|
|
545
|
+
* both measurements. Full key URLs and key IDs are deliberately omitted to
|
|
546
|
+
* keep cardinality bounded.
|
|
547
|
+
* @since 2.3.0
|
|
548
|
+
*/
|
|
549
|
+
function recordKeyLookup(meterProvider, attrs) {
|
|
550
|
+
getFederationMetrics(meterProvider).recordKeyLookup(attrs);
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Records one measurement each on `activitypub.document.fetch` (counter)
|
|
554
|
+
* and `activitypub.document.fetch.duration` (histogram) for one remote
|
|
555
|
+
* JSON-LD document loader invocation, with bounded
|
|
556
|
+
* `activitypub.lookup.kind` and `activitypub.lookup.result` attributes
|
|
557
|
+
* plus the optional remote-host, cache-enabled, and HTTP status-code
|
|
558
|
+
* attributes. Counter and histogram are always recorded together so
|
|
559
|
+
* aggregate rate and latency views stay in sync.
|
|
560
|
+
* @since 2.3.0
|
|
561
|
+
*/
|
|
562
|
+
function recordDocumentFetch(meterProvider, attrs) {
|
|
563
|
+
getFederationMetrics(meterProvider).recordDocumentFetch(attrs);
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Records one `activitypub.document.cache` measurement, classifying the
|
|
567
|
+
* lookup as `hit` (the cache returned an entry) or `miss` (the cache was
|
|
568
|
+
* consulted and returned nothing, prompting a delegate fetch).
|
|
569
|
+
* @since 2.3.0
|
|
570
|
+
*/
|
|
571
|
+
function recordDocumentCache(meterProvider, attrs) {
|
|
572
|
+
getFederationMetrics(meterProvider).recordDocumentCache(attrs);
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Classifies a thrown value from a key or document fetch into the bounded
|
|
576
|
+
* {@link LookupResult} taxonomy and, when an HTTP response was received,
|
|
577
|
+
* surfaces its status code.
|
|
578
|
+
*
|
|
579
|
+
* - `FetchError` with a `Response` whose status is `404` or `410`:
|
|
580
|
+
* `result=not_found` and the response status code.
|
|
581
|
+
* - `FetchError` with any other `Response`: `result=error` and the
|
|
582
|
+
* response status code.
|
|
583
|
+
* - `FetchError` without a `Response`: `result=network_error`.
|
|
584
|
+
* - An `AbortError` (typically from a cancelled fetch): `result=network_error`.
|
|
585
|
+
* - A bare `TypeError` (the shape native `fetch()` raises on DNS, connect,
|
|
586
|
+
* and TLS failures before any response is observed):
|
|
587
|
+
* `result=network_error`.
|
|
588
|
+
* - Any other value: `result=error`.
|
|
589
|
+
* @since 2.3.0
|
|
590
|
+
*/
|
|
591
|
+
function classifyFetchError(error) {
|
|
592
|
+
if (error instanceof _fedify_vocab_runtime.FetchError) {
|
|
593
|
+
if (error.response != null) {
|
|
594
|
+
const status = error.response.status;
|
|
595
|
+
return {
|
|
596
|
+
result: status === 404 || status === 410 ? "not_found" : "error",
|
|
597
|
+
statusCode: status
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
return { result: "network_error" };
|
|
601
|
+
}
|
|
602
|
+
if (isAbortError$1(error)) return { result: "network_error" };
|
|
603
|
+
if (error instanceof TypeError) return { result: "network_error" };
|
|
604
|
+
return { result: "error" };
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Wraps a {@link DocumentLoader} so each invocation records one
|
|
608
|
+
* measurement on `activitypub.document.fetch` (counter) and one on
|
|
609
|
+
* `activitypub.document.fetch.duration` (histogram), classifying the
|
|
610
|
+
* outcome via {@link classifyFetchError} when the wrapped loader throws
|
|
611
|
+
* and as `fetched` on success. The wrapper rethrows whatever the
|
|
612
|
+
* wrapped loader throws so caller behavior is unchanged.
|
|
613
|
+
*
|
|
614
|
+
* The wrapper records the hostname of the requested URL on
|
|
615
|
+
* `activitypub.remote.host` when the URL parses; full URLs, paths, and
|
|
616
|
+
* query strings are deliberately excluded to keep cardinality bounded.
|
|
617
|
+
* HTTP status codes are recorded only when the failure carries a
|
|
618
|
+
* `Response` (currently, when the wrapped loader throws a
|
|
619
|
+
* {@link FetchError} with a non-`null` `response`).
|
|
620
|
+
* @since 2.3.0
|
|
621
|
+
*/
|
|
622
|
+
function instrumentDocumentLoader(loader, options) {
|
|
623
|
+
const meterProvider = options.meterProvider;
|
|
624
|
+
if (meterProvider == null) return loader;
|
|
625
|
+
return async (url, opts) => {
|
|
626
|
+
const start = performance.now();
|
|
627
|
+
let remoteUrl;
|
|
628
|
+
try {
|
|
629
|
+
remoteUrl = new URL(url);
|
|
630
|
+
} catch {
|
|
631
|
+
remoteUrl = void 0;
|
|
632
|
+
}
|
|
633
|
+
try {
|
|
634
|
+
const result = await loader(url, opts);
|
|
635
|
+
recordDocumentFetch(meterProvider, {
|
|
636
|
+
durationMs: getDurationMs(start),
|
|
637
|
+
kind: options.kind,
|
|
638
|
+
result: "fetched",
|
|
639
|
+
remoteUrl,
|
|
640
|
+
cacheEnabled: options.cacheEnabled
|
|
641
|
+
});
|
|
642
|
+
return result;
|
|
643
|
+
} catch (error) {
|
|
644
|
+
const classified = classifyFetchError(error);
|
|
645
|
+
recordDocumentFetch(meterProvider, {
|
|
646
|
+
durationMs: getDurationMs(start),
|
|
647
|
+
kind: options.kind,
|
|
648
|
+
result: classified.result,
|
|
649
|
+
remoteUrl,
|
|
650
|
+
cacheEnabled: options.cacheEnabled,
|
|
651
|
+
statusCode: classified.statusCode
|
|
652
|
+
});
|
|
653
|
+
throw error;
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
452
658
|
* Times an awaited public key fetch and records exactly one
|
|
453
659
|
* `activitypub.signature.key_fetch.duration` measurement, classifying the
|
|
454
660
|
* outcome as `hit`, `fetched`, or `error` based on the `cached` flag and
|
|
@@ -828,24 +1034,48 @@ async function resolveFetchedKey(document, cacheKey, keyId, cls, { documentLoade
|
|
|
828
1034
|
};
|
|
829
1035
|
}
|
|
830
1036
|
async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, onFetchError) {
|
|
831
|
-
const
|
|
832
|
-
|
|
833
|
-
"sig",
|
|
834
|
-
"key"
|
|
835
|
-
]);
|
|
836
|
-
const keyId = cacheKey.href;
|
|
837
|
-
const keyCache = options.keyCache;
|
|
838
|
-
const cached = await getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger);
|
|
839
|
-
if (cached?.key === null && cached.cached) return await onCachedUnavailable(cacheKey, keyId, keyCache, logger);
|
|
840
|
-
if (cached != null) return cached;
|
|
841
|
-
logger.debug("Fetching key {keyId} to verify signature...", { keyId });
|
|
842
|
-
let document;
|
|
1037
|
+
const start = performance.now();
|
|
1038
|
+
let outcome = { result: "error" };
|
|
843
1039
|
try {
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
1040
|
+
const logger = (0, _logtape_logtape.getLogger)([
|
|
1041
|
+
"fedify",
|
|
1042
|
+
"sig",
|
|
1043
|
+
"key"
|
|
1044
|
+
]);
|
|
1045
|
+
const keyId = cacheKey.href;
|
|
1046
|
+
const keyCache = options.keyCache;
|
|
1047
|
+
const cached = await getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger);
|
|
1048
|
+
if (cached?.key === null && cached.cached) {
|
|
1049
|
+
const cachedUnavailable = await onCachedUnavailable(cacheKey, keyId, keyCache, logger);
|
|
1050
|
+
outcome = { result: "hit" };
|
|
1051
|
+
return cachedUnavailable;
|
|
1052
|
+
}
|
|
1053
|
+
if (cached != null) {
|
|
1054
|
+
outcome = { result: "hit" };
|
|
1055
|
+
return cached;
|
|
1056
|
+
}
|
|
1057
|
+
logger.debug("Fetching key {keyId} to verify signature...", { keyId });
|
|
1058
|
+
let document;
|
|
1059
|
+
try {
|
|
1060
|
+
document = (await (options.documentLoader ?? (0, _fedify_vocab_runtime.getDocumentLoader)())(keyId)).document;
|
|
1061
|
+
} catch (error) {
|
|
1062
|
+
const classified = classifyFetchError(error);
|
|
1063
|
+
const errored = await onFetchError(error, cacheKey, keyId, keyCache, logger);
|
|
1064
|
+
outcome = classified;
|
|
1065
|
+
return errored;
|
|
1066
|
+
}
|
|
1067
|
+
const resolved = await resolveFetchedKey(document, cacheKey, keyId, cls, options, logger);
|
|
1068
|
+
outcome = { result: resolved.key != null ? "fetched" : "invalid" };
|
|
1069
|
+
return resolved;
|
|
1070
|
+
} finally {
|
|
1071
|
+
recordKeyLookup(options.meterProvider, {
|
|
1072
|
+
durationMs: getDurationMs(start),
|
|
1073
|
+
result: outcome.result,
|
|
1074
|
+
remoteUrl: cacheKey,
|
|
1075
|
+
cacheEnabled: options.keyCache != null,
|
|
1076
|
+
statusCode: outcome.statusCode
|
|
1077
|
+
});
|
|
847
1078
|
}
|
|
848
|
-
return await resolveFetchedKey(document, cacheKey, keyId, cls, options, logger);
|
|
849
1079
|
}
|
|
850
1080
|
async function fetchKeyInternal(keyId, cls, options = {}) {
|
|
851
1081
|
return await fetchKeyWithResult(typeof keyId === "string" ? new URL(keyId) : keyId, cls, options, (_cacheKey, _keyId, _keyCache, _logger) => {
|
|
@@ -1427,7 +1657,8 @@ async function verifyRequestDraft(request, span, metricsContext, { documentLoade
|
|
|
1427
1657
|
documentLoader,
|
|
1428
1658
|
contextLoader,
|
|
1429
1659
|
keyCache,
|
|
1430
|
-
tracerProvider
|
|
1660
|
+
tracerProvider,
|
|
1661
|
+
meterProvider
|
|
1431
1662
|
}));
|
|
1432
1663
|
if (fetchError != null) return keyFetchErrorResult(keyIdUrl, fetchError);
|
|
1433
1664
|
if (key == null) return invalidSignatureResult(keyIdUrl);
|
|
@@ -1642,7 +1873,8 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
1642
1873
|
documentLoader,
|
|
1643
1874
|
contextLoader,
|
|
1644
1875
|
keyCache,
|
|
1645
|
-
tracerProvider
|
|
1876
|
+
tracerProvider,
|
|
1877
|
+
meterProvider
|
|
1646
1878
|
}));
|
|
1647
1879
|
if (fetchError != null) {
|
|
1648
1880
|
setFailure(keyFetchErrorResult(keyId, fetchError));
|
|
@@ -2011,6 +2243,12 @@ Object.defineProperty(exports, "importJwk", {
|
|
|
2011
2243
|
return importJwk;
|
|
2012
2244
|
}
|
|
2013
2245
|
});
|
|
2246
|
+
Object.defineProperty(exports, "instrumentDocumentLoader", {
|
|
2247
|
+
enumerable: true,
|
|
2248
|
+
get: function() {
|
|
2249
|
+
return instrumentDocumentLoader;
|
|
2250
|
+
}
|
|
2251
|
+
});
|
|
2014
2252
|
Object.defineProperty(exports, "isAbortError", {
|
|
2015
2253
|
enumerable: true,
|
|
2016
2254
|
get: function() {
|
|
@@ -2041,6 +2279,12 @@ Object.defineProperty(exports, "parseRfc9421SignatureInput", {
|
|
|
2041
2279
|
return parseRfc9421SignatureInput;
|
|
2042
2280
|
}
|
|
2043
2281
|
});
|
|
2282
|
+
Object.defineProperty(exports, "recordDocumentCache", {
|
|
2283
|
+
enumerable: true,
|
|
2284
|
+
get: function() {
|
|
2285
|
+
return recordDocumentCache;
|
|
2286
|
+
}
|
|
2287
|
+
});
|
|
2044
2288
|
Object.defineProperty(exports, "recordFanoutRecipients", {
|
|
2045
2289
|
enumerable: true,
|
|
2046
2290
|
get: function() {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import {
|
|
6
|
-
import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-
|
|
7
|
-
import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-
|
|
4
|
+
import { n as version, t as name } from "./deno-B_9yJW3w.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-iRBg8jTk.mjs";
|
|
6
|
+
import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CceiKpCy.mjs";
|
|
7
|
+
import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-CkkMJBjF.mjs";
|
|
8
8
|
import { getLogger } from "@logtape/logtape";
|
|
9
9
|
import { CryptographicKey } from "@fedify/vocab";
|
|
10
10
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -569,7 +569,8 @@ async function verifyRequestDraft(request, span, metricsContext, { documentLoade
|
|
|
569
569
|
documentLoader,
|
|
570
570
|
contextLoader,
|
|
571
571
|
keyCache,
|
|
572
|
-
tracerProvider
|
|
572
|
+
tracerProvider,
|
|
573
|
+
meterProvider
|
|
573
574
|
}));
|
|
574
575
|
if (fetchError != null) return keyFetchErrorResult(keyIdUrl, fetchError);
|
|
575
576
|
if (key == null) return invalidSignatureResult(keyIdUrl);
|
|
@@ -784,7 +785,8 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
784
785
|
documentLoader,
|
|
785
786
|
contextLoader,
|
|
786
787
|
keyCache,
|
|
787
|
-
tracerProvider
|
|
788
|
+
tracerProvider,
|
|
789
|
+
meterProvider
|
|
788
790
|
}));
|
|
789
791
|
if (fetchError != null) {
|
|
790
792
|
setFailure(keyFetchErrorResult(keyId, fetchError));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
2
|
import { CryptographicKey, Multikey } from "@fedify/vocab";
|
|
3
|
-
import { MeterProvider, TracerProvider } from "@opentelemetry/api";
|
|
4
3
|
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
4
|
+
import { MeterProvider, TracerProvider } from "@opentelemetry/api";
|
|
5
5
|
|
|
6
6
|
//#region src/sig/key.d.ts
|
|
7
7
|
/**
|
|
@@ -52,6 +52,13 @@ interface FetchKeyOptions {
|
|
|
52
52
|
* @since 1.3.0
|
|
53
53
|
*/
|
|
54
54
|
tracerProvider?: TracerProvider;
|
|
55
|
+
/**
|
|
56
|
+
* The OpenTelemetry meter provider to use for recording
|
|
57
|
+
* `activitypub.key.lookup` and `activitypub.key.lookup.duration`. If
|
|
58
|
+
* omitted, the global meter provider is used.
|
|
59
|
+
* @since 2.3.0
|
|
60
|
+
*/
|
|
61
|
+
meterProvider?: MeterProvider;
|
|
55
62
|
}
|
|
56
63
|
/**
|
|
57
64
|
* The result of {@link fetchKey}.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
2
|
import { CryptographicKey, Multikey } from "@fedify/vocab";
|
|
3
|
-
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
4
3
|
import { MeterProvider, TracerProvider } from "@opentelemetry/api";
|
|
4
|
+
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
5
5
|
|
|
6
6
|
//#region src/sig/key.d.ts
|
|
7
7
|
/**
|
|
@@ -52,6 +52,13 @@ interface FetchKeyOptions {
|
|
|
52
52
|
* @since 1.3.0
|
|
53
53
|
*/
|
|
54
54
|
tracerProvider?: TracerProvider;
|
|
55
|
+
/**
|
|
56
|
+
* The OpenTelemetry meter provider to use for recording
|
|
57
|
+
* `activitypub.key.lookup` and `activitypub.key.lookup.duration`. If
|
|
58
|
+
* omitted, the global meter provider is used.
|
|
59
|
+
* @since 2.3.0
|
|
60
|
+
*/
|
|
61
|
+
meterProvider?: MeterProvider;
|
|
55
62
|
}
|
|
56
63
|
/**
|
|
57
64
|
* The result of {@link fetchKey}.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
4
|
+
import { n as version, t as name } from "./deno-B_9yJW3w.mjs";
|
|
5
|
+
import { f as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-iRBg8jTk.mjs";
|
|
5
6
|
import { getLogger } from "@logtape/logtape";
|
|
6
7
|
import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
7
8
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -306,24 +307,48 @@ async function resolveFetchedKey(document, cacheKey, keyId, cls, { documentLoade
|
|
|
306
307
|
};
|
|
307
308
|
}
|
|
308
309
|
async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, onFetchError) {
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
"sig",
|
|
312
|
-
"key"
|
|
313
|
-
]);
|
|
314
|
-
const keyId = cacheKey.href;
|
|
315
|
-
const keyCache = options.keyCache;
|
|
316
|
-
const cached = await getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger);
|
|
317
|
-
if (cached?.key === null && cached.cached) return await onCachedUnavailable(cacheKey, keyId, keyCache, logger);
|
|
318
|
-
if (cached != null) return cached;
|
|
319
|
-
logger.debug("Fetching key {keyId} to verify signature...", { keyId });
|
|
320
|
-
let document;
|
|
310
|
+
const start = performance.now();
|
|
311
|
+
let outcome = { result: "error" };
|
|
321
312
|
try {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
313
|
+
const logger = getLogger([
|
|
314
|
+
"fedify",
|
|
315
|
+
"sig",
|
|
316
|
+
"key"
|
|
317
|
+
]);
|
|
318
|
+
const keyId = cacheKey.href;
|
|
319
|
+
const keyCache = options.keyCache;
|
|
320
|
+
const cached = await getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger);
|
|
321
|
+
if (cached?.key === null && cached.cached) {
|
|
322
|
+
const cachedUnavailable = await onCachedUnavailable(cacheKey, keyId, keyCache, logger);
|
|
323
|
+
outcome = { result: "hit" };
|
|
324
|
+
return cachedUnavailable;
|
|
325
|
+
}
|
|
326
|
+
if (cached != null) {
|
|
327
|
+
outcome = { result: "hit" };
|
|
328
|
+
return cached;
|
|
329
|
+
}
|
|
330
|
+
logger.debug("Fetching key {keyId} to verify signature...", { keyId });
|
|
331
|
+
let document;
|
|
332
|
+
try {
|
|
333
|
+
document = (await (options.documentLoader ?? getDocumentLoader())(keyId)).document;
|
|
334
|
+
} catch (error) {
|
|
335
|
+
const classified = classifyFetchError(error);
|
|
336
|
+
const errored = await onFetchError(error, cacheKey, keyId, keyCache, logger);
|
|
337
|
+
outcome = classified;
|
|
338
|
+
return errored;
|
|
339
|
+
}
|
|
340
|
+
const resolved = await resolveFetchedKey(document, cacheKey, keyId, cls, options, logger);
|
|
341
|
+
outcome = { result: resolved.key != null ? "fetched" : "invalid" };
|
|
342
|
+
return resolved;
|
|
343
|
+
} finally {
|
|
344
|
+
recordKeyLookup(options.meterProvider, {
|
|
345
|
+
durationMs: getDurationMs(start),
|
|
346
|
+
result: outcome.result,
|
|
347
|
+
remoteUrl: cacheKey,
|
|
348
|
+
cacheEnabled: options.keyCache != null,
|
|
349
|
+
statusCode: outcome.statusCode
|
|
350
|
+
});
|
|
325
351
|
}
|
|
326
|
-
return await resolveFetchedKey(document, cacheKey, keyId, cls, options, logger);
|
|
327
352
|
}
|
|
328
353
|
async function fetchKeyInternal(keyId, cls, options = {}) {
|
|
329
354
|
return await fetchKeyWithResult(typeof keyId === "string" ? new URL(keyId) : keyId, cls, options, (_cacheKey, _keyId, _keyCache, _logger) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { d as validateCryptoKey, t as doubleKnock } from "./http-
|
|
3
|
+
import { d as validateCryptoKey, t as doubleKnock, v as recordDocumentCache } from "./http-CToqG5ap.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
5
|
import { curry } from "es-toolkit";
|
|
6
6
|
import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
@@ -55,10 +55,25 @@ const logger = getLogger([
|
|
|
55
55
|
* @param parameters The parameters for the cache.
|
|
56
56
|
* @returns The decorated document loader which is cache-enabled.
|
|
57
57
|
*/
|
|
58
|
-
function kvCache({ loader, kv, prefix, rules }) {
|
|
58
|
+
function kvCache({ loader, kv, prefix, rules, meterProvider, kind }) {
|
|
59
59
|
const keyPrefix = prefix ?? ["_fedify", "remoteDocument"];
|
|
60
60
|
rules ??= [[new URLPattern({}), Temporal.Duration.from({ minutes: 5 })]];
|
|
61
61
|
for (const [p, duration] of rules) if (Temporal.Duration.compare(duration, { days: 30 }) > 0) throw new TypeError("The maximum cache duration is 30 days: " + (p instanceof URLPattern ? `${p.protocol}://${p.username}:${p.password}@${p.hostname}:${p.port}/${p.pathname}?${p.search}#${p.hash}` : p.toString()));
|
|
62
|
+
const lookupKind = kind ?? "object";
|
|
63
|
+
function emitCacheMetric(url, result) {
|
|
64
|
+
if (meterProvider == null) return;
|
|
65
|
+
let remoteUrl;
|
|
66
|
+
try {
|
|
67
|
+
remoteUrl = new URL(url);
|
|
68
|
+
} catch {
|
|
69
|
+
remoteUrl = void 0;
|
|
70
|
+
}
|
|
71
|
+
recordDocumentCache(meterProvider, {
|
|
72
|
+
kind: lookupKind,
|
|
73
|
+
result,
|
|
74
|
+
remoteUrl
|
|
75
|
+
});
|
|
76
|
+
}
|
|
62
77
|
return async (url, options) => {
|
|
63
78
|
if (url in preloadedContexts) {
|
|
64
79
|
logger.debug("Using preloaded context: {url}.", { url });
|
|
@@ -81,6 +96,7 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
81
96
|
});
|
|
82
97
|
}
|
|
83
98
|
if (cache == null) {
|
|
99
|
+
emitCacheMetric(url, "miss");
|
|
84
100
|
const remoteDoc = await loader(url, options);
|
|
85
101
|
try {
|
|
86
102
|
await kv.set(key, remoteDoc, { ttl: match });
|
|
@@ -92,6 +108,7 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
92
108
|
}
|
|
93
109
|
return remoteDoc;
|
|
94
110
|
}
|
|
111
|
+
emitCacheMetric(url, "hit");
|
|
95
112
|
return cache;
|
|
96
113
|
};
|
|
97
114
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
require("./chunk-DDcVe30Y.cjs");
|
|
4
|
-
const require_http = require("./http-
|
|
4
|
+
const require_http = require("./http-CWoeyogl.cjs");
|
|
5
5
|
let _logtape_logtape = require("@logtape/logtape");
|
|
6
6
|
let es_toolkit = require("es-toolkit");
|
|
7
7
|
let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
|
|
@@ -56,10 +56,25 @@ const logger = (0, _logtape_logtape.getLogger)([
|
|
|
56
56
|
* @param parameters The parameters for the cache.
|
|
57
57
|
* @returns The decorated document loader which is cache-enabled.
|
|
58
58
|
*/
|
|
59
|
-
function kvCache({ loader, kv, prefix, rules }) {
|
|
59
|
+
function kvCache({ loader, kv, prefix, rules, meterProvider, kind }) {
|
|
60
60
|
const keyPrefix = prefix ?? ["_fedify", "remoteDocument"];
|
|
61
61
|
rules ??= [[new URLPattern({}), Temporal.Duration.from({ minutes: 5 })]];
|
|
62
62
|
for (const [p, duration] of rules) if (Temporal.Duration.compare(duration, { days: 30 }) > 0) throw new TypeError("The maximum cache duration is 30 days: " + (p instanceof URLPattern ? `${p.protocol}://${p.username}:${p.password}@${p.hostname}:${p.port}/${p.pathname}?${p.search}#${p.hash}` : p.toString()));
|
|
63
|
+
const lookupKind = kind ?? "object";
|
|
64
|
+
function emitCacheMetric(url, result) {
|
|
65
|
+
if (meterProvider == null) return;
|
|
66
|
+
let remoteUrl;
|
|
67
|
+
try {
|
|
68
|
+
remoteUrl = new URL(url);
|
|
69
|
+
} catch {
|
|
70
|
+
remoteUrl = void 0;
|
|
71
|
+
}
|
|
72
|
+
require_http.recordDocumentCache(meterProvider, {
|
|
73
|
+
kind: lookupKind,
|
|
74
|
+
result,
|
|
75
|
+
remoteUrl
|
|
76
|
+
});
|
|
77
|
+
}
|
|
63
78
|
return async (url, options) => {
|
|
64
79
|
if (url in _fedify_vocab_runtime.preloadedContexts) {
|
|
65
80
|
logger.debug("Using preloaded context: {url}.", { url });
|
|
@@ -82,6 +97,7 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
82
97
|
});
|
|
83
98
|
}
|
|
84
99
|
if (cache == null) {
|
|
100
|
+
emitCacheMetric(url, "miss");
|
|
85
101
|
const remoteDoc = await loader(url, options);
|
|
86
102
|
try {
|
|
87
103
|
await kv.set(key, remoteDoc, { ttl: match });
|
|
@@ -93,6 +109,7 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
93
109
|
}
|
|
94
110
|
return remoteDoc;
|
|
95
111
|
}
|
|
112
|
+
emitCacheMetric(url, "hit");
|
|
96
113
|
return cache;
|
|
97
114
|
};
|
|
98
115
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
+
import { c as recordDocumentCache } from "./metrics-iRBg8jTk.mjs";
|
|
4
5
|
import { getLogger } from "@logtape/logtape";
|
|
5
6
|
import { preloadedContexts } from "@fedify/vocab-runtime";
|
|
6
7
|
//#region src/utils/kv-cache.ts
|
|
@@ -44,10 +45,25 @@ var MockKvStore = class {
|
|
|
44
45
|
* @param parameters The parameters for the cache.
|
|
45
46
|
* @returns The decorated document loader which is cache-enabled.
|
|
46
47
|
*/
|
|
47
|
-
function kvCache({ loader, kv, prefix, rules }) {
|
|
48
|
+
function kvCache({ loader, kv, prefix, rules, meterProvider, kind }) {
|
|
48
49
|
const keyPrefix = prefix ?? ["_fedify", "remoteDocument"];
|
|
49
50
|
rules ??= [[new URLPattern({}), Temporal.Duration.from({ minutes: 5 })]];
|
|
50
51
|
for (const [p, duration] of rules) if (Temporal.Duration.compare(duration, { days: 30 }) > 0) throw new TypeError("The maximum cache duration is 30 days: " + (p instanceof URLPattern ? `${p.protocol}://${p.username}:${p.password}@${p.hostname}:${p.port}/${p.pathname}?${p.search}#${p.hash}` : p.toString()));
|
|
52
|
+
const lookupKind = kind ?? "object";
|
|
53
|
+
function emitCacheMetric(url, result) {
|
|
54
|
+
if (meterProvider == null) return;
|
|
55
|
+
let remoteUrl;
|
|
56
|
+
try {
|
|
57
|
+
remoteUrl = new URL(url);
|
|
58
|
+
} catch {
|
|
59
|
+
remoteUrl = void 0;
|
|
60
|
+
}
|
|
61
|
+
recordDocumentCache(meterProvider, {
|
|
62
|
+
kind: lookupKind,
|
|
63
|
+
result,
|
|
64
|
+
remoteUrl
|
|
65
|
+
});
|
|
66
|
+
}
|
|
51
67
|
return async (url, options) => {
|
|
52
68
|
if (url in preloadedContexts) {
|
|
53
69
|
logger.debug("Using preloaded context: {url}.", { url });
|
|
@@ -70,6 +86,7 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
70
86
|
});
|
|
71
87
|
}
|
|
72
88
|
if (cache == null) {
|
|
89
|
+
emitCacheMetric(url, "miss");
|
|
73
90
|
const remoteDoc = await loader(url, options);
|
|
74
91
|
try {
|
|
75
92
|
await kv.set(key, remoteDoc, { ttl: match });
|
|
@@ -81,6 +98,7 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
81
98
|
}
|
|
82
99
|
return remoteDoc;
|
|
83
100
|
}
|
|
101
|
+
emitCacheMetric(url, "hit");
|
|
84
102
|
return cache;
|
|
85
103
|
};
|
|
86
104
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import {
|
|
6
|
-
import { n as fetchKey, o as validateCryptoKey } from "./key-
|
|
4
|
+
import { n as version, t as name } from "./deno-B_9yJW3w.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-iRBg8jTk.mjs";
|
|
6
|
+
import { n as fetchKey, o as validateCryptoKey } from "./key-CkkMJBjF.mjs";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
|
|
9
9
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|