Change:
When going over our telemetry for debug actions we have the ability to track usage counts of debug actions triggered from keyboard shortcuts and commands, as they execute commands which we emit telemetry for, but we don't seem to have telemetry in place for breakpoints set in the gutter (click or context menu). This is unfortunate as my hypothesis is that the majority of breakpoints are set this way. Ask Add ability to track breakpoint toggles (add/remove/change) from Gutter click Add ability to track breakpoint toggles from gutter context menu
would you like to contribute a PR for this? It shuold be fairly simple and you already have the nice code pointers.
I'd be happy too, but we should land on an agreement on how to implement it. What's the best approach? 1) Add telemetry directly to the gutter actions 2) Re-wire the gutter actions to execute a command instead?
for the best approach let's first see what you want to get exactly? total amount of all breakpoints set (including the gutter) grained events for breakpoint setting based on the way the user initated that aciton In case of 1 we should just add a telemetry ping in the  since everyone should go through there In case of 2 depends on how fine grained you want it, if for every place then we should add an argument or something like that in the addBreakpoints method and then also report that to telemetry.
I'd like us to be able to contribute a source/initiator to given breakpoint, so we can get an UI usage distributions, etc.
I suggest the following Add a third argument In the implementation of that method use the telemetry service to report the appropriate event with the context. And you should nicely get all the errors of all the callers of , simply pass different string context for each caller and you shuold be good to go. Let me know if you have any questions
Cool, I'l see what I can get cooking!
Removing my assignment for this. feel free to assign me back if you do not have time to tackle this and if we need this for August
hey, would you still like this? If yes I can also look into it in October
I'd still like to do this to get my hands dirty.
cool, unasigning myself and let's leave it for October
Verified by code review, adding verified label

Discussion:
logMessage: l.logMessage } ); <del> this.debugService.addBreakpoints(uri.revive(dto.uri), rawbps); </del> <ins> this.debugService.addBreakpoints(uri.revive(dto.uri), rawbps, 'extension'); </ins> } else if (dto.type === 'function') { this.debugService.addFunctionBreakpoint(dto.functionName, dto.id); }

return Promise.resolve(null); } if (debugService.getConfigurationManager().canSetBreakpointsIn(widget.getModel())) { <del> return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber, column: position.column > 1 ? position.column : undefined }]); </del> <ins> return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber, column: position.column > 1 ? position.column : undefined }], 'debugCommands.inlineBreakpointCommand'); </ins> } }

return Promise.all(bps.map(bp => debugService.removeBreakpoints(bp.getId()))); } if (debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) { <del> return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber }]); </del> <ins> return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber }], 'debugEditorActions.toggleBreakpointAction'); </ins> } return Promise.resolve(null);

const position = editor.getPosition(); const uri = editor.getModel().uri; const bpExists = !!(debugService.getModel().getBreakpoints({ column: position.column, lineNumber: position.lineNumber, uri }).length); <del> return (bpExists ? Promise.resolve(null) : <Promise<any>>debugService.addBreakpoints(uri, [{ lineNumber: position.lineNumber, column: position.column }])).then((breakpoints) => { </del> <ins> return (bpExists ? Promise.resolve(null) : <Promise<any>>debugService.addBreakpoints(uri, [{ lineNumber: position.lineNumber, column: position.column }], 'debugEditorActions.runToCursorAction')).then((breakpoints) => { </ins> if (breakpoints && breakpoints.length) { breakpointToRemove = breakpoints[0]; }

/** * Adds new breakpoints to the model for the file specified with the uri. Notifies debug adapter of breakpoint changes. */ <del> addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[]): TPromise<IBreakpoint[]>; </del> <ins> addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[], context: string): TPromise<IBreakpoint[]>; </ins> /** * Updates the breakpoints.

condition, hitCondition, logMessage <del> }]); </del> <ins> }], `breakpointWidget`); </ins> } }

nls.localize('addBreakpoint', "Add Breakpoint"), null, true, <del> () => this.debugService.addBreakpoints(uri, [{ lineNumber }]) </del> <ins> () => this.debugService.addBreakpoints(uri, [{ lineNumber }], `debugEditorContextMenu`) </ins> )); actions.push(new Action( 'addConditionalBreakpoint',

breakpoints.forEach(bp => this.debugService.removeBreakpoints(bp.getId())); } } else if (canSetBreakpoints) { <del> this.debugService.addBreakpoints(uri, [{ lineNumber }]); </del> <ins> this.debugService.addBreakpoints(uri, [{ lineNumber }], `debugEditorGutter`); </ins> } } }));

return this.sendAllBreakpoints(); } <del> addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[]): TPromise<IBreakpoint[]> { </del> <ins> addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[], context: string): TPromise<IBreakpoint[]> { </ins> const breakpoints = this.model.addBreakpoints(uri, rawBreakpoints); breakpoints.forEach(bp => aria.status(nls.localize('breakpointAdded', "Added breakpoint, line {0}, file {1}", bp.lineNumber, uri.fsPath))); <ins> breakpoints.forEach(bp => this.telemetryDebugAddBreakpoint(bp, context)); </ins> return this.sendBreakpoints(uri).then(() => breakpoints); }

error: message }); } <ins> private telemetryDebugAddBreakpoint(breakpoint: IBreakpoint, context: string): TPromise<any> { /* __GDPR__ "debugAddBreakpoint" : { "context": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "hasCondition": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "hasHitCondition": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "hasLogMessage": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ return this.telemetryService.publicLog('debugAddBreakpoint', { context: context, hasCondition: !!breakpoint.condition, hasHitCondition: !!breakpoint.hitCondition, hasLogMessage: !!breakpoint.logMessage }); } </ins> }