首页 > 解决方案 > 如何在交叉组装环境中最好地部署 Sentry?

问题描述

因此,我们构建了这个库/框架,其中充满了与跨多个应用程序(C#、.Net 4.7.1、WPF、MVVM)共享的业务流程和公共元素相关的代码。我们的 Logging 东西都是通过这个框架设置的,所以自然而然地感觉它是 Sentry 的最佳位置。我们各个应用程序中的所有引用都手动指向 dlls,即我们的共享库 thingy 自行安装的文件夹。到目前为止,一切都很好。

当我们最初设置 Sentry 时,一切似乎都运行良好。我们做了一些更新,错误似乎正在下降。那是因为我们很棒,而 Sentry 帮助我们变得更了不起,对吧?没有!嗯,我的意思是。

范围正在被处置,因此我们不再收到未处理的异常。起初我们没有注意到,因为当我们通过 Logging.Log() 方法处理错误时,我们仍然会收到哨兵日志。此日志记录方法调用 SentrySdk.Init(),我怀疑它正在执行程序集中处理客户端。

我们还开始使用 Sentry 进行一些简单的使用情况跟踪,方法是在 Sentry 中启动一个名为 Usage-Tracker 的单独项目,并将一个"DoThingApplication has been launched"带有ApplicationName.UsageTrackerEnum 的简单项目作为参数传递给我们的 Logging 方法。

问题:using(sentryClientStuff){ ComposeObjects(); }在我的设置可以有一个包裹我的 Sentry 实例并且仍然让我的日志记录方法查找现有客户端并在它存在时使用它的情况下,有什么好方法来处理这个问题?

注意事项:

一些相关的想法


在实践中,我真的想要一种交叉组装单例的东西。

标签: c#wpfsentry

解决方案


这里真的发生了很多事情。同样,如果不查看任何代码,也很难想象事物是如何布局的。如果您分享项目结构的一些(甚至是虚拟的)示例,则更有可能获得您正在寻找的答案。

我会尝试将其分解并解决我可以解决的问题:

关于:

Usage-Tracker:您可以创建一个新客户端并绑定到一个范围。这样,SentrySdk静态类的任何使用(我假设你的Logger.Log路由)都会被使用。换句话说,SentrySdk.Init像您当前一样调用,使用您的共享库在任何应用程序之间共享的选项,然后使用DSN您的Usage-Tracker项目在 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 提交哈希。如果返回 null,它将查看接受数字版本号的默认 AssemblyVersionAttribute。

如果您在构建服务器中修补程序集,Release则应自动报告正确的。SentryOptions如果没有,您可以通过采用传递as 参数的委托来为每个应用程序定义它。

就像是:

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 捕获未处理异常的能力。你能分享一个repro吗?

此日志记录方法调用 SentrySdk.Init(),我怀疑它正在执行程序集中处理客户端。:除非您使用“手动”创建客户端,否则运行过程new SentryClient中只有 1 个客户端。请注意我说的是运行过程而不是组装。实例不包含在程序集中。程序集只包含可以执行的代码。如果您调用它,它将调用绑定到当前范围。如果你不这样做,总会有一个隐含的范围,即根范围。在这种情况下,这一切都足够透明,你不应该关心那里有一个范围。你也不能处理那个范围,因为你从来没有这样做过(你没有打电话所以你没有'SentrySdk.CaptureExceptionSentryClientPushScopePushScopeDispose

我们各个应用程序中的所有引用都手动指向 dlls,即我们的共享库 thingy 自行安装的文件夹。

根据您的环境,需要考虑的一件事是通过NuGet分发包。我不确定您是否希望在非 .NET Framework 应用程序(如 .NET Core)中使用这些库。但考虑到 .NET Core 3.0 带来了 WPF 和 WinForm 等 Windows 桌面框架支持,最终您可能会这样做。如果是这种情况,请考虑针对您的代码库.NET Standard而不是.NET Framework针对您的代码库


推荐阅读