Как лучше всего развернуть Sentry в среде кросс-сборки? - PullRequest
1 голос
/ 25 марта 2019

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

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

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

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

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

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

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

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


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

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

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

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

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

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

1 Ответ

2 голосов
/ 26 марта 2019

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

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

Относительно:

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

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

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. Если это возвращает ноль, он будет смотреть на атрибут 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 on).

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

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

...