@fedify/fedify 2.3.0-dev.1110 → 2.3.0-dev.1119
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/{assert_rejects-B-qJtC9Z.mjs → assert_rejects-DQP-q39h.mjs} +27 -2
- package/dist/{builder-B-Y6fwSu.mjs → builder-Ond_h57y.mjs} +3 -3
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/outgoing-jsonld.test.mjs +1 -1
- package/dist/compat/public-audience.test.mjs +1 -1
- package/dist/compat/transformers.test.mjs +2 -2
- package/dist/{context-C0C_sRha.d.cts → context-Ch-ZLyTQ.d.cts} +1 -1
- package/dist/{context-Dqgt8saU.d.ts → context-cSUMk2da.d.ts} +1 -1
- package/dist/{deno-hqC7tKJn.mjs → deno-DVsHS7rA.mjs} +1 -1
- package/dist/{docloader-BOEuuXkX.mjs → docloader-WsWfKaE5.mjs} +2 -2
- package/dist/federation/builder.test.mjs +3 -3
- package/dist/federation/collection.test.mjs +2 -2
- package/dist/federation/handler.test.mjs +8 -7
- package/dist/federation/idempotency.test.mjs +5 -5
- package/dist/federation/inbox.test.mjs +1 -1
- package/dist/federation/keycache.test.mjs +1 -1
- package/dist/federation/kv.test.mjs +2 -2
- package/dist/federation/metrics.test.d.mts +2 -0
- package/dist/federation/metrics.test.mjs +107 -0
- package/dist/federation/middleware.test.mjs +390 -10
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +1 -1
- package/dist/federation/mq.test.mjs +2 -2
- package/dist/federation/negotiation.test.mjs +2 -2
- package/dist/federation/router.test.mjs +2 -2
- package/dist/federation/send.test.mjs +11 -11
- package/dist/federation/webfinger.test.mjs +3 -3
- package/dist/{getMachineId-bsd-etIyxDet.mjs → getMachineId-bsd-BY01PL1n.mjs} +1 -1
- package/dist/{getMachineId-darwin-D23zTf4g.mjs → getMachineId-darwin-Dr1gkBkp.mjs} +1 -1
- package/dist/{getMachineId-win-Dpap6v5i.mjs → getMachineId-win-QEYwcJiy.mjs} +1 -1
- package/dist/{http-O8MYWwk8.js → http-CouJSFVK.js} +461 -37
- package/dist/{http-DV0il3vk.cjs → http-CubOB9wq.cjs} +513 -35
- package/dist/{http-BDZeS5om.d.ts → http-D6LP89UO.d.ts} +7 -1
- package/dist/{http-C87EWkO0.d.cts → http-D6aw3j2U.d.cts} +7 -1
- package/dist/{http-BLopFpvC.mjs → http-DUV8ysti.mjs} +86 -37
- package/dist/{key-DW1EVmtP.mjs → key-BoWaYRHm.mjs} +1 -1
- package/dist/{kv-cache-C3NWWiTg.js → kv-cache-DBNpsneh.js} +1 -1
- package/dist/{kv-cache-Dya-TWMe.cjs → kv-cache-Dz31ATUT.cjs} +1 -1
- package/dist/{ld-BNkk2Yal.mjs → ld-B5K1mSuG.mjs} +60 -9
- package/dist/{send-hokVCPu6.mjs → metrics-C4attqv0.mjs} +124 -224
- package/dist/{middleware-D6FbOjuK.mjs → middleware-BDKFRjue.mjs} +1 -1
- package/dist/{middleware-DUWeXjZR.cjs → middleware-CmsDtIHI.cjs} +75 -309
- package/dist/{middleware-CjzI3aYo.js → middleware-Dtjz-hSk.js} +46 -280
- package/dist/{middleware-DA2WTBr4.mjs → middleware-t0jC8I99.mjs} +59 -34
- package/dist/{mod-DXY9JF28.d.cts → mod-B-Lin9Sy.d.ts} +25 -2
- package/dist/{mod-DHO9lk3D.d.ts → mod-BDhgfjP7.d.cts} +25 -2
- package/dist/{mod-B0rWmfW5.d.cts → mod-BR_BB0bh.d.cts} +1 -1
- package/dist/{mod-Dx3-hqyo.d.ts → mod-C6E8rkcz.d.ts} +1 -1
- package/dist/{mod-BhU_H1I_.d.ts → mod-DLrRb0dx.d.ts} +1 -1
- package/dist/{mod-CLPnQPsv.d.cts → mod-P9tE2WmM.d.cts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +5 -5
- package/dist/mod.d.ts +5 -5
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/client.test.mjs +2 -2
- package/dist/nodeinfo/handler.test.mjs +3 -3
- package/dist/nodeinfo/types.test.mjs +2 -2
- package/dist/otel/exporter.test.mjs +2 -2
- package/dist/{outgoing-jsonld-BgFLCJQ_.mjs → outgoing-jsonld-BNL8AC14.mjs} +1 -1
- package/dist/{owner-jvJAtR5O.mjs → owner-hDxI0ufu.mjs} +2 -2
- package/dist/{proof-BD92WeqV.cjs → proof-BUWfVr6Q.cjs} +78 -11
- package/dist/{proof-mfmHH9j0.mjs → proof-DhVuz4bc.mjs} +25 -7
- package/dist/{proof-5kT7OUPV.js → proof-n60t8o9P.js} +78 -11
- package/dist/send-BPhyR5Oo.mjs +225 -0
- package/dist/sig/accept.test.mjs +1 -1
- package/dist/sig/http.test.mjs +212 -6
- package/dist/sig/key.test.mjs +4 -4
- package/dist/sig/ld.test.mjs +138 -5
- 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 +4 -4
- package/dist/sig/proof.test.mjs +167 -6
- package/dist/{std__assert-CRDpx_HF.mjs → std__assert-BTEgfoJo.mjs} +2 -27
- package/dist/utils/docloader.test.mjs +5 -5
- package/dist/utils/kv-cache.test.mjs +1 -1
- 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 +5 -5
- /package/dist/{accept-CceiKpCy.mjs → accept-CgDcxvjV.mjs} +0 -0
- /package/dist/{activity-listener-tztVvlNb.mjs → activity-listener-BeTGV3wc.mjs} +0 -0
- /package/dist/{client-B_A6mfn3.mjs → client-Bneh_DYR.mjs} +0 -0
- /package/dist/{collection-CA3V5zyK.mjs → collection-Cc3DVAhE.mjs} +0 -0
- /package/dist/{execAsync-DCBrgFiV.mjs → execAsync-Dxb7rNf3.mjs} +0 -0
- /package/dist/{getMachineId-linux-ObI47Hql.mjs → getMachineId-linux-Bbhofx-s.mjs} +0 -0
- /package/dist/{getMachineId-unsupported-Ddu-PFeh.mjs → getMachineId-unsupported-dIOte2Ct.mjs} +0 -0
- /package/dist/{keys-C3kae-6B.mjs → keys-CSYsOMFG.mjs} +0 -0
- /package/dist/{kv-x2IvBUyq.mjs → kv-QHE0oeM3.mjs} +0 -0
- /package/dist/{kv-cache-CiiNwT6W.mjs → kv-cache-DihufyAQ.mjs} +0 -0
- /package/dist/{public-audience-N3pyOx2p.mjs → public-audience-c9zmYKgA.mjs} +0 -0
- /package/dist/{types-BFowWFTT.mjs → types-D09GN0uZ.mjs} +0 -0
|
@@ -2,10 +2,10 @@ import { Temporal } from "@js-temporal/polyfill";
|
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
import { t as __exportAll } from "./chunk-CRNNMoPX.js";
|
|
4
4
|
import { r as getDefaultActivityTransformers } from "./transformers-BGMIq1cs.js";
|
|
5
|
-
import {
|
|
6
|
-
import { c as getKeyOwner, d as detachSignature, f as hasSignatureLike, i as verifyObject, m as verifyJsonLd, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, p as signJsonLd, r as signObject, s as doesActorOwnKey } from "./proof-
|
|
5
|
+
import { E as version, T as name, _ as recordFanoutRecipients, a as verifyRequestDetailed, b as recordOutboxEnqueue, d as validateCryptoKey, f as getDurationMs, h as isAbortError, i as verifyRequest, m as getRemoteHost, n as parseRfc9421SignatureInput, o as exportJwk, p as getFederationMetrics, t as doubleKnock, u as importJwk, v as recordInboxActivity, x as formatAcceptSignature, y as recordOutboxActivity } from "./http-CouJSFVK.js";
|
|
6
|
+
import { c as getKeyOwner, d as detachSignature, f as hasSignatureLike, i as verifyObject, m as verifyJsonLd, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, p as signJsonLd, r as signObject, s as doesActorOwnKey } from "./proof-n60t8o9P.js";
|
|
7
7
|
import { n as getNodeInfo, t as nodeInfoToJson } from "./types-CAY3OdLq.js";
|
|
8
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-DBNpsneh.js";
|
|
9
9
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
10
10
|
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
11
11
|
import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
|
|
@@ -779,264 +779,6 @@ async function buildCollectionSynchronizationHeader(collectionId, actorIds) {
|
|
|
779
779
|
return `collectionId="${collectionId}", url="${url}", digest="${encodeHex(await digest(actorIds))}"`;
|
|
780
780
|
}
|
|
781
781
|
//#endregion
|
|
782
|
-
//#region src/federation/metrics.ts
|
|
783
|
-
var FederationMetrics = class {
|
|
784
|
-
deliverySent;
|
|
785
|
-
deliveryPermanentFailure;
|
|
786
|
-
signatureVerificationFailure;
|
|
787
|
-
deliveryDuration;
|
|
788
|
-
inboxProcessingDuration;
|
|
789
|
-
httpServerRequestCount;
|
|
790
|
-
httpServerRequestDuration;
|
|
791
|
-
queueTaskEnqueued;
|
|
792
|
-
queueTaskStarted;
|
|
793
|
-
queueTaskCompleted;
|
|
794
|
-
queueTaskFailed;
|
|
795
|
-
queueTaskDuration;
|
|
796
|
-
queueTaskInFlight;
|
|
797
|
-
constructor(meterProvider) {
|
|
798
|
-
const meter = meterProvider.getMeter(name, version);
|
|
799
|
-
this.deliverySent = meter.createCounter("activitypub.delivery.sent", {
|
|
800
|
-
description: "ActivityPub delivery attempts.",
|
|
801
|
-
unit: "{attempt}"
|
|
802
|
-
});
|
|
803
|
-
this.deliveryPermanentFailure = meter.createCounter("activitypub.delivery.permanent_failure", {
|
|
804
|
-
description: "ActivityPub deliveries abandoned as permanent failures.",
|
|
805
|
-
unit: "{failure}"
|
|
806
|
-
});
|
|
807
|
-
this.signatureVerificationFailure = meter.createCounter("activitypub.signature.verification_failure", {
|
|
808
|
-
description: "ActivityPub signature verification failures.",
|
|
809
|
-
unit: "{failure}"
|
|
810
|
-
});
|
|
811
|
-
this.deliveryDuration = meter.createHistogram("activitypub.delivery.duration", {
|
|
812
|
-
description: "Duration of ActivityPub delivery attempts.",
|
|
813
|
-
unit: "ms"
|
|
814
|
-
});
|
|
815
|
-
this.inboxProcessingDuration = meter.createHistogram("activitypub.inbox.processing_duration", {
|
|
816
|
-
description: "Duration of ActivityPub inbox listener processing.",
|
|
817
|
-
unit: "ms"
|
|
818
|
-
});
|
|
819
|
-
this.httpServerRequestCount = meter.createCounter("fedify.http.server.request.count", {
|
|
820
|
-
description: "HTTP requests handled by Federation.fetch().",
|
|
821
|
-
unit: "{request}"
|
|
822
|
-
});
|
|
823
|
-
this.httpServerRequestDuration = meter.createHistogram("fedify.http.server.request.duration", {
|
|
824
|
-
description: "Duration of HTTP requests handled by Federation.fetch().",
|
|
825
|
-
unit: "ms",
|
|
826
|
-
advice: { explicitBucketBoundaries: [
|
|
827
|
-
5,
|
|
828
|
-
10,
|
|
829
|
-
25,
|
|
830
|
-
50,
|
|
831
|
-
75,
|
|
832
|
-
100,
|
|
833
|
-
250,
|
|
834
|
-
500,
|
|
835
|
-
750,
|
|
836
|
-
1e3,
|
|
837
|
-
2500,
|
|
838
|
-
5e3,
|
|
839
|
-
7500,
|
|
840
|
-
1e4
|
|
841
|
-
] }
|
|
842
|
-
});
|
|
843
|
-
this.queueTaskEnqueued = meter.createCounter("fedify.queue.task.enqueued", {
|
|
844
|
-
description: "Tasks Fedify enqueued for inbox, outbox, or fanout work.",
|
|
845
|
-
unit: "{task}"
|
|
846
|
-
});
|
|
847
|
-
this.queueTaskStarted = meter.createCounter("fedify.queue.task.started", {
|
|
848
|
-
description: "Tasks Fedify began processing as a queue worker.",
|
|
849
|
-
unit: "{task}"
|
|
850
|
-
});
|
|
851
|
-
this.queueTaskCompleted = meter.createCounter("fedify.queue.task.completed", {
|
|
852
|
-
description: "Queue tasks Fedify finished processing without throwing.",
|
|
853
|
-
unit: "{task}"
|
|
854
|
-
});
|
|
855
|
-
this.queueTaskFailed = meter.createCounter("fedify.queue.task.failed", {
|
|
856
|
-
description: "Queue tasks Fedify abandoned because processing threw.",
|
|
857
|
-
unit: "{task}"
|
|
858
|
-
});
|
|
859
|
-
this.queueTaskDuration = meter.createHistogram("fedify.queue.task.duration", {
|
|
860
|
-
description: "Duration of queue task processing in Fedify workers.",
|
|
861
|
-
unit: "ms",
|
|
862
|
-
advice: { explicitBucketBoundaries: [
|
|
863
|
-
5,
|
|
864
|
-
10,
|
|
865
|
-
25,
|
|
866
|
-
50,
|
|
867
|
-
75,
|
|
868
|
-
100,
|
|
869
|
-
250,
|
|
870
|
-
500,
|
|
871
|
-
750,
|
|
872
|
-
1e3,
|
|
873
|
-
2500,
|
|
874
|
-
5e3,
|
|
875
|
-
7500,
|
|
876
|
-
1e4
|
|
877
|
-
] }
|
|
878
|
-
});
|
|
879
|
-
this.queueTaskInFlight = meter.createUpDownCounter("fedify.queue.task.in_flight", {
|
|
880
|
-
description: "Queue tasks currently being processed in this Fedify process.",
|
|
881
|
-
unit: "{task}"
|
|
882
|
-
});
|
|
883
|
-
}
|
|
884
|
-
recordDelivery(inbox, durationMs, success, activityType) {
|
|
885
|
-
const deliveryAttributes = {
|
|
886
|
-
"activitypub.remote.host": getRemoteHost(inbox),
|
|
887
|
-
"activitypub.delivery.success": success
|
|
888
|
-
};
|
|
889
|
-
if (activityType != null) deliveryAttributes["activitypub.activity.type"] = activityType;
|
|
890
|
-
this.deliverySent.add(1, deliveryAttributes);
|
|
891
|
-
this.deliveryDuration.record(durationMs, deliveryAttributes);
|
|
892
|
-
}
|
|
893
|
-
recordPermanentFailure(inbox, statusCode) {
|
|
894
|
-
this.deliveryPermanentFailure.add(1, {
|
|
895
|
-
"activitypub.remote.host": getRemoteHost(inbox),
|
|
896
|
-
"http.response.status_code": statusCode
|
|
897
|
-
});
|
|
898
|
-
}
|
|
899
|
-
recordSignatureVerificationFailure(reason, remoteHost) {
|
|
900
|
-
const attributes = { "activitypub.verification.failure_reason": reason };
|
|
901
|
-
if (remoteHost != null) attributes["activitypub.remote.host"] = remoteHost;
|
|
902
|
-
this.signatureVerificationFailure.add(1, attributes);
|
|
903
|
-
}
|
|
904
|
-
recordInboxProcessingDuration(activityType, durationMs) {
|
|
905
|
-
this.inboxProcessingDuration.record(durationMs, { "activitypub.activity.type": activityType });
|
|
906
|
-
}
|
|
907
|
-
recordHttpServerRequest(method, endpoint, durationMs, options = {}) {
|
|
908
|
-
const attributes = {
|
|
909
|
-
"http.request.method": normalizeHttpMethod(method),
|
|
910
|
-
"fedify.endpoint": endpoint
|
|
911
|
-
};
|
|
912
|
-
if (options.statusCode != null) attributes["http.response.status_code"] = options.statusCode;
|
|
913
|
-
if (options.routeTemplate != null) attributes["fedify.route.template"] = options.routeTemplate;
|
|
914
|
-
this.httpServerRequestCount.add(1, attributes);
|
|
915
|
-
this.httpServerRequestDuration.record(durationMs, attributes);
|
|
916
|
-
}
|
|
917
|
-
recordQueueTaskEnqueued(common, attempt) {
|
|
918
|
-
const attributes = buildQueueTaskAttributes(common);
|
|
919
|
-
attributes["fedify.queue.task.attempt"] = attempt;
|
|
920
|
-
this.queueTaskEnqueued.add(1, attributes);
|
|
921
|
-
}
|
|
922
|
-
recordQueueTaskStarted(common) {
|
|
923
|
-
this.queueTaskStarted.add(1, buildQueueTaskAttributes(common));
|
|
924
|
-
}
|
|
925
|
-
incrementQueueTaskInFlight(common) {
|
|
926
|
-
this.queueTaskInFlight.add(1, buildQueueTaskInFlightAttributes(common));
|
|
927
|
-
}
|
|
928
|
-
decrementQueueTaskInFlight(common) {
|
|
929
|
-
this.queueTaskInFlight.add(-1, buildQueueTaskInFlightAttributes(common));
|
|
930
|
-
}
|
|
931
|
-
recordQueueTaskOutcome(common, result, durationMs) {
|
|
932
|
-
const attributes = buildQueueTaskAttributes(common);
|
|
933
|
-
attributes["fedify.queue.task.result"] = result;
|
|
934
|
-
if (result === "completed") this.queueTaskCompleted.add(1, attributes);
|
|
935
|
-
else if (result === "failed") this.queueTaskFailed.add(1, attributes);
|
|
936
|
-
this.queueTaskDuration.record(durationMs, attributes);
|
|
937
|
-
}
|
|
938
|
-
};
|
|
939
|
-
function buildQueueTaskAttributes(common) {
|
|
940
|
-
const attributes = { "fedify.queue.role": common.role };
|
|
941
|
-
const backend = getQueueBackend(common.queue);
|
|
942
|
-
if (backend != null) attributes["fedify.queue.backend"] = backend;
|
|
943
|
-
const nativeRetrial = common.queue?.nativeRetrial;
|
|
944
|
-
if (typeof nativeRetrial === "boolean") attributes["fedify.queue.native_retrial"] = nativeRetrial;
|
|
945
|
-
if (common.activityType != null) attributes["activitypub.activity.type"] = common.activityType;
|
|
946
|
-
return attributes;
|
|
947
|
-
}
|
|
948
|
-
function buildQueueTaskInFlightAttributes(common) {
|
|
949
|
-
return buildQueueTaskAttributes({
|
|
950
|
-
role: common.role,
|
|
951
|
-
queue: common.queue
|
|
952
|
-
});
|
|
953
|
-
}
|
|
954
|
-
/**
|
|
955
|
-
* Returns the constructor name of the given message queue, when it is a
|
|
956
|
-
* meaningful identifier. Used as a best-effort `fedify.queue.backend`
|
|
957
|
-
* attribute on queue task metrics; returns `undefined` for plain object
|
|
958
|
-
* literals (whose constructor is `Object`) so the attribute does not appear
|
|
959
|
-
* with a non-informative value.
|
|
960
|
-
* @since 2.3.0
|
|
961
|
-
*/
|
|
962
|
-
function getQueueBackend(queue) {
|
|
963
|
-
const name = queue?.constructor?.name;
|
|
964
|
-
if (name == null || name === "" || name === "Object") return void 0;
|
|
965
|
-
return name;
|
|
966
|
-
}
|
|
967
|
-
/**
|
|
968
|
-
* Records `fedify.queue.task.enqueued` for an outgoing outbox enqueue.
|
|
969
|
-
*
|
|
970
|
-
* Both `Context.sendActivity()` and `OutboxContext.forwardActivity()` enqueue
|
|
971
|
-
* outbox messages with the same metric attributes (role, queue, activity
|
|
972
|
-
* type, attempt), so they share this helper rather than each defining a local
|
|
973
|
-
* closure.
|
|
974
|
-
* @since 2.3.0
|
|
975
|
-
*/
|
|
976
|
-
function recordOutboxEnqueue(meterProvider, outboxQueue, message) {
|
|
977
|
-
getFederationMetrics(meterProvider).recordQueueTaskEnqueued({
|
|
978
|
-
role: "outbox",
|
|
979
|
-
queue: outboxQueue,
|
|
980
|
-
activityType: message.activityType
|
|
981
|
-
}, message.attempt);
|
|
982
|
-
}
|
|
983
|
-
/**
|
|
984
|
-
* Whether the given thrown value is an `AbortError`.
|
|
985
|
-
*
|
|
986
|
-
* `processQueuedTask` distinguishes aborted tasks (recorded as
|
|
987
|
-
* `fedify.queue.task.result=aborted`) from other failures so that backend
|
|
988
|
-
* shutdown signals do not inflate the `fedify.queue.task.failed` counter.
|
|
989
|
-
* @since 2.3.0
|
|
990
|
-
*/
|
|
991
|
-
function isAbortError(error) {
|
|
992
|
-
if (error == null || typeof error !== "object") return false;
|
|
993
|
-
const name = error.name;
|
|
994
|
-
return typeof name === "string" && name === "AbortError";
|
|
995
|
-
}
|
|
996
|
-
const KNOWN_HTTP_METHODS = new Set([
|
|
997
|
-
"CONNECT",
|
|
998
|
-
"DELETE",
|
|
999
|
-
"GET",
|
|
1000
|
-
"HEAD",
|
|
1001
|
-
"OPTIONS",
|
|
1002
|
-
"PATCH",
|
|
1003
|
-
"POST",
|
|
1004
|
-
"PUT",
|
|
1005
|
-
"QUERY",
|
|
1006
|
-
"TRACE"
|
|
1007
|
-
]);
|
|
1008
|
-
function normalizeHttpMethod(method) {
|
|
1009
|
-
const upper = method.toUpperCase();
|
|
1010
|
-
return KNOWN_HTTP_METHODS.has(upper) ? upper : "_OTHER";
|
|
1011
|
-
}
|
|
1012
|
-
const federationMetrics = /* @__PURE__ */ new WeakMap();
|
|
1013
|
-
/**
|
|
1014
|
-
* Gets the cached Fedify metric instruments for a meter provider.
|
|
1015
|
-
* @since 2.3.0
|
|
1016
|
-
*/
|
|
1017
|
-
function getFederationMetrics(meterProvider = metrics.getMeterProvider()) {
|
|
1018
|
-
let instruments = federationMetrics.get(meterProvider);
|
|
1019
|
-
if (instruments == null) {
|
|
1020
|
-
instruments = new FederationMetrics(meterProvider);
|
|
1021
|
-
federationMetrics.set(meterProvider, instruments);
|
|
1022
|
-
}
|
|
1023
|
-
return instruments;
|
|
1024
|
-
}
|
|
1025
|
-
/**
|
|
1026
|
-
* Gets the bounded remote host attribute value for a URL.
|
|
1027
|
-
* @since 2.3.0
|
|
1028
|
-
*/
|
|
1029
|
-
function getRemoteHost(url) {
|
|
1030
|
-
return url.hostname;
|
|
1031
|
-
}
|
|
1032
|
-
/**
|
|
1033
|
-
* Gets an elapsed duration in milliseconds from a `performance.now()` value.
|
|
1034
|
-
* @since 2.3.0
|
|
1035
|
-
*/
|
|
1036
|
-
function getDurationMs(start) {
|
|
1037
|
-
return Math.max(0, performance.now() - start);
|
|
1038
|
-
}
|
|
1039
|
-
//#endregion
|
|
1040
782
|
//#region src/federation/inbox.ts
|
|
1041
783
|
async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, meterProvider, tracerProvider, idempotencyStrategy }) {
|
|
1042
784
|
const logger = getLogger([
|
|
@@ -1075,6 +817,7 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
1075
817
|
code: SpanStatusCode.UNSET,
|
|
1076
818
|
message: `Activity ${activity.id?.href} has already been processed.`
|
|
1077
819
|
});
|
|
820
|
+
recordInboxActivity(meterProvider, "rejected", getTypeId(activity).href);
|
|
1078
821
|
return "alreadyProcessed";
|
|
1079
822
|
}
|
|
1080
823
|
}
|
|
@@ -1084,6 +827,7 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
1084
827
|
code: SpanStatusCode.ERROR,
|
|
1085
828
|
message: "Missing actor."
|
|
1086
829
|
});
|
|
830
|
+
recordInboxActivity(meterProvider, "rejected", getTypeId(activity).href);
|
|
1087
831
|
return "missingActor";
|
|
1088
832
|
}
|
|
1089
833
|
span.setAttribute("activitypub.actor.id", activity.actorId.href);
|
|
@@ -1119,6 +863,7 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
1119
863
|
queue,
|
|
1120
864
|
activityType: getTypeId(activity).href
|
|
1121
865
|
}, 0);
|
|
866
|
+
recordInboxActivity(meterProvider, "queued", getTypeId(activity).href);
|
|
1122
867
|
logger.info("Activity {activityId} is enqueued.", {
|
|
1123
868
|
activityId: activity.id?.href,
|
|
1124
869
|
activity: json,
|
|
@@ -1138,6 +883,7 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
1138
883
|
code: SpanStatusCode.UNSET,
|
|
1139
884
|
message: `Unsupported activity type: ${getTypeId(activity).href}`
|
|
1140
885
|
});
|
|
886
|
+
recordInboxActivity(meterProvider, "rejected", getTypeId(activity).href);
|
|
1141
887
|
span.end();
|
|
1142
888
|
return "unsupportedActivity";
|
|
1143
889
|
}
|
|
@@ -1147,7 +893,7 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
1147
893
|
const activityType = getTypeId(activity).href;
|
|
1148
894
|
const started = performance.now();
|
|
1149
895
|
try {
|
|
1150
|
-
await listener(inboxContextFactory(recipient, json, activity
|
|
896
|
+
await listener(inboxContextFactory(recipient, json, activity.id?.href, activityType), activity);
|
|
1151
897
|
} finally {
|
|
1152
898
|
getFederationMetrics(meterProvider).recordInboxProcessingDuration(activityType, getDurationMs(started));
|
|
1153
899
|
}
|
|
@@ -1172,9 +918,11 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
1172
918
|
code: SpanStatusCode.ERROR,
|
|
1173
919
|
message: String(error)
|
|
1174
920
|
});
|
|
921
|
+
recordInboxActivity(meterProvider, "rejected", getTypeId(activity).href);
|
|
1175
922
|
span.end();
|
|
1176
923
|
return "error";
|
|
1177
924
|
}
|
|
925
|
+
recordInboxActivity(meterProvider, "processed", getTypeId(activity).href);
|
|
1178
926
|
if (cacheKey != null) await kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
1179
927
|
logger.info("Activity {activityId} has been processed.", {
|
|
1180
928
|
activityId: activity.id?.href,
|
|
@@ -1442,8 +1190,8 @@ async function handleObject(request, { values, context, objectDispatcher, author
|
|
|
1442
1190
|
* @param parameters The parameters for handling the collection.
|
|
1443
1191
|
* @returns A promise that resolves to an HTTP response.
|
|
1444
1192
|
*/
|
|
1445
|
-
async function handleCollection(request, { name: name$
|
|
1446
|
-
const spanName = name$
|
|
1193
|
+
async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound }) {
|
|
1194
|
+
const spanName = name$2.trim().replace(/\s+/g, "_");
|
|
1447
1195
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
1448
1196
|
const tracer = tracerProvider.getTracer(name, version);
|
|
1449
1197
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
@@ -1485,7 +1233,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
1485
1233
|
collection = new OrderedCollection({
|
|
1486
1234
|
id: baseUri,
|
|
1487
1235
|
totalItems: totalItems == null ? null : Number(totalItems),
|
|
1488
|
-
items: filterCollectionItems(itemsOrResponse, name$
|
|
1236
|
+
items: filterCollectionItems(itemsOrResponse, name$2, filterPredicate)
|
|
1489
1237
|
});
|
|
1490
1238
|
} else {
|
|
1491
1239
|
const lastCursor = await collectionCallbacks.lastCursor?.(context, identifier);
|
|
@@ -1506,7 +1254,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
1506
1254
|
} else {
|
|
1507
1255
|
const uri = new URL(baseUri);
|
|
1508
1256
|
uri.searchParams.set("cursor", cursor);
|
|
1509
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
1257
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
|
|
1510
1258
|
kind: SpanKind.SERVER,
|
|
1511
1259
|
attributes: {
|
|
1512
1260
|
"activitypub.collection.id": uri.href,
|
|
@@ -1550,7 +1298,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
1550
1298
|
id: uri,
|
|
1551
1299
|
prev,
|
|
1552
1300
|
next,
|
|
1553
|
-
items: filterCollectionItems(items, name$
|
|
1301
|
+
items: filterCollectionItems(items, name$2, filterPredicate),
|
|
1554
1302
|
partOf
|
|
1555
1303
|
});
|
|
1556
1304
|
}
|
|
@@ -1825,7 +1573,7 @@ async function handleInbox(request, options) {
|
|
|
1825
1573
|
* @returns A promise that resolves to an HTTP response.
|
|
1826
1574
|
*/
|
|
1827
1575
|
async function handleInboxInternal(request, parameters, span) {
|
|
1828
|
-
const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, unverifiedActivityHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, inboxChallengePolicy, tracerProvider } = parameters;
|
|
1576
|
+
const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, unverifiedActivityHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, inboxChallengePolicy, meterProvider, tracerProvider } = parameters;
|
|
1829
1577
|
const logger = getLogger([
|
|
1830
1578
|
"fedify",
|
|
1831
1579
|
"federation",
|
|
@@ -1903,6 +1651,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1903
1651
|
contextLoader: ctx.contextLoader,
|
|
1904
1652
|
documentLoader: ctx.documentLoader,
|
|
1905
1653
|
keyCache,
|
|
1654
|
+
meterProvider,
|
|
1906
1655
|
tracerProvider
|
|
1907
1656
|
});
|
|
1908
1657
|
} catch (error) {
|
|
@@ -1938,6 +1687,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1938
1687
|
contextLoader: ctx.contextLoader,
|
|
1939
1688
|
documentLoader: ctx.documentLoader,
|
|
1940
1689
|
keyCache,
|
|
1690
|
+
meterProvider,
|
|
1941
1691
|
tracerProvider
|
|
1942
1692
|
});
|
|
1943
1693
|
} catch (error) {
|
|
@@ -1985,6 +1735,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1985
1735
|
documentLoader: ctx.documentLoader,
|
|
1986
1736
|
timeWindow: signatureTimeWindow,
|
|
1987
1737
|
keyCache,
|
|
1738
|
+
meterProvider,
|
|
1988
1739
|
tracerProvider
|
|
1989
1740
|
});
|
|
1990
1741
|
if (verification.verified === false) {
|
|
@@ -2233,8 +1984,8 @@ var CustomCollectionHandler = class {
|
|
|
2233
1984
|
* @param CollectionPage The CollectionPage constructor.
|
|
2234
1985
|
* @param filterPredicate Optional filter predicate for items.
|
|
2235
1986
|
*/
|
|
2236
|
-
constructor(name$
|
|
2237
|
-
this.name = name$
|
|
1987
|
+
constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), Collection, CollectionPage, filterPredicate) {
|
|
1988
|
+
this.name = name$1;
|
|
2238
1989
|
this.values = values;
|
|
2239
1990
|
this.context = context;
|
|
2240
1991
|
this.callbacks = callbacks;
|
|
@@ -3488,6 +3239,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3488
3239
|
});
|
|
3489
3240
|
}
|
|
3490
3241
|
}
|
|
3242
|
+
recordOutboxActivity(this.meterProvider, "abandoned", message.activityType);
|
|
3491
3243
|
return;
|
|
3492
3244
|
}
|
|
3493
3245
|
if (this.outboxQueue?.nativeRetrial) {
|
|
@@ -3518,11 +3270,15 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3518
3270
|
queue: outboxQueue,
|
|
3519
3271
|
activityType: retryMessage.activityType
|
|
3520
3272
|
}, retryMessage.attempt);
|
|
3273
|
+
recordOutboxActivity(this.meterProvider, "retried", retryMessage.activityType);
|
|
3521
3274
|
}
|
|
3522
|
-
} else
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3275
|
+
} else {
|
|
3276
|
+
logger.error("Failed to send activity {activityId} to {inbox} after {attempt} attempts; giving up:\n{error}", {
|
|
3277
|
+
...logData,
|
|
3278
|
+
error
|
|
3279
|
+
});
|
|
3280
|
+
recordOutboxActivity(this.meterProvider, "abandoned", message.activityType);
|
|
3281
|
+
}
|
|
3526
3282
|
return;
|
|
3527
3283
|
}
|
|
3528
3284
|
logger.info("Successfully sent activity {activityId} to {inbox}.", { ...logData });
|
|
@@ -3557,6 +3313,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3557
3313
|
activity: message.activity,
|
|
3558
3314
|
recipient: message.identifier
|
|
3559
3315
|
});
|
|
3316
|
+
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
3560
3317
|
return;
|
|
3561
3318
|
}
|
|
3562
3319
|
}
|
|
@@ -3573,6 +3330,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3573
3330
|
code: SpanStatusCode.ERROR,
|
|
3574
3331
|
message: `Unsupported activity type: ${activityType}`
|
|
3575
3332
|
});
|
|
3333
|
+
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
3576
3334
|
span.end();
|
|
3577
3335
|
return;
|
|
3578
3336
|
}
|
|
@@ -3585,6 +3343,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3585
3343
|
} finally {
|
|
3586
3344
|
getFederationMetrics(this.meterProvider).recordInboxProcessingDuration(activityType, getDurationMs(started));
|
|
3587
3345
|
}
|
|
3346
|
+
recordInboxActivity(this.meterProvider, "processed", activityType);
|
|
3588
3347
|
} catch (error) {
|
|
3589
3348
|
try {
|
|
3590
3349
|
await this.inboxErrorHandler?.(context, error);
|
|
@@ -3635,13 +3394,17 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3635
3394
|
queue: inboxQueue,
|
|
3636
3395
|
activityType
|
|
3637
3396
|
}, retryMessage.attempt);
|
|
3397
|
+
recordInboxActivity(this.meterProvider, "retried", activityType);
|
|
3638
3398
|
}
|
|
3639
|
-
} else
|
|
3640
|
-
error,
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3399
|
+
} else {
|
|
3400
|
+
logger.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
3401
|
+
error,
|
|
3402
|
+
activityId: activity.id?.href,
|
|
3403
|
+
activity: message.activity,
|
|
3404
|
+
recipient: message.identifier
|
|
3405
|
+
});
|
|
3406
|
+
recordInboxActivity(this.meterProvider, "abandoned", activityType);
|
|
3407
|
+
}
|
|
3645
3408
|
span.setStatus({
|
|
3646
3409
|
code: SpanStatusCode.ERROR,
|
|
3647
3410
|
message: String(error)
|
|
@@ -4668,6 +4431,7 @@ var ContextImpl = class ContextImpl {
|
|
|
4668
4431
|
queue: this.federation.fanoutQueue,
|
|
4669
4432
|
activityType: message.activityType
|
|
4670
4433
|
}, 0);
|
|
4434
|
+
recordFanoutRecipients(this.federation.meterProvider, globalThis.Object.keys(message.inboxes).length, message.activityType);
|
|
4671
4435
|
return true;
|
|
4672
4436
|
}
|
|
4673
4437
|
async *getFollowers(identifier) {
|
|
@@ -4731,6 +4495,7 @@ var ContextImpl = class ContextImpl {
|
|
|
4731
4495
|
if (await verifyObject(Activity, json, {
|
|
4732
4496
|
contextLoader,
|
|
4733
4497
|
documentLoader: options.documentLoader ?? this.documentLoader,
|
|
4498
|
+
meterProvider: this.meterProvider,
|
|
4734
4499
|
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
4735
4500
|
keyCache
|
|
4736
4501
|
}) == null) {
|
|
@@ -4873,6 +4638,7 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
4873
4638
|
contextLoader: options.contextLoader ?? this.contextLoader,
|
|
4874
4639
|
documentLoader: options.documentLoader ?? this.documentLoader,
|
|
4875
4640
|
timeWindow: this.federation.signatureTimeWindow,
|
|
4641
|
+
meterProvider: this.meterProvider,
|
|
4876
4642
|
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
4877
4643
|
});
|
|
4878
4644
|
}
|