Sentry-javascript: Исключение, не связанное с ошибкой, зафиксировано с помощью ключей: error, headers, message, name, ok

Созданный на 28 окт. 2019  ·  48Комментарии  ·  Источник: getsentry/sentry-javascript

Пакет + Версия

  • [x] @sentry/browser
  • [] @sentry/node
  • [] raven-js
  • [] raven-node _ (ворон вместо узла) _
  • [ ] Другие:
  • [x] @angular/core

Версия:

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

Описание

У меня есть начальная настройка для приложения Angular с глобальным ErrorInterceptor
вот как я его отправляю

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

и я снова и снова получаю эту ошибку (исключение без ошибок, зафиксированное ключами: error, headers, message, name, ok) и не могу понять, что не так в описании и как это воспроизвести.

Needs Reproduction

Самый полезный комментарий

В настоящее время мы используем следующее, чтобы игнорировать это.

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

Все 48 Комментарий

Это означает, что предоставленный вами объект не является экземпляром Error который содержит трассировку стека в приложении Angular.

Вы должны (как указано в сообщении) использовать Sentry.captureException(error.error) или Sentry.captureException(error.message) зависимости от ваших потребностей.

@kamilogorek ой хорошо) tnx

@kamilogorek все еще получает эту ошибку, даже с этим

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

+1, все еще получаю эту ошибку, как бы я ни выразился.

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",
  ...
}

Я решил сделать это

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

Спасибо за обходной путь @gchronos! Я надеюсь, что в ближайшее время будет возможное исправление.

Просто вмешиваюсь, чтобы сказать, что я тоже получаю эти ошибки. Я использую Angular 8, и, прочитав довольно много вопросов по этому поводу, я понимаю, что это может быть случай, когда я не обрабатываю ошибку должным образом в моем компоненте обработки ошибок. Я пробовал обходные пути, предложенные другими, определяющими исключение, перед передачей в captureException, но это не уменьшило количество ошибок. Было бы здорово, если бы кто-нибудь мог дать дополнительные сведения по этому поводу, или мне просто придется использовать решение GChronos (спасибо!).

+1

+1

Может ли кто-нибудь предоставить репродукцию, которую я мог бы использовать для отладки? Я пытался использовать базовое приложение angular-cli, и я не могу воспроизвести это поведение. Спасибо!

@kamilogorek Я считаю, что вы можете

Я могу сообщить вам дополнительную информацию, это наш ErrorHandler:

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

В нашем отслеживании Sentry мы всегда получаем повторяющиеся события для следующих:

  • Object.a Исключение без ошибок, захваченное ключами: ...
  • captureException Исключение без ошибок, захваченное ключами: ...

(О других событиях сообщается нормально, как один элемент в списке)

Мы собрали несколько сотен таких событий "Non.Error", и, что интересно, все они имеют следующее общее:

  • browser.name: Интернет Samsung 100%
  • браузер: Samsung Internet 9.4 100%

И ошибки в основном следующие:

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

Хорошо, я визуализировал инъекционный SentryErrorHandler и реализует ErrorHandler вместо расширений, и у меня больше нет подобных проблем.
Итак, я изменился с

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

У меня была первая конфигурация в течение 2 лет без проблем, но после обновления до Angular 8 у меня появилось несколько сторожевых исключений.

@ jonathan-payiq удалось ли вам выяснить, в чем причина этого? Или вы просто игнорируете все эти исключения, не связанные с ошибками?

В настоящее время мы их игнорируем.
Мы выяснили из хлебных крошек, что это происходит, когда веб-просмотр / браузер находится в фоновом режиме (не виден), поэтому исправление для нас состоит в том, чтобы предотвратить получение, пока страница не отображается. Очевидно, браузеры Samsung плохо справляются с обновлением сети в фоновом режиме.

@ jonathan-payiq, как именно вы их игнорируете? Заранее спасибо.

В настоящее время мы используем следующее, чтобы игнорировать это.

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

@kamilogorek удалось воспроизвести проблему?

Закрытие проблемы, так как кажется, что исходная проблема была частично решена или есть рабочее решение. Я бы предпочел, чтобы кто-то создал новую проблему со свежим описанием, если проблема все еще существует.
Пожалуйста, не стесняйтесь пинговать меня, если это все еще актуально, и я с радостью открою его снова и поработаю над ним.
Ваше здоровье!

Это не решено. Я просто попытался интегрировать Sentry с Angular 8 и обнаружил эту проблему.

Я не понимаю, как Sentry может требовать настройки из коробки, это полностью неверно.

Я не понимаю, как Sentry может требовать настройки из коробки, это полностью неверно.

@Rush представляет воспроизводимый случай, в котором вы объясняете и показываете, что не так, а затем мы можем проверить ваше требование.

@kamilogorek По правде говоря, я не работаю с Angular уже более 6 месяцев, здесь достаточно отчетов, чтобы подтвердить это, таким образом, IMO нет необходимости в дальнейших случаях воспроизведения, вы можете найти это самостоятельно довольно легко. Я сам знаю, что это не так, поскольку у нас есть такая же проблема в нашем проекте с использованием Angular v8, а теперь и v9 (без исходных карт).

Совершенно верно, и кроме того, я плачу за Sentry, чтобы он работал за меня. Это не проект с открытым исходным кодом, в котором я рассчитываю запачкать руки.

Мне нравится Sentry, но я могу поискать альтернативы ...

В качестве примера я использовал приложение https://github.com/gothinkster/angular-realworld-example-app , чтобы каждый мог воспроизвести то же самое.

Клонированное приложение Barebone, следовало документации Sentry по Angular и загружало исходные карты. Вот результаты.


Пример 1: нарушенная логика

Что Angular дает вам в обработчике ошибок + какое событие мы фиксируем:

Screenshot 2020-04-16 at 12 01 13

Как это выглядит в пользовательском интерфейсе:

Screenshot 2020-04-16 at 12 07 02

Примечание: все на месте, вы можете легко указать на правильную строку кода, которая была сломана, сообщение об ошибке и тип ошибки верны, потому что Angular дает вам целый объект Error для работы.


Пример 2: прерванный сервисный звонок

Что Angular дает вам в обработчике ошибок + какое событие мы фиксируем:

Screenshot 2020-04-16 at 12 00 49

Как это выглядит в пользовательском интерфейсе:

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

Примечание. Невозможно определить, какой тип ошибки был выдан, потому что Angular не предоставляет вам эту информацию. Однако вы можете взглянуть на сериализованные данные, чтобы сказать, что произошла ошибка «404 Not Found», которая, скорее всего, возникла из-за недопустимого вызова XHR. Затем вы можете исследовать поток хлебных крошек, чтобы увидеть, что _на самом деле_ был вызов XHR для данного URL-адреса (который в данном случае содержал опечатку), которому предшествовал щелчок по точному элементу DOM, который вызвал его. Этой информации должно хватить в 99% случаев, чтобы решить проблему.


Мы можем работать только с тем, что нам дает фреймворк. В противном случае нам пришлось бы исправлять сам фреймворк.

Мы можем работать только с тем, что нам дает фреймворк. В противном случае нам пришлось бы исправлять сам фреймворк.

Это ваш способ сказать «не наша проблема»? Перед переключением на часового (от некоторых конкурентов) эти ошибки XHR были замечены отлично, и они использовали тот же метод установки с обработчиком угловых ошибок.

@kamilogorek, как поставщик, вы также можете открыть

Перед переключением на часового (от некоторых конкурентов) эти ошибки XHR были замечены отлично, и они использовали тот же метод установки с обработчиком угловых ошибок.

@szechyjs, тогда было бы здорово, если бы вы могли поделиться решением вместо этого, так как это SDK с открытым исходным кодом, и мы можем повторять улучшения, если знаем, к чему мы стремимся.

... вы также можете открыть тикет с помощью фреймворка. Я уверен, что это привлечет внимание.

Я только что открыл тикет с дежурной поддержкой и упомянул об этой проблеме.

Прохожий здесь. В моем случае я хочу сообщить об обработанных отказах в react native, и в итоге я увидел ту же ошибку, что и OP. Поскольку the object you provide is not an instance of Error , я использовал следующее.

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
}

Тогда я звоню

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

и я вижу

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

Надеюсь это поможет!

В моем случае раздел Breadcrumbs от Sentry очень помог мне определить причину. В основном это происходило, когда на некоторых внешних API было 404.

Скоро обновятся документы и внесены необходимые изменения в JS SDK:

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

Он должен быть выпущен на этой неделе! :)

Простое исправление для этого (поскольку это происходит только с ошибками, перехваченными HTTP):

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

Только что выпущены новые документы и 5.16.0 - https://docs.sentry.io/platforms/javascript/angular/
Я постарался сделать его как можно более подробным и подробным, поэтому он «может выглядеть» как большой объем кода.

@kamilogorek У меня тоже проблема с приложением Vue. Есть ли там исправление?

То же самое. исключение выдается в обработчике ошибок интеграции vuejs sentry.
https://sentry.io/share/issue/eaf13a2455e04150aaaab595d0d7bafe/

@sblawrie, какая именно у вас проблема? Некоторые подробности были бы полезны, пожалуйста.
@cincauhangus похоже, что где-то в вашем коде вы abort, always, catch, done keys).

Что-то вроде:

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

Итак, errorHandler Vue получает весь объект обещания, где он ожидает быть экземпляром Error .

@kamilogorek спасибо за разъяснения. Я внес некоторые изменения и буду следить за тем, сохраняется ли проблема.

Используя Angular 8 и имел ту же проблему, исключение без ошибок. Изменил пример кода extractError следующим образом:

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

Изменен мой Sentry.init beforeSend на основе приведенного выше примера beforeSend @untilinvite. Это изменение предназначено для обработки второго сообщения журнала из https://github.com/getsentry/sentry-javascript/issues/2169, которое также разрешается как сообщение об ошибке.

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

Мы внесли изменения, которые были добавлены в документы с выпуском 5.16.0 и мы по-прежнему получаем ошибки Non-Error exception captured with keys: error, headers, message, name, ok . Я надеюсь, что пакет @ sentry / angular исправит эти проблемы?

Угловой: v9.1
Сторожевой: v5.20

@szechyjs вы также читали вторую часть о http-перехватчиках? Обычно это основная проблема, из-за которой ошибка не может быть обнаружена правильно - https://docs.sentry.io/platforms/javascript/angular/

@szechyjs вы также читали вторую часть о http-перехватчиках? Обычно это основная проблема, из-за которой ошибка не может быть обнаружена правильно - https://docs.sentry.io/platforms/javascript/angular/

Мы не используем перехватчики.

Привет, я потратил некоторое время на эту проблему и обнаружил, что error.error.message на ошибках типа HttpErrorResponse не обязательно содержит какую-либо информацию. Если мы посмотрим на конструктор, то увидим, что Angular устанавливает опору сообщения для корневого объекта, а не для ErrorEvent .

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

Изменив эту строку https://github.com/getsentry/sentry-javascript/blob/8eb72865dcd62ff719441105c7eda28007a07e9d/packages/angular/src/errorhandler.ts#L112
к

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

обработчик ошибок перешел к return error.message; и выдал ожидаемую ошибку.

Отличный улов @jakkn , спасибо! Обновлен обработчик в ПР https://github.com/getsentry/sentry-javascript/pull/2903

У меня проблема с приложением Express, которое я только что унаследовал. Не знаю, как это могло произойти, но похоже, что это происходит для большинства ошибок, которые выдает приложение, и я использую стандартную настройку Express из документации.

например, https://sentry.io/share/issue/bfd4f674c10b4b4a8b6a291dde8e2a66/

Я столкнулся с той же ошибкой, хотя она была для обработчика экспресс-запросов, а не для angular. В основном я вызывал next с pojo вместо объекта Error. Я делаю несколько забавных вещей в моем собственном обработчике экспресс-ошибок, чтобы превратить его во что-то интересное, но поскольку промежуточное ПО запроса sentryio идет первым, оно не получало эту упорядоченную ошибку.

В конце концов, создали служебную функцию, которая превращала бы предоставленное в нечто более разумное:

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

Я думаю, это объединяет трассировки стека, но на самом деле, если бы в это было передано pojo, трассировки стека все равно не было бы.

В нашем случае, до того, как это было исправлено, подавляющее большинство событий, о которых сообщалось, относились к этой конкретной проблеме, и поскольку это долго работающий веб-сервер узла, хлебные крошки почти бесполезны - и все ошибки объединяются в один этот тип события.

const exception = error.error || error.message || error.originalError || ошибка;

это будет оцениваться как истина / ложь

const exception = error.error || error.message || error.originalError || ошибка;

это будет оцениваться как истина / ложь

Вряд ли, но возможно. Все сводится к тому, какую «ошибку» вы отправите в поток. Но в конце концов, это должно включать какую-то полезную информацию.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги