c# - 如何在交叉组装环境中最好地部署 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.UsageTracker
Enum 的简单项目作为参数传递给我们的 Logging 方法。
问题:using(sentryClientStuff){ ComposeObjects(); }
在我的设置可以有一个包裹我的 Sentry 实例并且仍然让我的日志记录方法查找现有客户端并在它存在时使用它的情况下,有什么好方法来处理这个问题?
注意事项:
- 我相信在任何这种情况发生之前,我们仍然需要拨打电话将 Sentry 日志发送到我们的 UsageTracker。
- 如果我在我们的共享库中设置哨兵客户端/范围,我想传递尽可能少的选项。也许是发布和环境。也许检查指纹的标签并将其设置在 Log 方法中。
- 我对任何这方面的新方法持开放态度。
一些相关的想法
也许有一种更好的方法来处理引用可以解决这个问题以及当它们在客户端和共享框架/库之间变得不匹配时的其他一些痛苦
也许可以通过添加一些单元测试来找到答案,但我可以使用 Sentry 特定示例或在那里轻推,因为我对此一无所知。
也许有一种方法可以使用我的共享库返回一个哨兵客户端或范围,我可以在我的客户端程序集中使用它,它不会那么脆弱,并且库也可以以某种方式使用它。
也许有一个更好的解决方案我无法想象,因为我只是一个好的程序员,它让我无法理解。我愿意接受任何建议/更正/嘲笑。
也许有一种更聪明的方法来处理 Sentry 中的“Usage-Tracker”类型的信号
在实践中,我真的想要一种交叉组装单例的东西。
解决方案
这里真的发生了很多事情。同样,如果不查看任何代码,也很难想象事物是如何布局的。如果您分享项目结构的一些(甚至是虚拟的)示例,则更有可能获得您正在寻找的答案。
我会尝试将其分解并解决我可以解决的问题:
关于:
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.CaptureException
SentryClient
PushScope
PushScope
Dispose
我们各个应用程序中的所有引用都手动指向 dlls,即我们的共享库 thingy 自行安装的文件夹。:
根据您的环境,需要考虑的一件事是通过NuGet分发包。我不确定您是否希望在非 .NET Framework 应用程序(如 .NET Core)中使用这些库。但考虑到 .NET Core 3.0 带来了 WPF 和 WinForm 等 Windows 桌面框架支持,最终您可能会这样做。如果是这种情况,请考虑针对您的代码库.NET Standard
而不是.NET Framework
针对您的代码库。
推荐阅读
- arrays - 如何在菜单数组内的子菜单中过滤角色
- jquery - 在不使用日期选择器的情况下获取完整日历的第一个和最后一个可见日期
- postgresql - 无法理解为什么二级关联表会给我语法错误
- javascript - 在 plyr 视频播放器中集成 VAST
- html - 如何将文本添加到网页的响应式背景画布?
- node.js - 从源“http://localhost:3000”访问“https://sua-ap-web-1.agora.io/api/v1?action=stringuid”的 XMLHttpRequest 已被 CORS 策略阻止
- javascript - 如何根据 React 中的元素大小计算属性?
- macos - Flutter Desktop(macOS) TextField - 如何禁用自动回绕文本
- css - 为什么不应该应用 css 转换?
- powershell - 使用 Powershell 从多个文件夹复制特定子文件夹