121 lines · 4.6 KB · TypeScript
RawDownload
import { makeLocalFileTracer, makeTraceSink } from "@t3tools/shared/observability";import { parsePersistedServerObservabilitySettings } from "@t3tools/shared/serverSettings";import * as Effect from "effect/Effect";import * as FileSystem from "effect/FileSystem";import * as Layer from "effect/Layer";import * as Logger from "effect/Logger";import * as Option from "effect/Option";import * as References from "effect/References";import * as Tracer from "effect/Tracer";import { OtlpSerialization, OtlpTracer } from "effect/unstable/observability"; import * as DesktopBackendOutputLogModule from "./DesktopBackendOutputLog.ts";import * as DesktopEnvironment from "./DesktopEnvironment.ts"; const DESKTOP_TRACE_BATCH_WINDOW_MS = 200; export { DesktopBackendOutputLog } from "./DesktopBackendOutputLog.ts"; export type DesktopLogAnnotations = Record<string, unknown>; export interface DesktopComponentLogger {  readonly annotate: <A, E, R>(    effect: Effect.Effect<A, E, R>,    annotations?: DesktopLogAnnotations,  ) => Effect.Effect<A, E, R>;  readonly logDebug: (message: string, annotations?: DesktopLogAnnotations) => Effect.Effect<void>;  readonly logInfo: (message: string, annotations?: DesktopLogAnnotations) => Effect.Effect<void>;  readonly logWarning: (    message: string,    annotations?: DesktopLogAnnotations,  ) => Effect.Effect<void>;  readonly logError: (message: string, annotations?: DesktopLogAnnotations) => Effect.Effect<void>;} export function makeComponentLogger(component: string): DesktopComponentLogger {  const annotate: DesktopComponentLogger["annotate"] = (effect, annotations) =>    effect.pipe(      Effect.annotateLogs({        component,        ...annotations,      }),    );   return {    annotate,    logDebug: (message, annotations) => annotate(Effect.logDebug(message), annotations),    logInfo: (message, annotations) => annotate(Effect.logInfo(message), annotations),    logWarning: (message, annotations) => annotate(Effect.logWarning(message), annotations),    logError: (message, annotations) => annotate(Effect.logError(message), annotations),  };} const readPersistedOtlpTracesUrl = Effect.gen(function* () {  const fileSystem = yield* FileSystem.FileSystem;  const environment = yield* DesktopEnvironment.DesktopEnvironment;  const raw = yield* fileSystem.readFileString(environment.serverSettingsPath).pipe(Effect.option);  if (Option.isNone(raw)) {    return Option.none();  }   const parsed = parsePersistedServerObservabilitySettings(raw.value);  return Option.fromNullishOr(parsed.otlpTracesUrl);}); const resolveOtlpTracesUrl = Effect.gen(function* () {  const environment = yield* DesktopEnvironment.DesktopEnvironment;  if (Option.isSome(environment.otlpTracesUrl)) {    return environment.otlpTracesUrl;  }  return yield* readPersistedOtlpTracesUrl;}); const desktopLoggerLayer = Layer.mergeAll(  Logger.layer([Logger.consolePretty(), Logger.tracerLogger], { mergeWithExisting: false }),  Layer.succeed(References.MinimumLogLevel, "Info"),); const tracerLayer = Layer.unwrap(  Effect.gen(function* () {    const environment = yield* DesktopEnvironment.DesktopEnvironment;    const otlpTracesUrl = yield* resolveOtlpTracesUrl;    const tracePath = environment.path.join(environment.logDir, "desktop.trace.ndjson");    const sink = yield* makeTraceSink({      filePath: tracePath,      maxBytes: DesktopBackendOutputLogModule.DESKTOP_LOG_FILE_MAX_BYTES,      maxFiles: DesktopBackendOutputLogModule.DESKTOP_LOG_FILE_MAX_FILES,      batchWindowMs: DESKTOP_TRACE_BATCH_WINDOW_MS,    });    const delegate = Option.isNone(otlpTracesUrl)      ? undefined      : yield* OtlpTracer.make({          url: otlpTracesUrl.value,          exportInterval: `${environment.otlpExportIntervalMs} millis`,          resource: {            serviceName: "desktop",            attributes: {              "service.runtime": "desktop",              "service.mode": environment.isDevelopment ? "development" : "packaged",            },          },        });    const tracer = yield* makeLocalFileTracer({      filePath: tracePath,      maxBytes: DesktopBackendOutputLogModule.DESKTOP_LOG_FILE_MAX_BYTES,      maxFiles: DesktopBackendOutputLogModule.DESKTOP_LOG_FILE_MAX_FILES,      batchWindowMs: DESKTOP_TRACE_BATCH_WINDOW_MS,      sink,      ...(delegate ? { delegate } : {}),    });     return Layer.succeed(Tracer.Tracer, tracer);  }),).pipe(Layer.provideMerge(OtlpSerialization.layerJson)); export const layer = Layer.mergeAll(  DesktopBackendOutputLogModule.layer,  desktopLoggerLayer,  tracerLayer,  Layer.succeed(Tracer.MinimumTraceLevel, "Info"),  Layer.succeed(References.TracerTimingEnabled, true),);