Path: blob/main/src/vs/editor/contrib/inlineCompletions/browser/structuredLogger.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Disposable } from '../../../../base/common/lifecycle.js';6import { IObservable, observableFromEvent } from '../../../../base/common/observable.js';7import { URI } from '../../../../base/common/uri.js';8import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';9import { IDataChannelService } from '../../../../platform/dataChannel/common/dataChannel.js';1011export interface IRecordableLogEntry {12sourceId: string;13time: number;14}1516export interface IRecordableEditorLogEntry extends IRecordableLogEntry {17modelUri: URI; // This has to be a URI, so that it gets translated automatically in remote scenarios18modelVersion: number;19}2021export type EditorLogEntryData = IDocumentEventDataSetChangeReason | IDocumentEventFetchStart;22export type LogEntryData = IEventFetchEnd;2324export interface IDocumentEventDataSetChangeReason {25sourceId: 'TextModel.setChangeReason';26source: 'inlineSuggestion.accept' | 'snippet' | string;27}2829interface IDocumentEventFetchStart {30sourceId: 'InlineCompletions.fetch';31kind: 'start';32requestId: number;33}3435export interface IEventFetchEnd {36sourceId: 'InlineCompletions.fetch';37kind: 'end';38requestId: number;39error: string | undefined;40result: IFetchResult[];41}4243interface IFetchResult {44range: string;45text: string;46isInlineEdit: boolean;47source: string;48}495051/**52* The sourceLabel must not contain '@'!53*/54export function formatRecordableLogEntry<T extends IRecordableLogEntry>(entry: T): string {55return entry.sourceId + ' @@ ' + JSON.stringify({ ...entry, modelUri: (entry as any).modelUri?.toString(), sourceId: undefined });56}5758export class StructuredLogger<T extends IRecordableLogEntry> extends Disposable {59public static cast<T extends IRecordableLogEntry>(): typeof StructuredLogger<T> {60return this as typeof StructuredLogger<T>;61}6263public readonly isEnabled;64private readonly _isEnabledContextKeyValue;6566constructor(67private readonly _key: string,68@IContextKeyService private readonly _contextKeyService: IContextKeyService,69@IDataChannelService private readonly _dataChannelService: IDataChannelService,70) {71super();72this._isEnabledContextKeyValue = observableContextKey<boolean>('structuredLogger.enabled:' + this._key, this._contextKeyService).recomputeInitiallyAndOnChange(this._store);73this.isEnabled = this._isEnabledContextKeyValue.map(v => v !== undefined);74}7576public log(data: T): boolean {77const enabled = this._isEnabledContextKeyValue.get();78if (!enabled) {79return false;80}81this._dataChannelService.getDataChannel<T>('structuredLogger:' + this._key).sendData(data);82return true;83}84}8586function observableContextKey<T>(key: string, contextKeyService: IContextKeyService): IObservable<T | undefined> {87return observableFromEvent(contextKeyService.onDidChangeContext, () => contextKeyService.getContextKeyValue<T>(key));88}899091