Skip to content

Commit e621241

Browse files
authored
Merge pull request #72 from moazbuilds/fix/logging
[Fix] log view trimming
2 parents 88aa73e + d6886e7 commit e621241

2 files changed

Lines changed: 34 additions & 6 deletions

File tree

src/agents/monitoring/logger.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,24 @@ export class AgentLoggerService {
105105
stream.write(data);
106106
}
107107

108+
/**
109+
* Flush buffered data to disk for an agent's log
110+
* Call this before status changes to ensure data is readable by the UI
111+
*/
112+
async flush(agentId: number): Promise<void> {
113+
const stream = this.activeStreams.get(agentId);
114+
if (!stream || !stream.writable) {
115+
return;
116+
}
117+
118+
return new Promise<void>((resolve) => {
119+
// Write empty string with callback - ensures buffer is flushed to OS
120+
stream.write('', 'utf-8', () => {
121+
resolve();
122+
});
123+
});
124+
}
125+
108126
/**
109127
* Close an agent's log stream and release file lock
110128
*/
@@ -114,15 +132,19 @@ export class AgentLoggerService {
114132
const monitor = AgentMonitorService.getInstance();
115133
const agent = monitor.getAgent(agentId);
116134

117-
// Release lock FIRST
118-
if (agent) {
119-
await this.lockService.releaseLock(agent.logPath);
120-
}
135+
// First, close stream and wait for it to finish flushing
136+
await new Promise<void>((resolve) => {
137+
stream.on('finish', resolve);
138+
stream.end();
139+
});
121140

122-
// Then close stream
123-
stream.end();
124141
this.activeStreams.delete(agentId);
125142
logger.debug(`Closed log stream for agent ${agentId}`);
143+
144+
// Release lock AFTER stream is fully closed
145+
if (agent) {
146+
await this.lockService.releaseLock(agent.logPath);
147+
}
126148
}
127149
}
128150

src/agents/monitoring/status.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { AgentMonitorService } from './monitor.js';
2+
import { AgentLoggerService } from './logger.js';
23
import type { AgentStatus } from './types.js';
34
import type { WorkflowEventEmitter } from '../../workflows/events/emitter.js';
45
import type { ParsedTelemetry } from '../../shared/telemetry/index.js';
@@ -62,22 +63,27 @@ export class StatusService {
6263
// Mark skipped by monitoring ID (for cleanup coordination)
6364
async markSkipped(monitoringId: number): Promise<void> {
6465
this.skippedIds.add(monitoringId);
66+
await AgentLoggerService.getInstance().flush(monitoringId);
6567
await this.monitor.markSkipped(monitoringId);
6668
this.emitStatus(monitoringId, 'skipped');
6769
}
6870

6971
// Status updates (DB + UI)
72+
// All status changes flush the log first to ensure data is readable
7073
async complete(id: number, telemetry?: ParsedTelemetry): Promise<void> {
74+
await AgentLoggerService.getInstance().flush(id);
7175
await this.monitor.complete(id, telemetry);
7276
this.emitStatus(id, 'completed');
7377
}
7478

7579
async fail(id: number, error: Error | string): Promise<void> {
80+
await AgentLoggerService.getInstance().flush(id);
7681
await this.monitor.fail(id, error);
7782
this.emitStatus(id, 'failed');
7883
}
7984

8085
async pause(id: number): Promise<void> {
86+
await AgentLoggerService.getInstance().flush(id);
8187
await this.monitor.markPaused(id);
8288
this.emitStatus(id, 'paused');
8389
}

0 commit comments

Comments
 (0)