History

feat: add native resource telemetry

Replace scheduled process shell probes with a persistent native collector, Electron power/process telemetry, Effect services, diagnostics UI, attribution, and release packaging.

Julius Marminge committed 4 months ago

Commit dbd8a8e1 parent 79ad07162 files · +7741 −1957Browse files

Showing the changes to scripts (2 of 62 files). Show all

Unified · Split

2 files
  1. scripts/build-desktop-artifact.test.ts +24 −0
  2. scripts/build-desktop-artifact.ts +106 −0
scripts/build-desktop-artifact.test.ts+24−0
@@ -9,12 +9,15 @@ import { · 8 unmodified lines
99 createStageWorkspaceConfig,
1010 createStagePnpmConfig,
1111 DESKTOP_ASAR_UNPACK,
12+ DESKTOP_EXTRA_RESOURCES,
1213 resolveDesktopRuntimeDependencies,
1314 resolveFffNativeDependencies,
1415 resolveBuildOptions,
1516 resolveDesktopBuildIconAssets,
1617 resolveDesktopProductName,
1718 resolveDesktopUpdateChannel,
19+ resolveResourceMonitorRustTargets,
20+ resourceMonitorExecutableName,
1821 resolveGitHubPublishConfig,
1922 resolveMockUpdateServerPort,
2023 resolveMockUpdateServerUrl,
@@ -175,6 +178,27 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { · 154 unmodified lines
175178 assert.deepStrictEqual(DESKTOP_ASAR_UNPACK, ["node_modules/@ff-labs/fff-bin-*/**/*"]);
176179 });
177180
181+ it("stages the resource monitor as an external executable resource", () => {
182+ assert.deepStrictEqual(DESKTOP_EXTRA_RESOURCES, [
183+ {
184+ from: "apps/desktop/prod-resources/resource-monitor",
185+ to: "resource-monitor",
186+ },
187+ ]);
188+ assert.deepStrictEqual(resolveResourceMonitorRustTargets("mac", "universal"), [
189+ "aarch64-apple-darwin",
190+ "x86_64-apple-darwin",
191+ ]);
192+ assert.deepStrictEqual(resolveResourceMonitorRustTargets("linux", "x64"), [
193+ "x86_64-unknown-linux-gnu",
194+ ]);
195+ assert.deepStrictEqual(resolveResourceMonitorRustTargets("win", "arm64"), [
196+ "aarch64-pc-windows-msvc",
197+ ]);
198+ assert.equal(resourceMonitorExecutableName("mac"), "t3-resource-monitor");
199+ assert.equal(resourceMonitorExecutableName("win"), "t3-resource-monitor.exe");
200+ });
201+
178202 it("promotes target fff binaries to direct staged dependencies", () => {
179203 assert.deepStrictEqual(resolveFffNativeDependencies("mac", "arm64", "0.9.4"), {
180204 "@ff-labs/fff-bin-darwin-arm64": "0.9.4",
scripts/build-desktop-artifact.ts+106−0
@@ -72,6 +72,26 @@ interface PlatformConfig { · 71 unmodified lines
7272 readonly archChoices: ReadonlyArray<typeof BuildArch.Type>;
7373 }
7474
75+export function resolveResourceMonitorRustTargets(
76+ platform: typeof BuildPlatform.Type,
77+ arch: typeof BuildArch.Type,
78+): ReadonlyArray<string> {
79+ if (platform === "mac") {
80+ if (arch === "universal") {
81+ return ["aarch64-apple-darwin", "x86_64-apple-darwin"];
82+ }
83+ return [arch === "arm64" ? "aarch64-apple-darwin" : "x86_64-apple-darwin"];
84+ }
85+ if (platform === "linux") {
86+ return [arch === "arm64" ? "aarch64-unknown-linux-gnu" : "x86_64-unknown-linux-gnu"];
87+ }
88+ return [arch === "arm64" ? "aarch64-pc-windows-msvc" : "x86_64-pc-windows-msvc"];
89+}
90+
91+export function resourceMonitorExecutableName(platform: typeof BuildPlatform.Type): string {
92+ return platform === "win" ? "t3-resource-monitor.exe" : "t3-resource-monitor";
93+}
94+
7595 const PLATFORM_CONFIG: Record<typeof BuildPlatform.Type, PlatformConfig> = {
7696 mac: {
7797 cliFlag: "--mac",
@@ -292,6 +312,12 @@ interface StagePackageJson { · 214 unmodified lines
292312
293313 export const STAGE_INSTALL_ARGS = ["install", "--prod"] as const;
294314 export const DESKTOP_ASAR_UNPACK = ["node_modules/@ff-labs/fff-bin-*/**/*"] as const;
315+export const DESKTOP_EXTRA_RESOURCES = [
316+ {
317+ from: "apps/desktop/prod-resources/resource-monitor",
318+ to: "resource-monitor",
319+ },
320+] as const;
295321
296322 export function resolveFffNativeDependencies(
297323 platform: typeof BuildPlatform.Type,
@@ -497,6 +523,78 @@ const runCommand = Effect.fn("runCommand")(function* ( · 199 unmodified lines
497523 }
498524 });
499525
526+const stageResourceMonitor = Effect.fn("stageResourceMonitor")(function* (input: {
527+ readonly repoRoot: string;
528+ readonly stageResourcesDir: string;
529+ readonly platform: typeof BuildPlatform.Type;
530+ readonly arch: typeof BuildArch.Type;
531+ readonly verbose: boolean;
532+}) {
533+ const fs = yield* FileSystem.FileSystem;
534+ const path = yield* Path.Path;
535+ const manifestPath = path.join(input.repoRoot, "native/resource-monitor/Cargo.toml");
536+ const executableName = resourceMonitorExecutableName(input.platform);
537+ const rustTargets = resolveResourceMonitorRustTargets(input.platform, input.arch);
538+ const builtBinaries: string[] = [];
539+
540+ for (const rustTarget of rustTargets) {
541+ const spawnCommand = yield* resolveSpawnCommand("cargo", [
542+ "build",
543+ "--locked",
544+ "--release",
545+ "--manifest-path",
546+ manifestPath,
547+ "--target",
548+ rustTarget,
549+ ]);
550+ yield* runCommand(
551+ ChildProcess.make(spawnCommand.command, spawnCommand.args, {
552+ cwd: input.repoRoot,
553+ shell: spawnCommand.shell,
554+ }),
555+ {
556+ label: `cargo build resource monitor (${rustTarget})`,
557+ verbose: input.verbose,
558+ },
559+ );
560+
561+ const binaryPath = path.join(
562+ input.repoRoot,
563+ "native/resource-monitor/target",
564+ rustTarget,
565+ "release",
566+ executableName,
567+ );
568+ if (!(yield* fs.exists(binaryPath))) {
569+ return yield* new BuildScriptError({
570+ message: `Resource monitor build did not produce ${binaryPath}.`,
571+ });
572+ }
573+ builtBinaries.push(binaryPath);
574+ }
575+
576+ const destinationDirectory = path.join(input.stageResourcesDir, "resource-monitor");
577+ const destinationPath = path.join(destinationDirectory, executableName);
578+ yield* fs.remove(destinationDirectory, { recursive: true, force: true }).pipe(Effect.ignore);
579+ yield* fs.makeDirectory(destinationDirectory, { recursive: true });
580+
581+ if (builtBinaries.length === 1) {
582+ yield* fs.copyFile(builtBinaries[0]!, destinationPath);
583+ } else {
584+ yield* runCommand(
585+ ChildProcess.make("lipo", ["-create", ...builtBinaries, "-output", destinationPath]),
586+ {
587+ label: "lipo resource monitor universal binary",
588+ verbose: input.verbose,
589+ },
590+ );
591+ }
592+
593+ if (input.platform !== "win") {
594+ yield* fs.chmod(destinationPath, 0o755);
595+ }
596+});
597+
500598 function generateMacIconSet(
501599 sourcePng: string,
502600 targetIcns: string,
@@ -755,6 +853,7 @@ const createBuildConfig = Effect.fn("createBuildConfig")(function* ( · 252 unmodified lines
755853 directories: {
756854 buildResources: "apps/desktop/resources",
757855 },
856+ extraResources: DESKTOP_EXTRA_RESOURCES,
758857 };
759858 const updateChannel = resolveDesktopUpdateChannel(version);
760859 const publishConfig = yield* resolveGitHubPublishConfig(updateChannel);
@@ -941,6 +1040,13 @@ const buildDesktopArtifact = Effect.fn("buildDesktopArtifact")(function* ( · 180 unmodified lines
9411040 yield* fs.copy(distDirs.desktopDist, path.join(stageAppDir, "apps/desktop/dist-electron"));
9421041 yield* fs.copy(distDirs.desktopResources, stageResourcesDir);
9431042 yield* fs.copy(distDirs.serverDist, path.join(stageAppDir, "apps/server/dist"));
1043+ yield* stageResourceMonitor({
1044+ repoRoot,
1045+ stageResourcesDir,
1046+ platform: options.platform,
1047+ arch: options.arch,
1048+ verbose: options.verbose,
1049+ });
9441050
9451051 yield* assertPlatformBuildResources(
9461052 options.platform,