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

Only requests using apollo client, Response body of network in sentry session replay is undefined. #8345

Closed
3 tasks done
jabelic opened this issue Jun 16, 2023 · 7 comments · Fixed by getsentry/sentry-docs#7210
Assignees
Labels
Package: replay Issues related to the Sentry Replay SDK Type: Bug

Comments

@jabelic
Copy link

jabelic commented Jun 16, 2023

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/browser

SDK Version

7.55.2

Framework Version

Nuxt.js: 2.15.8, @apollo/client: 3.5.8

Link to Sentry event

No response

SDK Setup

  initErrorTracker(username: string): void {
    if (this.isInitializedSentry) return;
    this.sentry.init({
      dsn: "******************",
      environment: "development",
      release: "",
      integrations: [new this.sentry.BrowserTracing()],
      ignoreErrors: [/some error message/],
      tracesSampleRate: 0.01,
      replaysSessionSampleRate: 0.1,
      replaysOnErrorSampleRate: 1
    });
    this.sentry.configureScope(scope => scope.setUser({ id: username }));
    this.isInitializedSentry = true;
    this.log('sentry initialized.');
  }

  initSessionReplay(username: string): void {
    if (this.replay) return;
    const replay = new this.sentry.Replay({
      maskAllText: false,
      maskAllInputs: false,
      blockAllMedia: false,
      networkDetailAllowUrls: [/.*/],
      networkCaptureBodies: true
    });
    this.sentry.configureScope(scope => scope.setUser({ id: username }));
    this.sentry.getCurrentHub().getClient()?.addIntegration?.(replay);
    this.replay = replay;
    this.log('sentry replay initialized.');
  }

Steps to Reproduce

When replaying a Sentry session in this environment, the Network response body is undefined.

This problem only occurs for response bodies of API requests using the apollo client response bodies for fetch api requests can be retrieved.

Note that the networkDetailAllowUrls above is a sample, and in my environment, I have set the regular expression to allow only specific APIs to pass through. I have confirmed that the regular expression is correct.

Also, Content-Type of response is application/json.

Expected Result

In the Network tab of the sentry session replay, the response body should be visible.

Actual Result

Response body is undefined in the Network tab of sentry session replay. Response size has been retrieved.

sentry-session-replay-network

@mydea
Copy link
Member

mydea commented Jun 16, 2023

Hi @jabelic,

could you provide one or both of:

  1. An example body that is sent in a network request that is not captured (the raw body, ideally, and possibly also headers?)
  2. A link to a replay in your org, if you are comfortable with sharing this with us for debugging purposes & are using SaaS

I don't really see how apollo or similar should affect that, except that the sent payload is not JSON possibly, but we should still capture it as plain text in that case (and have some tests for that...), so not entirely sure what's going on there...!

@mydea mydea self-assigned this Jun 16, 2023
@mydea mydea added Package: replay Issues related to the Sentry Replay SDK and removed Waiting for: Product Owner labels Jun 16, 2023
@jabelic
Copy link
Author

jabelic commented Jun 16, 2023

Hi @mydea !
Here is an example of a response body:

{
    "data": {
        "getTeacher": {
            "id": 1,
            "userId”:1,
            "managementUserId": 1,
            "username": “example",
            "changedPasswordFlag": true,
            "name": “example",
            "gender": "other",
            "createdDate": "2016-11-11 00:00:00",
            "position": “manager",
            "memo": “example\n",
            "mainClassroom": {
                "id": 4,
                "classroomName": “example",
                "__typename": “class"
            },
            "__typename": “example"
        }
    }
}

Due to confidentiality issues, some properties have been removed or renamed.

And here is the response header.

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://192.168.0.175:3010
Content-Length: 28025
Content-Type: application/json; charset=utf-8
Date: Fri, 16 Jun 2023 10:34:48 GMT
Etag: W/"6d79-NzSQK0+xWBm2ceVBHFlw4EM/YZo"
Vary: Origin
X-Powered-By: Express

Thank you 😄

@ubugeeei
Copy link

ubugeeei commented Jun 17, 2023

Hi @mydea (cc @jabelic) !

I had the same problem, so I did some research and found that in packages/replay/src/coreHandlers/util/fetchUtils.ts, in _parseFetchBody response.text, I got DOMException: The user aborted a request. .

async function _parseFetchBody(response: Response): Promise<string | undefined> {
try {
return await response.text();
} catch {
return undefined;
}
}

I was investigating an issue on apollo-client for such a problem and I found it.

apollographql/apollo-client#6769

He seemed to have the same phenomenon with LogRocket, and the cause was that Apollo was sending an abort signal through AbortControler during the cleanup process to cancel all queries whenever a query was completed.

apollographql/apollo-client#6769 (comment)

I was able to solve this problem at Sentry by taking the same steps described below!

apollographql/apollo-client#6769 (comment)

const abortController = new AbortController();

const httpLink = createHttpLink({
  uri: "http://localhost:4000/graphql",
  fetchOptions: {
    mode: "cors",
    signal: abortController.signal, // here!
  },
});

Perhaps you could leave something in the Sentry documentation for troubleshooting when using the apollo-client.

@mydea
Copy link
Member

mydea commented Jun 19, 2023

Hi @ubugeeei ,

thanks for digging into this and finding a solution! This is awesome, I will see how we can add this to the docs the best way. Thanks a bunch, I'll keep this open until the docs are updated for this!

@ubugeeei
Copy link

@mydea
Yeah, thanks to you too!

@phryneas
Copy link

Hi, I'm an Apollo Client maintainer.
I'll also see that I bring this up on our side, if there's any way we can be a little bit less eager to abort our AbortControllers.
It's a bit unexpected that other libraries seem to be reusing them beyond the normal initial fetch, but maybe we can cater towards it a little bit.

@mydea
Copy link
Member

mydea commented Jun 19, 2023

Hi, I'm an Apollo Client maintainer. I'll also see that I bring this up on our side, if there's any way we can be a little bit less eager to abort our AbortControllers. It's a bit unexpected that other libraries seem to be reusing them beyond the normal initial fetch, but maybe we can cater towards it a little bit.

Cool, that sounds like a great idea! For reference, this is what we're doing with fetch - we monkey patch it here: https://github.com/getsentry/sentry-javascript/blob/develop/packages/utils/src/instrument.ts#L140

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Package: replay Issues related to the Sentry Replay SDK Type: Bug
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

4 participants