From 10dc8e64de2014e2546eb192b1ec53583df60903 Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Sun, 7 Jul 2024 14:34:19 +0200 Subject: [PATCH] Send real errors to telemetry Every call to `telemetry.sendError` contained the same boilerplate code to create an object with the property `error`, which contains a string representation of the real error. This change moves this conversion into the `Telemetry` implementation. This reduces the need for boilerplate code in other places. This change also affects `monaco-yaml`. Because the telemetry now resolves the real error, the browser can log the error to the console with a better stack trace. --- src/languageserver/handlers/settingsHandlers.ts | 3 +-- src/languageserver/telemetry.ts | 5 +++-- src/languageservice/services/documentSymbols.ts | 5 ++--- src/languageservice/services/yamlCodeLens.ts | 3 +-- src/languageservice/services/yamlCompletion.ts | 6 +++--- src/languageservice/services/yamlDefinition.ts | 3 +-- src/languageservice/services/yamlHover.ts | 3 +-- src/languageservice/services/yamlLinks.ts | 3 +-- src/languageservice/services/yamlValidation.ts | 3 +-- src/languageservice/telemetry.ts | 2 +- 10 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/languageserver/handlers/settingsHandlers.ts b/src/languageserver/handlers/settingsHandlers.ts index e2351ea7a..fff3e1b4a 100644 --- a/src/languageserver/handlers/settingsHandlers.ts +++ b/src/languageserver/handlers/settingsHandlers.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { configure as configureHttpRequests, xhr } from 'request-light'; import { Connection, DidChangeConfigurationNotification, DocumentFormattingRequest } from 'vscode-languageserver'; -import { convertErrorToTelemetryMsg } from '../../languageservice/utils/objects'; import { isRelativePath, relativeToAbsolutePath } from '../../languageservice/utils/paths'; import { checkSchemaURI, JSON_SCHEMASTORE_URL, KUBERNETES_SCHEMA_URL } from '../../languageservice/utils/schemaUrls'; import { LanguageService, LanguageSettings, SchemaPriority } from '../../languageservice/yamlLanguageService'; @@ -28,7 +27,7 @@ export class SettingsHandler { // Register for all configuration changes. await this.connection.client.register(DidChangeConfigurationNotification.type); } catch (err) { - this.telemetry.sendError('yaml.settings.error', { error: convertErrorToTelemetryMsg(err) }); + this.telemetry.sendError('yaml.settings.error', err); } } this.connection.onDidChangeConfiguration(() => this.pullConfiguration()); diff --git a/src/languageserver/telemetry.ts b/src/languageserver/telemetry.ts index b18979ff4..a1db7f2aa 100644 --- a/src/languageserver/telemetry.ts +++ b/src/languageserver/telemetry.ts @@ -5,6 +5,7 @@ import { Connection } from 'vscode-languageserver'; import { TelemetryEvent, Telemetry } from '../languageservice/telemetry'; +import { convertErrorToTelemetryMsg } from '../languageservice/utils/objects'; export class TelemetryImpl implements Telemetry { constructor(private readonly connection: Connection) {} @@ -13,8 +14,8 @@ export class TelemetryImpl implements Telemetry { this.connection.telemetry.logEvent(event); } - sendError(name: string, properties: unknown): void { - this.send({ name, type: 'track', properties: properties }); + sendError(name: string, error: unknown): void { + this.send({ name, type: 'track', properties: { error: convertErrorToTelemetryMsg(error) } }); } sendTrack(name: string, properties: unknown): void { diff --git a/src/languageservice/services/documentSymbols.ts b/src/languageservice/services/documentSymbols.ts index 42520736b..7f6625b3c 100644 --- a/src/languageservice/services/documentSymbols.ts +++ b/src/languageservice/services/documentSymbols.ts @@ -12,7 +12,6 @@ import { TextDocument } from 'vscode-languageserver-textdocument'; import { yamlDocumentsCache } from '../parser/yaml-documents'; import { Telemetry } from '../telemetry'; import { isMap, isSeq, Node } from 'yaml'; -import { convertErrorToTelemetryMsg } from '../utils/objects'; export class YAMLDocumentSymbols { private jsonDocumentSymbols; @@ -53,7 +52,7 @@ export class YAMLDocumentSymbols { } } } catch (err) { - this.telemetry?.sendError('yaml.documentSymbols.error', { error: convertErrorToTelemetryMsg(err) }); + this.telemetry?.sendError('yaml.documentSymbols.error', err); } return results; } @@ -75,7 +74,7 @@ export class YAMLDocumentSymbols { } } } catch (err) { - this.telemetry?.sendError('yaml.hierarchicalDocumentSymbols.error', { error: convertErrorToTelemetryMsg(err) }); + this.telemetry?.sendError('yaml.hierarchicalDocumentSymbols.error', err); } return results; diff --git a/src/languageservice/services/yamlCodeLens.ts b/src/languageservice/services/yamlCodeLens.ts index b1ae69d37..71a21bb64 100644 --- a/src/languageservice/services/yamlCodeLens.ts +++ b/src/languageservice/services/yamlCodeLens.ts @@ -11,7 +11,6 @@ import { YAMLSchemaService } from './yamlSchemaService'; import { JSONSchema } from '../jsonSchema'; import { Telemetry } from '../telemetry'; import { getSchemaUrls } from '../utils/schemaUrls'; -import { convertErrorToTelemetryMsg } from '../utils/objects'; import { getSchemaTitle } from '../utils/schemaUtils'; export class YamlCodeLens { @@ -39,7 +38,7 @@ export class YamlCodeLens { result.push(lens); } } catch (err) { - this.telemetry?.sendError('yaml.codeLens.error', { error: convertErrorToTelemetryMsg(err) }); + this.telemetry?.sendError('yaml.codeLens.error', err); } return result; diff --git a/src/languageservice/services/yamlCompletion.ts b/src/languageservice/services/yamlCompletion.ts index 513a23d63..e0e828798 100644 --- a/src/languageservice/services/yamlCompletion.ts +++ b/src/languageservice/services/yamlCompletion.ts @@ -29,7 +29,7 @@ import { YAMLSchemaService } from './yamlSchemaService'; import { ResolvedSchema } from 'vscode-json-languageservice/lib/umd/services/jsonSchemaService'; import { JSONSchema, JSONSchemaRef } from '../jsonSchema'; import { stringifyObject, StringifySettings } from '../utils/json'; -import { convertErrorToTelemetryMsg, isDefined, isString } from '../utils/objects'; +import { isDefined, isString } from '../utils/objects'; import * as nls from 'vscode-nls'; import { setKubernetesParserOption } from '../parser/isKubernetes'; import { asSchema } from '../parser/jsonParser07'; @@ -281,7 +281,7 @@ export class YamlCompletion { } }, error: (message: string) => { - this.telemetry?.sendError('yaml.completion.error', { error: convertErrorToTelemetryMsg(message) }); + this.telemetry?.sendError('yaml.completion.error', message); }, log: (message: string) => { console.log(message); @@ -533,7 +533,7 @@ export class YamlCompletion { const types: { [type: string]: boolean } = {}; this.getValueCompletions(schema, currentDoc, node, offset, document, collector, types, doComplete); } catch (err) { - this.telemetry?.sendError('yaml.completion.error', { error: convertErrorToTelemetryMsg(err) }); + this.telemetry?.sendError('yaml.completion.error', err); } this.finalizeParentCompletion(result); diff --git a/src/languageservice/services/yamlDefinition.ts b/src/languageservice/services/yamlDefinition.ts index b2f1b975b..8b9261344 100644 --- a/src/languageservice/services/yamlDefinition.ts +++ b/src/languageservice/services/yamlDefinition.ts @@ -10,7 +10,6 @@ import { isAlias } from 'yaml'; import { Telemetry } from '../telemetry'; import { yamlDocumentsCache } from '../parser/yaml-documents'; import { matchOffsetToDocument } from '../utils/arrUtils'; -import { convertErrorToTelemetryMsg } from '../utils/objects'; import { TextBuffer } from '../utils/textBuffer'; export class YamlDefinition { @@ -33,7 +32,7 @@ export class YamlDefinition { } } } catch (err) { - this.telemetry?.sendError('yaml.definition.error', { error: convertErrorToTelemetryMsg(err) }); + this.telemetry?.sendError('yaml.definition.error', err); } return undefined; diff --git a/src/languageservice/services/yamlHover.ts b/src/languageservice/services/yamlHover.ts index a0e72ce3a..f45643525 100644 --- a/src/languageservice/services/yamlHover.ts +++ b/src/languageservice/services/yamlHover.ts @@ -17,7 +17,6 @@ import { JSONSchema } from '../jsonSchema'; import { URI } from 'vscode-uri'; import * as path from 'path'; import { Telemetry } from '../telemetry'; -import { convertErrorToTelemetryMsg } from '../utils/objects'; import { ASTNode } from 'vscode-json-languageservice'; import { stringify as stringifyYAML } from 'yaml'; @@ -55,7 +54,7 @@ export class YAMLHover { currentDoc.currentDocIndex = currentDocIndex; return this.getHover(document, position, currentDoc); } catch (error) { - this.telemetry?.sendError('yaml.hover.error', { error: convertErrorToTelemetryMsg(error) }); + this.telemetry?.sendError('yaml.hover.error', error); } } diff --git a/src/languageservice/services/yamlLinks.ts b/src/languageservice/services/yamlLinks.ts index fe22e455c..eac352e09 100644 --- a/src/languageservice/services/yamlLinks.ts +++ b/src/languageservice/services/yamlLinks.ts @@ -7,7 +7,6 @@ import { DocumentLink } from 'vscode-languageserver-types'; import { TextDocument } from 'vscode-languageserver-textdocument'; import { Telemetry } from '../telemetry'; import { yamlDocumentsCache } from '../parser/yaml-documents'; -import { convertErrorToTelemetryMsg } from '../utils/objects'; export class YamlLinks { constructor(private readonly telemetry?: Telemetry) {} @@ -23,7 +22,7 @@ export class YamlLinks { // Wait for all the promises to return and then flatten them into one DocumentLink array return Promise.all(linkPromises).then((yamlLinkArray) => [].concat(...yamlLinkArray)); } catch (err) { - this.telemetry?.sendError('yaml.documentLink.error', { error: convertErrorToTelemetryMsg(err) }); + this.telemetry?.sendError('yaml.documentLink.error', err); } } } diff --git a/src/languageservice/services/yamlValidation.ts b/src/languageservice/services/yamlValidation.ts index fd26af2e8..496cb62be 100644 --- a/src/languageservice/services/yamlValidation.ts +++ b/src/languageservice/services/yamlValidation.ts @@ -14,7 +14,6 @@ import { JSONValidation } from 'vscode-json-languageservice/lib/umd/services/jso import { YAML_SOURCE } from '../parser/jsonParser07'; import { TextBuffer } from '../utils/textBuffer'; import { yamlDocumentsCache } from '../parser/yaml-documents'; -import { convertErrorToTelemetryMsg } from '../utils/objects'; import { Telemetry } from '../telemetry'; import { AdditionalValidator } from './validation/types'; import { UnusedAnchorsValidator } from './validation/unused-anchors'; @@ -107,7 +106,7 @@ export class YAMLValidation { index++; } } catch (err) { - this.telemetry?.sendError('yaml.validation.error', { error: convertErrorToTelemetryMsg(err) }); + this.telemetry?.sendError('yaml.validation.error', err); } let previousErr: Diagnostic; diff --git a/src/languageservice/telemetry.ts b/src/languageservice/telemetry.ts index c5c71426b..7da6fec26 100644 --- a/src/languageservice/telemetry.ts +++ b/src/languageservice/telemetry.ts @@ -18,7 +18,7 @@ export interface TelemetryEvent { export interface Telemetry { send(event: TelemetryEvent): void; - sendError(name: string, properties: unknown): void; + sendError(name: string, error: unknown): void; sendTrack(name: string, properties: unknown): void; }