Sentry-javascript: Exception sans erreur capturée avec les clés : erreur, en-têtes, message, nom, ok

Créé le 28 oct. 2019  ·  48Commentaires  ·  Source: getsentry/sentry-javascript

Forfait + Version

  • [x] @sentry/browser
  • [ ] @sentry/node
  • [ ] raven-js
  • [ ] raven-node _(corbeau pour nœud)_
  • [ ] autre:
  • [x] @angular/core

Version:

5.7.1 (@sentry/browser)
8.2.11 (@angular/core)

La description

J'ai une configuration initiale pour l'application Angular avec l'intercepteur d'erreur global
voici comment je l'envoie

    const eventId = Sentry.captureException(error.originalError || error);
    Sentry.showReportDialog({ eventId });

et je reçois cette erreur (exception de non-erreur capturée avec des clés : erreur, en-têtes, message, nom, ok) erreur encore et encore, et je ne peux pas comprendre ce qui ne va pas dans la description et comment la reproduire.

Needs Reproduction

Commentaire le plus utile

Nous utilisons actuellement ce qui suit pour l'ignorer.

Sentry.init({
  ignoreErrors: [
    'Non-Error exception captured'
  ]
});

Tous les 48 commentaires

Cela signifie que l'objet que vous fournissez n'est pas une instance de Error qui contient le stacktrace dans l'application Angular.

Vous devriez (comme l'indique le message) utiliser Sentry.captureException(error.error) ou Sentry.captureException(error.message) selon vos besoins.

@kamilogorek oh ok) tnx

@kamilogorek obtient toujours cette erreur, même avec cela

    const exception = error.error || error.message || error.originalError || error;
    const eventId = Sentry.captureException(exception);

+1, j'obtiens toujours cette erreur, peu importe comment je la dis.

sentry.error-handler.ts

export class SentryErrorHandler extends GeneralErrorHandler {
  ...
  handleError(error) {
    ...
    const exception = error.originalError || error.error || error
    Sentry.captureException(exception)
  }
}

package.json

{
  ...
  "@angular/core": "^8.2.11",
  "@sentry/browser": "^5.7.1",
  ...
}

j'ai décidé de faire ça

Sentry.init({
            dsn: environment.sentryUrl,
            beforeSend(event, hint) {
                /* tslint:disable:no-string-literal only-arrow-functions */
                const isNonErrorException =
                    event.exception.values[0].value.startsWith('Non-Error exception captured') ||
                    hint.originalException['message'].startsWith('Non-Error exception captured');
                /* tslint:enable:no-string-literal only-arrow-functions */

                if (isNonErrorException) {
                    // We want to ignore those kind of errors
                    return null;
                }
                return event;
            }
        });

Merci pour la solution de contournement @gchronos ! J'espère qu'il y aura bientôt un correctif potentiel.

Juste pour dire que je reçois également ces erreurs. J'utilise Angular 8 et après avoir lu pas mal de problèmes à ce sujet, je me rends compte qu'il se peut que je ne gère pas correctement l'erreur dans mon composant de gestion des erreurs. J'ai essayé les solutions de contournement suggérées par d'autres définissant l'exception avant d'être transmise à captureException, mais cela n'a pas réduit les erreurs. Ce serait formidable si quelqu'un pouvait donner plus d'informations à ce sujet ou je devrais simplement utiliser la solution de GChronos (Merci!).

+1

+1

Quelqu'un peut-il fournir une reproduction que je pourrais utiliser pour déboguer cela? J'ai essayé d'utiliser l'application angular-cli de base et je ne peux pas reproduire ce comportement. Merci!

@kamilogorek Je pense que vous pouvez lancer un nouveau projet Angular 8 et faire une demande http vers un point de terminaison renvoyant 500 et ne pas détecter l'erreur dans le service http afin qu'elle se propage à Sentry.

Je peux donner plus d'informations, voici notre ErrorHandler :

@Injectable()
export class SentryErrorHandler implements ErrorHandler {
  constructor() { }
  handleError(error) {
    Sentry.captureException(error.originalError || error.error || error);
  }
}

Dans notre suivi Sentry, nous obtenons toujours des événements en double pour ceux-ci :

  • Object.a Exception non-erreur capturée avec les clés : ...
  • captureException Exception sans erreur capturée avec les clés : ...

(Les autres événements sont signalés comme un seul élément de la liste)

Nous avons rassemblé quelques centaines de ces événements « Non.Error », et il est intéressant de noter qu'ils ont tous en commun :

  • nom.du.navigateur : Samsung Internet 100 %
  • navigateur : Samsung Internet 9.4 100%

Et les erreurs sont principalement les suivantes :

{
  error: [Object], 
  headers: [Object], 
  message: Http failure during parsing for https://foo.bar/baz, 
  name: HttpErrorResponse, 
  ok: False, 
  status: 200, 
  statusText: OK, 
  url: https://foo.bar/baz
}

Ok, j'ai rendu le SentryErrorHandler injectable et implémente ErrorHandler au lieu d'extend et il n'y a plus de problèmes comme ça pour moi.
Alors j'ai changé de

export class SentryErrorHandler extends ErrorHandler {

 constructor() {
     super();
 }

 handleError(err: any): void {
     if (environment.production === true || environment.preprod === true) {
         Sentry.captureMessage(err.originalError || err);
     }
     throw err;
 }
}

à

@Injectable()
export class SentryErrorHandler implements ErrorHandler {

 constructor() { }

 handleError(err: any): void {
     if (environment.production === true || environment.preprod === true) {
         Sentry.captureException(err.originalError || err);
     }
     throw err;
 }
}

J'ai eu la première config pendant 2 ans sans problème mais depuis la mise à jour vers Angular 8 j'ai plusieurs exceptions sentinelles.

@jonathan-payiq avez-vous pu découvrir les causes de cela ? Ou ignorez-vous simplement toutes ces exceptions de non-erreur maintenant ?

Nous les ignorons actuellement.
Nous avons découvert à partir du fil d'Ariane que cela se produit lorsque la vue Web/le navigateur est en arrière-plan (non visible), donc la solution pour nous est d'empêcher la récupération de se produire alors que la page n'est pas visible. Apparemment, les navigateurs Samsung gèrent mal l'actualisation du réseau en arrière-plan.

@jonathan-payiq, comment les ignorez-vous exactement ? Merci d'avance.

Nous utilisons actuellement ce qui suit pour l'ignorer.

Sentry.init({
  ignoreErrors: [
    'Non-Error exception captured'
  ]
});

@kamilogorek avez-vous pu reproduire le problème ?

Clôture du problème, car il semble que le problème d'origine ait été partiellement résolu ou qu'il existe une solution fonctionnelle. Je préférerais que quelqu'un crée un nouveau problème avec une nouvelle description si c'est toujours un problème.
N'hésitez pas à me contacter si c'est toujours d'actualité, et je me ferai un plaisir de rouvrir et de travailler dessus.
À votre santé!

Il n'a pas été résolu. Je viens d'essayer d'intégrer Sentry avec Angular 8 et j'ai trouvé ce problème.

Je ne comprends pas comment Sentry peut prétendre à une configuration prête à l'emploi, c'est complètement faux.

Je ne comprends pas comment Sentry peut prétendre à une configuration prête à l'emploi, c'est complètement faux.

@Rush fournit un cas reproductible, où vous expliquez et montrez ce qui ne va pas, puis nous pouvons vérifier votre réclamation.

@kamilogorek La vérité à dire, cela ne fonctionne pas avec Angular depuis plus de 6 mois, il y a assez de rapports ici pour le confirmer, donc IMO il n'y a pas besoin d'autres cas de repro, vous pouvez le découvrir par vous-même assez facilement. Je sais moi-même que ce n'est pas le cas, car nous avons le même problème dans notre projet utilisant Angular v8, et maintenant v9 (pas de sourcemaps).

Exactement, et en plus je paie pour que Sentry fasse le travail à ma place. Ce n'est pas un projet open source où je m'attends à me salir les mains.

J'aime Sentry mais je pourrais chercher des alternatives...

J'ai utilisé une application https://github.com/gothinkster/angular-realworld-example-app comme exemple, juste pour que tout le monde puisse également faire la même reproduction.

Application clonée Barebone, suivi des documents angulaires de Sentry et téléchargé les sourcesmaps. Voici les résultats.


Exemple 1 : logique brisée

Ce que Angular vous donne dans un gestionnaire d'erreurs + quel événement nous capturons :

Screenshot 2020-04-16 at 12 01 13

À quoi cela ressemble dans l'interface utilisateur :

Screenshot 2020-04-16 at 12 07 02

Remarque : tout est en place, vous pouvez facilement pointer vers la bonne ligne de code qui a été cassée, le message d'erreur et le type d'erreur sont corrects, car Angular vous donne un objet Error entier avec lequel travailler.


Exemple 2 : appel de service interrompu

Ce que Angular vous donne dans un gestionnaire d'erreurs + quel événement nous capturons :

Screenshot 2020-04-16 at 12 00 49

À quoi cela ressemble dans l'interface utilisateur :

Screenshot 2020-04-16 at 12 07 12
Screenshot 2020-04-16 at 12 08 03

Remarque : il n'y a aucun moyen de savoir quel type d'erreur a été généré, car Angular ne vous donne pas cette information. Cependant, vous pouvez jeter un œil aux données sérialisées pour dire qu'il y avait une erreur "404 Not Found", qui _probablement_ provenait d'un appel XHR invalide. Ensuite, vous pouvez enquêter sur le fil d'Ariane pour voir qu'en fait il y a eu un appel XHR à l'URL donnée (qui dans ce cas contenait une faute de frappe), précédé d'un clic sur un élément DOM exact, qui l'a déclenché. Avec ces informations, cela devrait suffire dans 99% des cas pour résoudre le problème.


Nous ne pouvons travailler qu'avec ce que nous a donné le cadre. Sinon, nous serions obligés de patcher le framework lui-même.

Nous ne pouvons travailler qu'avec ce que nous a donné le cadre. Sinon, nous serions obligés de patcher le framework lui-même.

Est-ce votre façon de dire « pas notre problème » ? Avant de passer à sentinelle (de certains concurrents), ces erreurs XHR étaient parfaitement capturées et elles utilisaient la même méthode d'installation avec un gestionnaire d'erreurs angulaires.

@kamilogorek en tant que fournisseur, vous pouvez également ouvrir un ticket avec le framework. Je suis sûr que cela attirerait l'attention.

Avant de passer à sentinelle (de certains concurrents), ces erreurs XHR étaient parfaitement capturées et elles utilisaient la même méthode d'installation avec un gestionnaire d'erreurs angulaires.

@szechyjs, ce serait formidable si vous pouviez partager la solution à la place, car il s'agit d'un SDK open source et nous pouvons itérer sur les améliorations si nous savons ce que nous visons.

... vous pouvez également ouvrir un ticket avec le framework. Je suis sûr que cela attirerait l'attention.

Je viens d'ouvrir un ticket avec l'assistance sentinelle et j'ai référencé ce problème.

Un passant ici. Pour mon cas, je souhaite signaler les rejets traités dans React Native et j'ai fini par voir la même erreur que l'OP. Depuis the object you provide is not an instance of Error , j'ai utilisé ce qui suit.

export interface IError extends Error {
  code?: ErrorCode
  msg?: string
}

export const appError = (code: ErrorCode, msg: string = ''): IError => {
  const errmsg = `code: ${code}, msg: ${msg}`
  const err: IError = new Error(errmsg)
  err.code = code
  err.msg = msg
  err.name = 'appError'
  return err
}

Puis j'appelle

export const logError = (err: Error) => {
  sentry.captureException(err)
}

et je vois

スクリーンショット 0032-05-24 1 58 38

J'espère que cela t'aides!

Dans mon cas, la section Breadcrumbs de Sentry m'a beaucoup aidé à identifier la cause. Cela s'est surtout produit lorsqu'il y avait quelques 404 sur certaines API externes.

La mise à jour de la documentation et les modifications nécessaires du SDK JS arrivent :

https://github.com/getsentry/sentry-docs/pull/1695/
https://github.com/getsentry/sentry-javascript/pull/2601

Il devrait sortir cette semaine ! :)

Solution simple pour cela (car cela ne se produit qu'avec les erreurs HTTP interceptées) :

handleError(error: Error | HttpErrorResponse | any) {
      // ... 
      if (error.constructor.name === "HttpErrorResponse") {
                error.error.Message + " (" + error.message + ")";
                error = error.error;
      }
      // ...
      Sentry.captureMessage(err.originalError || err.error || error);

     throw err;
 }

De nouveaux documents et 5.16.0 viennent d'être publiés - https://docs.sentry.io/platforms/javascript/angular/
J'ai essayé de le rendre aussi explicite et détaillé que possible, et c'est pourquoi il "peut ressembler" à beaucoup de code.

@kamilogorek J'ai aussi ce problème sur une application Vue. Y a-t-il un correctif là-bas?

Pareil ici. l'exception est levée dans le gestionnaire d'erreurs d'intégration de sentinelle vuejs.
https://sentry.io/share/issue/eaf13a2455e04150aaaab595d0d7bafe/

@sblawrie quel problème avez-vous exactement ? Quelques détails supplémentaires seraient utiles s'il vous plaît.
@cincauhangus il semble que quelque part dans votre code vous lancez une erreur avec l'instance de promesse elle-même (notez les clés abort, always, catch, done ).

Quelque chose comme:

const promise = new Promise((resolve, reject) => (...));
// somehow somewhere in the code
function foo () {
  // ...
  throw promise
}

Ainsi, le errorHandler de Vue obtient un objet de promesse entier, où il s'attend à être une instance de Error .

@kamilogorek merci pour la clarification. J'ai apporté quelques modifications et je surveillerai si le problème persiste.

Utilisation d'Angular 8 et même problème d'exception sans erreur. Modification de l'exemple de code « extractError » comme suit :

private static extractError(error: any) {
    // Try to unwrap zone.js error.
    // https://github.com/angular/angular/blob/master/packages/core/src/util/errors.ts
    if (error && error.ngOriginalError) {
      error = error.ngOriginalError;
    }
    // We can handle messages and Error objects directly.
    if (typeof error === 'string' || error instanceof Error) {
      return error;
    }
    // If it's http module error, extract as much information from it as we can.
    if (error instanceof HttpErrorResponse) {
      // The `error` property of http exception can be either an `Error` object, which we can use directly...
      if (error.error instanceof Error) {
        return error.error;
      }
      // ... or an`ErrorEvent`, which can provide us with the message but no stack...
      if (error.error instanceof ErrorEvent) {
        return error.error.message;
      }
      // ...or the request body itself, which we can use as a message instead.
      if (typeof error.error === 'string') {
        return `Server returned code ${error.status} with body "${error.error}"`;
      }
      // If we don't have any detailed information, fallback to the request message itself.
      return error.message;
    }

    // ***** CUSTOM *****
    // The above code doesn't always work since 'instanceof' relies on the object being created with the 'new' keyword
    if (error.error && error.error.message) {
      return error.error.message;
    }
    if (error.message) {
      return error.message;
    }
    // ***** END CUSTOM *****

    // Skip if there's no error, and let user decide what to do with it.
    return null;
  }

Modifié mon Sentry.init beforeSend exemple basé sur beforeSend d » @untilinvite ci - dessus. Ce changement consiste à gérer un deuxième message de journal de https://github.com/getsentry/sentry-javascript/issues/2169 se résolvant également en tant que non-erreur.

 Sentry.init({
        dsn: AppConfig.envSettings.sentryDSN,
        maxBreadcrumbs: 50,
        environment: this.getEnvName(),
        integrations: [new Sentry.Integrations.Breadcrumbs({ console: false })],
        beforeSend(event, hint) {
          // Note: issue with double entries during http exceptions: https://github.com/getsentry/sentry-javascript/issues/2169
          // Note: issue with a second entry not being set correctly (as a non-error): https://github.com/getsentry/sentry-javascript/issues/2292#issuecomment-554932519
          const isNonErrorException = event.exception.values[0].value.startsWith('Non-Error exception captured');
          if (isNonErrorException) {
            if (!event.extra.__serialized__) {
              return null;
            }
            let realErrMsg = event.extra.__serialized__.error ? event.extra.__serialized__.error.message : null;
            realErrMsg = realErrMsg || event.extra.__serialized__.message;
            // this is a useless error message that masks the actual error.  Lets try to set it properly
            event.exception.values[0].value = realErrMsg;
            event.message = realErrMsg;
          }
          return event;
        }
      });

Nous avons apporté les modifications qui ont été ajoutées aux documents avec la version 5.16.0 et nous obtenons toujours des erreurs Non-Error exception captured with keys: error, headers, message, name, ok . J'espère que le package @sentry/angular résoudra ces problèmes ?

Angulaire : v9.1
Sentinelle : v5.20

@szechyjs avez-vous également lu la deuxième partie sur les intercepteurs http ? C'est généralement le principal problème qui empêche l'erreur d'être détectée correctement - https://docs.sentry.io/platforms/javascript/angular/

@szechyjs avez-vous également lu la deuxième partie sur les intercepteurs http ? C'est généralement le principal problème qui empêche l'erreur d'être détectée correctement - https://docs.sentry.io/platforms/javascript/angular/

Nous n'utilisons pas d'intercepteurs.

Bonjour, j'ai passé du temps sur ce problème et j'ai trouvé que error.error.message sur les erreurs de type HttpErrorResponse ne contient pas nécessairement d'informations. Si nous regardons le constructeur, nous verrons qu'Angular définit le message prop sur l'objet racine et non sur ErrorEvent .

https://github.com/angular/angular/blob/cb3db0d31b91bea14c7f567fe7e7220b9592c11b/packages/common/http/src/response.ts#L345

En modifiant cette ligne https://github.com/getsentry/sentry-javascript/blob/8eb72865dcd62ff719441105c7eda28007a07e9d/packages/angular/src/errorhandler.ts#L112
à

if (error.error instanceof ErrorEvent && error.error.message)

le gestionnaire d'erreurs est passé à return error.message; et a renvoyé l'erreur attendue.

Super prise @jakkn , merci ! Gestionnaire mis à jour dans le PR https://github.com/getsentry/sentry-javascript/pull/2903

J'ai ce problème sur une application Express dont je viens d'hériter. Aucune idée de comment cela pourrait se produire, mais cela semble se produire pour la plupart des erreurs que l'application génère, et j'utilise la configuration Express standard de la documentation.

par exemple https://sentry.io/share/issue/bfd4f674c10b4b4a8b6a291dde8e2a66/

J'ai rencontré cette même erreur, bien que ce soit pour le gestionnaire de demandes express et non angulaire. Fondamentalement, j'appelais next avec un pojo au lieu d'un objet Error. Je fais des choses amusantes dans mon propre gestionnaire d'erreurs express pour le transformer en quelque chose d'intéressant, mais comme le middleware de requête sentryio commence en premier, il n'a pas eu cette erreur triée.

En fin de compte, créé une fonction utilitaire qui transformerait tout ce qui était fourni en quelque chose de plus raisonnable :

export const handleMaybeError = err => {
  if (err instanceof Error) return err
  const newErr = new Error(err.message || 'unexpected')
  for (const [key, value] of Object.entries(err)) {
    newErr[key] = value
  }
  return newErr
}

export const someController = (req, res, next) => {
  try {
    await handleResponse(req, res)
  } catch (err) {
    next(handleMaybeError(err))
  }
}

Cela mélange les traces de la pile, je pense, mais vraiment si c'était un pojo passé dedans, il n'y avait de toute façon pas de trace de la pile.

Dans notre cas, avant que cela ne soit corrigé, la grande majorité des événements signalés concernaient ce problème particulier et, comme il s'agit d'un serveur Web de nœud de longue durée, les fils d'Ariane sont presque inutiles - et toutes les erreurs sont regroupées dans ce type d'événement.

const exception = erreur.erreur || message d'erreur || error.originalError || Erreur;

cela évaluera à vrai/faux

const exception = erreur.erreur || message d'erreur || error.originalError || Erreur;

cela évaluera à vrai/faux

Peu probable, bien que possible. Tout dépend de l'"erreur" que vous envoyez dans le flux. Mais après tout, cela devrait inclure une sorte d'informations utiles.

Cette page vous a été utile?
0 / 5 - 0 notes