Can Sentry catch network error (XHR or fetch) in browser? - sentry

I am currently integrating Sentry into an Angular web application.
I am successfully reporting console.log / warn / error and exceptions in Sentry as "issue".
However, when a request to my server fails (HTTP 4XX or 5XX), Sentry totally ignores this error and does not send it.
I have tried all possible values for tracingOrigins.
Sentry.init({
dsn: '******',
integrations: [
new CaptureConsole(),
new Integrations.BrowserTracing({
tracingOrigins: ['localhost', 'http://localhost:4646/api']
})
],
tracesSampleRate: 1.0,
debug: true
});
What can I do ?

You can use the unhandled rejection event found here: https://developer.mozilla.org/en-US/docs/Web/API/Window/unhandledrejection_event
When your promises fail and error out, but are uncaught, this event will fire. Here you can add Sentry.captureException.
However the fact that you have CaptureConsole means you are likely sending all console errors as sentry events, and uncaught 4xx and 5xx should be sent. I assume you are catching and handling these then?
One way to handle these is add Sentry.captureException in your fetch/xhr library when it processes the response object.
If its easier to just log every uncaught error, you can patch the Promise object:
window.Promise = class extends Promise {
catch(func, ...args) {
let loggingFunc = (error = {}, ...args) => {
console.warn('Promise caught', error);
Sentry.breadcrumb('Promise caught', error.message, Sentry.Severity.Error);
return func(error, ...args);
};
return super.catch(loggingFunc, ...args);
}
};

I think you'd want an instance of Sentry running on your server to capture backend errors. You'd probably want to set these up in Sentry as two different projects.
Alternatively, you could manually track them in your Angular app when you get the response back - something like Sentry.captureException(err);

Related

A callback was provided to intercept the upstream response, but a network error occurred while making the request

I am using the method described in the answer of this question Log network failures in Cypress to log network failures. I basically intercept every failing request and its response and log it in some array as follows:
cy.intercept('*', (request) => {
request.continue(response => {
if(response.statusMessage !== "OK") {
networkFails.push({request, response})
}
})
})
The tests run perfectly fine, the problem is at the end of the tests I get this error
How do I solve this problem?
I ran into the same issue, and it turns out using request.continue is what was causing it.
request.continue is expecting a response, but when you get a socket hangup (ConnResetException), or in my case the socket being closed before it was finished writing, it triggers a cypress error.
Instead of request.continue, you'll want to use request.on( 'response', response => {
Your full code snippet should look like this:
cy.intercept('*', (request) => {
request.on( 'response', response => {
if(response.statusMessage !== "OK") {
networkFails.push({request, response})
}
})
})
The cypress documentation does a great job of explaining all of the different options here: https://docs.cypress.io/api/commands/intercept#Request-events
For reference, this was the specific cypress error I was getting while using .continue(). The error message was a bit different from yours but essentially the same problem requiring the same solution.
A callback was provided to intercept the upstream response, but a network error occurred while making the request:
Error: Socket closed before finished writing response

Custom GraphQL Error types for Validation

Is this possible to set custom GraphQL Error types for at least BAD_USER_INPUT code?
On the backend I've got an error type something like this:
throw {
type: 'ValidationError',
code: 422,
success: false,
message: `Something didn't work well`,
}
on Frontend I am still getting the same error type when some fields don't pass schema validation:
That's not really comfortable to take care of the both error formats on the frontend.
Is it possible to somehow:
Except errors and BAD_USER_INPUT receive data response 200 and check it by success?
Or maybe it's just possible to make my format of error (the one I'm sending form backend)?
I already wanted to make it using global error handler:
export default ({ graphQLErrors, networkError, operation, forward }, nuxtContext) => {
console.log('Global error handler')
console.log(graphQLErrors, networkError, operation, forward)
}
apollo: {
...
// setup a global error handler (see below for example)
errorHandler: '~/plugins/graphql/apollo-error-handler.js',
...
}
But it doesn't seem to work at all
Formatting errors can be achieved in Apollo Graphql server using formatError function. You can raise custom errors from your application from which the necessary error response can be constructed at formatError function.

handle http errors in rxjs lastValueFrom

I have started to use the lastValueFrom() to handle my observable http requests. One of these http calls is returning an error from the server-side, and I am getting the name: 'EmptyError', message: 'no elements in sequence' message
const response = await lastValueFrom(
this.service.doStuff()
).catch((e) => {
console.log('#1', e);
return {} as DoStuffResponse;
});
at #1 the error is EmptyError , not the error from the http call.
I understand why I am getting it (the http observable does not return a value)
However, what I'd like to know is what the actual error is (a 422 unprocessable entity in this case)
Is this possible ?
I have not found a method to catch the Http errors from lastValueFrom and this does not appear to be documented in rxjs.
As a result I've decided to avoid lastValueFrom when doing Http requests. Instead I stick with Subscribe and always get the Http response codes in the error.
As an aside, many people noticed Subscribe as being deprecated in VSCode, but this is not true; just a certain overload. I know you didn't mention the deprecation as a motivator for using lastValueFrom, but I think most people, including myself, used the VSCode deprecation alert as a prompt to switch.
That said, this Subscribe syntax is still valid and should give you the Http error code:
this.someService.getResults.subscribe(
{
next: (results) => {
console.log('Here are the results...', results);
},
error: (err: any) => {
console.log('Here is the error...', err.status);
},
complete: () => { }
});

cy.wait(#someXhr) taimeouts

I'm having a problem with stubbing a simple request to an API using the cypress' cy.server() and cy.route().
Here's the failing test:
it.only("should show an error message for server errors", () => {
const name = "It doesnt matter";
const email = "takenemail#yopmail.com";
const pass = "123123";
// run the server and define the stubbed route
cy.server();
cy.route(
"POST",
`${serverBaseUrl}/auth/register`,
"fixture:register-fail.json"
).as("postRegister");
// fill in the registration form and hit submit
cy.visit("/auth/register");
cy.get(selectors.registerForm.name).type(name);
cy.get(selectors.registerForm.email).type(email);
cy.get(selectors.registerForm.password).type(pass);
cy.get(selectors.registerForm.registerButton).click();
// intercept the request and mock it
cy.wait("#postRegister"); // this fails.
cy.get(selectors.registerForm.genericErrors).contains(
"This email has already been taken"
);
});
and the error:
cy.wait() timed out waiting 5000ms for the 1st request to the route: postRegister. No request ever occurred.
Note: even though it says that No request ever occurred. I can still see the request being send and a response received in the console's Network tab (which means the stub has been bypassed and a regular request's been made).
Any ideas what's happening?
Thanks in advance.
Ok, seems like i have found the problem.
It turns out that using the fetch API is not supported by cypress.
The workaround - using whatwg-fetch, which is basically a polyfill for the fetch api, working with XHR behind the scenes.
Install the whatwg-fetch package: npm install whatwg-fetch --save
Import it in your project: import "whatwg-fetch";
Last, but very important - remove the fetch object from the window before every page load in the cypress environment like this:
// you can define this in the commands file for example...
Cypress.on("window:before:load", (win) => delete win.fetch);
or an alternative, per-visit approach:
it("some test", () => {
cy.visit("/url", {
onBeforeLoad: win => delete win.fetch // <---
});
// ...the rest of the test
});
Doing this will kick-in the polyfill and the stubbing should be working properly after this intervention.

How to get more error information from an Angular http ajax call

I have been trying to diagnose a http problem for what seems forever now.
I thought I would go back to a very simple sample Ionic (Angular) application I can use to test, where I have the following test code...
public onClick() : void {
this.http.get(this.url).subscribe(res => {
this.result = res.statusText;
console.log(res);
}, error => {
this.result = `failed ${error.statusText}`;
console.log(error);
});
}
The url just comes from an input.
If I force an error, (eg put an incorrect url), I notice the error from the observable always has a status os 0, and no statusText. In the browser network tab, I see the 404 as expected...
identityx 404 xhr polyfills.js:3 160 B 10 ms
Is there a way to get better error information back from the http call, rather than just 0 all the time (and no status text)? I've look through the error object, but can't see anything.
Thanks in advance!

Resources