高效调试:实时监控应用状态

在多级产品中,经常会遇到某个环节响应时间极短的情况,如果该环节不能在几秒或几毫秒内响应请求,调用进程就会因为等待响应而超时。本文将介绍一套开源库,这套库能够帮助避免这类问题。

使用代码

本文介绍的代码是开源的,遵循BSD许可证,并且可以在GitHub上找到。

可以通过NuGet将这些组件添加到解决方案中。对于服务器组件(想从中获取调试信息的代码):

Install-Package Ratcow.Debugging.Server

或者在Visual Studio的“包管理器”中搜索Ratcow.Debugging.Server。对于客户端(应该创建一个主机应用程序来查看数据):

Install-Package Ratcow.Debugging.Client

或者在Visual Studio的“包管理器”中搜索Ratcow.Debugging.Client。本文使用的是最新版本,客户端是0.0.1,服务器是0.0.2。但是接口非常简单,所以不太可能会有破坏性更改。

在应用程序中,必须注册一些实例以使它们可用,注册实例时,将提供一个或多个属性的名称。例如,给定这个类:

public class TestClassOuter { public TestClassOuter() { Value = new TestClass(); } public TestClass Value { get; set; } } public class TestClass { public string S { get; set; } public int I { get; set; } }

可以看到外部类TestClassOuter包含一个内部类的属性,而内部类TestClass有两个属性。这个例子展示了两种可能的注册方式。

可以这样做:

var c = new TestClass { I = 10, S = "hello" }; var dbs = new DebugInterface(); dbs.RegisterProperties(c, "c", "I", "S");

也可以这样做:

var c = new TestOuterClass(); c.Value.I = 10; c.Value.S = "hello"; var dbs = new DebugInterface(); dbs.RegisterProperties(c, "c", "Value");

此时,有一个有效的DebugInterface。可以将其注册到WCF接口并开始调试值。在应用程序中,这将非常相似。为此,向应用程序添加一个私有变量(或使用最喜欢的IoC容器)。这个实例必须在应用程序的整个生命周期中存在。

ServiceHost debugInterfaceService; debugInterfaceService = Ratcow.Debugging.Server.DebugInterface.Start(dbs);

此时,应用程序现在将通过库中嵌入的WCF服务导出注册的属性,只要在app.config中添加了WCF配置。(这一步将在未来的版本中消失,这只是因为提前发布了库,以便在项目中使用它们。)

XML配置如下:

<system.serviceModel> <services> <!-- simple generic debug interface --> <service behaviorConfiguration="DebugInterfaceBehave" name="Ratcow.Debugging.Server.DebugInterface"> <endpoint address="http://127.0.0.1:9001/DebugInterface" binding="basicHttpBinding" contract="Ratcow.Debugging.Server.IDebugInterface" /> <host> <baseAddresses> <add baseAddress="http://127.0.0.1:9001/DebugInterface" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="DebugInterfaceBehave"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>

现在应用程序正在运行 - 验证服务是否激活。访问主机机器上的http://127.0.0.1:9001/DebugInterface。应该看到服务的概览。如果没有,可能需要查看防火墙访问权限,并且可能需要以管理员权限运行应用程序(只是为了起步)。可以在稍后更改应用程序的权限,以允许WCF服务运行 - 但是为了测试它是否成功运行,在这里需要走一些捷径。

客户端可以像想要的那样复杂。但是一个基本的客户端包含在GitHub仓库中,如下所示:

class Program { static void Main(string[] args) { var client = new DebugInterfaceClient("http://127.0.0.1:9001/DebugInterface"); var names = client.GetVariableNames(); foreach (var name in names) { Console.Write(name); var value = client.GetVariableValue(name); Console.WriteLine($": {value}"); } Console.WriteLine("\r\n----------------------"); Console.WriteLine("any key to exit"); Console.ReadLine(); } }

重要的是:

  • 使用服务器组件的URL实例化客户端。如果它在另一台机器上,将需要使用那台机器的IP地址或DNS名称。
  • 在客户端上调用GetVariableNames()将给一个注册名称的完整列表,以字符串数组的形式。
  • 调用GetVariableValue()并传递一个从GetVariableNames()调用中收到的有效名称,将让实时获取该变量的当前值。库将把数据转换为JSON,所以可以根据需要处理这些数据。JSON在这个应用程序中非常有用,因为它是中性的,并且会序列化任何值,而不会真正关心类实例是否可以在另一端被反序列化。它也是语言无关的。

真的,就是这样!!有一个变量的实时视图,调试器永远不会参与减慢/停止应用程序的进度。如此频繁地使用这种技术,以至于创建了这个相当通用的库,以使其他人可以使用相同的技术。

像所有的调试接口一样 - 可能会想要从生产构建中排除这段代码。

这个库仍在发展中,将在更多变化发生时更新本文。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485