Sentry-javascript: تم تسجيل استثناء غير خطأ باستخدام المفاتيح: خطأ ، رؤوس ، رسالة ، اسم ، حسنًا

تم إنشاؤها على ٢٨ أكتوبر ٢٠١٩  ·  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 });

وأحصل على هذا الخطأ (تم التقاط استثناء غير خطأ بالمفاتيح: خطأ ، رؤوس ، رسالة ، اسم ، حسنًا) مرارًا وتكرارًا ، ولا يمكنني فهم الخطأ من الوصف وكيفية إعادة إنتاجه.

Needs Reproduction

التعليق الأكثر فائدة

نحن نستخدم حاليًا ما يلي لتجاهلها.

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

ال 48 كومينتر

هذا يعني أن الكائن الذي تقدمه ليس مثيلًا لـ Error الذي يحمل تتبع المكدس في تطبيق Angular.

يجب عليك (كما تشير الرسالة إلى) استخدام Sentry.captureException(error.error) أو Sentry.captureException(error.message) حسب احتياجاتك.

تضمين التغريدة

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

هل يمكن لأي شخص تقديم repro يمكنني استخدامه لتصحيح هذا؟ حاولت استخدام تطبيق base angular-cli ولا يمكنني إعادة إنتاج هذا السلوك. شكرا!

kamilogorek أعتقد أنه يمكنك بدء مشروع Angular 8 جديد ، وتقديم طلب http نحو نقطة نهاية بإرجاع 500 وليس اكتشاف الخطأ في خدمة http حتى ينتشر إلى Sentry.

يمكنني التناغم مع بعض المعلومات الإضافية ، هذا هو ErrorHandler الخاص بنا:

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

في تتبع Sentry لدينا ، نحصل دائمًا على أحداث مكررة لهذه الأحداث:

  • Object.a استثناء غير خطأ تم التقاطه باستخدام المفاتيح: ...
  • التقاط استثناء غير خطأ مع المفاتيح: ...

(يتم الإبلاغ عن الأحداث الأخرى على ما يرام كعنصر واحد في القائمة)

لقد جمعنا بضع مئات من أحداث "Non.Error" هذه ، ومن المثير للاهتمام أنها تشترك جميعًا فيما يلي:

  • اسم المتصفح: Samsung Internet 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;
 }
}

لقد حصلت على التكوين الأول لمدة عامين دون مشاكل ولكن منذ الترقية إلى 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's 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 لم يتم العثور عليه" ، والذي _على الأرجح _ جاء من مكالمة XHR غير صالحة. بعد ذلك ، يمكنك التحقق من تدفق فتات التنقل لترى أنه _ في الواقع _ كان هناك استدعاء XHR لعنوان url المحدد (والذي احتوى في هذه الحالة على خطأ إملائي) ، مسبوقًا بنقرة على عنصر DOM محدد ، مما أدى إلى تشغيله. باستخدام هذه المعلومات ، يجب أن تكون كافية في 99٪ من الحالات لإصلاح المشكلة.


لا يمكننا العمل إلا مع ما قدمناه من إطار العمل. خلاف ذلك ، سيتعين علينا إصلاح الإطار نفسه.

لا يمكننا العمل إلا مع ما قدمناه من إطار العمل. خلاف ذلك ، سيتعين علينا إصلاح الإطار نفسه.

هل هذه طريقتك في قول "ليست مشكلتنا"؟ قبل التبديل إلى الحارس (من بعض المنافسين) ، تم التقاط أخطاء XHR هذه على ما يرام واستخدموا نفس طريقة التثبيت مع معالج الخطأ الزاوي.

kamilogorek بصفتك

قبل التبديل إلى الحارس (من بعض المنافسين) ، تم التقاط أخطاء XHR هذه على ما يرام واستخدموا نفس طريقة التثبيت مع معالج الخطأ الزاوي.

szechyjs ، سيكون رائعًا إذا كان بإمكانك مشاركة الحل بدلاً من ذلك ، لأنه SDK مفتوح المصدر ويمكننا تكرار التحسينات إذا عرفنا ما نهدف إليه.

... يمكنك أيضًا فتح تذكرة مع الإطار. أنا متأكد من أنه سيحظى ببعض الاهتمام.

لقد فتحت للتو تذكرة بدعم الحارس وأشرت إلى هذه المشكلة.

أحد المارة هنا. بالنسبة لحالتي ، أريد الإبلاغ عن الرفض الذي تم التعامل معه في رد الفعل الأصلي وانتهى بي الأمر برؤية نفس الخطأ مثل 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

أتمنى أن يساعدك هذا!

في حالتي ، ساعدني قسم فتات الخبز من Sentry كثيرًا في تحديد السبب. حدث ذلك غالبًا عندما كان هناك حوالي 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.
https://sentry.io/share/issue/eaf13a2455e04150aaaab595d0d7bafe/

sblawrie ما المشكلة التي لديك بالضبط؟ بعض التفاصيل الإضافية ستكون مفيدة من فضلك.
cincauhangus يبدو أنه في مكان ما في الكود الخاص بك يظهر خطأ في مثيل الوعد نفسه (لاحظ مفاتيح abort, always, catch, done ).

شيء مثل:

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

لذا فإن errorHandler من Vue يحصل على كائن وعد كامل ، حيث يتوقع أن يكون مثيل Error .

kamilogorek شكرا للتوضيح. لقد أجريت بعض التغييرات وسأراقب ما إذا كانت لا تزال تمثل مشكلة.

باستخدام Angular 8 وكان له نفس استثناء Non-Error. عدل مثال كود '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 الخاص بي قبل الإرسال استنادًا إلى untilinvite 's beforeSend أعلاه. يهدف هذا التغيير إلى معالجة رسالة سجل ثانية من 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 الذي ورثته للتو. لا توجد فكرة عن كيفية حدوث ذلك ، ولكن يبدو أنه يحدث لمعظم الأخطاء التي يلقيها التطبيق ، وأنا أستخدم الإعداد السريع القياسي من المستندات.

على سبيل المثال https://sentry.io/share/issue/bfd4f674c10b4b4a8b6a291dde8e2a66/

لقد أصبت بهذا الخطأ نفسه ، على الرغم من أنه كان لمعالج الطلب السريع وليس الزاوي. في الأساس ، كنت أتصل بـ next باستخدام pojo بدلاً من كائن Error. أقوم ببعض الأشياء الممتعة في معالج الخطأ السريع الخاص بي لتحويله إلى شيء مثير للاهتمام ، ولكن نظرًا لأن البرامج الوسيطة لطلب الحارس تبدأ أولاً ، لم تحصل على هذا الخطأ المنظم.

في النهاية ، تم إنشاء وظيفة فائدة من شأنها تحويل كل ما تم تقديمه إلى شيء أكثر منطقية:

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

أعتقد أن هذا يزيل آثار المكدس ، ولكن في الحقيقة إذا كانت بوجو تم تمريرها إلى هذا ، فلا يوجد أي أثر للمكدس على أي حال.

في حالتنا ، قبل إصلاح ذلك ، كانت الغالبية العظمى من الأحداث التي تم الإبلاغ عنها تتعلق بهذه المشكلة بالذات ولأنها خادم ويب عقدة طويل التشغيل ، فإن فتات التنقل شبه عديمة الفائدة - ويتم تجميع جميع الأخطاء في هذا النوع من الأحداث.

استثناء ثابت = خطأ خطأ || error.message || error.originalError || خطأ؛

سيتم تقييم هذا إلى صواب / خطأ

استثناء ثابت = خطأ خطأ || error.message || error.originalError || خطأ؛

سيتم تقييم هذا إلى صواب / خطأ

من غير المحتمل ، بينما ممكن. كل ذلك يعود إلى "الخطأ" الذي ترسله إلى أسفل الدفق. لكن بعد كل شيء ، يجب أن يتضمن هذا نوعًا من المعلومات المفيدة.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات