Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 64
Fleet node structured logging: capabilities registered and actions invoked#1237
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
d6ce447ac2343ffd5f2638c4b99fFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,6 +2,7 @@ import fs from 'node:fs'; | ||
| import path from 'node:path'; | ||
| import { HarnessDriverClient } from '@agent-relay/harness-driver'; | ||
| import { startServeNode, type FleetNodeDefinition, type RunningNode } from '@agent-relay/fleet'; | ||
| import { createLogger } from '@agent-relay/utils'; | ||
| import type { CoreDependencies, CoreProjectPaths, CoreRelay, SpawnedProcess } from '../commands/core.js'; | ||
| import { track } from '../telemetry/index.js'; | ||
| @@ -32,6 +33,12 @@ type UpOptions = { | ||
| discoverConfig?: boolean; | ||
| /** Registered node name override (e.g. from a persisted Cloud enrollment). */ | ||
| nodeName?: string; | ||
| /** Write structured node logs (capabilities, action invocations) to this file. */ | ||
| logFile?: string; | ||
| /** Log verbosity floor: debug | info | warn | error. Defaults to info. */ | ||
| logLevel?: string; | ||
| /** Emit logs as JSON lines instead of human-readable text. */ | ||
| logJson?: boolean; | ||
| }; | ||
| type DownOptions = { | ||
| @@ -136,6 +143,30 @@ function vlog(deps: CoreDependencies, verbose: boolean | undefined, message: str | ||
| } | ||
| } | ||
| /** True when any log flag (or `--verbose`) opts the node into structured logging. */ | ||
| function nodeLoggingEnabled(options: UpOptions): boolean { | ||
| return Boolean(options.logFile || options.logLevel || options.logJson || options.verbose); | ||
| } | ||
| /** | ||
| * Translate the `--log-*` (and `--verbose`) flags into the `AGENT_RELAY_LOG_*` | ||
| * environment the shared `createLogger` reads. `--verbose` alone raises the | ||
| * floor to DEBUG so per-capability registration lines surface; an explicit | ||
| * `--log-level` always wins. Called before the fleet sidecar starts. | ||
| */ | ||
| function applyNodeLogEnv(options: UpOptions, deps: CoreDependencies): void { | ||
| if (options.logFile) { | ||
| deps.env.AGENT_RELAY_LOG_FILE = options.logFile; | ||
| } | ||
| const level = options.logLevel ?? (options.verbose ? 'debug' : undefined); | ||
| if (level) { | ||
| deps.env.AGENT_RELAY_LOG_LEVEL = level.toUpperCase(); | ||
willwashburn marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| if (options.logJson) { | ||
| deps.env.AGENT_RELAY_LOG_JSON = '1'; | ||
| } | ||
| } | ||
willwashburn marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| type ErrorWithCode = { code?: unknown }; | ||
| function isRecord(value: unknown): value is Record<string, unknown> { | ||
| @@ -390,8 +421,14 @@ async function startNodeCapabilityProviders( | ||
| providerName: nodeDefinition.name, | ||
| ...(workspaceKey ? { triggers: createTriggerSyncClient({ workspaceKey, baseUrl }) } : {}), | ||
| reconnect: true, | ||
| warn: (message) => deps.warn(message), | ||
| log: (message) => deps.log(message), | ||
| // With any --log-* flag (or --verbose), surface the node's full lifecycle | ||
| // — capabilities registered, every action invoked/completed — through the | ||
| // shared logger, which honors AGENT_RELAY_LOG_FILE/_LEVEL/_JSON. Without a | ||
| // flag, keep the prior behavior: the registration summary via log, warnings | ||
| // via warn. | ||
| ...(nodeLoggingEnabled(options) | ||
| ? { logger: createLogger('fleet') } | ||
| : { warn: (message) => deps.warn(message), log: (message) => deps.log(message) }), | ||
| }) | ||
| ); | ||
| } catch (err) { | ||
| @@ -1099,6 +1136,10 @@ export async function runUpCommand(options: UpOptions, deps: CoreDependencies): | ||
| deps.env.RELAY_API_KEY = options.workspaceKey; | ||
| } | ||
| // Point the shared logger at a file / level / format before the fleet | ||
| // sidecar (which reads this env when it builds its logger) starts. | ||
| applyNodeLogEnv(options, deps); | ||
coderabbitai[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| // Resolved BEFORE the broker starts so an explicit bad --config fails | ||
| // fast instead of tearing down a broker that just came up. | ||
| const nodeDefinition = await resolveNodeDefinitionForUp(paths, options, deps); | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.