亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Sentry.io 在異步 Node.js 服務器上管理錯誤范圍/上下文

Sentry.io 在異步 Node.js 服務器上管理錯誤范圍/上下文

慕婉清6462132 2021-12-02 19:18:09
基本上你在 Node.js 中有并發請求。并且您可能希望使用特定于每個請求的數據來豐富可能的錯誤??梢酝ㄟ^以下方式在應用程序的不同部分收集此特定于請求的數據Sentry.configureScope(scope => scope.setSomeUsefulData(...))Sentry.addBreadcrumb({ ... })稍后在深度嵌套的異步函數調用中的某個地方拋出錯誤。Sentry 如何知道先前收集的哪些數據實際上與此特定錯誤相關,考慮到請求是同時處理的,并且在發生錯誤時無法訪問某個哨兵“范圍”來獲取與此特定請求相關的數據,從而導致在錯誤中。還是我必須通過所有函數調用傳遞哨兵作用域?喜歡server.on('request', (requestContext) => {  // Create new Sentry scope  Sentry.configureScope(sentryScope => {    Products.getProductById(id, sentryScope); // And pass it on  });});// all the way down until...function parseNumber(input, sentryScope) {  // ...}或者哨兵是否使用某種魔法將特定數據映射到相關事件?或者我錯過了什么?
查看完整描述

1 回答

?
30秒到達戰場

TA貢獻1828條經驗 獲得超6個贊

看起來他們使用 Node.js 域(https://nodejs.org/api/domain.html)為每個請求創建一個單獨的“上下文”。


從 Sentry 文檔中,您需要使用 requestHandler 才能正常工作。


例如對于快遞(https://docs.sentry.io/platforms/node/express/):


const express = require('express');

const app = express();

const Sentry = require('@sentry/node');


Sentry.init({ dsn: 'https://[email protected]/1240240' });


// The request handler must be the first middleware on the app

app.use(Sentry.Handlers.requestHandler());


// All controllers should live here

app.get('/', function rootHandler(req, res) {

  res.end('Hello world!');

});

處理程序看起來像這樣:


(來自:@sentry/node/dist/handlers.js)


function requestHandler(options) {

    return function sentryRequestMiddleware(req, res, next) {

        if (options && options.flushTimeout && options.flushTimeout > 0) {

            // tslint:disable-next-line: no-unbound-method

            var _end_1 = res.end;

            res.end = function (chunk, encoding, cb) {

                var _this = this;

                sdk_1.flush(options.flushTimeout)

                    .then(function () {

                    _end_1.call(_this, chunk, encoding, cb);

                })

                    .then(null, function (e) {

                    utils_1.logger.error(e);

                });

            };

        }

        var local = domain.create();

        local.add(req);

        local.add(res);

        local.on('error', next);

        local.run(function () {

            core_1.getCurrentHub().configureScope(function (scope) {

                return scope.addEventProcessor(function (event) { return parseRequest(event, req, options); });

            });

            next();

        });

    };

}

exports.requestHandler = requestHandler;

因此,您可以看到根據新請求創建的新域。


我主要是通過發現這個問題來找到這個信息的:https : //github.com/getsentry/sentry-javascript/issues/1939


如果您想將“上下文”添加到 Node 后端的其他異步部分(例如,如果您有工作人員/線程/某些工作不是從 HTTP 請求啟動的……),上面的問題中有一些示例說明了如何實現完成(通過手動創建集線器/域..)。


如果您有興趣,現在也可以使用 async_hooks 來保持 Node.js 中具有各種異步函數/回調/setTimeouts 的上下文的某種意義:https ://nodejs.org/api/async_hooks.html


這是一個很好的介紹:


https://itnext.io/request-id-tracing-in-node-js-applications-c517c7dab62d?


以及一些實現此功能的庫:


https://github.com/Jeff-Lewis/cls-hooked


https://github.com/vicanso/async-local-storage


例如,這樣的事情應該工作:


const ALS = require("async-local-storage");


function withScope(fn, requestId) {

  ALS.scope();

  ALS.set("requestId", requestId, false);

  return await fn();

}


async function work() {

  try {

    await part1();

    await part2();

  } catch(e) {

     Sentry.withScope((scope) => {

       scope.setTag("requestId", ALS.get("requestId"));

       Sentry.captureException(new Error("..."))

     }) 

  }

}


withScope(work, "1234-5678");


不過,您必須自己跟蹤面包屑,例如添加面包屑:


ALS.set("breadcrumbs", [...ALS.get("breadcrumbs"), new_breadcrumb]);

您需要在 Sentry 的 beforeSend() 回調中手動設置這些:


beforeSend: function(data) {

  data.breadcrumbs = ALS.get("breadcrumbs");

  return data;

}


查看完整回答
反對 回復 2021-12-02
  • 1 回答
  • 0 關注
  • 237 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號