Skip to content

Commit f62c148

Browse files
committed
feat(logs): add api-proxy log persistence and preservation
- Add volume mount for api-proxy logs in docker-compose - Redirect api-proxy stdout/stderr to /var/log/api-proxy/api-proxy.log - Create api-proxy logs directory during writeConfigs() - Preserve api-proxy logs after cleanup (similar to squid logs) - Support both proxyLogsDir (workflow mode) and default mode - When proxyLogsDir is set, write logs to sibling directory - When proxyLogsDir is not set, move logs to /tmp/api-proxy-logs-<timestamp> - Fix permissions on preserved logs for GitHub Actions artifact upload This ensures api-proxy logs are accessible after smoke-claude and smoke-codex workflows finish, as requested in comment 3902135209.
1 parent 4c0e1c5 commit f62c148

2 files changed

Lines changed: 54 additions & 2 deletions

File tree

containers/api-proxy/Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@ USER apiproxy
2828
# 10001 - Anthropic API proxy
2929
EXPOSE 10000 10001
3030

31-
# Start the proxy server
32-
CMD ["node", "server.js"]
31+
# Redirect stdout/stderr to log file for persistence
32+
# Use shell form to enable redirection and tee for both file and console
33+
CMD node server.js 2>&1 | tee -a /var/log/api-proxy/api-proxy.log

src/docker-manager.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,12 @@ export function generateDockerCompose(
242242
// Squid logs path: use proxyLogsDir if specified (direct write), otherwise workDir/squid-logs
243243
const squidLogsPath = config.proxyLogsDir || `${config.workDir}/squid-logs`;
244244

245+
// API proxy logs path: if proxyLogsDir is specified, write to sibling directory
246+
// Otherwise, write to workDir/api-proxy-logs (will be moved to /tmp after cleanup)
247+
const apiProxyLogsPath = config.proxyLogsDir
248+
? path.join(path.dirname(config.proxyLogsDir), 'api-proxy-logs')
249+
: path.join(config.workDir, 'api-proxy-logs');
250+
245251
// Build Squid volumes list
246252
const squidVolumes = [
247253
`${config.workDir}/squid.conf:/etc/squid/squid.conf:ro`,
@@ -931,6 +937,10 @@ export function generateDockerCompose(
931937
ipv4_address: networkConfig.proxyIp,
932938
},
933939
},
940+
volumes: [
941+
// Mount log directory for api-proxy logs
942+
`${apiProxyLogsPath}:/var/log/api-proxy:rw`,
943+
],
934944
environment: {
935945
// Pass API keys securely to sidecar (not visible to agent)
936946
...(config.openaiApiKey && { OPENAI_API_KEY: config.openaiApiKey }),
@@ -1039,6 +1049,20 @@ export async function writeConfigs(config: WrapperConfig): Promise<void> {
10391049
}
10401050
logger.debug(`Squid logs directory created at: ${squidLogsDir}`);
10411051

1052+
// Create api-proxy logs directory for persistence
1053+
// If proxyLogsDir is specified, write to sibling directory (timeout-safe)
1054+
// Otherwise, write to workDir/api-proxy-logs (will be moved to /tmp after cleanup)
1055+
// Note: API proxy runs as user 'apiproxy' (non-root)
1056+
const apiProxyLogsDir = config.proxyLogsDir
1057+
? path.join(path.dirname(config.proxyLogsDir), 'api-proxy-logs')
1058+
: path.join(config.workDir, 'api-proxy-logs');
1059+
if (!fs.existsSync(apiProxyLogsDir)) {
1060+
fs.mkdirSync(apiProxyLogsDir, { recursive: true, mode: 0o777 });
1061+
// Explicitly set permissions to 0o777 (not affected by umask)
1062+
fs.chmodSync(apiProxyLogsDir, 0o777);
1063+
}
1064+
logger.debug(`API proxy logs directory created at: ${apiProxyLogsDir}`);
1065+
10421066
// Create /tmp/gh-aw/mcp-logs directory
10431067
// This directory exists on the HOST for MCP gateway to write logs
10441068
// Inside the AWF container, it's hidden via tmpfs mount (see generateDockerCompose)
@@ -1465,6 +1489,33 @@ export async function cleanup(workDir: string, keepFiles: boolean, proxyLogsDir?
14651489
}
14661490
}
14671491

1492+
// Preserve api-proxy logs before cleanup
1493+
if (proxyLogsDir) {
1494+
// Logs were written directly to sibling of proxyLogsDir during runtime (timeout-safe)
1495+
// Just fix permissions so they're readable
1496+
const apiProxyLogsDir = path.join(path.dirname(proxyLogsDir), 'api-proxy-logs');
1497+
if (fs.existsSync(apiProxyLogsDir)) {
1498+
try {
1499+
execa.sync('chmod', ['-R', 'a+rX', apiProxyLogsDir]);
1500+
logger.info(`API proxy logs available at: ${apiProxyLogsDir}`);
1501+
} catch (error) {
1502+
logger.debug('Could not fix api-proxy log permissions:', error);
1503+
}
1504+
}
1505+
} else {
1506+
// Default behavior: move from workDir/api-proxy-logs to timestamped /tmp directory
1507+
const apiProxyLogsDir = path.join(workDir, 'api-proxy-logs');
1508+
const apiProxyLogsDestination = path.join(os.tmpdir(), `api-proxy-logs-${timestamp}`);
1509+
if (fs.existsSync(apiProxyLogsDir) && fs.readdirSync(apiProxyLogsDir).length > 0) {
1510+
try {
1511+
fs.renameSync(apiProxyLogsDir, apiProxyLogsDestination);
1512+
logger.info(`API proxy logs preserved at: ${apiProxyLogsDestination}`);
1513+
} catch (error) {
1514+
logger.debug('Could not preserve api-proxy logs:', error);
1515+
}
1516+
}
1517+
}
1518+
14681519
// Handle squid logs
14691520
if (proxyLogsDir) {
14701521
// Logs were written directly to proxyLogsDir during runtime (timeout-safe)

0 commit comments

Comments
 (0)