Расширенный мониторинг интерфейса — Sentry Monitoring Практика проекта Next.js

монитор
Расширенный мониторинг интерфейса — Sentry Monitoring Практика проекта Next.js

предисловие

В последней связанной статье были представлены основы Sentry — локальная установка В этой статье Sentry используется для практики внешнего мониторинга на основе реальных проектов. Выберите проект Next.js для практического случая и конкретный адрес проекта.next-sentry-easy.

Предыдущий:Основы внешнего мониторинга — Docker + Sentry для создания внешней системы мониторинга

Статей по сборке Sentry в опенсорс-сообществе много, а вот практических статей по настройке и использованию сопутствующих деталей, не очень дружелюбных к новичкам, не так много, а связанных с Next.js и того меньше. Отечественное сообщество Next.js невелико, честно говоря, я не нашел идеального решения для мониторинга Next.js, поэтому сам пробовал несколько решений, и Sentry — одно из них. Причины написания этой статьи следующие:

В официальном репозитории примеров Next.js есть две демонстрации о sentry, и обе имеют некоторые проблемы.

  • Первыйwith-sentry-simpleЭто самый простой простой пример, но в этой демонстрации есть ошибки - об этом можно сообщить только на стороне клиента, но на стороне сервера не было успешно сообщено.

  • второйwith-sentryЭто относительно сложный случай, и проблема в том, что он слишком сложен и не подходит для изучения новичками.

Итак, вот краткое изложение, чтобы получить более подходящую и полную демонстрацию для новичков.

Создайте новый проект Sentry

Создайте новый проект Node.js.После создания нового проекта Sentry назначит проекту адрес DSN. Как показано ниже:

Инициализировать проект

  • package.json
"@sentry/browser": "^5.11.0",
"@sentry/node": "^5.11.0",
  • next.config.js
const withSourceMaps = require('@zeit/next-source-maps')

module.exports = withSourceMaps({
  env: {
    SENTRY_DSN: 'http://e69fa8afd38e43e59fc3baf48ec0c681@localhost:9000/11'
  },
  webpack: (config, options) => {
    if (!options.isServer) {
      config.resolve.alias['@sentry/node'] = '@sentry/browser'
    }
    return config
  },
})

Приведенная выше конфигурация обусловлена ​​особенностями Next.js.Среда рендеринга на стороне сервера имеет сценарии как на стороне сервера, так и на стороне клиента.В проекте может быть только один тип введения, который обычно вводится.@sentry/node, поэтому, когда клиент заменяет его на@sentry/browser.

  • _app.js
  import * as Sentry from '@sentry/node'
    
  Sentry.init({
    // Replace with your project's Sentry DSN
    dsn: process.env.SENTRY_DSN,
  });

  static async getInitialProps ({ Component, ctx }) {
    let pageProps = {};
    try {
      if (Component.getInitialProps) {
        pageProps = await Component.getInitialProps({ ctx })
      }
      return { pageProps }
    } catch (err) {
      // This will work on both client and server sides.
      console.log('The Error happened in: ', typeof window === 'undefined' ? 'Server' : 'Client');
      Sentry.captureException(err)
      return { pageProps };
    }
  }

Изначально настроить Sentry в _app.js, здесь просто настраивается только параметр dsn. Кроме того, операция выполняется в функции getInitialProps, при возникновении ошибки используйтеSentry.captureException()обострить.

Обратите внимание, что он в основном отвечает за отрисовку страницы и перехват ошибок во время переходов маршрутизации, которые могут перехватывать ошибки как в клиентских, так и в серверных сценариях. По определенным причинам вы можете проверить статьи, связанные с Next.js, которые я написал ранее.

  • _error.js
import * as Sentry from '@sentry/node';

const MyError = ({ statusCode, err }) => {
  if (err) {
    // This will work on both client and server sides in production.
    Sentry.captureException(err);
  }

  return <Error statusCode={statusCode} />
}

_error.js, как мы все знаем, является встроенным компонентом ошибок Next.js. Компонент будет отображаться при возникновении ошибки при запуске программы. Поэтому он в основном отвечает за перехват ошибок при запуске программы. запуск, например нажатие кнопок, отправка форм и другие интерактивные операции.

Эффект

Описанная выше работа по инициализации завершена, давайте запустим проект и просто проверим результат:

  • Произошла ошибка при запуске

Как показано на рисунке ниже, щелкните страницы ошибок клиента и сервера соответственно.

  • Список проблем проекта Sentry

Как показано на рисунке ниже, Sentry обычно перехватывает исключения, возникающие в коде.

  • оповещение по электронной почте

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

Проект расширения — запрос данных захвата

Проект инициализации завершен выше, и аномальные ошибки в клиенте, сервере, инициализации и работе могут быть зафиксированы в обычном режиме. Однако в процессе использования обнаруживается, что Sentry не может перехватывать ошибки сетевых запросов. Например, в проекте используется Fetch.Как показано на рисунке ниже, сетевой запрос страницы инициализации сообщает об ошибке 404, но консоль Sentry не фиксирует ошибку.

fetch-error-not-report

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

  • Обернуть FetchError
class FetchError extends Error {
  constructor(url = 'http://localhost', props) {

    super(props);
    const { message, traceId, userId } = props;

    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, FetchError)
    }

    this.name = 'FetchError'
    // Custom debugging information
    this.url = url
    this.message = message
    traceId && (this.traceId = traceId)
    userId && (this.userId = userId)
    this.date = new Date()
    console.log(this)
  }
}

export default FetchError
  • инкапсулировать выборку
import fetch from 'isomorphic-unfetch';
import * as Sentry from '@sentry/node';
import FetchError from './FetchError';

function dealStatus(res) {
  if (res.status !== 200) {
    const err = new FetchError(res.url, {
      traceId: Math.random() * 10000, // create your application traceId
      userId: 26,
      message: `${typeof window !== 'undefined' ? 'Client' : 'Server'} fetch error - ${res.status}`
    })
    // This will work on both client and server sides in production.
    Sentry.captureException(err);
  }
  return res;
}

// initial fetch
const unfetch = Object.create(null);

...

HTTP_METHOD.forEach(method => {
  // is can send data in opt.body
  const bodyData = BODY_METHOD.includes(method);
  unfetch[method] = (path, { data } = {}) => {
    let url = path;
    const opts = {
      method,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      mode: 'cors',
      cache: 'no-cache'
    };

    ...

    return fetch(url, opts)
      .then(dealStatus)
      .then(res => res.json());
  };
});

export default unfetch;

Выше просто инкапсулируйте функцию Fetch, а затем обработайте в ней исключение error.Если код возврата не 200, значит в этом запросе ошибка, используйтеSentry.captureException(err);Сообщить об ошибке.

Конкретный эффект показан на следующем рисунке:

Видно, что Sentry успешно сообщил об аномальной информации запроса данных.

На самом деле здесь есть проблема, что, если сервер выйдет из строя? Разве это не день, когда разработчики засыпаны бесчисленными электронными письмами? Разве это не разумно, может ли Fetch Error не отправлять электронные письма? Об этом будет сказано ниже-

Проект расширения — расположение исходного кода

Что означает местоположение исходного кода?Давайте взглянем на текущую нормальную информацию об ошибках, как показано на следующем рисунке:

Как видно из рисунка выше, поскольку код сжат, неверный контекст и информация о стеке также сжаты.Этот вид устранения неполадок в коде довольно сложен, но ошибка есть. Как мы все знаем, нашим инструментом сборки обычно является веб-пакет, а исходную карту можно настроить для сопоставления кода. Здесь Sentry также может более точно найти информацию об ошибке, настроив информацию о версии выпуска.

Часовой чиновникДаны три схемы конфигурации: релизный API, sentry-cli и sentry-webpack-plugin.Для первых двух необходимо вручную загрузить файл исходной карты проекта, а третья загружается, когда проект создается с помощью конфигурации кода. , поэтому здесь используется третий, более удобный. В других сообществах есть соответствующие статьи, вы можете их прочитать.

  • Шаг 1: Установите зависимости
yarn add @zeit/next-source-maps @sentry/webpack-plugin
  • Шаг 2: Настройте .sentryclirc
[defaults]
url = http://localhost:9000/
org = luffyzh
project = next-sentry-example

[auth]
token = your token api

Этот файл конфигурации является ключевым файлом для настройки выпуска.Параметры по умолчанию – это путь сообщения, название организации и имя проекта. Благодаря этим трем элементам информации можно точно определить местонахождение конкретных проектов. Затем нам нужно сгенерировать токен под авторизацией, как показано ниже:

При генерации токена необходимо проверить права на проект: запись! ! !

  • Шаг 3: Настройте next.config.js
const webpack = require('webpack')
const withSourceMaps = require('@zeit/next-source-maps')()
const SentryCliPlugin = require('@sentry/webpack-plugin')

module.exports = withSourceMaps({
  webpack: (config, { isServer, buildId }) => {
    config.plugins.push(
      ...[
        new webpack.DefinePlugin({
          'process.env.SENTRY_RELEASE': JSON.stringify(buildId)
        }),
        new SentryCliPlugin({
          include: ['.next'], // 上传的文件夹,next项目传.next文件夹就行
          ignore: ['node_modules', 'next.config.js'], // 忽略的文件
          configFile: '.sentryclirc', // 上传相关的配置文件
          release: buildId,           // 版本号
          urlPrefix: '~/_next'        // 最关键的,相对路径
        })
      ]
    )
    ...
    return config
  },
})

Очень важным моментом здесь является то, чтоurlPrefixЭтот параметр, который по умолчанию равен~То есть доменное имя плюс путь к загружаемому файлу, но проект Next.js особенный, и перед ним будет добавлен путь к файлу./_nextПоэтому вам нужно добавить этот элемент конфигурации для нормального доступа к нему, иначе SENTRY не получит соответствующий файл исходной карты.

  • Шаг 4: Конфигурация кода
// _app.js
Sentry.init({
  // Replace with your project's Sentry DSN
  dsn: process.env.SENTRY_DSN,
  release: process.env.SENTRY_RELEASE, // 版本号
});

Здесь также следует отметить, чтоSentry.init({})Номер версии должен соответствоватьnext.config.jsНомер версии в элементе конфигурации тот же, так что Sentry можно связать. В проектах Next.js это очень просто, просто используйте встроенный buildId~

  • Шаг 5: сборка + просмотр эффекта

бегатьyarn buildКоманда обнаружит, что консоль постоянно загружает файлы исходной карты, как показано на следующем рисунке:

После сборки вы можете просмотреть файл исходной карты соответствующей версии в консоли проекта Sentry, как показано на следующем рисунке:

Затем повторно запустите программу, вы обнаружите, что информацию о стеке ошибок уже можно просмотреть в исходном коде, и можно просмотреть исключение, вызванное определенной строкой кода~

Проект расширения – отзывы пользователей

Что касается отзывов пользователей, доброжелательный видит доброжелательный, а мудрый видит мудрость.Если вы хотите, чтобы онлайн-проект выглядел элегантно, когда он падает, и у вас есть просьба к вашим пользователям помочь вам устранить проблему и воспроизвести шаги, это нормально. . Однако не все хотят этого, потому что это означает, что вы позволяете пользователям обнаруживать системные проблемы.Некоторые люди могут не хотеть, чтобы пользователи обнаруживали их, или они хотят, чтобы личные отзывы решали их своевременно, чтобы их не обнаружило больше людей~ В общем , Это тоже точка знаний, просто настройте его играть и играть:

Sentry.init({
  // Replace with your project's Sentry DSN
  dsn: process.env.SENTRY_DSN,
  beforeSend(event) {
    // Check if it is an exception, if so, show the report dialog
    if (process.browser && event.exception) {
      Sentry.showReportDialog({
        eventId: event.event_id
      });
    }
    return event;
  }
});

По сути, это просто API.Sentry.showReportDialog(), мы вызываем его, когда возникает исключение, чтобы пользователь мог заполнить соответствующий контент для отображения. Конкретный процесс показан на следующем рисунке:

  • Шаг 1: При запуске программы возникает ошибка

  • Шаг 2: Заполните информацию о возврате

  • Шаг 3: Sentry контролирует отзывы пользователей для просмотра соответствующей информации.

Как видно из рисунка выше, есть предложения обратной связи, и в списке отзывов Sentry соответствующий контент отзыва также отображается нормально~

Проект расширения - ссылка Github/Gitlab

Продолжайте расширять проект, то есть ошибки, отслеживаемые Sentry, также можно связать с Github/Gitlab, а затем напрямую создать новую проблему.Для тестовых студентов это просто хорошая новость~

Для первой конфигурации инициализации нам нужно связать проект на странице сведений об ошибке, как показано на следующем рисунке:

Затем установите соответствующие плагины, в качестве примера возьмем Github:

Здесь его установить нельзя, потому что эти плагины нужно ставить вместе с Sentry, то есть настраивать соответствующие плагины через файл config.yml. Конкретное содержание - содержание предыдущей статьи.По некоторым причинам (эпидемия не закончилась, сети дома нет, а сеть 4G действительно немного трудоемка) здесь установка производиться не будет. Соответствующие адреса являются следующими:Sentry устанавливает Github Integrations.

После установки соответствующий эффект проблемы выглядит следующим образом:

Следующие скриншоты взяты из интернета, соответствующие статье ->Еще одна статья Sentry

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

Расширенный проект — уровни ошибок и настройки почты

Вдогонку выше сказано, что Fetch Error это исключение для перехвата запросов данных, тогда если сервер рухнет и перезагрузится, при условии что будет 10 000 обращений, то разработчики будут засыпаны почтой, что не очень разумно, есть ли вообще решение? как? Да ~ это настройка напоминания по электронной почте.

Настройка электронной почты не требует кода, очень проста в использовании и, конечно же, очень важна Конкретные настройки показаны на следующем рисунке:

Project -> Alerts -> Rules -> EditСделайте настройки.

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

// unfetch.js

/* config the fetch error is warning */
Sentry.withScope(function(scope) {
  scope.setLevel('warning');
  Sentry.captureException(err);
});

С помощью приведенного выше кода мы устанавливаем для ошибки выборки уровень предупреждения, как показано ниже:

  • Цвет уровня предупреждения — оранжевый, а другие обычные исключения — красный.

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

Наконец, перезапустите проект, вы обнаружите, что по электронной почте все еще есть предупреждения для других исключений, и нет предупреждений по электронной почте для Fetch Error, но мы все равно увидим их в консоли Sentry ~ отлично!

Суммировать

На данный момент, следуя основам первой статьи, также была написана практическая глава, включающая практически все доступные сценарии. Я надеюсь, что это будет полезно для всех.Фронтенд-мониторинг по-прежнему имеет относительно важное значение в процессе производства и разработки. Если вы заинтересованы, вы можете связаться с нами~

Адрес проекта следующий:next-sentry-easy, Этот проект оптимизирует ошибки Next.js_with-sentry-simple и упрощает сложную логику Next.js_with-sentry. Лично для меня это относительно средний проект. Если вам интересно, помните Star, спасибо~

Базовый кодmasterфилиал, полный кодfull-demoветвь.