M5: outbound requests, previews, the media proxy and served traffic
- HttpScope (AsyncLocal) tags each outbound request with a purpose and a trigger:
- purpose is set by the caller: actor, key, object, webfinger, context, nodeinfo;
- trigger is set by the job kind, by "verify" during inbox verification, or defaults
to "request".
- FederationHttp records every JSON, media and stream fetch: status, time, bytes, hops,
and an outcome of ok, refused or failed, with a reason: disallowed, remembered,
bad-redirect, too-many-redirects, content-type, too-large, bad-json, private-address,
timeout, network, or the status. A fetch a reader caused (trigger "request") is only
counted per server per day.
- Link previews record a 'preview' event: card, no-card or failed.
- The media proxy counts cache hits.
- TrafficMeter counts the client API per endpoint group, method and status class. It
counts our served documents (actor, outbox, collection, object, activity, licence,
webfinger, nodeinfo) by kind, status and whether signed, per day and never per server,
and never names a circle's collections.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ELjqpznMFMNrJoJUj6K5p2
This commit is contained in:
1 parent
e247001bdb
commit
d37999970c
14 files changed
+487
-19
No files matched your search
@@ -81,5 +81,33 @@ namespace PrivaPub.Tests.Statistics
|
||||
Assert.DoesNotContain(bob.Name, everything);
|
||||
Assert.DoesNotContain("/notes/", everything);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Client_and_served_traffic_is_counted_per_day_never_per_server()
|
||||
{
|
||||
var token = TestContext.Current.CancellationToken;
|
||||
var persona = await _host.Persona(await _host.SignUp(), "served");
|
||||
var reader = new RemoteActor(_peer, "reader");
|
||||
var day = DateTime.UtcNow.Date;
|
||||
await _host.Get<InteractionLedger>().Flush(token);
|
||||
var before = await DB.Default.Find<ServerDay>().Match(d => d.Day == day).ExecuteFirstAsync(token) ?? new ServerDay();
|
||||
using var client = _host.Client();
|
||||
|
||||
Assert.Equal(HttpStatusCode.OK, (await client.GetAsync("/api/v1/instance", token)).StatusCode);
|
||||
using (var actorRequest = new HttpRequestMessage(HttpMethod.Get, $"/peasants/{persona.UserName}"))
|
||||
{
|
||||
actorRequest.Headers.Accept.ParseAdd("application/activity+json");
|
||||
Assert.Equal(HttpStatusCode.OK, (await client.SendAsync(actorRequest, token)).StatusCode);
|
||||
}
|
||||
Assert.Equal(HttpStatusCode.OK, (await client.SendAsync(reader.SignedGet($"/peasants/{persona.UserName}/anus"), token)).StatusCode);
|
||||
await _host.Get<InteractionLedger>().Flush(token);
|
||||
|
||||
var after = await DB.Default.Find<ServerDay>().Match(d => d.Day == day).ExecuteFirstAsync(token);
|
||||
long Grew(Dictionary<string, long> now, Dictionary<string, long> then, string key) => now.GetValueOrDefault(key) - then.GetValueOrDefault(key);
|
||||
Assert.True(Grew(after.Client, before.Client, "api/v1/instance:GET:2xx") >= 1);
|
||||
Assert.True(Grew(after.Served, before.Served, "actor:200:unsigned") >= 1);
|
||||
Assert.True(Grew(after.Served, before.Served, "outbox:200:signed") >= 1);
|
||||
Assert.DoesNotContain(after.Served.Keys, k => k.Contains(persona.UserName));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user