Как наилучшим образом развернуть Sentry в среде кросс-ассемблера?

#c# #wpf #sentry

#c# #wpf #sentry

Вопрос:

Итак, мы создали эту библиотеку / фреймворк, полную кода, связанного с бизнес-процессами и общими элементами, которые используются совместно несколькими приложениями (C #, .Net 4.7.1, WPF, MVVM). Все наши материалы для ведения журнала настроены с помощью этого фреймворка, поэтому, естественно, он казался лучшим местом для Sentry. Все ссылки в наших отдельных приложениях вручную указывают на библиотеки DLL, папку, в которую устанавливается наша общая библиотека thingy. Пока все хорошо.

Когда мы изначально настраивали Sentry, казалось, что все работает отлично. Мы делаем некоторые обновления, и, похоже, количество ошибок снижается. Это потому, что мы крутые, а Sentry помог нам стать еще круче, верно? Нет! Ну, я имею в виду что-то вроде.

Область действия удаляется, поэтому мы больше не получаем необработанных исключений. Сначала мы этого не заметили, потому что мы все еще получаем журналы sentry при обработке ошибок с помощью нашего метода Logging.Log(). Этот метод ведения журнала вызывает SentrySdk.Init (), который, как я подозреваю, отправляет клиента в исполняемую сборку.

Мы также начали использовать Sentry для простого отслеживания использования, запустив отдельный проект в Sentry под названием Usage-Tracker и передав simple "DoThingApplication has been launched" с ApplicationName.UsageTracker перечислением в качестве параметра нашему методу ведения журнала.

Вопрос: каков хороший способ справиться с этим, когда в моей установке может быть экземпляр Sentry, который оборачивает мой using(sentryClientStuff){ ComposeObjects(); } , и при этом мой метод ведения журнала будет искать существующий клиент и использовать его, если он существует?

Предостережения:

  • Я полагаю, что прежде чем что-либо из этого произойдет, нам все еще нужно выполнить вызов для отправки журнала Sentry в наш UsageTracker.
  • Я хотел бы передать как можно меньше опций, если я настраиваю клиент Sentry / область видимости в нашей общей библиотеке. Возможно, релиз и среда. Возможно, проверьте теги на наличие отпечатка пальца и установите его в методе Log.
  • Я открыт для новых подходов к любому из этого.

Некоторые связанные мысли


  • Может быть, есть лучший способ обработки ссылок, который мог бы решить как эту, так и некоторые другие проблемы, связанные с несоответствием между клиентом и общей платформой / библиотекой

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

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

  • Может быть, есть лучшее решение, которое я не могу придумать, потому что я просто вроде как нормальный программист, и оно ускользает от меня. Я открыт для любых советов / исправлений / насмешек.

  • Может быть, есть более разумный способ обработки сигналов типа «Отслеживание использования» в Sentry

На самом деле я хочу, чтобы на практике использовалась одноэлементная кросс-сборка.

Комментарии:

1. Усвоенный урок: должен произойти только один SentrySdk.Init() . Используйте ConfigureScope в инструкции using, аналогичной вашей функции ожидания вызова, для отправки ошибки в проект с другим Dsn.

Ответ №1:

Здесь действительно происходит много всего. Также, не глядя ни на какой код, трудно представить, как все устроено. Больше шансов, что вы сможете получить ответ, который ищете, если поделитесь каким-нибудь (даже фиктивным) примером структуры вашего проекта.

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

Что касается:

Отслеживание использования: Вы можете создать нового клиента и привязать его к области видимости. Таким образом, любое использование SentrySdk статического класса (к которому, как я предполагаю, направляются ваши Logger.Log маршруты) будет поддерживаться. Другими словами, вызывайте SentrySdk.Init так, как вы делаете в данный момент, с параметрами, которые являются общими для любого приложения, использующего вашу общую библиотеку, и после этого создайте клиент, используя DSN ваш проект отслеживания использования в sentry. Укажите область видимости, привяжите клиент, и вы сможете использовать SentrySdk с ним.

В репозитории SDK на GitHub есть пример:

 using (SentrySdk.PushScope())
{
    SentrySdk.AddBreadcrumb(request.Path, "request-path");

    // Change the SentryClient in case the request is to the admin part:
    if (request.Path.StartsWith("/admin"))
    {
        // Within this scope, the _adminClient will be used instead of whatever
        // client was defined before this point:
        SentrySdk.BindClient(_adminClient);
    }

    SentrySdk.CaptureException(new Exception("Error at the admin section"));
    // Else it uses the default client

    _middleware?.Invoke(request);

} // Scope is disposed.
  

SDK нужно инициализировать только один раз, но вы всегда можете создать новый клиент с помощью new SentryClient , создать новую область ( SentrySdk.PushScope() ) и привязать его к этой новой области ( SentrySdk.BindClient ). Как только вы открываете область видимости, клиент больше не доступен через SentrySdk.CaptureException или любой другой метод в статическом классе SentrySdk .

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

 using (var c = new SentryClient(new SentryOptions { Dsn = new Dsn("...") })) {
    c.CaptureMessage("hello world!");
}
  

using Блок предназначен для того, чтобы убедиться, что фоновый поток сбрасывает событие.

Центральное место для инициализации SDK: Будет конфигурация, которую вы хотите зафиксировать в вашей общей платформе / библиотеке, но, безусловно, каждое приложение (корневой каталог композиции) будет иметь свои собственные настройки. Релиз обнаруживается автоматически. Из docs.sentry.io:

SDK сначала рассмотрит атрибут AssemblyInformationalVersionAttribute начальной сборки, который принимает строку в качестве значения и часто используется для установки хэша GIT commit. Если это возвращает null, он будет смотреть на атрибут AssemblyVersionAttribute по умолчанию, который принимает числовой номер версии.

Если вы исправляете свои сборки на сервере сборки, о правильной Release должно быть сообщено автоматически. Если нет, вы могли бы определить его для каждого приложения, используя делегат, который передает SentryOptions в качестве аргумента.

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

Framework code :

 
public class MyLogging 
{
    void Init(Action<SentryOptions> configuration)
    {
        var o = new SentryOptions();
        // Add things that should run for all users of this library:
        o.AddInAppExclude("SomePrefixTrueForAllApplications");
        o.AddEventProcessor(new GeneralEventProessor());
        // Give the application a chance to reconfigure anything it needs:
        configuration?.Invoke(o);
    }
}
  

App code :

 void Main() 
{
    MyLogging.Init(o => o.Environment = "my env");
}
  

Область действия удаляется, поэтому мы больше не получаем необработанных исключений.«

Не уверен, что понимаю, что здесь происходит. Нажатие и выталкивание (удаление) областей не влияют на способность SDK перехватывать необработанные исключения. Не могли бы вы, пожалуйста, поделиться воспроизведением?

Этот метод ведения журнала вызывает SentrySdk.Init (), который, как я подозреваю, удаляет клиента из исполняемой сборки.: Если вы не создадите клиента «вручную» с помощью new SentryClient , в запущенном процессе есть только 1 клиент. Пожалуйста, обратите внимание, я сказал запущенный процесс, а не сборку. Экземпляры не хранятся в сборке. Сборка содержит только код, который может быть выполнен. При вызове SentrySdk.CaptureException он отправит вызов в SentryClient привязанную к текущей области видимости. Если вы этого не сделали PushScope , всегда существует неявная область видимости, корневая область. В этом случае все достаточно прозрачно, вас не должно волновать, что там есть область видимости. Вы также не можете избавиться от этой области, поскольку у вас никогда не было дескриптора для этого (вы не вызывали, PushScope поэтому вы не получили то, что он возвращает для вызова Dispose ).

Все ссылки в наших отдельных приложениях вручную указывают на библиотеки DLL, папку, в которую устанавливается наша общая библиотека thingy.:

В зависимости от вашей среды следует учитывать одну вещь — распространять пакеты через NuGet. Я не уверен, собираетесь ли вы использовать эти библиотеки в приложениях, отличных от .NET Framework (например .NET Core). Но, учитывая, что .NET Core 3.0 предоставляет поддержку Windows Desktop Framework, такую как WPF и WinForm, возможно, что в конечном итоге вы это сделаете. В этом случае рассмотрите возможность таргетинга .NET Standard вместо .NET Framework на ваши библиотеки кода.

Комментарии:

1. Спасибо @Bruno, у меня просто возникла еще одна проблема, которую я должен решить, но должен заняться этим позже сегодня. Я подозреваю, что моя библиотека не должна пытаться обрабатывать SentrySdk. Инициализация(). В нынешнем виде каждый раз, когда метод Logging.Log() использует ApplicationName. Проверяется параметр AnyName Enum и создается SentrySdk. Инициализация вызывается с правильным Dsn в дополнение к инициализации, ранее вызванной в using главном приложении.