Debug Panel: oTel data source support and Import/export (#299256)

* otel data source and Import/export

* Handle chat customization events in import/export

* PR feedback updates

* Fix reopen issue

* Simplify and pass core events for export

* Perf optimizations and label changes

* add session title to export/import
This commit is contained in:
Vijay Upadya
2026-03-09 18:44:34 -07:00
committed by GitHub
parent 21d682f185
commit 5c84259481
13 changed files with 502 additions and 100 deletions

View File

@@ -39,6 +39,12 @@ export class ChatDebugServiceImpl extends Disposable implements IChatDebugServic
/** Events that were returned by providers (not internally logged). */
private readonly _providerEvents = new WeakSet<IChatDebugEvent>();
/** Session URIs created via import, allowed through the invokeProviders guard. */
private readonly _importedSessions = new ResourceMap<boolean>();
/** Human-readable titles for imported sessions. */
private readonly _importedSessionTitles = new ResourceMap<string>();
activeSessionResource: URI | undefined;
log(sessionResource: URI, name: string, details?: string, level: ChatDebugLogLevel = ChatDebugLogLevel.Info, options?: { id?: string; category?: string; parentEventId?: string }): void {
@@ -135,10 +141,10 @@ export class ChatDebugServiceImpl extends Disposable implements IChatDebugServic
}
async invokeProviders(sessionResource: URI): Promise<void> {
if (!LocalChatSessionUri.isLocalSession(sessionResource)) {
if (!LocalChatSessionUri.isLocalSession(sessionResource) && !this._importedSessions.has(sessionResource)) {
return;
}
// Cancel only the previous invocation for THIS session, not others.
// Each session has its own pipeline so events from multiple sessions
// can be streamed concurrently.
@@ -247,6 +253,51 @@ export class ChatDebugServiceImpl extends Disposable implements IChatDebugServic
return undefined;
}
isCoreEvent(event: IChatDebugEvent): boolean {
return !this._providerEvents.has(event);
}
setImportedSessionTitle(sessionResource: URI, title: string): void {
this._importedSessionTitles.set(sessionResource, title);
}
getImportedSessionTitle(sessionResource: URI): string | undefined {
return this._importedSessionTitles.get(sessionResource);
}
async exportLog(sessionResource: URI): Promise<Uint8Array | undefined> {
for (const provider of this._providers) {
if (provider.provideChatDebugLogExport) {
try {
const data = await provider.provideChatDebugLogExport(sessionResource, CancellationToken.None);
if (data !== undefined) {
return data;
}
} catch (err) {
onUnexpectedError(err);
}
}
}
return undefined;
}
async importLog(data: Uint8Array): Promise<URI | undefined> {
for (const provider of this._providers) {
if (provider.resolveChatDebugLogImport) {
try {
const sessionUri = await provider.resolveChatDebugLogImport(data, CancellationToken.None);
if (sessionUri !== undefined) {
this._importedSessions.set(sessionUri, true);
return sessionUri;
}
} catch (err) {
onUnexpectedError(err);
}
}
}
return undefined;
}
override dispose(): void {
for (const cts of this._invocationCts.values()) {
cts.cancel();