mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-04 20:13:18 +00:00
Epic P2. Closes the three real traceability gaps so every diagnostic log can carry a requestId from origin (ccs.ts main) through HTTP edges and spawned daemons. - log-context: add REQUEST_ID_HEADER/ENV/PATTERN, resolveRequestIdFromEnv, forwardRequestIdEnv. runWithRequestId now reuses a forwarded CCS_REQUEST_ID when well-formed (child re-anchor), else mints fresh. - request-logging-middleware: wrap the Express dashboard handler chain in withRequestContext so downstream route-handler logs carry requestId (mirrors src/proxy/server/proxy-server.ts, which is untouched prior art). - forward CCS_REQUEST_ID at the 4 child-daemon spawn sites: delegation headless-executor, cursor-daemon, cursor-profile-executor, copilot-executor. - cursor-daemon-entry: re-anchor via runWithRequestId so daemon startup logs correlate with the spawning CLI invocation (ALS does not cross spawn). - logger adoption toe-hold: delegation/session-manager (load/save failures) and docker/supervisord-lifecycle (restart failure) now use createLogger. api/channels/shared have no touchable diagnostic console.error (CLI-UX only or pure data); dispatcher's only diagnostic is in pre-dispatch.ts, owned by plan #1165. Those defer to P3's full per-site sweep. Tests: request-context-middleware (handler log requestId === header), request-id-forwarding (env resolve/reject, re-anchor, forwardRequestIdEnv). validate + validate:ci-parity green.
66 lines
2.4 KiB
TypeScript
66 lines
2.4 KiB
TypeScript
import { afterEach, describe, expect, test } from 'bun:test';
|
|
import {
|
|
REQUEST_ID_ENV,
|
|
forwardRequestIdEnv,
|
|
getRequestId,
|
|
resolveRequestIdFromEnv,
|
|
runWithRequestId,
|
|
} from '../../../../src/services/logging';
|
|
|
|
describe('requestId cross-process forwarding', () => {
|
|
const originalEnv = process.env[REQUEST_ID_ENV];
|
|
|
|
afterEach(() => {
|
|
if (originalEnv === undefined) delete process.env[REQUEST_ID_ENV];
|
|
else process.env[REQUEST_ID_ENV] = originalEnv;
|
|
});
|
|
|
|
test('resolveRequestIdFromEnv returns a well-formed forwarded id', () => {
|
|
process.env[REQUEST_ID_ENV] = '12345678-1234-1234-1234-1234567890ab';
|
|
expect(resolveRequestIdFromEnv()).toBe('12345678-1234-1234-1234-1234567890ab');
|
|
});
|
|
|
|
test('resolveRequestIdFromEnv trims surrounding whitespace', () => {
|
|
process.env[REQUEST_ID_ENV] = ' abcdef123456 ';
|
|
expect(resolveRequestIdFromEnv()).toBe('abcdef123456');
|
|
});
|
|
|
|
test('resolveRequestIdFromEnv rejects garbage (too short, spaces, control chars)', () => {
|
|
process.env[REQUEST_ID_ENV] = 'short';
|
|
expect(resolveRequestIdFromEnv()).toBeUndefined();
|
|
process.env[REQUEST_ID_ENV] = 'has spaces here';
|
|
expect(resolveRequestIdFromEnv()).toBeUndefined();
|
|
});
|
|
|
|
test('resolveRequestIdFromEnv returns undefined when unset', () => {
|
|
delete process.env[REQUEST_ID_ENV];
|
|
expect(resolveRequestIdFromEnv()).toBeUndefined();
|
|
});
|
|
|
|
test('runWithRequestId reuses a forwarded env id (child re-anchor)', () => {
|
|
process.env[REQUEST_ID_ENV] = 'forwarded-id-1234';
|
|
const { requestId } = runWithRequestId(() => getRequestId());
|
|
expect(requestId).toBe('forwarded-id-1234');
|
|
});
|
|
|
|
test('runWithRequestId mints a fresh id when no env id is present', () => {
|
|
delete process.env[REQUEST_ID_ENV];
|
|
const { requestId } = runWithRequestId(() => undefined);
|
|
expect(requestId).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
|
|
expect(requestId).not.toBe('forwarded-id-1234');
|
|
});
|
|
|
|
test('forwardRequestIdEnv emits the active id for a child spawn env', () => {
|
|
delete process.env[REQUEST_ID_ENV];
|
|
runWithRequestId(() => {
|
|
const envFragment = forwardRequestIdEnv();
|
|
expect(envFragment[REQUEST_ID_ENV]).toBe(getRequestId());
|
|
});
|
|
});
|
|
|
|
test('forwardRequestIdEnv is empty when no context is active', () => {
|
|
delete process.env[REQUEST_ID_ENV];
|
|
expect(forwardRequestIdEnv()).toEqual({});
|
|
});
|
|
});
|