Path: blob/main/src/vs/editor/contrib/inlineCompletions/browser/structuredLogger.ts
5270 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 {55// eslint-disable-next-line local/code-no-any-casts56return entry.sourceId + ' @@ ' + JSON.stringify({ ...entry, modelUri: (entry as any).modelUri?.toString(), sourceId: undefined });57}5859export class StructuredLogger<T extends IRecordableLogEntry> extends Disposable {60public static cast<T extends IRecordableLogEntry>(): typeof StructuredLogger<T> {61return this as typeof StructuredLogger<T>;62}6364public readonly isEnabled;65private readonly _isEnabledContextKeyValue;6667constructor(68private readonly _key: string,69@IContextKeyService private readonly _contextKeyService: IContextKeyService,70@IDataChannelService private readonly _dataChannelService: IDataChannelService,71) {72super();73this._isEnabledContextKeyValue = observableContextKey<boolean>('structuredLogger.enabled:' + this._key, this._contextKeyService).recomputeInitiallyAndOnChange(this._store);74this.isEnabled = this._isEnabledContextKeyValue.map(v => v !== undefined);75}7677public log(data: T): boolean {78const enabled = this._isEnabledContextKeyValue.get();79if (!enabled) {80return false;81}82this._dataChannelService.getDataChannel<T>('structuredLogger:' + this._key).sendData(data);83return true;84}85}8687function observableContextKey<T>(key: string, contextKeyService: IContextKeyService): IObservable<T | undefined> {88return observableFromEvent(contextKeyService.onDidChangeContext, () => contextKeyService.getContextKeyValue<T>(key));89}909192