pi-mono/packages/chord/src/data/principal.ts
Mario Zechner 378d45a05b feat(chord): telemetry, spans across hosts (slice 9)
Chord's telemetry schema; spans for calls, methods, relays, holds, activations, natives, loads, reloads, resolves,
revocations, routines, jobs and HTTP requests; trace carriers on hold and call (bounded, printable ASCII) continued by
relays and workers; events and host-wide metrics; the app kit passes an adapter to its hosts. renderTrace escapes
control characters. Example 62 prints a trace across three hosts.
2026-11-04 10:02:48 +00:00

58 lines
2.2 KiB
TypeScript

// Principals: the app's caller identities, and the keys Chord derives from them.
import type { Context } from "../context/index.ts";
import type { JsonValue } from "../json.ts";
import { chordMetrics } from "../telemetry.ts";
/** An app's principal: plain JSON with a `kind`. Chord never persists it. */
export type Principal = { readonly kind: string; readonly [field: string]: JsonValue };
/** An app's own principal key; it must be the same function on every host. */
export type PrincipalKeyFunction<P extends Principal = Principal> = (principal: P) => string;
/**
* The key of a principal: its canonical JSON, or `customKey(principal)`. Cached per principal object; a custom key's
* cache is keyed by the function too, so a live principal never retains a dropped function.
*/
export function principalKey<P extends Principal>(
principal: P,
context: Context,
customKey?: PrincipalKeyFunction<P>,
): string {
const cache = customKey === undefined ? defaultKeys : customKeyCache(customKey);
let key = cache.get(principal);
if (key === undefined) {
key = customKey === undefined ? canonicalJson(principal, context) : customKey(principal);
cache.set(principal, key);
}
return key;
}
const defaultKeys = new WeakMap<Principal, string>();
const customKeys = new WeakMap<PrincipalKeyFunction<never>, WeakMap<Principal, string>>();
function customKeyCache(customKey: PrincipalKeyFunction<never>): WeakMap<Principal, string> {
let cache = customKeys.get(customKey);
if (cache === undefined) {
cache = new WeakMap();
customKeys.set(customKey, cache);
}
return cache;
}
/** Canonical JSON: sorted object keys, `-0` written as `0`. Counts one walk. */
export function canonicalJson(value: JsonValue, context: Context): string {
chordMetrics(context.telemetry.metrics).counter("chord.data.walks").add(1);
return canonical(value);
}
function canonical(value: JsonValue): string {
// JSON.stringify writes -0 as 0.
if (value === null || typeof value !== "object") return JSON.stringify(value);
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
const fields = Object.keys(value)
.sort()
.map((key) => `${JSON.stringify(key)}:${canonical(value[key]!)}`);
return `{${fields.join(",")}}`;
}