Skip to content
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

Track time it takes to get a response from DevX API #875

Merged
merged 11 commits into from
Apr 1, 2021

Conversation

millicentachieng
Copy link
Contributor

@millicentachieng millicentachieng commented Mar 3, 2021

Overview

Add a custom event which allows us to capture the time it takes for a call to our DevX API to return a response.

Application Insights JS SDK offers two methods to use to track events:

  • appInsights.startTrackEvent(eventName), to be called just before the tracked call
  • appInsights.stopTrackEvent(eventName, properties) to be called just after the tracked call

Application Insights will add a custom property duration with the API call duration in milliseconds.

Testing Instructions

  • Open Developer Tools on browser then go Network tab
  • Fetching samples, code snippets, permissions or autocomplete options should trigger a tracked API call
  • Inspect data sent to Application Insights. Below is an example of how the data should look like:
    image

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2021

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2021

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

Copy link
Contributor

@jobala jobala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion

Instead of using trackApiCallEvent to make network requests consider overriding fetch because developers won't have to remember to use trackApiCallEvent instead of fetch and this approach also maintains the intuitiveness of using fetch for network calls.

You can override fetch with the following snippet.

windows.fetch = telemetry.trackedApiCall

Remember to do this in App.tsx and to change the signature of trackApiCallEvent so that the componentName param is last that way you'll avoid breaking calls to fetch that you are not interested in tracking.

@zengin
Copy link

zengin commented Mar 3, 2021

@jobala I wouldn't recommend changing a global function at the JavaScript API level. trackApiCallEvent is a descriptive name implying what it is doing. This way, we also make sure that telemetry is "opt-in". Otherwise developers may start emitting telemetry unintentionally if fetch is redefined. I understand that optional componentName can act as the arbiter of this decision, but that is more implicit and easy to cause a mistake.

@millicentachieng network calls to DevX API are failing when I use the static deployment. Constructed URL seems to be wrong. Is that expected?

Request URL: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net/[object%20Object]/api/graphexplorersnippets?lang=javascript

@millicentachieng
Copy link
Contributor Author

Thanks for the feedback @zengin and @jobala.

I'm leaning towards having the tracking being opt-in as well. @ddyett, what's your take?

Regarding the API call for fetching snippets, it's an issue that's been fixed not too long ago. I'll merge the fix into this branch.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2021

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

src/telemetry/telemetry.ts Outdated Show resolved Hide resolved
@ddyett
Copy link

ddyett commented Mar 3, 2021

I'm leaning towards having the tracking being opt-in as well. @ddyett, what's your take?

Whether it's opt in depends on comfort level that we are properly sanitized. I think there's benefit in telemetry automatically being available provided we trust it's sanitized and it doesn't generate massive increases in data costs. The typical pattern I've seen in the past is that we actually put this as part of middleware in the http pipeline which generally automatically covers everyone. I don't have a problem with this current approach but when someone wants to add a new call the answer will probably be yes we should track it so the pure fetch call should almost never be used.

My expectation would have been that trackApiCallEvent accepts the function so it's explicit what's been called. That way you can just expose from telelmetry class a trackevent and it becomes non-specific to making a web call or some other action we want to track. I see though that you want information from the parameters and response so that limits that.

Copy link
Collaborator

@thewahome thewahome left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion 2: Middleware

We can take advantage of redux middleware which will allow us to keep the code as-is and add the side-effects in a more react way.

Middleware has access to the state and action properties which would be useful to create the custom event. It would also give us the advantage of one source of truth for when we need to change/add/remove a parameter to track.

Here is a short introduction to redux middleware.

@jobala
Copy link
Contributor

jobala commented Mar 8, 2021

@millicentachieng

It makes sense for users to explicitly opt in to track requests and we can make the design better by separating the tracking and network request functionality because it is not obivous from the name that trackApiCallEvent also makes a network call.

The tracking and network call can be separated using the decorator pattern and we'll have the added advantage of not modifying fetch calls to trackApiCallEvent calls. The code is show below

@telemetry.trackApiCallEvent
fetch(...)

The decorator implementation below shows how you can use a decorator to get the elapsed time.

const trackApiCallEvent = (
  target: Object,
  propertyKey: string,
  descriptor: PropertyDescriptor
) => {
  const method = descriptor.value;

  descriptor.value = function (...args) {
    const start = ...
    const result = method.apply(this, args);
    const finish = ...
    const elapsedTime = finish - start
    return result;
  };

EDIT:
I just realized this is what @ddyett was talking about in his comment. Another advantage of this approach is you get the paramaters and response as well.

My expectation would have been that trackApiCallEvent accepts the function so it's explicit what's been called. That way you can just expose from telelmetry class a trackevent and it becomes non-specific to making a web call or some other action we want to track. I see though that you want information from the parameters and response so that limits that.

@millicentachieng
Copy link
Contributor Author

millicentachieng commented Mar 12, 2021

@jobala, @thewahome I've reviewed your comments on using a decorator or middleware but I have another suggestion. Application Insights has a setting where you can enable auto-tracking of fetch calls. The result is what we are looking for. Here's a sample of the data collected:

{
    "baseType": "RemoteDependencyData",
    "baseData": {
        "id": "|eca9e4e2d022464eb9291ffe5cb60194.e3e36b21410349b5",
        "ver": 2,
        "name": "GET https://graphexplorerapi.azurewebsites.net/samples",
        "resultCode": "200",
        "duration": "00:00:01.835",
        "success": true,
        "data": "GET https://graphexplorerapi.azurewebsites.net/samples",
        "target": "graphexplorerapi.azurewebsites.net",
        "type": "Fetch",
        "properties": {
            "HttpMethod": "GET",
            "ApplicationName": "Graph Explorer v4",
            "IsAuthenticated": "true"
        },
        "measurements": {}
    }
}

We can then have a processor that filter's out fetch requests that we do not need.

@thewahome
Copy link
Collaborator

This looks good!! Would the preprocessor be able to also filter out the url contents for PII?

@thewahome
Copy link
Collaborator

Do we plan on using it for all our external calls? Including the run query?

@millicentachieng
Copy link
Contributor Author

@thewahome Yes, the processor will sanitize the urls.

@millicentachieng
Copy link
Contributor Author

It also captures results from run query. I'm thinking that can be an important metric too to see which queries have a high failure rate, whether caused by missing permissions or wrongly formatted query.

@github-actions
Copy link
Contributor

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

1 similar comment
@github-actions
Copy link
Contributor

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

@millicentachieng
Copy link
Contributor Author

@thewahome, @jobala Please review the new changes

@github-actions
Copy link
Contributor

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

Copy link
Contributor

@MIchaelMainer MIchaelMainer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we performed a review of the Application Insights data captured with these changes to verify that we aren't capturing customer data? What were the user actions in the staging site and did they exercise all of the changes in the this PR?

src/app/utils/query-url-sanitization.ts Show resolved Hide resolved
src/telemetry/filters.ts Outdated Show resolved Hide resolved
src/telemetry/filters.ts Show resolved Hide resolved
src/telemetry/filters.ts Show resolved Hide resolved
src/telemetry/telemetry.ts Outdated Show resolved Hide resolved
@github-actions
Copy link
Contributor

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

@github-actions
Copy link
Contributor

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

@thewahome thewahome self-requested a review March 29, 2021 10:25
@thewahome
Copy link
Collaborator

@millicentachieng If you'd like to test the telemetry on the staging site, you can:

- name: Build And Deploy
        env:
          REACT_APP_INSTRUMENTATION_KEY: ${{ secrets.REACT_APP_INSTRUMENTATION_KEY }}
  • in the secrets page you can add a new secret: REACT_APP_INSTRUMENTATION_KEY

Once the staging environment is created, you will be able to test your changes

@github-actions
Copy link
Contributor

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

@github-actions
Copy link
Contributor

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

@github-actions
Copy link
Contributor

github-actions bot commented Apr 1, 2021

Azure Static Web Apps: Your stage site is ready! Visit it here: https://jolly-sand-0ac78c710-875.centralus.azurestaticapps.net

@millicentachieng millicentachieng merged commit 3fb99df into dev Apr 1, 2021
@millicentachieng millicentachieng deleted the feature/trackDevXAPICalls branch April 1, 2021 13:42
thewahome added a commit that referenced this pull request Apr 13, 2021
* Chore(deps): Bump elliptic from 6.5.3 to 6.5.4 (#917)
* Chore(deps): Bump y18n from 3.2.1 to 3.2.2 (#919)
* Track time it takes to get a response from DevX API (#875)
* Fix: javascript injection (#925)
@millicentachieng millicentachieng linked an issue May 20, 2021 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

We should add instrumentation for outgoingservicerequest
6 participants