authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-08 01:11:09-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-08 01:11:09-07:00
log77d9ffc822ac4c1f3600dc6c97e92fc94e9e12a3
tree9b012e4a798040c97b2f2ecf144c0eb2966e08c1
parent161715b1e4fa6d20fe3eb1cb9c91904bf83ca4c1
signature Signed by PGP key B5690EEEBB952194

refactor(server): classify telemetry exports (#10277)


16 files changed, 20 insertions(+), 12 deletions(-)

apps/server/integration/NetworkTransferMeasurement.integration.ts+3-3
...@@ -120,7 +120,7 @@ function rawDataBytes(data: NodeSocket.NodeWS.RawData): number {...@@ -120,7 +120,7 @@ function rawDataBytes(data: NodeSocket.NodeWS.RawData): number {
120 return data.byteLength;120 return data.byteLength;
121}121}
122122
123export function makeWebSocketTransferRecorder(): WebSocketTransferRecorder {123function makeWebSocketTransferRecorder(): WebSocketTransferRecorder {
124 let socket: NodeWebSocketWithTransport | null = null;124 let socket: NodeWebSocketWithTransport | null = null;
125 // Held separately from the WebSocket so wire totals survive a close, which125 // Held separately from the WebSocket so wire totals survive a close, which
126 // is when a reconnect measurement reads them.126 // is when a reconnect measurement reads them.
...@@ -176,7 +176,7 @@ export function transferDelta(...@@ -176,7 +176,7 @@ export function transferDelta(
176 };176 };
177}177}
178178
179export function countingWsRpcProtocolLayer(input: {179function countingWsRpcProtocolLayer(input: {
180 readonly url: string;180 readonly url: string;
181 readonly cookie: string;181 readonly cookie: string;
182 readonly recorder: WebSocketTransferRecorder;182 readonly recorder: WebSocketTransferRecorder;
...@@ -194,7 +194,7 @@ export function countingWsRpcProtocolLayer(input: {...@@ -194,7 +194,7 @@ export function countingWsRpcProtocolLayer(input: {
194 );194 );
195}195}
196196
197export const makeCountingWsRpcClient = RpcClient.make(WsRpcGroup);197const makeCountingWsRpcClient = RpcClient.make(WsRpcGroup);
198export type CountingWsRpcClient = Effect.Success<typeof makeCountingWsRpcClient>;198export type CountingWsRpcClient = Effect.Success<typeof makeCountingWsRpcClient>;
199199
200export interface MeasuredWsClient {200export interface MeasuredWsClient {
apps/server/integration/TransferBudgetReport.integration.ts+1-1
...@@ -56,7 +56,7 @@ const TRANSFER_BUDGET = {...@@ -56,7 +56,7 @@ const TRANSFER_BUDGET = {
56 measuredTurnWebSocketMessages: 21,56 measuredTurnWebSocketMessages: 21,
57} satisfies ProviderTransferBudget;57} satisfies ProviderTransferBudget;
5858
59export const TRANSFER_BUDGETS: Readonly<Record<string, ProviderTransferBudget>> = {59const TRANSFER_BUDGETS: Readonly<Record<string, ProviderTransferBudget>> = {
60 codex: TRANSFER_BUDGET,60 codex: TRANSFER_BUDGET,
61 claudeAgent: TRANSFER_BUDGET,61 claudeAgent: TRANSFER_BUDGET,
62};62};
apps/server/integration/TransferBudgetScenario.integration.ts+1-1
...@@ -26,7 +26,7 @@ import {...@@ -26,7 +26,7 @@ import {
26 TRANSFER_HISTORY_TURN_COUNT,26 TRANSFER_HISTORY_TURN_COUNT,
27} from "./fixtures/transferBudget.ts";27} from "./fixtures/transferBudget.ts";
2828
29export const TRANSFER_PROJECT_ID = ProjectId.make("transfer-budget-project");29const TRANSFER_PROJECT_ID = ProjectId.make("transfer-budget-project");
30export const TRANSFER_THREAD_ID = ThreadId.make("transfer-budget-thread");30export const TRANSFER_THREAD_ID = ThreadId.make("transfer-budget-thread");
31export const TRANSFER_MEASURED_TURN_INDEX = TRANSFER_HISTORY_TURN_COUNT;31export const TRANSFER_MEASURED_TURN_INDEX = TRANSFER_HISTORY_TURN_COUNT;
3232
apps/server/src/diagnostics/ProcessDiagnostics.ts+1
...@@ -54,6 +54,7 @@ function canSignalCategory(category: ResourceTelemetryProcessCategory): boolean...@@ -54,6 +54,7 @@ function canSignalCategory(category: ResourceTelemetryProcessCategory): boolean
54 );54 );
55}55}
5656
57/** @public Service construction is part of the canonical Effect module API. */
57export const make = Effect.fn("makeProcessDiagnostics")(function* () {58export const make = Effect.fn("makeProcessDiagnostics")(function* () {
58 const telemetry = yield* ResourceTelemetry.ResourceTelemetry;59 const telemetry = yield* ResourceTelemetry.ResourceTelemetry;
59 const refreshedTelemetry = telemetry.refresh.pipe(Effect.catch(() => telemetry.latest));60 const refreshedTelemetry = telemetry.refresh.pipe(Effect.catch(() => telemetry.latest));
apps/server/src/diagnostics/ProcessResourceMonitor.ts+1
...@@ -28,6 +28,7 @@ function isLegacyBackendCategory(category: ResourceTelemetryProcessCategory): bo...@@ -28,6 +28,7 @@ function isLegacyBackendCategory(category: ResourceTelemetryProcessCategory): bo
28 );28 );
29}29}
3030
31/** @public Service construction is part of the canonical Effect module API. */
31export const make = Effect.fn("makeProcessResourceMonitor")(function* () {32export const make = Effect.fn("makeProcessResourceMonitor")(function* () {
32 const telemetry = yield* ResourceTelemetry.ResourceTelemetry;33 const telemetry = yield* ResourceTelemetry.ResourceTelemetry;
33 const readHistory: ProcessResourceMonitor["Service"]["readHistory"] = (input) =>34 const readHistory: ProcessResourceMonitor["Service"]["readHistory"] = (input) =>
apps/server/src/diagnostics/TraceDiagnostics.ts+1
...@@ -411,6 +411,7 @@ function readTraceFile(...@@ -411,6 +411,7 @@ function readTraceFile(
411 );411 );
412}412}
413413
414/** @public Service construction is part of the canonical Effect module API. */
414export const make = Effect.gen(function* () {415export const make = Effect.gen(function* () {
415 const fileSystem = yield* FileSystem.FileSystem;416 const fileSystem = yield* FileSystem.FileSystem;
416417
apps/server/src/resourceTelemetry/DesktopTelemetryReceiver.ts+1
...@@ -327,6 +327,7 @@ export function requireDesktopTelemetryWriteProgress(...@@ -327,6 +327,7 @@ export function requireDesktopTelemetryWriteProgress(
327 : Effect.fail(new DesktopTelemetryControlStalled({ fd, remainingBytes }));327 : Effect.fail(new DesktopTelemetryControlStalled({ fd, remainingBytes }));
328}328}
329329
330/** @public Service construction is part of the canonical Effect module API. */
330export const make = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(function* () {331export const make = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(function* () {
331 const config = yield* ServerConfig;332 const config = yield* ServerConfig;
332 const serverSettings = yield* ServerSettingsService;333 const serverSettings = yield* ServerSettingsService;
apps/server/src/resourceTelemetry/Model.ts+1-1
...@@ -68,7 +68,7 @@ export interface MergeProcessesResult {...@@ -68,7 +68,7 @@ export interface MergeProcessesResult {
68 readonly deltas: ReadonlyArray<ProcessDelta>;68 readonly deltas: ReadonlyArray<ProcessDelta>;
69}69}
7070
71export const emptyGroupCounters = (): GroupCounters => ({71const emptyGroupCounters = (): GroupCounters => ({
72 cpuTimeMs: 0,72 cpuTimeMs: 0,
73 ioReadBytes: 0,73 ioReadBytes: 0,
74 ioWriteBytes: 0,74 ioWriteBytes: 0,
apps/server/src/resourceTelemetry/NativeTelemetryClient.ts+1
...@@ -360,6 +360,7 @@ export function canCommandNativeTelemetrySidecar(...@@ -360,6 +360,7 @@ export function canCommandNativeTelemetrySidecar(
360 return hasHandle && (status === "healthy" || status === "degraded");360 return hasHandle && (status === "healthy" || status === "degraded");
361}361}
362362
363/** @public Service construction is part of the canonical Effect module API. */
363export const make = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(function* () {364export const make = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(function* () {
364 const binary = yield* ResourceMonitorBinary.ResourceMonitorBinary;365 const binary = yield* ResourceMonitorBinary.ResourceMonitorBinary;
365 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;366 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
apps/server/src/resourceTelemetry/ResourceMonitorBinary.ts+2-2
...@@ -90,7 +90,7 @@ export const ResourceMonitorHostLinuxLibc = Context.Reference<ResourceMonitorLin...@@ -90,7 +90,7 @@ export const ResourceMonitorHostLinuxLibc = Context.Reference<ResourceMonitorLin
90 },90 },
91);91);
9292
93export function resourceMonitorPlatformKey(93function resourceMonitorPlatformKey(
94 platform: NodeJS.Platform,94 platform: NodeJS.Platform,
95 architecture: NodeJS.Architecture,95 architecture: NodeJS.Architecture,
96): string | undefined {96): string | undefined {
...@@ -103,7 +103,7 @@ export function resourceMonitorPlatformKey(...@@ -103,7 +103,7 @@ export function resourceMonitorPlatformKey(
103 return `${platform}-${architecture}`;103 return `${platform}-${architecture}`;
104}104}
105105
106export function resourceMonitorRustTarget(106function resourceMonitorRustTarget(
107 platform: NodeJS.Platform,107 platform: NodeJS.Platform,
108 architecture: NodeJS.Architecture,108 architecture: NodeJS.Architecture,
109 linuxLibc?: ResourceMonitorLinuxLibc,109 linuxLibc?: ResourceMonitorLinuxLibc,
apps/server/src/resourceTelemetry/ResourceTelemetry.ts+1
...@@ -142,6 +142,7 @@ function buildHealth(input: {...@@ -142,6 +142,7 @@ function buildHealth(input: {
142 };142 };
143}143}
144144
145/** @public Service construction is part of the canonical Effect module API. */
145export const make = Effect.fn("resourceTelemetry.resourceTelemetry.make")(function* () {146export const make = Effect.fn("resourceTelemetry.resourceTelemetry.make")(function* () {
146 const nativeClient = yield* NativeTelemetryClient.NativeTelemetryClient;147 const nativeClient = yield* NativeTelemetryClient.NativeTelemetryClient;
147 const desktopReceiver = yield* DesktopTelemetryReceiver.DesktopTelemetryReceiver;148 const desktopReceiver = yield* DesktopTelemetryReceiver.DesktopTelemetryReceiver;
apps/server/src/telemetry/AnalyticsService.ts+2-1
...@@ -67,7 +67,7 @@ export class AnalyticsService extends Context.Service<...@@ -67,7 +67,7 @@ export class AnalyticsService extends Context.Service<
67 );67 );
68}68}
6969
70export function serverOsFromNodePlatform(platform: string): ClientOs {70function serverOsFromNodePlatform(platform: string): ClientOs {
71 switch (platform) {71 switch (platform) {
72 case "darwin":72 case "darwin":
73 return "macOS";73 return "macOS";
...@@ -82,6 +82,7 @@ export function serverOsFromNodePlatform(platform: string): ClientOs {...@@ -82,6 +82,7 @@ export function serverOsFromNodePlatform(platform: string): ClientOs {
82 }82 }
83}83}
8484
85/** @public Service construction is part of the canonical Effect module API. */
85export const make = Effect.gen(function* () {86export const make = Effect.gen(function* () {
86 const telemetryConfig = yield* TelemetryEnvConfig;87 const telemetryConfig = yield* TelemetryEnvConfig;
87 const httpClient = yield* HttpClient.HttpClient;88 const httpClient = yield* HttpClient.HttpClient;
apps/server/src/usage/UsageLimitSources.ts+1
...@@ -60,6 +60,7 @@ function sourceLabel(id: string, config: UsageLimitSourceConfig): string {...@@ -60,6 +60,7 @@ function sourceLabel(id: string, config: UsageLimitSourceConfig): string {
60 }60 }
61}61}
6262
63/** @public Service construction is part of the canonical Effect module API. */
63export const make = Effect.gen(function* () {64export const make = Effect.gen(function* () {
64 const api = yield* makeCliproxyApi;65 const api = yield* makeCliproxyApi;
65 const settingsService = yield* ServerSettingsService;66 const settingsService = yield* ServerSettingsService;
apps/server/src/usage/usageAggregation.ts+1-1
...@@ -23,7 +23,7 @@ import { cacheSavingsUsd, priceUsage, type RateTable } from "./usagePricing.ts";...@@ -23,7 +23,7 @@ import { cacheSavingsUsd, priceUsage, type RateTable } from "./usagePricing.ts";
23 * `en-CA` yields ISO-ordered parts, which is why it is used here rather than23 * `en-CA` yields ISO-ordered parts, which is why it is used here rather than
24 * assembling the day from `Date` getters (those are host-local only).24 * assembling the day from `Date` getters (those are host-local only).
25 */25 */
26export function makeDayFormatter(timeZone: string): (timestampMs: number) => string {26function makeDayFormatter(timeZone: string): (timestampMs: number) => string {
27 let format: Intl.DateTimeFormat;27 let format: Intl.DateTimeFormat;
28 try {28 try {
29 format = new Intl.DateTimeFormat("en-CA", {29 format = new Intl.DateTimeFormat("en-CA", {
apps/server/src/usage/usageScanCache.ts+1-1
...@@ -26,7 +26,7 @@ import type { CodexScanState, UsageRecord } from "./usageTranscripts.ts";...@@ -26,7 +26,7 @@ import type { CodexScanState, UsageRecord } from "./usageTranscripts.ts";
26// entries would keep serving double-counted records forever.26// entries would keep serving double-counted records forever.
27// v3: entries carry the parse position and reducer state so a grown file27// v3: entries carry the parse position and reducer state so a grown file
28// re-parses only its appended bytes instead of starting over.28// re-parses only its appended bytes instead of starting over.
29export const USAGE_SCAN_CACHE_VERSION = 3 as const;29const USAGE_SCAN_CACHE_VERSION = 3 as const;
3030
31export interface CachedFile {31export interface CachedFile {
32 readonly size: number;32 readonly size: number;
apps/server/src/usage/usageTranscripts.ts+1-1
...@@ -79,7 +79,7 @@ export function mightCarryUsage(line: string, provider: UsageProviderKind): bool...@@ -79,7 +79,7 @@ export function mightCarryUsage(line: string, provider: UsageProviderKind): bool
79 */79 */
80export const GROK_COST_USD_TICKS_PER_DOLLAR = 10_000_000_000;80export const GROK_COST_USD_TICKS_PER_DOLLAR = 10_000_000_000;
8181
82export function grokCostTicksToUsd(ticks: unknown): number | null {82function grokCostTicksToUsd(ticks: unknown): number | null {
83 if (typeof ticks !== "number" || !Number.isFinite(ticks) || ticks < 0) return null;83 if (typeof ticks !== "number" || !Number.isFinite(ticks) || ticks < 0) return null;
84 return ticks / GROK_COST_USD_TICKS_PER_DOLLAR;84 return ticks / GROK_COST_USD_TICKS_PER_DOLLAR;
85}85}