Sentry-javascript: وظائف Google Cloud - إعداد عميل Sentry

تم إنشاؤها على ١٨ يونيو ٢٠١٩  ·  35تعليقات  ·  مصدر: getsentry/sentry-javascript

مرحبا فريق الحب سينتري ، شكرا لك!

أنا أستخدم Google Cloud Functions w / Typescript لمشروع جديد وأحب استخدام تطبيق Sentry لالتقاط الأخطاء.

من هذا التعليق ، يبدو أن وظائف السحابة لا تسمح للجهات الخارجية بالتعامل مع معالج الأخطاء العام في Node.

هل هذا لا يزال دقيقا؟ هل يمكنني الحصول على مكتبة Sentry JS تعمل مع وظائف Google Cloud؟

ذات صلة: https://forum.sentry.io/t/google-cloud-functions-client-setup/1970

ال 35 كومينتر

مرحبًا ، شكرًا! :)

هل هذا لا يزال دقيقا؟ هل يمكنني الحصول على مكتبة Sentry JS تعمل مع وظائف Google Cloud؟

وفقًا لـ https://github.com/googleapis/nodejs-error-reporting#catching -and-report-application-wide-uncaught-errors و https://github.com/googleapis/nodejs-error-reporting#unhandled - الرفض من الممكن القيام بذلك الآن ، ومع ذلك ، لم أختبره بنفسي بعد.

يمكنني القيام بذلك في غضون أيام قليلة ، ولكن يمكنك إعطائها إذا كان لديك بعض وقت الفراغ :)

kamilogorek شكرا. مثير للانتباه!

لست متأكدًا من كيفية تفاعل ذلك مع وظائف Google Cloud. أنا الآن في منتصف التخطيط الفني ، لذا لن أقوم باختبار ذلك قريبًا. لكنني سأخبرك إذا / متى أفعل. :)

في الوقت الحالي ، نلّف جميع وظائف السحابة الخاصة بنا في:

try () {
...
} catch (e) {
  Sentry.captureException(e);
}

لكننا لا نرى شفرة المصدر أو سياق آخر في Sentry.

هل هناك طريقة أفضل للقيام بهذا التكامل؟

vpontis اختبرته للتو بنفسي ويبدو أن دقة السياق تعمل بشكل جيد. ما هي وظيفتك / التكوين؟

image

مرحبا kamilogorek شكرا للمساعدة!

لقد قمت بتكرار ما تحصل عليه مع Hello World ، وهذا رائع.

لكن لا توجد متغيرات سياق. هل لا يمكنك رؤية قيمة المتغيرات في النطاق؟ أم أن هذه فقط ميزة Python؟

image


أيضًا ، يبدو أن الأخطاء الأكثر تعقيدًا التي أواجهها هي عندما أقوم بالكتابة / القراءة لقاعدة البيانات وهناك بعض الأخطاء في البث / الحدث.

على سبيل المثال ، في لقطة الشاشة أدناه ، لا يمكنني حتى معرفة الوظيفة التي تم استدعاؤها منها.

ما هي توصيتك؟ هل هناك طريقة للحصول على StackTrace أطول يتضمن الاستدعاء من معالج الوظيفة الأصلي؟ أو أحتاج فقط لإضافة المزيد من فتات الخبز؟

image


أيضًا ، أي فكرة عما يحدث مع شفرة المصدر هذه لم يتم العثور على أخطاء؟

image

لكن لا توجد متغيرات سياق. هل لا يمكنك رؤية قيمة المتغيرات في النطاق؟ أم أن هذه فقط ميزة Python؟

إنها ميزة Python فقط. JS لا توفر آلية لتطبيق هذه الميزة للأسف.

على سبيل المثال ، في لقطة الشاشة أدناه ، لا يمكنني حتى معرفة الوظيفة التي تم استدعاؤها منها. ما هي توصيتك؟ هل هناك طريقة للحصول على StackTrace أطول يتضمن الاستدعاء من معالج الوظيفة الأصلي؟ أو أحتاج فقط لإضافة المزيد من فتات الخبز؟

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

ونظرًا لأن المثيلات بدون خادم طويلة الأمد ، يمكنك استدعاء:

Sentry.configureScope(scope => scope.clear())
// or
Sentry.configureScope(scope => scope.clearBreadcrumbs())

للحصول على سجل نظيف.

أيضًا ، أي فكرة عما يحدث مع شفرة المصدر هذه لم يتم العثور على أخطاء؟

قم بإيقاف تشغيل Enable JavaScript source fetching في إعدادات مشاريعك ، على سبيل المثال. https://sentry.io/settings/kamil-ogorek/projects/testing-project/
إنه تطبيق عقدة بدون خادم ، لذلك لا فائدة من القيام بذلك.

إنها ميزة Python فقط. JS لا توفر آلية لتطبيق هذه الميزة للأسف.

اللعنة. أحببت هذا بخصوص بايثون!

مفيد للغاية ، شكرا لك كامل. سأقوم بتنفيذ هذه التغييرات وسأعود إليك هنا إذا كان لدي المزيد من الأسئلة. أنا متأكد من أن هذه المشكلة ستكون مفيدة للأشخاص الآخرين الذين يستخدمون Sentry على JS serverless.

مدهش! سأغلق المشكلة من أجل الفرز ، ولكن لا تتردد في الاتصال بي في أي وقت وسأعيد فتحه إذا لزم الأمر! :)

kamilogorek لقد أضفت Breadcrumbs على Google Cloud Functions وأعتقد أنني أرى فتات تنقل من مكالمات وظيفية مختلفة.

هل هذا منطقي؟ كيف يمكنني تقييد مسارات التنقل لتكون من طلب HTTP واحد فقط مع وظائف Google Cloud؟

من المنطقي ، ومع ذلك ، هل يمكنك أن تريني مثالاً على الكود الذي تستخدمه في وظائف السحابة الخاصة بك؟ بهذه الطريقة سيكون من الأسهل فهم كل شيء.

kamilogorek لقد كنت مفيدًا حقًا!

لقد تحولنا إلى استخدام Koa مع Docker / Node. لذلك لدينا تكامل Koa تم إعداده على النحو التالي: https://docs.sentry.io/platforms/node/koa/

إنها تعمل بشكل رائع باستثناء فتات الخبز ، ونرى فتات الخبز لجميع الطلبات على الخادم ، وليس فقط فتات الخبز المرتبطة بالطلب الحالي.

هل هنالك طريقة لإصلاحه؟

هل هنالك طريقة لإصلاحه؟

يوجد ، لكني أحتاج إلى اختباره قبل تقديم الرمز هنا :)
سأحاول الرد عليك في غضون يوم أو يومين.

kamilogorek أنت أسطورة مطلقة يا صديقي

vpontis لذا فإن الشيء الوحيد الذي تحتاج إليه حقًا هو إنشاء مثيل مجال في أحد البرامج الوسيطة. بمجرد وجوده هناك ، سيكتشفه SDK ويستخدم لفصل السياقات. يمكنك أيضًا نقل parseRequest إلى هناك أيضًا. (مثال على أساس https://github.com/koajs/examples/blob/master/errors/app.js)

const Sentry = require("@sentry/node");
const Koa = require("koa");
const app = (module.exports = new Koa());
const domain = require("domain");

Sentry.init({
  // ...
});

app.use(async function(ctx, next) {
  const local = domain.create();
  local.add(ctx);
  local.on("error", next);
  local.run(() => {
    Sentry.configureScope(scope => {
      scope.addEventProcessor(event => Sentry.Handlers.parseRequest(event, ctx.request));
    });
    next();
  });
});

app.use(async function(ctx, next) {
  try {
    await next();
  } catch (err) {
    // some errors will have .status
    // however this is not a guarantee
    ctx.status = err.status || 500;
    ctx.type = "html";
    ctx.body = "<p>Something <em>exploded</em>, please contact Maru.</p>";

    // since we handled this manually we'll
    // want to delegate to the regular app
    // level error handling as well so that
    // centralized still functions correctly.
    ctx.app.emit("error", err, ctx);
  }
});

// response

app.use(async function() {
  throw new Error("boom boom");
});

// error handler

app.on("error", function(err) {
  Sentry.captureException(err);
});

if (!module.parent) app.listen(3000);

يقبل parseRequest بعض الخيارات التي قد ترغب في استخدامها لاختيار بيانات الطلب التي تريد استخراجها - https://github.com/getsentry/sentry-javascript/blob/f71c17426c7053d46fe3e2e35e77c564749d0eb7/packages/node/src/handlers .ts # L177

@ kamilogorek شكرا!

بعض الأفكار:

  1. يمكنك ربط العقدة الفعلية req و res بالمجال المخزن على ctx.req و `ctx.res

  2. يمكنك تمرير العقدة req إلى parseRequest

  3. لماذا تتصل بـ ctx.app.emit("error", err, ctx); بعد اكتشاف الخطأ يدويًا؟

    // since we handled this manually we'll
    // want to delegate to the regular app
    // level error handling as well so that
    // centralized still functions correctly.
    ctx.app.emit("error", err, ctx);

ألن تكون هذه هي الحالة التي تريد فيها فقط إرجاع الاستجابة وعدم تمرير الخطأ إلى معالج الخطأ المركزي؟

  1. في Koa next هو async . هل سيتسبب ذلك في أي مشكلات داخل Node domain.run(...)

خبرني إذا كان لذلك أي معنى. هذا بالفعل مفيد للغاية. سأختبرها لاحقًا هذا الأسبوع.

آه re 3 أرى أنك تقوم فقط بنسخ ذلك من المثال لذلك سأتجاهل هذا الجزء :). اختباره الآن ...

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

يبدو أيضًا أن المجالات لا تعمل حتى في Node 12 (أخطط للترقية قريبًا للحصول على دعم تتبع المكدس غير المتزامن).

في كلتا الحالتين ، لا أفهم كيف يعمل هذا الرمز مع المجال لذلك أنا متردد في وضعه في جزء مهم من التطبيق.

هل هناك طريقة أخرى لوضع "المحور" الحالي على ctx والاتصال بـ addBreadcrumb بطريقة ما مرتبطة بالطلب الحالي؟ لست متأكدًا تمامًا من كيفية عمل المحاور ومعالجة الرسائل في Sentry ...

لقد حصلت على هذا الكود يعمل (هاتان وظيفتان وسيطتان متتاليتان) لكنني لا أشعر بالراحة مع _لماذا_ يعمل ...

export const setSentryDomain = async (ctx, next) => {
  await new Promise(async (resolve, reject) => {
    const local = domain.create();

    local.add(ctx.req);
    local.add(ctx.res);

    local.run(async () => {
      Sentry.configureScope((scope) => {
        scope.addEventProcessor((event) => Sentry.Handlers.parseRequest(event, ctx.req));
      });

      await next();
      resolve();
    });
  });
};

export const catchErrors = async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    console.log('got error');
    ctx.app.emit('error', err, ctx);
  }
};

أنا أسميها ليلة. لم أحصل على حل عملي كنت سعيدًا به.

أدركت أيضًا أن معظم فتات التنقل الخاصة بي تأتي من عبارات console.log والتي يتم التقاطها تلقائيًا بواسطة Sentry. لذلك أحتاج إلى معرفة كيفية جعل فتات الخبز هذه في النطاق الصحيح ...

لقد طعنت حول الكود ويبدو أن المجالات تحل هذه المشكلة. لكن المجالات لا تبدو موثوقة بوظائف غير متزامنة وستختفي قريبًا ...

هل هناك طريقة أخرى لوضع "المحور" الحالي على ctx واستدعاء addBreadcrumb بطريقة ما مرتبطة بالطلب الحالي؟

يمكنك تعيين لوحة الوصل مباشرة إلى ctx ، لكنها لن تعمل مع فتات الخبز التي تم التقاطها تلقائيًا ، نظرًا لأن تلك تتطلب Sentry.getCurrentHub() لإرجاع المحور ، يجب تعيين مسار التنقل إليه. وأحد الطرق التي يكتشفها هو استخدام domain.active .

لكن المجالات لا تبدو موثوقة بوظائف غير متزامنة وستختفي قريبًا ...

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

نحن نلعب الآن بـ zone.js ، لأنه سيساعد بشكل كبير ، لكنه لا يزال PoC ضخمًا في الوقت الحالي ولا يمكننا معرفة متى أو حتى إذا كنا سنستخدمه لاستبدال المجالات.

مرحبا kamilogorek ،

أحاول التقاط أخطاء لم تتم معالجتها في تطبيق Sentry ، وجربت ما ذكرته في https://github.com/getsentry/sentry-javascript/issues/2122#issuecomment -503440087

لكني أعتقد أن Google لا تتيح لك الاتصال بـ process.on('uncaughtException') ، لم أتمكن من تسجيل أي أخطاء في Sentry باستخدام هذا الأسلوب.

هل هناك أي طريقة أخرى تنصح بها بالتجربة ، فإن لف كل جسم وظيفي في كتلة جرب لا يبدو أنه الطريقة المثالية للذهاب.

نحن نقدم طريقة wrap ، لكنني لا أعتقد أنها أفضل بكثير من try / catch tbh.

exports.helloBackground = (data, context) => {
  return `Hello ${data.name || 'World'}!`;
};

// becomes

exports.helloBackground = (data, context) => {
  return Sentry.wrap(() => {
    return `Hello ${data.name || 'World'}!`;
  })
};

يبدو لي أن هذه المشكلة قد تستحق الإبقاء عليها مفتوحة كطلب ميزة لدعم وظائف Firebase / google cloud بطريقة أبسط.

لقد تأثرت بشكل لا يصدق بسهولة الإعداد من جانب العميل وخيبت أملي عندما أدركت أن إعداد جانب الخادم سيكون أكثر تعقيدًا. هل هناك أي خطة لتحسين التجربة على برنامج "شركاء Google المعتمدون" (الوظائف على وجه التحديد)؟

goleary هل تمانع في فتح عدد جديد يصف بالضبط ما تود رؤيته؟
هذا الموضوع كبير بالفعل ويصعب متابعته.

شكرا

ألا يوجد حتى الآن طريقة أبسط لإعداد هذا؟ من الناحية المثالية ، أن تكون قادرًا على ضبطه مرة واحدة عالميًا ، دون الحاجة إلى ضبطه لكل وظيفة؟

marcospgp لا ، ولن يكون هناك ، للأسف ، لأن Google نفسها لا توفر آلية تسمح بذلك. انظر إلى المراسل الخاص بهم - https://cloud.google.com/error-reporting/docs/setup/nodejs فهو يستخدم مكالمات يدوية أيضًا.

حسنًا ، لقد قمت بإعداد وظائف Sentry on Firebase السحابية (التي تستخدم وظائف google cloud خلف الكواليس) ولقد تلقيت للتو تقرير خطأ - لذلك يبدو أنه يعمل!

هذا هو index.js الخاص بي ، حيث توجد جميع أكواد Sentry:

const admin = require("firebase-admin");
const functions = require("firebase-functions");
const Sentry = require("@sentry/node");

/**
 * Set up Sentry for error reporting
 */
if (functions.config().sentry && functions.config().sentry.dsn) {
  Sentry.init({ dsn: functions.config().sentry.dsn });
} else {
  console.warn(
    "/!\\ sentry.dsn environment variable not found. Skipping setting up Sentry..."
  );
}

admin.initializeApp();

const { function1 } = require("./cloud-functions/function1");
const { function2 } = require("./cloud-functions/function2");

module.exports = {
  function1,
  function2
};

هل كان marcospgp هو index.js أعلاه قادرًا على إرسال استثناءات غير معلومة داخل ./cloud-functions/function1 و ./cloud-functions/function2 إلى Sentry ، أو هل كان عليك تسجيل الدخول بنشاط إلى Sentry داخل هذه الملفات؟

لقد جربت للتو حل marcospgp ، ولكن لا يبدو أنه يسجل استثناءات غير معلومة ، يجب أن يقوم بتسجيلها يدويًا (باستخدام sentry.captureException() ؟)

مثل goleary هنا ، لا يتم تسجيل أي شيء.

يبدو أيضًا أن .wrap() لم يعد متاحًا.

هل يعني ذلك أننا يجب أن نلف كل الكود يدويًا داخل try / catches؟

Dinduks هذا ما أفعله. النفقات العامة مزعجة بعض الشيء ولكن القدرة على استخدام الحارس تستحق الجهد المبذول في تسجيل وظيفة سحابة Firebase (ليس رائعًا).

Dinduks wrap لا يزال موجودًا ، راجع: https://github.com/getsentry/sentry-javascript/blob/master/packages/browser/src/exports.ts#L40
ومع ذلك ، ضع في اعتبارك أنها تنفذ الوظيفة على الفور وتعطيك القيمة المرتجعة مرة أخرى. لذلك لست متأكدًا مما إذا كان ذلك مفيدًا أكثر من المحاولة / الالتقاط العادية التي تتيح لك القيام ببعض الإجراءات الاحتياطية للمستخدم أيضًا.

const myHandler = (req, res) => Sentry.wrap(() => {
  someFunctionThatCanBreak(req);
  return res.send(200);
});

لا أعتقد أنها فكرة جيدة ، لكنني أنشأت غلافًا يشبه هذا.

import * as Sentry from "@sentry/node";

export const sentryWrapper = (f) => {
  return async function () {
    try {
      // eslint-disable-next-line prefer-rest-params
      return await f.apply(this, arguments);
    } catch (e) {
      Sentry.captureException(e);
      await Sentry.flush(2000);
      throw new Error(e);
    }
  };
};

سيتم استخدامه على النحو التالي.

export const getChannelVideoTest = functions.https.onRequest(
  sentryWrapper(async (req, res) => {
    someFunctionThatCanBreak(req);
    return res.send(200);
  }),
);

أود أن أعرف ما إذا كانت هناك طريقة أفضل.

تضمين التغريدة
أنا أعاني من هذا أيضًا.

لقد نجحت في Sentry.init() وواجهت مشكلاتي عندما أغلقت كل الكود الخاص بي في كشف حساب try {} catch {} واستدعاء يدوي إلى Sentry.captureException و Sentry.flush() .
ومع ذلك ، لا يمكنني الإبلاغ عن أي شيء إذا قمت بإزالة كشف حساب try/catch .
ينطبق الأمر نفسه على مراقبة الأداء حيث لا أحصل على أي شيء إلا إذا قمت يدويًا بإنشاء معاملة Sentry.startTransaction() في بداية الوظيفة.

هل هذا متوقع؟
هل هناك أي طريقة لإرسال الأخطاء التي لم تتم معالجتها إلى Sentry؟
إذا لم يكن الأمر كذلك ، فهل هذا يعني أن علامة تبويب الأداء ستحدد دائمًا معدل الفشل عند 0٪؟ (لأننا اكتشفنا الخطأ وقمنا بالإبلاغ عنه يدويًا ، فإن المعاملة يتم إغلاقها بشكل صحيح ، وبالتالي هل تتمتع بحالة جيدة؟)

axelvaindal نحن لا ندعم مراقبة الأداء بدون خادم حتى الآن. أما عن هذا السؤال:

هل هناك أي طريقة لإرسال الأخطاء التي لم تتم معالجتها إلى Sentry؟

ثم لا ، ليس حقًا ، لأن GCF لا توفر طريقة للربط مع الاستثناءات / الرفض غير المعالَج ، لذلك نحن غير قادرين على اعتراض ذلك. تحتاج إلى لف معالجاتك (انظر التعليق أعلاه لك) من أجل الإمساك به يدويًا.

يمكنك أيضًا قراءة تطبيق معالج AWSLambda الخاص بنا للحصول على بعض الأفكار حول كيفية تحسين هذا المقتطف - https://github.com/getsentry/sentry-javascript/blob/master/packages/serverless/src/awslambda.ts

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