-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
additional telemetry for webExtension #317
Conversation
This reverts commit 4288bc9.
…om/microsoft/powerplatform-vscode into users/nityagi/Additional_telemetry_preview
} else { | ||
_telemetry?.sendTelemetryErrorEvent(eventName); | ||
_telemetry?.sendTelemetryException(new Error(), telemetryData.properties); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you probably need to throw the exception so that you'll have a call stack.
And should you add the errorMessage to the Error()?
const errorMessages: string[] = []; | ||
errorMessages.push(errorMessage); | ||
_telemetry?.sendTelemetryErrorEvent(telemetryData.eventName, telemetryData.properties, telemetryData.measurements, errorMessages); | ||
const error: Error = new Error(errorMessage); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again, throw the error so you get a stack trace on it.
} | ||
sendAPISuccessTelemetry(requestUrl, new Date().getTime() - requestSentAtTime); | ||
sendAPISuccessTelemetry(requestUrl, PORTAL_LANGUAGES, httpMethod.GET, new Date().getTime() - requestSentAtTime); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the success line is called no matter if the response was ok or not.
causing double telemetry
this pattern seems the same with other places too
@@ -32,32 +34,32 @@ export async function saveData( | |||
} | |||
requestBody = JSON.stringify(data); | |||
} else { | |||
sendAPIFailureTelemetry(requestUrl, 0, BAD_REQUEST); // no API request is made in this case since we do not know in which column should we save the value | |||
sendAPIFailureTelemetry(requestUrl, entityName, httpMethod.PATCH, 0, BAD_REQUEST); // no API request is made in this case since we do not know in which column should we save the value | |||
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.save.file.error", "Unable to complete the request"), localize("microsoft-powerapps-portals.webExtension.save.file.error.desc", "One or more attribute names have been changed or removed. Contact your admin.")); | |||
} | |||
|
|||
if (requestBody) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this condition shouldn't be needed. place the contents inside the if block above.
The 'data' will never be falsey in that code path.
} | ||
|
||
export function sendAPITelemetry(URL: string, isSuccessful?: boolean, duration?: number, errorMessage?: string, eventName?: string) { | ||
export function sendAPITelemetry(URL: string, entity: string, httpMethod: string, isSuccessful?: boolean, duration?: number, errorMessage?: string, eventName?: string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function looks to be a core implementation function of the other functions.
I would even consider not using this function at all and remove all the error vs success conditionals to make the code easier to understand and with less conditionals.
From the patterns of usage, it looks like you want to track an event to 'start' the http request, and either a Success or Failure event after the call returns.. And not all implementations seem to be doing this correctly either.
I would suggest creating a single helper method which normalizes the API calls and telemetry semantics. By making a utility for the 'pattern' and making the behavior more general and consistent. This will make for simpler code at call sites and not much given up by way of context.
This will simplify any usage of the fetch calls so that they are easy to implement, and you won't have issues with missing infor or typos from copy/paste errors.
you'll probably need to return something like undefined | Response
for the cases where an exception was thrown. Optionally, you could turn all invalid responses into a new Error, that gets thrown, and then in the catch do your logging, but then re-throw the error so the caller can do the actual handling. This would allow for telemetry to be recorded at the lowest level, but callers wouldn't need to do their own logging of it; just catch and provide whatever dialog or ignore the error.
Another thing that we've done on the Power Apps Runtime team is that we created our own FetchError class, which the helpers throw. When callers see this error, they can assume that the telemetry has been logged and this error indicates additional information about the response in case custom logic is needed.
e.g. something like export async function apiFetchWithTelemetry(entityName: string, requestUrl: string, requestInit?: RequestInit): Promise<Response>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you'll probably also find no need to have the three utility methods for telemetry specific to APIs since the implementation can simply be in this single pattern function.
@@ -51,11 +51,11 @@ export async function fetchDataFromDataverseAndUpdateVFS( | |||
|
|||
if (!response.ok) { | |||
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.fetch.authorization.error", "Authorization Failed. Please run again to authorize it"), localize("microsoft-powerapps-portals.webExtension.fetch.authorization.desc", "Try again")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not guaranteed to be an authorization error at this point in the code. it only means it wasn't a 200-299 response code.
@@ -75,7 +75,7 @@ export async function fetchDataFromDataverseAndUpdateVFS( | |||
else { | |||
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.parameter.error", "One or more commands are invalid or malformed"), localize("microsoft-powerapps-portals.webExtension.parameter.desc", "Check the parameters and try again")); | |||
} | |||
sendAPIFailureTelemetry(requestUrl, new Date().getTime() - requestSentAtTime, errorMsg); | |||
sendAPIFailureTelemetry(requestUrl, entity, Constants.httpMethod.GET, new Date().getTime() - requestSentAtTime, errorMsg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd move telemetry recording to before showing UX.
@@ -75,7 +75,7 @@ export async function fetchDataFromDataverseAndUpdateVFS( | |||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This condition will only work for English locales. You should probably update your code to detect specific statusCodes first. Or handle specific error types.
You would also likely benefit from using node-fetch
instead so that you have guaranteed Error-derived exceptions vs strings being thrown. See: ERROR-HANDLING.md
@@ -32,32 +34,32 @@ export async function saveData( | |||
} | |||
requestBody = JSON.stringify(data); | |||
} else { | |||
sendAPIFailureTelemetry(requestUrl, 0, BAD_REQUEST); // no API request is made in this case since we do not know in which column should we save the value | |||
sendAPIFailureTelemetry(requestUrl, entityName, httpMethod.PATCH, 0, BAD_REQUEST); // no API request is made in this case since we do not know in which column should we save the value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would consider NOT using the sendAPIFailureTelemetry event for this kind of error since there's no actual API being called yet.
Record this simply as another error or perhaps throw so the caller knows this is an invalid input?
this seems more like a caller having invalid parameters vs an API issue.
@@ -22,7 +22,6 @@ export function activate(context: vscode.ExtensionContext): void { | |||
context.subscriptions.push(_telemetry); | |||
|
|||
setTelemetryReporter(_telemetry); | |||
sendInfoTelemetry("Start"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add the Start event back. This is required for our telemetry pipeline to work. 'Start' means 'session started'.
You should add on the user's pac CLI user id, as is done in the desktop client's extension.
No description provided.