Skip to content

Commit

Permalink
Also keep track of hits
Browse files Browse the repository at this point in the history
  • Loading branch information
hansott committed Dec 6, 2024
1 parent 1cf5380 commit cf1194f
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 29 deletions.
74 changes: 51 additions & 23 deletions library/agent/Hostnames.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,40 @@ t.test("it works", async () => {
t.same(hostnames.asArray(), []);

hostnames.add("aikido.dev", 443);
t.same(hostnames.asArray(), [{ hostname: "aikido.dev", port: 443 }]);
t.same(hostnames.asArray(), [{ hostname: "aikido.dev", port: 443, hits: 1 }]);

hostnames.add("aikido.dev", 80);
t.same(hostnames.asArray(), [
{ hostname: "aikido.dev", port: 443 },
{ hostname: "aikido.dev", port: 80 },
{ hostname: "aikido.dev", port: 443, hits: 1 },
{ hostname: "aikido.dev", port: 80, hits: 1 },
]);

hostnames.add("google.com", 80);
t.same(hostnames.asArray(), [
{ hostname: "aikido.dev", port: 443 },
{ hostname: "aikido.dev", port: 80 },
{ hostname: "google.com", port: 80 },
{ hostname: "aikido.dev", port: 443, hits: 1 },
{ hostname: "aikido.dev", port: 80, hits: 1 },
{ hostname: "google.com", port: 80, hits: 1 },
]);

hostnames.add("google.com", undefined);
t.same(hostnames.asArray(), [
{ hostname: "aikido.dev", port: 80 },
{ hostname: "google.com", port: 80 },
{ hostname: "google.com", port: undefined },
{ hostname: "aikido.dev", port: 80, hits: 1 },
{ hostname: "google.com", port: 80, hits: 1 },
{ hostname: "google.com", port: undefined, hits: 1 },
]);

hostnames.add("github.com", 80);
t.same(hostnames.asArray(), [
{ hostname: "google.com", port: 80 },
{ hostname: "google.com", port: undefined },
{ hostname: "github.com", port: 80 },
{ hostname: "google.com", port: 80, hits: 1 },
{ hostname: "google.com", port: undefined, hits: 1 },
{ hostname: "github.com", port: 80, hits: 1 },
]);

hostnames.add("jetbrains.com", 80);
t.same(hostnames.asArray(), [
{ hostname: "google.com", port: undefined },
{ hostname: "github.com", port: 80 },
{ hostname: "jetbrains.com", port: 80 },
{ hostname: "google.com", port: undefined, hits: 1 },
{ hostname: "github.com", port: 80, hits: 1 },
{ hostname: "jetbrains.com", port: 80, hits: 1 },
]);

hostnames.clear();
Expand All @@ -52,29 +52,57 @@ t.test("it respects max size", async () => {
hostnames.add("aikido.dev", 2);

t.same(hostnames.asArray(), [
{ hostname: "aikido.dev", port: 1 },
{ hostname: "aikido.dev", port: 2 },
{ hostname: "aikido.dev", port: 1, hits: 1 },
{ hostname: "aikido.dev", port: 2, hits: 1 },
]);

hostnames.add("aikido.dev", 3);
hostnames.add("aikido.dev", 4);

t.same(hostnames.asArray(), [
{ hostname: "aikido.dev", port: 3 },
{ hostname: "aikido.dev", port: 4 },
{ hostname: "aikido.dev", port: 3, hits: 1 },
{ hostname: "aikido.dev", port: 4, hits: 1 },
]);

hostnames.add("google.com", 1);

t.same(hostnames.asArray(), [
{ hostname: "aikido.dev", port: 4 },
{ hostname: "google.com", port: 1 },
{ hostname: "aikido.dev", port: 4, hits: 1 },
{ hostname: "google.com", port: 1, hits: 1 },
]);

hostnames.add("google.com", 2);

t.same(hostnames.asArray(), [
{ hostname: "google.com", port: 1 },
{ hostname: "google.com", port: 2 },
{ hostname: "google.com", port: 1, hits: 1 },
{ hostname: "google.com", port: 2, hits: 1 },
]);
});

t.test("it tracks hits", async () => {
const hostnames = new Hostnames(3);

hostnames.add("aikido.dev", 443);
hostnames.add("aikido.dev", 443);
t.same(hostnames.asArray(), [{ hostname: "aikido.dev", port: 443, hits: 2 }]);

hostnames.add("aikido.dev", 80);
t.same(hostnames.asArray(), [
{ hostname: "aikido.dev", port: 443, hits: 2 },
{ hostname: "aikido.dev", port: 80, hits: 1 },
]);

hostnames.add("google.com", 80);
t.same(hostnames.asArray(), [
{ hostname: "aikido.dev", port: 443, hits: 2 },
{ hostname: "aikido.dev", port: 80, hits: 1 },
{ hostname: "google.com", port: 80, hits: 1 },
]);

hostnames.add("aikido.dev", 443);
t.same(hostnames.asArray(), [
{ hostname: "aikido.dev", port: 443, hits: 3 },
{ hostname: "aikido.dev", port: 80, hits: 1 },
{ hostname: "google.com", port: 80, hits: 1 },
]);
});
34 changes: 28 additions & 6 deletions library/agent/Hostnames.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
type Ports = Set<number | undefined>;
type Ports = Map<string, number>;

export class Hostnames {
private map: Map<string, Ports> = new Map();

constructor(private readonly maxEntries: number = 200) {}

private portKey(port: number | undefined) {
return port === undefined ? "__NO_PORT__" : port.toString();
}

private keyToPort(key: string) {
return key === "__NO_PORT__" ? undefined : parseInt(key, 10);
}

add(hostname: string, port: number | undefined) {
const portKey = this.portKey(port);
if (!this.map.has(hostname)) {
this.map.set(hostname, new Set([port]));
this.map.set(hostname, new Map([[portKey, 1]]));
} else {
this.map.get(hostname)?.add(port);
const ports = this.map.get(hostname) as Ports;
if (ports.has(portKey)) {
ports.set(portKey, ports.get(portKey)! + 1);
} else {
ports.set(portKey, 1);
}
}

if (this.length > this.maxEntries) {
Expand All @@ -18,8 +32,10 @@ export class Hostnames {
const ports: Ports = this.map.get(firstAdded) as Ports;

if (ports.size > 1) {
const firstPort = ports.values().next().value;
ports.delete(firstPort);
const firstPort = ports.keys().next().value;
if (firstPort) {
ports.delete(firstPort);
}
} else {
this.map.delete(firstAdded);
}
Expand All @@ -36,7 +52,13 @@ export class Hostnames {

asArray() {
return Array.from(this.map.entries()).flatMap(([hostname, ports]) =>
Array.from(ports).map((port) => ({ hostname, port }))
Array.from(ports.entries()).map(([port, hits]) => {
return {
hostname,
port: this.keyToPort(port),
hits,
};
})
);
}

Expand Down

0 comments on commit cf1194f

Please sign in to comment.