Sentry-javascript: Nicht-Fehler-Ausnahme mit Schlüsseln erfasst: Fehler, Header, Nachricht, Name, ok

Erstellt am 28. Okt. 2019  ·  48Kommentare  ·  Quelle: getsentry/sentry-javascript

Paket + Version

  • [x] @sentry/browser
  • [ ] @sentry/node
  • [ ] raven-js
  • [ ] raven-node _(Rabe für Knoten)_
  • [ ] Sonstiges:
  • [x] @angular/core

Ausführung:

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

Beschreibung

Ich habe eine Ersteinrichtung für die Angular-App mit globalem ErrorInterceptor
hier wie ich es sende

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

und ich erhalte diesen Fehler (Non-Error-Ausnahme mit Schlüsseln erfasst: Fehler, Header, Nachricht, Name, ok) immer wieder und kann nicht verstehen, was an der Beschreibung falsch ist und wie man es reproduziert.

Needs Reproduction

Hilfreichster Kommentar

Wir verwenden derzeit Folgendes, um es zu ignorieren.

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

Alle 48 Kommentare

Dies bedeutet, dass das von Ihnen bereitgestellte Objekt keine Instanz von Error , die den Stacktrace in der Angular-App enthält.

Sie sollten (wie die Nachricht darauf hinweist) je nach Bedarf Sentry.captureException(error.error) oder Sentry.captureException(error.message) .

@kamilogorek oh ok) tnx

@kamilogorek bekommt immer noch diesen Fehler, auch wenn das

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

+1, erhalte immer noch diesen Fehler, egal wie ich ihn ausdrücke.

sentry.error-handler.ts

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

Paket.json

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

Ich habe mich dazu entschieden

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;
            }
        });

Vielen Dank für die Problemumgehung @gchronos! Ich hoffe, dass es bald eine mögliche Lösung geben wird.

Ich melde mich nur, um zu sagen, dass ich auch diese Fehler bekomme. Ich verwende Angular 8 und nachdem ich einige Probleme dazu gelesen habe, stelle ich fest, dass ich den Fehler in meiner Fehlerbehandlungskomponente möglicherweise nicht richtig behandle. Ich habe die von anderen vorgeschlagenen Problemumgehungen ausprobiert, die die Ausnahme definieren, bevor sie an captureException übergeben wird, aber dies hat die Fehler nicht reduziert. Es wäre toll, wenn jemand dazu etwas beitragen könnte, oder ich muss einfach die (Danke!) Lösung von GChronos verwenden.

+1

+1

Kann jemand ein Repro bereitstellen, mit dem ich dies debuggen könnte? Ich habe versucht, die Basis-Angular-Cli-App zu verwenden, und kann dieses Verhalten nicht reproduzieren. Vielen Dank!

@kamilogorek Ich glaube, Sie können ein neues Angular 8-Projekt zurückgibt , und den Fehler im http-Dienst nicht abfangen, damit er an Sentry weitergegeben wird.

Ich kann mich mit ein paar weiteren Informationen einklinken, dies ist unser ErrorHandler:

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

In unserem Sentry-Tracking erhalten wir immer doppelte Ereignisse für diese:

  • Object.a Non-Error-Ausnahme mit Schlüsseln erfasst: ...
  • captureException Ausnahme ohne Fehler, die mit Schlüsseln erfasst wurde: ...

(Andere Ereignisse werden als ein Element in der Liste in Ordnung gemeldet)

Wir haben ein paar Hundert dieser "Non.Error"-Ereignisse gesammelt, und interessanterweise haben sie alle Folgendes gemeinsam:

  • browser.name: Samsung Internet 100%
  • Browser: Samsung Internet 9,4 100%

Und die Fehler sind meistens die folgenden:

{
  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, ich habe den SentryErrorHandler injizierbar gerendert und den ErrorHandler implementiert, anstatt ihn zu erweitern, und für mich gibt es keine derartigen Probleme mehr.
Also wechselte ich von

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;
 }
}

zu

@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;
 }
}

Ich hatte die erste Konfiguration seit 2 Jahren ohne Probleme, aber seit dem Upgrade auf Angular 8 habe ich mehrere Wachausnahmen.

@jonathan-payiq konntest du herausfinden, was das verursacht? Oder ignorieren Sie jetzt einfach alle diese Nicht-Fehler-Ausnahmen?

Wir ignorieren sie derzeit.
Wir haben aus den Breadcrumbs herausgefunden, dass dies passiert, wenn sich die Webansicht/der Browser im Hintergrund befindet (nicht sichtbar). Daher besteht die Lösung für uns darin, das Abrufen zu verhindern, während die Seite nicht sichtbar ist. Anscheinend verarbeiten Samsung-Browser die Netzwerkaktualisierung im Hintergrund schlecht.

@jonathan-payiq wie genau ignorierst du sie? Danke im Voraus.

Wir verwenden derzeit Folgendes, um es zu ignorieren.

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

@kamilogorek konntest du das Problem reproduzieren?

Schließen des Problems, da das ursprüngliche Problem anscheinend teilweise behoben wurde oder es eine funktionierende Lösung gibt. Ich würde es vorziehen, wenn jemand ein neues Problem mit einer neuen Beschreibung erstellt, wenn es immer noch ein Problem ist.
Bitte zögern Sie nicht, mich anzupingen, wenn es noch relevant ist, und ich werde es gerne wieder öffnen und daran arbeiten.
Danke schön!

Es wurde nicht gelöst. Ich habe gerade versucht, Sentry in Angular 8 zu integrieren, und habe dieses Problem gefunden.

Ich verstehe nicht, wie Sentry das Out-of-the-Box-Setup beanspruchen kann, es ist völlig falsch.

Ich verstehe nicht, wie Sentry das Out-of-the-Box-Setup beanspruchen kann, es ist völlig falsch.

@Rush liefert einen reproduzierbaren Fall, in dem Sie erklären und zeigen, was nicht stimmt, und dann können wir Ihren Anspruch überprüfen.

@kamilogorek Um ehrlich zu sein, dass Angular seit über 6 Monaten nicht mehr funktioniert, gibt es hier genug Berichte, um dies zu bestätigen, daher sind IMO keine weiteren Repro-Fälle erforderlich, Sie können es ziemlich einfach selbst herausfinden. Ich weiß selbst, dass dies nicht der Fall ist, da wir in unserem Projekt mit Angular v8 und jetzt v9 (keine Sourcemaps) das gleiche Problem haben.

Genau, und außerdem bezahle ich dafür, dass Sentry die Arbeit für mich erledigt. Es ist kein Open-Source-Projekt, bei dem ich erwarte, mir die Hände schmutzig zu machen.

Ich mag Sentry, aber ich könnte nach Alternativen suchen...

Ich habe als Beispiel eine https://github.com/gothinkster/angular-realworld-example-app-App verwendet, nur damit jeder die gleiche Reproduktion auch machen kann.

Barebone geklonte App, folgte den Angular-Dokumenten von Sentry und lud die Quellkarten hoch. Hier sind die Ergebnisse.


Beispiel 1: Gebrochene Logik

Was Angular Ihnen in einem Fehlerhandler bietet + welches Ereignis wir erfassen:

Screenshot 2020-04-16 at 12 01 13

So sieht es in der Benutzeroberfläche aus:

Screenshot 2020-04-16 at 12 07 02

Hinweis: Alles ist vorhanden, Sie können leicht auf die richtige Codezeile zeigen, die beschädigt wurde, Fehlermeldung und Fehlertyp sind korrekt, da Angular Ihnen ein ganzes Error Objekt zur Verfügung stellt, mit dem Sie arbeiten können.


Beispiel 2: Unterbrochener Serviceruf

Was Angular Ihnen in einem Fehlerhandler bietet + welches Ereignis wir erfassen:

Screenshot 2020-04-16 at 12 00 49

So sieht es in der Benutzeroberfläche aus:

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

Hinweis: Es gibt keine Möglichkeit zu sagen, welche Art von Fehler ausgegeben wurde, da Angular Ihnen diese Informationen nicht liefert. Sie können jedoch einen Blick auf die serialisierten Daten werfen, um zu erkennen, dass der Fehler "404 Not Found" aufgetreten ist, der _höchstwahrscheinlich_ von einem ungültigen XHR-Aufruf stammt. Dann können Sie den Breadcrumbs-Flow untersuchen, um zu sehen, dass es _tatsächlich_ einen XHR-Aufruf an die angegebene URL gab (der in diesem Fall einen Tippfehler enthielt), gefolgt von einem Klick auf ein genaues DOM-Element, das ihn ausgelöst hat. Mit diesen Informationen sollte es in 99% der Fälle ausreichen, das Problem zu beheben.


Wir können nur mit dem arbeiten, was uns der Rahmen gegeben hat. Andernfalls müssten wir das Framework selbst mit einem Monkey-Patch versehen.

Wir können nur mit dem arbeiten, was uns der Rahmen gegeben hat. Andernfalls müssten wir das Framework selbst mit einem Monkey-Patch versehen.

Ist das Ihre Art "nicht unser Problem" zu sagen? Vor dem Wechsel zu Sentry (von einigen Konkurrenten) wurden diese XHR-Fehler problemlos erfasst und dieselbe Installationsmethode mit einem Winkelfehlerhandler verwendet.

@kamilogorek als Vendor könntest du auch ein Ticket mit dem Framework eröffnen. Ich bin sicher, es würde einige Aufmerksamkeit erregen.

Vor dem Wechsel zu Sentry (von einigen Konkurrenten) wurden diese XHR-Fehler problemlos erfasst und dieselbe Installationsmethode mit einem Winkelfehlerhandler verwendet.

@szechyjs, dann wäre es großartig, wenn Sie stattdessen die Lösung teilen könnten, da es sich um ein Open-Source-SDK handelt und wir Verbesserungen durchlaufen können, wenn wir wissen, was wir anstreben.

... könntest du auch ein Ticket mit dem Framework eröffnen. Ich bin sicher, es würde einige Aufmerksamkeit erregen.

Ich habe gerade ein Ticket beim Sentry-Support eröffnet und auf dieses Problem verwiesen.

Ein Passant hier. Für meinen Fall möchte ich behandelte Ablehnungen in React Native melden und habe am Ende den gleichen Fehler wie beim OP gesehen. Seit the object you provide is not an instance of Error ich mich mit dem Folgenden herumgesprochen.

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
}

Dann rufe ich an

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

und ich sehe

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

Hoffe das hilft!

In meinem Fall hat mir die Breadcrumbs-Sektion von Sentry sehr geholfen, die Ursache zu lokalisieren. Es passierte meistens, wenn es einige 404 auf einigen externen APIs gab.

Docs-Update und notwendige JS SDK-Änderungen kommen:

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

Es soll diese Woche erscheinen! :)

Einfache Lösung dafür (da dies nur bei HTTP-abgefangenen Fehlern passiert):

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;
 }

Neue Dokumente und 5.16.0 gerade veröffentlicht - https://docs.sentry.io/platforms/javascript/angular/
Ich habe versucht, es so explizit und detailliert wie möglich zu machen, und deshalb "kann es wie viel Code aussehen".

@kamilogorek Ich habe dieses Problem auch bei einer Vue-App. Gibt es da eine Lösung?

Hier gilt das gleiche. Die Ausnahme wird im Fehlerhandler der vuejs Sentry-Integration ausgelöst.
https://sentry.io/share/issue/eaf13a2455e04150aaaab595d0d7bafe/

@sblawrie welches Problem hast du genau? Ein paar weitere Details wären bitte hilfreich.
@cincauhangus es sieht so aus, als ob Sie irgendwo in Ihrem Code einen Fehler mit der Promise-Instanz selbst abort, always, catch, done ).

Etwas wie:

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

Das errorHandler von Vue bekommt also ein ganzes Promise-Objekt, wo es eine Error Instanz erwartet.

@kamilogorek danke für die Klarstellung. Ich habe einige Änderungen vorgenommen und werde beobachten, ob es immer noch ein Problem gibt.

Verwenden von Angular 8 und hatte das gleiche Problem Non-Error-Ausnahme. Der Beispielcode 'extractError' wurde wie folgt geändert:

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;
  }

Meine Sentry.init beforeSend wurde basierend auf dem obigen beforeSend-Beispiel von https://github.com/getsentry/sentry-javascript/issues/2169 zu behandeln, die ebenfalls als Nicht-Fehler behoben wird.

 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;
        }
      });

Wir haben die Änderungen vorgenommen, die mit der Version 5.16.0 an den Dokumenten hinzugefügt wurden, und wir erhalten immer noch Non-Error exception captured with keys: error, headers, message, name, ok Fehler. Ich hoffe, dass das @sentry/angular- Paket diese Probleme behebt?

Winkel: v9.1
Wache: v5.20

@szechyjs hast du auch den zweiten Teil über http-Abfangjäger gelesen? Dies ist normalerweise das Hauptproblem, bei dem der Fehler nicht richtig erkannt wird - https://docs.sentry.io/platforms/javascript/angular/

@szechyjs hast du auch den zweiten Teil über http-Abfangjäger gelesen? Dies ist normalerweise das Hauptproblem, bei dem der Fehler nicht richtig erkannt wird - https://docs.sentry.io/platforms/javascript/angular/

Wir verwenden keine Abfangjäger.

Hallo, ich habe einige Zeit mit diesem Problem verbracht und festgestellt, dass error.error.message zu Fehlern vom Typ HttpErrorResponse nicht unbedingt Informationen enthält. Wenn wir uns den Konstruktor ansehen, sehen wir, dass Angular die Message-Prop auf das Root-Objekt setzt und nicht auf ErrorEvent .

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

Durch Ändern dieser Zeile https://github.com/getsentry/sentry-javascript/blob/8eb72865dcd62ff719441105c7eda28007a07e9d/packages/angular/src/errorhandler.ts#L112
zu

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

der Fehlerhandler ging zu return error.message; und gab den erwarteten Fehler aus.

Toller Fang @jakkn , danke! Aktualisierter Handler in der PR https://github.com/getsentry/sentry-javascript/pull/2903

Ich habe dieses Problem bei einer Express-App, die ich gerade geerbt habe. Keine Ahnung, wie das passieren könnte, aber es scheint bei den meisten Fehlern zu passieren, die die App auslöst, und ich verwende das Standard-Express-Setup aus den Dokumenten.

zB https://sentry.io/share/issue/bfd4f674c10b4b4a8b6a291dde8e2a66/

Ich bin auf denselben Fehler gestoßen, obwohl er für den Express-Request-Handler und nicht eckig war. Im Grunde habe ich next mit einem Pojo anstelle eines Error-Objekts aufgerufen. Ich mache einige lustige Dinge in meinem eigenen Express-Error-Handler, um daraus etwas Interessantes zu machen, aber da die Sentryio-Anforderungs-Middleware zuerst geht, wurde dieser gemarshallte Fehler nicht angezeigt.

Am Ende erstellte ich eine Nutzenfunktion, die alles, was bereitgestellt wurde, in etwas Vernünftigeres verwandelte:

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))
  }
}

Das muxt die Stack-Traces zusammen, denke ich, aber wirklich, wenn es ein Pojo wäre, der hier hineingereicht wurde, gab es sowieso keinen Stack-Trace.

In unserem Fall, bevor dies behoben wurde, betraf die überwiegende Mehrheit der gemeldeten Ereignisse dieses spezielle Problem, und da es sich um einen Knoten-Webserver mit langer Laufzeit handelt, sind Breadcrumbs nahezu nutzlos – und alle Fehler werden in diesem einen Ereignistyp zusammengefasst.

const Exception = error.error || Fehlermeldung || error.originalError || Error;

dies wird zu wahr/falsch ausgewertet

const Exception = error.error || Fehlermeldung || error.originalError || Error;

dies wird zu wahr/falsch ausgewertet

Unwahrscheinlich, aber möglich. Es kommt alles darauf an, welchen "Fehler" Sie den Stream senden. Aber schließlich sollte dies einige nützliche Informationen enthalten.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen