Skip to content

Commit 26fc626

Browse files
authored
Agent Debug: Add configurable max session log size setting for debug file logging (#4890)
* Add configurable max session log size setting for debug file logging * update
1 parent 45ff6dc commit 26fc626

4 files changed

Lines changed: 35 additions & 8 deletions

File tree

package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4650,6 +4650,17 @@
46504650
"onExp"
46514651
]
46524652
},
4653+
"github.copilot.chat.agentDebugLog.fileLogging.maxSessionLogSizeMB": {
4654+
"type": "number",
4655+
"default": 100,
4656+
"minimum": 1,
4657+
"markdownDescription": "%github.copilot.config.chat.agentDebugLog.fileLogging.maxSessionLogSizeMB%",
4658+
"tags": [
4659+
"advanced",
4660+
"experimental",
4661+
"onExp"
4662+
]
4663+
},
46534664
"github.copilot.chat.otel.enabled": {
46544665
"type": "boolean",
46554666
"default": false,

package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@
379379
"github.copilot.config.chat.agentDebugLog.fileLogging.enabled": "Enable writing chat debug events to JSONL files on disk for diagnostics. When disabled, the built-in `troubleshoot` skill is also disabled. Requires window reload to take effect.",
380380
"github.copilot.config.chat.agentDebugLog.fileLogging.flushIntervalMs": "How often (in milliseconds) buffered debug log entries are flushed to disk. Lower values provide more up-to-date logs at the cost of more frequent disk writes.",
381381
"github.copilot.config.chat.agentDebugLog.fileLogging.maxRetainedSessionLogs": "Maximum number of chat debug session log directories to retain on disk. Each chat session produces one directory. Older session logs are automatically deleted when this limit is exceeded.",
382+
"github.copilot.config.chat.agentDebugLog.fileLogging.maxSessionLogSizeMB": "Maximum size in megabytes for a single chat debug session log file. When the log exceeds this size, older entries are truncated to retain the most recent data. Defaults to 100 MB.",
382383
"github.copilot.config.inlineEdits.diagnosticsContextProvider.enabled": "Enable diagnostics context provider for next edit suggestions.",
383384
"github.copilot.config.inlineEdits.chatSessionContextProvider.enabled": "Enable chat session context provider for next edit suggestions.",
384385
"github.copilot.config.codesearch.agent.enabled": "Enable code search capabilities in agent mode.",

src/extension/chat/vscode-node/chatDebugFileLoggerService.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ const DEFAULT_FLUSH_INTERVAL_MS = 4_000;
2525
const MIN_FLUSH_INTERVAL_MS = 2_000;
2626
const MAX_ATTR_VALUE_LENGTH = 5_000;
2727
const MAX_PENDING_CORE_EVENTS = 100;
28-
const MAX_SESSION_LOG_BYTES = 100 * 1024 * 1024; // 100MB
29-
const TRUNCATION_RETAIN_BYTES = 60 * 1024 * 1024; // 60 MB
28+
const DEFAULT_MAX_SESSION_LOG_MB = 100;
29+
const TRUNCATION_RETAIN_RATIO = 0.6; // retain 60% of max on truncation
3030
const MAX_SPAN_SESSION_INDEX = 10_000;
3131

3232

@@ -87,6 +87,7 @@ export class ChatDebugFileLoggerService extends Disposable implements IChatDebug
8787
private _debugLogsDirUri: URI | undefined;
8888
private _autoFlushTimer: ReturnType<typeof setInterval> | undefined;
8989
private _autoFlushIntervalMs: number;
90+
private _maxSessionLogBytes: number;
9091
private _totalBytesWritten = 0;
9192
private _totalSessionCount = 0;
9293

@@ -111,17 +112,22 @@ export class ChatDebugFileLoggerService extends Disposable implements IChatDebug
111112
*/
112113
this._telemetryService.sendMSFTTelemetryEvent('chatDebugFileLogger.disabled');
113114
this._autoFlushIntervalMs = DEFAULT_FLUSH_INTERVAL_MS;
115+
this._maxSessionLogBytes = DEFAULT_MAX_SESSION_LOG_MB * 1024 * 1024;
114116
return;
115117
}
116118

117119
this._autoFlushIntervalMs = Math.max(MIN_FLUSH_INTERVAL_MS, this._configurationService.getConfig(ConfigKey.Advanced.ChatDebugFileLoggingFlushInterval) ?? DEFAULT_FLUSH_INTERVAL_MS);
120+
this._maxSessionLogBytes = this._resolveMaxSessionLogBytes();
118121

119-
// React to flush interval changes at runtime
122+
// React to changes at runtime
120123
this._register(this._configurationService.onDidChangeConfiguration(e => {
121124
if (e.affectsConfiguration(ConfigKey.Advanced.ChatDebugFileLoggingFlushInterval.fullyQualifiedId)) {
122125
this._autoFlushIntervalMs = Math.max(MIN_FLUSH_INTERVAL_MS, this._configurationService.getConfig(ConfigKey.Advanced.ChatDebugFileLoggingFlushInterval) ?? DEFAULT_FLUSH_INTERVAL_MS);
123126
this._restartFlushTimer();
124127
}
128+
if (e.affectsConfiguration(ConfigKey.Advanced.ChatDebugFileLoggingMaxSessionLogSizeMB.fullyQualifiedId)) {
129+
this._maxSessionLogBytes = this._resolveMaxSessionLogBytes();
130+
}
125131
}));
126132

127133
// Subscribe to OTel span completions
@@ -142,6 +148,12 @@ export class ChatDebugFileLoggerService extends Disposable implements IChatDebug
142148
}
143149
}
144150

151+
private _resolveMaxSessionLogBytes(): number {
152+
const raw = this._configurationService.getExperimentBasedConfig(ConfigKey.Advanced.ChatDebugFileLoggingMaxSessionLogSizeMB, this._experimentationService);
153+
const mb = typeof raw === 'number' && Number.isFinite(raw) ? raw : DEFAULT_MAX_SESSION_LOG_MB;
154+
return Math.max(1, Math.floor(mb)) * 1024 * 1024;
155+
}
156+
145157
override dispose(): void {
146158
if (this._autoFlushTimer) {
147159
clearInterval(this._autoFlushTimer);
@@ -764,7 +776,7 @@ export class ChatDebugFileLoggerService extends Disposable implements IChatDebug
764776
}
765777
await fs.promises.appendFile(session.uri.fsPath, content, 'utf-8');
766778
session.bytesWritten += Buffer.byteLength(content, 'utf-8');
767-
if (session.bytesWritten > MAX_SESSION_LOG_BYTES) {
779+
if (session.bytesWritten > this._maxSessionLogBytes) {
768780
await this._truncateLogFile(session);
769781
}
770782
} catch (err) {
@@ -773,18 +785,20 @@ export class ChatDebugFileLoggerService extends Disposable implements IChatDebug
773785
}
774786

775787
/**
776-
* Truncate a log file to retain the newest ~80MB using a streaming
777-
* approach via a temp file to avoid loading the entire tail into memory.
788+
* Truncate a log file to retain the newest portion (TRUNCATION_RETAIN_RATIO
789+
* of the configured max size) using a streaming approach via a temp file
790+
* to avoid loading the entire tail into memory.
778791
*/
779792
private async _truncateLogFile(session: IActiveLogSession): Promise<void> {
780793
try {
781794
const filePath = session.uri.fsPath;
782795
const stat = await fs.promises.stat(filePath);
783-
if (stat.size <= MAX_SESSION_LOG_BYTES) {
796+
if (stat.size <= this._maxSessionLogBytes) {
784797
return;
785798
}
786799

787-
const skipBytes = stat.size - TRUNCATION_RETAIN_BYTES;
800+
const retainBytes = Math.floor(this._maxSessionLogBytes * TRUNCATION_RETAIN_RATIO);
801+
const skipBytes = stat.size - retainBytes;
788802
const fd = await fs.promises.open(filePath, 'r');
789803
try {
790804
// Read a small probe around the cut point to find the next newline

src/platform/configuration/common/configurationService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ export namespace ConfigKey {
692692
export const ChatDebugFileLogging = defineAndMigrateExpSetting<boolean>('chat.chatDebug.fileLogging.enabled', 'chat.agentDebugLog.fileLogging.enabled', false);
693693
export const ChatDebugFileLoggingFlushInterval = defineAndMigrateSetting<number>('chat.chatDebug.fileLogging.flushIntervalMs', 'chat.agentDebugLog.fileLogging.flushIntervalMs', 4000);
694694
export const ChatDebugFileLoggingMaxRetainedSessionLogs = defineSetting<number>('chat.agentDebugLog.fileLogging.maxRetainedSessionLogs', ConfigType.ExperimentBased, 50);
695+
export const ChatDebugFileLoggingMaxSessionLogSizeMB = defineSetting<number>('chat.agentDebugLog.fileLogging.maxSessionLogSizeMB', ConfigType.ExperimentBased, 100);
695696

696697
// OTel settings
697698
export const OTelEnabled = defineSetting<boolean>('chat.otel.enabled', ConfigType.Simple, false);

0 commit comments

Comments
 (0)