@fedify/fedify 1.3.0-dev.569 → 1.3.0-dev.570

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/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "@fedify/fedify",
3
- "version": "1.3.0-dev.569+d97ee744",
3
+ "version": "1.3.0-dev.570+61d94afc",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./mod.ts",
@@ -1,10 +1,13 @@
1
1
  import * as dntShim from "../_dnt.shims.js";
2
2
  import { getLogger } from "@logtape/logtape";
3
+ import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
3
4
  import { accepts } from "../deps/jsr.io/@std/http/1.0.11/negotiation.js";
5
+ import metadata from "../deno.js";
4
6
  import { verifyRequest } from "../sig/http.js";
5
7
  import { detachSignature, verifyJsonLd } from "../sig/ld.js";
6
8
  import { doesActorOwnKey } from "../sig/owner.js";
7
9
  import { verifyObject } from "../sig/proof.js";
10
+ import { getTypeId } from "../vocab/type.js";
8
11
  import { Activity, CryptographicKey, Link, Multikey, Object, OrderedCollection, OrderedCollectionPage, } from "../vocab/vocab.js";
9
12
  export function acceptsJsonLd(request) {
10
13
  const types = accepts(request);
@@ -68,21 +71,46 @@ export async function handleObject(request, { values, context, objectDispatcher,
68
71
  },
69
72
  });
70
73
  }
71
- export async function handleCollection(request, { name, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, onUnauthorized, onNotFound, onNotAcceptable, }) {
72
- if (collectionCallbacks == null)
73
- return await onNotFound(request);
74
+ export function handleCollection(request, params) {
75
+ const name = params.name.trim().replace(/\s+/g, "_");
76
+ const tracerProvider = params.tracerProvider ?? trace.getTracerProvider();
77
+ const tracer = tracerProvider.getTracer(metadata.name, metadata.version);
74
78
  const url = new URL(request.url);
75
79
  const cursor = url.searchParams.get("cursor");
80
+ return tracer.startActiveSpan(cursor == null
81
+ ? `activitypub.dispatch_collection ${name}`
82
+ : `activitypub.dispatch_collection_page ${name}`, { kind: SpanKind.SERVER }, async (span) => {
83
+ try {
84
+ return await handleCollectionInternal(request, cursor, params, span);
85
+ }
86
+ catch (e) {
87
+ span.setStatus({ code: SpanStatusCode.ERROR, message: String(e) });
88
+ throw e;
89
+ }
90
+ finally {
91
+ span.end();
92
+ }
93
+ });
94
+ }
95
+ async function handleCollectionInternal(request, cursor, { name, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, onUnauthorized, onNotFound, onNotAcceptable, }, span) {
96
+ if (collectionCallbacks == null)
97
+ return await onNotFound(request);
76
98
  let collection;
77
99
  const baseUri = uriGetter(identifier);
78
100
  if (cursor == null) {
79
101
  const firstCursor = await collectionCallbacks.firstCursor?.(context, identifier);
80
102
  const totalItems = await collectionCallbacks.counter?.(context, identifier);
103
+ if (totalItems != null) {
104
+ span.setAttribute("activitypub.collection.total_items", Number(totalItems));
105
+ }
81
106
  if (firstCursor == null) {
82
107
  const page = await collectionCallbacks.dispatcher(context, identifier, null, filter);
83
- if (page == null)
108
+ if (page == null) {
109
+ span.setStatus({ code: SpanStatusCode.ERROR });
84
110
  return await onNotFound(request);
111
+ }
85
112
  const { items } = page;
113
+ span.setAttribute("fedify.collection.items", items.length);
86
114
  collection = new OrderedCollection({
87
115
  id: baseUri,
88
116
  totalItems: totalItems == null ? null : Number(totalItems),
@@ -107,12 +135,16 @@ export async function handleCollection(request, { name, identifier, uriGetter, f
107
135
  }
108
136
  }
109
137
  else {
138
+ span.setAttribute("fedify.collection.cursor", cursor);
110
139
  const uri = new URL(baseUri);
111
140
  uri.searchParams.set("cursor", cursor);
112
141
  const page = await collectionCallbacks.dispatcher(context, identifier, cursor, filter);
113
- if (page == null)
142
+ if (page == null) {
143
+ span.setStatus({ code: SpanStatusCode.ERROR });
114
144
  return await onNotFound(request);
145
+ }
115
146
  const { items, prevCursor, nextCursor } = page;
147
+ span.setAttribute("fedify.collection.items", items.length);
116
148
  let prev = null;
117
149
  if (prevCursor != null) {
118
150
  prev = new URL(context.url);
@@ -142,6 +174,10 @@ export async function handleCollection(request, { name, identifier, uriGetter, f
142
174
  return await onUnauthorized(request);
143
175
  }
144
176
  }
177
+ if (collection.id != null) {
178
+ span.setAttribute("activitypub.collection.id", collection.id.href);
179
+ }
180
+ span.setAttribute("activitypub.collection.type", getTypeId(collection).href);
145
181
  const jsonLd = await collection.toJsonLd(context);
146
182
  return new Response(JSON.stringify(jsonLd), {
147
183
  headers: {
@@ -403,7 +403,10 @@ export class FederationImpl {
403
403
  }
404
404
  const callbacks = {
405
405
  dispatcher: async (context, identifier) => {
406
- const actor = await this.#getTracer().startActiveSpan("activitypub.dispatch_actor", { kind: SpanKind.SERVER }, async (span) => {
406
+ const actor = await this.#getTracer().startActiveSpan("activitypub.dispatch_actor", {
407
+ kind: SpanKind.SERVER,
408
+ attributes: { "fedify.actor.identifier": identifier },
409
+ }, async (span) => {
407
410
  try {
408
411
  const actor = await dispatcher(context, identifier);
409
412
  span.setAttribute("activitypub.actor.id", (actor?.id ?? context.getActorUri(identifier)).href);
@@ -560,7 +563,13 @@ export class FederationImpl {
560
563
  this.actorCallbacks = callbacks;
561
564
  const setters = {
562
565
  setKeyPairsDispatcher: (dispatcher) => {
563
- callbacks.keyPairsDispatcher = (ctx, identifier) => this.#getTracer().startActiveSpan("activitypub.dispatch_actor_key_pairs", { kind: SpanKind.SERVER }, async (span) => {
566
+ callbacks.keyPairsDispatcher = (ctx, identifier) => this.#getTracer().startActiveSpan("activitypub.dispatch_actor_key_pairs", {
567
+ kind: SpanKind.SERVER,
568
+ attributes: {
569
+ "activitypub.actor.id": ctx.getActorUri(identifier).href,
570
+ "fedify.actor.identifier": identifier,
571
+ },
572
+ }, async (span) => {
564
573
  try {
565
574
  return await dispatcher(ctx, identifier);
566
575
  }
@@ -600,7 +609,41 @@ export class FederationImpl {
600
609
  throw new RouterError("Path for object dispatcher must have at least one variable.");
601
610
  }
602
611
  const callbacks = {
603
- dispatcher,
612
+ dispatcher: (ctx, values) => {
613
+ const tracer = this.#getTracer();
614
+ return tracer.startActiveSpan("activitypub.dispatch_object", {
615
+ kind: SpanKind.SERVER,
616
+ attributes: {
617
+ "fedify.object.type": cls.typeId.href,
618
+ ...globalThis.Object.fromEntries(globalThis.Object.entries(values).map(([k, v]) => [
619
+ `fedify.object.values.${k}`,
620
+ v,
621
+ ])),
622
+ },
623
+ }, async (span) => {
624
+ try {
625
+ const object = await dispatcher(ctx, values);
626
+ span.setAttribute("activitypub.object.id", (object?.id ?? ctx.getObjectUri(cls, values)).href);
627
+ if (object == null) {
628
+ span.setStatus({ code: SpanStatusCode.ERROR });
629
+ }
630
+ else {
631
+ span.setAttribute("activitypub.object.type", getTypeId(object).href);
632
+ }
633
+ return object;
634
+ }
635
+ catch (e) {
636
+ span.setStatus({
637
+ code: SpanStatusCode.ERROR,
638
+ message: String(e),
639
+ });
640
+ throw e;
641
+ }
642
+ finally {
643
+ span.end();
644
+ }
645
+ });
646
+ },
604
647
  parameters: variables,
605
648
  };
606
649
  this.objectCallbacks[cls.typeId.href] = callbacks;
@@ -1180,6 +1223,7 @@ export class FederationImpl {
1180
1223
  uriGetter: context.getOutboxUri.bind(context),
1181
1224
  context,
1182
1225
  collectionCallbacks: this.outboxCallbacks,
1226
+ tracerProvider: this.tracerProvider,
1183
1227
  onUnauthorized,
1184
1228
  onNotFound,
1185
1229
  onNotAcceptable,
@@ -1192,6 +1236,7 @@ export class FederationImpl {
1192
1236
  uriGetter: context.getInboxUri.bind(context),
1193
1237
  context,
1194
1238
  collectionCallbacks: this.inboxCallbacks,
1239
+ tracerProvider: this.tracerProvider,
1195
1240
  onUnauthorized,
1196
1241
  onNotFound,
1197
1242
  onNotAcceptable,
@@ -1239,6 +1284,7 @@ export class FederationImpl {
1239
1284
  uriGetter: context.getFollowingUri.bind(context),
1240
1285
  context,
1241
1286
  collectionCallbacks: this.followingCallbacks,
1287
+ tracerProvider: this.tracerProvider,
1242
1288
  onUnauthorized,
1243
1289
  onNotFound,
1244
1290
  onNotAcceptable,
@@ -1259,6 +1305,7 @@ export class FederationImpl {
1259
1305
  ? ((i) => (i instanceof URL ? i.href : i.id?.href ?? "").startsWith(baseUrl))
1260
1306
  : undefined,
1261
1307
  collectionCallbacks: this.followersCallbacks,
1308
+ tracerProvider: this.tracerProvider,
1262
1309
  onUnauthorized,
1263
1310
  onNotFound,
1264
1311
  onNotAcceptable,
@@ -1271,6 +1318,7 @@ export class FederationImpl {
1271
1318
  uriGetter: context.getLikedUri.bind(context),
1272
1319
  context,
1273
1320
  collectionCallbacks: this.likedCallbacks,
1321
+ tracerProvider: this.tracerProvider,
1274
1322
  onUnauthorized,
1275
1323
  onNotFound,
1276
1324
  onNotAcceptable,
@@ -1282,6 +1330,7 @@ export class FederationImpl {
1282
1330
  uriGetter: context.getFeaturedUri.bind(context),
1283
1331
  context,
1284
1332
  collectionCallbacks: this.featuredCallbacks,
1333
+ tracerProvider: this.tracerProvider,
1285
1334
  onUnauthorized,
1286
1335
  onNotFound,
1287
1336
  onNotAcceptable,
@@ -1293,6 +1342,7 @@ export class FederationImpl {
1293
1342
  uriGetter: context.getFeaturedTagsUri.bind(context),
1294
1343
  context,
1295
1344
  collectionCallbacks: this.featuredTagsCallbacks,
1345
+ tracerProvider: this.tracerProvider,
1296
1346
  onUnauthorized,
1297
1347
  onNotFound,
1298
1348
  onNotAcceptable,