-
Notifications
You must be signed in to change notification settings - Fork 0
Merge upstream pingdotgg/t3code: 11 commits (tracing, IntelliJ, pagination, bug fixes) #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
915a054
ae3ea39
d2822a8
da107f3
48481aa
0853405
9013c07
1b272fd
752f96e
e8f5b4a
e9ed849
d4913f1
db1d3b6
14473d6
b0e22f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import { NetService } from "@t3tools/shared/Net"; | ||
| import { Config, Effect, LogLevel, Option, Schema } from "effect"; | ||
| import { parsePersistedServerObservabilitySettings } from "@t3tools/shared/serverSettings"; | ||
| import { Config, Effect, FileSystem, LogLevel, Option, Path, Schema } from "effect"; | ||
| import { Command, Flag, GlobalFlag } from "effect/unstable/cli"; | ||
|
|
||
| import { | ||
|
|
@@ -27,6 +28,8 @@ const BootstrapEnvelopeSchema = Schema.Struct({ | |
| authToken: Schema.optional(Schema.String), | ||
| autoBootstrapProjectFromCwd: Schema.optional(Schema.Boolean), | ||
| logWebSocketEvents: Schema.optional(Schema.Boolean), | ||
| otlpTracesUrl: Schema.optional(Schema.String), | ||
| otlpMetricsUrl: Schema.optional(Schema.String), | ||
| }); | ||
|
|
||
| const modeFlag = Flag.choice("mode", RuntimeMode.literals).pipe( | ||
|
|
@@ -81,6 +84,27 @@ const logWebSocketEventsFlag = Flag.boolean("log-websocket-events").pipe( | |
|
|
||
| const EnvServerConfig = Config.all({ | ||
| logLevel: Config.logLevel("T3CODE_LOG_LEVEL").pipe(Config.withDefault("Info")), | ||
| traceMinLevel: Config.logLevel("T3CODE_TRACE_MIN_LEVEL").pipe(Config.withDefault("Info")), | ||
| traceTimingEnabled: Config.boolean("T3CODE_TRACE_TIMING_ENABLED").pipe(Config.withDefault(true)), | ||
| traceFile: Config.string("T3CODE_TRACE_FILE").pipe( | ||
| Config.option, | ||
| Config.map(Option.getOrUndefined), | ||
| ), | ||
| traceMaxBytes: Config.int("T3CODE_TRACE_MAX_BYTES").pipe(Config.withDefault(10 * 1024 * 1024)), | ||
| traceMaxFiles: Config.int("T3CODE_TRACE_MAX_FILES").pipe(Config.withDefault(10)), | ||
| traceBatchWindowMs: Config.int("T3CODE_TRACE_BATCH_WINDOW_MS").pipe(Config.withDefault(200)), | ||
| otlpTracesUrl: Config.string("T3CODE_OTLP_TRACES_URL").pipe( | ||
| Config.option, | ||
| Config.map(Option.getOrUndefined), | ||
| ), | ||
| otlpMetricsUrl: Config.string("T3CODE_OTLP_METRICS_URL").pipe( | ||
| Config.option, | ||
| Config.map(Option.getOrUndefined), | ||
| ), | ||
| otlpExportIntervalMs: Config.int("T3CODE_OTLP_EXPORT_INTERVAL_MS").pipe( | ||
| Config.withDefault(10_000), | ||
| ), | ||
| otlpServiceName: Config.string("T3CODE_OTLP_SERVICE_NAME").pipe(Config.withDefault("t3-server")), | ||
| mode: Config.schema(RuntimeMode, "T3CODE_MODE").pipe( | ||
| Config.option, | ||
| Config.map(Option.getOrUndefined), | ||
|
|
@@ -131,12 +155,25 @@ const resolveOptionPrecedence = <Value>( | |
| ...values: ReadonlyArray<Option.Option<Value>> | ||
| ): Option.Option<Value> => Option.firstSomeOf(values); | ||
|
|
||
| const loadPersistedObservabilitySettings = Effect.fn(function* (settingsPath: string) { | ||
| const fs = yield* FileSystem.FileSystem; | ||
| const exists = yield* fs.exists(settingsPath).pipe(Effect.orElseSucceed(() => false)); | ||
| if (!exists) { | ||
| return { otlpTracesUrl: undefined, otlpMetricsUrl: undefined }; | ||
| } | ||
|
|
||
| const raw = yield* fs.readFileString(settingsPath).pipe(Effect.orElseSucceed(() => "")); | ||
| return parsePersistedServerObservabilitySettings(raw); | ||
|
Comment on lines
+158
to
+166
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't silently discard persisted OTLP settings on read failures. After Line 160 confirms the file exists, Line 165 turns every 🤖 Prompt for AI Agents |
||
| }); | ||
|
|
||
| export const resolveServerConfig = ( | ||
| flags: CliServerFlags, | ||
| cliLogLevel: Option.Option<LogLevel.LogLevel>, | ||
| ) => | ||
| Effect.gen(function* () { | ||
| const { findAvailablePort } = yield* NetService; | ||
| const path = yield* Path.Path; | ||
| const fs = yield* FileSystem.FileSystem; | ||
| const env = yield* EnvServerConfig; | ||
| const bootstrapFd = Option.getOrUndefined(flags.bootstrapFd) ?? env.bootstrapFd; | ||
| const bootstrapEnvelope = | ||
|
|
@@ -190,6 +227,11 @@ export const resolveServerConfig = ( | |
| ); | ||
| const derivedPaths = yield* deriveServerPaths(baseDir, devUrl); | ||
| yield* ensureServerDirectories(derivedPaths); | ||
| const persistedObservabilitySettings = yield* loadPersistedObservabilitySettings( | ||
| derivedPaths.settingsPath, | ||
| ); | ||
| const serverTracePath = env.traceFile ?? derivedPaths.serverTracePath; | ||
| yield* fs.makeDirectory(path.dirname(serverTracePath), { recursive: true }); | ||
| const noBrowser = resolveBooleanFlag( | ||
| flags.noBrowser, | ||
| Option.getOrElse( | ||
|
|
@@ -248,11 +290,35 @@ export const resolveServerConfig = ( | |
|
|
||
| const config: ServerConfigShape = { | ||
| logLevel, | ||
| traceMinLevel: env.traceMinLevel, | ||
| traceTimingEnabled: env.traceTimingEnabled, | ||
| traceBatchWindowMs: env.traceBatchWindowMs, | ||
| traceMaxBytes: env.traceMaxBytes, | ||
| traceMaxFiles: env.traceMaxFiles, | ||
| otlpTracesUrl: | ||
| env.otlpTracesUrl ?? | ||
| Option.getOrUndefined( | ||
| Option.flatMap(bootstrapEnvelope, (bootstrap) => | ||
| Option.fromUndefinedOr(bootstrap.otlpTracesUrl), | ||
| ), | ||
| ) ?? | ||
| persistedObservabilitySettings.otlpTracesUrl, | ||
| otlpMetricsUrl: | ||
| env.otlpMetricsUrl ?? | ||
| Option.getOrUndefined( | ||
| Option.flatMap(bootstrapEnvelope, (bootstrap) => | ||
| Option.fromUndefinedOr(bootstrap.otlpMetricsUrl), | ||
| ), | ||
| ) ?? | ||
| persistedObservabilitySettings.otlpMetricsUrl, | ||
| otlpExportIntervalMs: env.otlpExportIntervalMs, | ||
| otlpServiceName: env.otlpServiceName, | ||
| mode, | ||
| port, | ||
| cwd: process.cwd(), | ||
| baseDir, | ||
| ...derivedPaths, | ||
| serverTracePath, | ||
| host, | ||
| staticDir, | ||
| devUrl, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate the new observability settings at the boundary.
otlpTracesUrl/otlpMetricsUrlare accepted as arbitrary strings, and the new sizing/interval knobs have no lower-bound checks. A malformed endpoint or negative interval/rotation value now gets through config resolution and only fails later in the tracer/exporter.Also applies to: 93-107
🤖 Prompt for AI Agents