165 lines · 6.5 KB · TypeScript
RawDownload
import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient";import * as NodeServices from "@effect/platform-node/NodeServices";import { assert, describe, it } from "@effect/vitest";import * as Effect from "effect/Effect";import * as FileSystem from "effect/FileSystem";import * as Layer from "effect/Layer";import * as Schema from "effect/Schema"; import * as DesktopConfig from "./DesktopConfig.ts";import * as DesktopEnvironment from "./DesktopEnvironment.ts";import * as DesktopObservability from "./DesktopObservability.ts"; const DesktopBackendChildLogRecord = Schema.Struct({  message: Schema.String,  level: Schema.Literals(["INFO", "ERROR"]),  timestamp: Schema.String,  annotations: Schema.Record(Schema.String, Schema.Unknown),  spans: Schema.Record(Schema.String, Schema.Unknown),  fiberId: Schema.String,}); const decodeDesktopBackendChildLogRecord = Schema.decodeEffect(  Schema.fromJsonString(DesktopBackendChildLogRecord),); const TraceRecordLine = Schema.Struct({  name: Schema.String,  attributes: Schema.Record(Schema.String, Schema.Unknown),  events: Schema.Array(    Schema.Struct({      name: Schema.String,      attributes: Schema.Record(Schema.String, Schema.Unknown),    }),  ),}); const decodeTraceRecordLine = Schema.decodeUnknownSync(Schema.fromJsonString(TraceRecordLine)); const environmentInput = (baseDir: string) =>  ({    dirname: "/repo/apps/desktop/dist-electron",    homeDirectory: baseDir,    platform: "darwin",    processArch: "arm64",    appVersion: "1.2.3",    appPath: "/repo",    isPackaged: false,    resourcesPath: "/repo/resources",    runningUnderArm64Translation: false,  }) satisfies DesktopEnvironment.MakeDesktopEnvironmentInput; const makeEnvironmentLayer = (baseDir: string) =>  DesktopEnvironment.layer(environmentInput(baseDir)).pipe(    Layer.provide(      Layer.mergeAll(        NodeServices.layer,        DesktopConfig.layerTest({          T3CODE_HOME: baseDir,          VITE_DEV_SERVER_URL: "http://127.0.0.1:5733",        }),      ),    ),  ); describe("DesktopObservability", () => {  it.effect("persists desktop Effect logs as span events in desktop.trace.ndjson", () =>    Effect.gen(function* () {      const fileSystem = yield* FileSystem.FileSystem;      const baseDir = yield* fileSystem.makeTempDirectoryScoped({        prefix: "t3-desktop-observability-test-",      });      const environmentLayer = makeEnvironmentLayer(baseDir);      const tracePath = yield* Effect.gen(function* () {        const environment = yield* DesktopEnvironment.DesktopEnvironment;        return environment.path.join(environment.logDir, "desktop.trace.ndjson");      }).pipe(Effect.provide(environmentLayer));      const logPath = yield* Effect.gen(function* () {        const environment = yield* DesktopEnvironment.DesktopEnvironment;        return environment.path.join(environment.logDir, "desktop-main.log");      }).pipe(Effect.provide(environmentLayer));       yield* Effect.scoped(        Effect.gen(function* () {          yield* Effect.annotateCurrentSpan({ "desktop.test": true });          yield* Effect.logInfo("desktop trace event");        }).pipe(          Effect.withSpan("desktop-observability-test"),          Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))),        ),      );       const records = (yield* fileSystem.readFileString(tracePath))        .trim()        .split("\n")        .filter((line) => line.length > 0)        .map((line) => decodeTraceRecordLine(line));      const record = records.find((entry) => entry.name === "desktop-observability-test");       assert.notEqual(record, undefined);      if (!record) {        return;      }      assert.equal(record.attributes["desktop.test"], true);      assert.equal(        record.events.some((event) => event.name === "desktop trace event"),        true,      );      assert.isFalse(yield* fileSystem.exists(logPath));    }).pipe(      Effect.scoped,      Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)),    ),  );   it.effect("persists backend child output as structured JSON records in development", () =>    Effect.gen(function* () {      const fileSystem = yield* FileSystem.FileSystem;      const baseDir = yield* fileSystem.makeTempDirectoryScoped({        prefix: "t3-desktop-backend-output-log-test-",      });      const environmentLayer = makeEnvironmentLayer(baseDir);      const logPath = yield* Effect.gen(function* () {        const environment = yield* DesktopEnvironment.DesktopEnvironment;        return environment.path.join(environment.logDir, "server-child.log");      }).pipe(Effect.provide(environmentLayer));       yield* Effect.gen(function* () {        const factory = yield* DesktopObservability.DesktopBackendOutputLogFactory;        const outputLog = yield* factory.forInstance("primary");        yield* outputLog.writeSessionBoundary({          phase: "START",          details: "pid=123 port=3773 cwd=/repo",        });        yield* outputLog.writeOutputChunk("stdout", new TextEncoder().encode("hello server\n"));      }).pipe(        Effect.annotateLogs({ runId: "test-run" }),        Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))),      );       const log = yield* fileSystem.readFileString(logPath);      const lines = log.trimEnd().split("\n");      const boundary = yield* decodeDesktopBackendChildLogRecord(lines[0] ?? "");      const output = yield* decodeDesktopBackendChildLogRecord(lines[1] ?? "");       assert.equal(boundary.message, "backend child process session start");      assert.equal(boundary.level, "INFO");      assert.equal(boundary.annotations.component, "desktop-backend-child");      assert.equal(boundary.annotations.runId, "test-run");      assert.equal(boundary.annotations.instanceId, "primary");      assert.equal(boundary.annotations.phase, "START");      assert.equal(boundary.annotations.details, "pid=123 port=3773 cwd=/repo");       assert.equal(output.message, "backend child process output");      assert.equal(output.level, "INFO");      assert.equal(output.annotations.component, "desktop-backend-child");      assert.equal(output.annotations.runId, "test-run");      assert.equal(output.annotations.instanceId, "primary");      assert.equal(output.annotations.stream, "stdout");      assert.equal(output.annotations.text, "hello server\n");    }).pipe(      Effect.scoped,      Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)),    ),  );});