当前位置: 首页 > news >正文

界面开发框架DevExpress XAF实践:集成.NET Aspire后如何实现自定义遥测?

DevExpress XAF是一款强大的现代应用程序框架,允许同时开发ASP.NET和WinForms。DevExpress XAF采用模块化设计,开发人员可以选择内建模块,也可以自行创建,从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。

.NET Aspire是一组工具、模板和包,用于构建可观察的、可生产的应用程序。DevExpress XAF团队花费了一些时间考虑Aspire的功能,试图找到最好的集成点,让XAF开发人员能够利用Aspire开箱即用的业务流程特性。

点击获取DevExpress最新版下载

在最近的一篇文章中我们介绍了如何对一个 XAF Blazor 项目进行调整,来支持 .NET Aspire(点击这里回顾>>)。通过对启动逻辑进行一些修改——包括标准的 XAF 项目模板和 Aspire 的 Visual Studio 向导生成的代码,已经可以让 XAF Blazor 项目作为 Aspire 编排体系的一部分运行了。但那只是最小规模的编排,只有一个模块!接下来我们将会把部署方面的内容留到第三篇(敬请关注!),接下来得系列文章将介绍在示例项目中为实现以下三个场景所做的修改:

  1. 通过 OpenTelemetry 将自定义活动和指标记录到 Aspire 仪表盘
  2. 将 SQL Server 作为一个由 Aspire 协调运行的容器化依赖项
  3. 在编排中添加一个额外的服务,展示更复杂的系统结构

完整示例项目已托管在这个 GitHub 仓库中。下面基于我在第一篇文章中描述的项目初始状态,展开说明新的功能实现。

利用 OpenTelemetry 支持自定义指标与活动日志

Aspire 仪表盘的集成,是许多应用项目在启用 Aspire 后最直观的新特性之一。正如在演示项目的第一步中看到的,启用默认的跟踪和指标来源非常简单。接下来我们就会思考:如何将遥测系统用于我们自己的场景,比如记录自定义日志、报告业务指标与活动?

第一步,我创建了文件 XafAspireDemo.Blazor.Server/Controllers/ImportantBusinessOperationsController.cs,它实现了一个基本的 XAF 控制器,并提供了一个动作(Action)。该操作会自动出现在用户界面中,因此可以用作交互式测试触发器。以下是代码:

namespace XafAspireDemo.Blazor.Server.Controllers
{
public class ImportantBusinessOperationsController : Controller
{
SimpleAction importantBusinessAction;
IServiceProvider serviceProvider;public ImportantBusinessOperationsController()
{
importantBusinessAction = new SimpleAction(
this,
"ImportantBusinessAction",
PredefinedCategory.View
);
importantBusinessAction.Execute += ImportantBusinessAction_Execute;
}[ActivatorUtilitiesConstructor]
public ImportantBusinessOperationsController(IServiceProvider serviceProvider)
: this()
{
this.serviceProvider = serviceProvider;
}private async void ImportantBusinessAction_Execute(
object sender,
SimpleActionExecuteEventArgs e
)
{
var logger = serviceProvider.GetRequiredService<
ILogger<ImportantBusinessOperationsController>
>();importantBusinessAction.Enabled["ImportantBusinessActionRunning"] = false;logger.LogInformation("ImportantBusinessAction started.");try
{
// This is where we perform the magic for the important business action.
// Run a task that waits a random time between half a second and five seconds.
await Task.Run(() =>
{
Thread.Sleep(new Random().Next(500, 5000));
});
}
catch (Exception ex)
{
logger.LogError(ex, "ImportantBusinessAction failed.");
throw;
}
finally
{
importantBusinessAction.Enabled["ImportantBusinessActionRunning"] = true;
}
}protected override void OnActivated()
{
base.OnActivated();var logger = serviceProvider.GetRequiredService<
ILogger<ImportantBusinessOperationsController>
>();
logger.LogInformation("ImportantBusinessOperationsController activated.");
}protected override void OnDeactivated()
{
var logger = serviceProvider.GetRequiredService<
ILogger<ImportantBusinessOperationsController>
>();
logger.LogInformation("ImportantBusinessOperationsController deactivated.");base.OnDeactivated();
}
}
}

如你所见,这段代码已经加入了日志记录的逻辑。它使用的是 .NET 提供的标准 ILogger<T> 接口,并结合了构造函数依赖注入(通过 IServiceProvider 获取服务实例),这是XAF推荐的方式。

ASP.NET Core 的日志基础设施会自动将这些日志输出集成到 Aspire 仪表盘中。完成上述更改后,运行程序并点击Important Business Action按钮,即可在仪表盘中查看相关日志输出。按钮会被随机禁用一段时间,并在初始化与交互过程开始时输出日志内容,在仪表盘的“结构化日志(Structured Logs)”页面即可查看这些信息。

界面开发框架DevExpress XAF实践教程图集

界面开发框架DevExpress XAF实践教程图集

要记录 OpenTelemetry 的活动(Activity)并使用计量器(Meter),您需要在应用启动时初始化这些对象,并确保相关代码能够访问到它们。可以通过全局单例模式实现,但在这个示例项目中,更合理的方式是继续使用依赖注入机制,并让它来处理生命周期管理。

以下是 XafAspireDemo.Blazor.Server.Telemetry 类的实现:

namespace XafAspireDemo.Blazor.Server
{
public class Telemetry : IDisposable
{
public ActivitySource ActivitySource { get; }
public Meter Meter { get; }
public string MeterName => Meter.Name;
public Counter<long> ImportantBusinessOperationCounter { get; }
public Histogram<double> ImportantBusinessOperationDuration { get; }public Telemetry(
string serviceName = "XafAspireDemo.Blazor.Server",
string version = "1.0.0"
)
{
ActivitySource = new ActivitySource(serviceName, version);
Meter = new Meter(serviceName, version);ImportantBusinessOperationCounter = Meter.CreateCounter<long>(
"important_business_operation.execution_count"
);
ImportantBusinessOperationDuration = Meter.CreateHistogram<double>(
"important_business_operation.execution_duration"
);
}public void Dispose()
{
ActivitySource.Dispose();
Meter.Dispose();
}
}
}

这里的 ActivitySource、Meter、Counter<T> 和 Histogram<T> 类型都来自 System.Diagnostics.Metrics 命名空间。这个类在应用启动时创建相关对象,在应用结束时自动释放。

您只需要在 Startup.cs 中注册该类为单例服务即可:

builder.AddEntityFrameworkCoreInstrumentation();
});--> var telemetry = new Telemetry();
--> services.AddSingleton(telemetry);--> services
--> .AddOpenTelemetry()
--> .WithTracing(tracing => tracing.AddSource("XafAspireDemo.Blazor.Server"))
--> .WithMetrics(metrics =>
--> {
--> metrics.AddMeter(telemetry.MeterName);
--> });services.AddSingleton(
typeof(Microsoft.AspNetCore.SignalR.HubConnectionHandler<>),

接下来我们要将遥测功能应用到前面创建的业务操作中,只需在 ImportantBusinessAction_Execute 方法中添加几行代码即可:

private async void ImportantBusinessAction_Execute(
object sender,
SimpleActionExecuteEventArgs e
)
{
--> var telemetry = serviceProvider.GetRequiredService<Telemetry>();
var logger = serviceProvider.GetRequiredService<
ILogger<ImportantBusinessOperationsController>
>();importantBusinessAction.Enabled["ImportantBusinessActionRunning"] = false;--> using var activity = telemetry.ActivitySource.StartActivity("ImportantBusinessAction");
logger.LogInformation("ImportantBusinessAction started.");try
{
...
}
catch (Exception ex)
{
logger.LogError(ex, "ImportantBusinessAction failed.");
--> activity?.SetStatus(ActivityStatusCode.Error);
--> activity?.AddException(ex);
throw;
}
finally
{
--> activity?.Stop();importantBusinessAction.Enabled["ImportantBusinessActionRunning"] = true;--> telemetry.ImportantBusinessOperationCounter.Add(1);
--> telemetry.ImportantBusinessOperationDuration.Record(
--> activity.Duration.TotalMilliseconds
--> );
}
}

在方法开始处,我们通过依赖注入获取遥测服务,然后开启一个活动(Activity)。如果执行过程中发生错误,会记录异常信息,并将活动状态设为错误,最后记录计数器和直方图的相关指标值。

这样,当您执行该业务操作时,Aspire 仪表盘便能显示相应的指标与活动信息。值得注意的是,OpenTelemetry 会自动关联活动与指标(如执行时长记录),不需要你手动建立连接。

界面开发框架DevExpress XAF实践教程图集

界面开发框架DevExpress XAF实践教程图集

相关文章:

  • 如何使用.Net Reactor 批量加密 DLL
  • Axure RP11安装、激活、汉化
  • springcloud openfeign 请求报错 java.net.UnknownHostException:
  • Axure项目实战:驾驶舱(数据一张图)制作教程
  • 同为.net/C#的跨平台运行时的mono和.net Core有什么区别?
  • 2025年- H56-Lc164--200.岛屿数量(图论,深搜)--Java版
  • 深入了解 C# 异步编程库 AsyncEx
  • CppCon 2014 学习第2天:Using Web Services in C++
  • 【Java Web】速通JavaScript
  • Flutte ListView 列表组件
  • OpenCV CUDA模块结构分析与形状描述符------计算指定阶数的矩(Moments)所需的总数量函数:numMoments
  • 小程序 - 视图与逻辑
  • React从基础入门到高级实战:React 生态与工具 - React Query:异步状态管理
  • 飞牛NAS+Docker技术搭建个人博客站:公网远程部署实战指南
  • Ubuntu 24.04 LTS Chrome 中文输入法(搜狗等)失效?一行命令解决
  • 5.29打卡
  • 服务器密码安全运维解决新思路:凭据管理SMS+双因素SLA认证结合的方案
  • 我用Qt+Python实现了个监控QQ消息自动下载文件处理的办公外挂程序
  • 数据仓库分层 4 层模型是什么?
  • 动手学深度学习pytorch学习笔记 —— 第四章(2)
  • pc28网站开发/怎么制作网站?
  • 视频源网站怎么做/全国疫情防控最新数据
  • 网站开发用户登录前 登录后/百度词条
  • 企业网站建设开发注意事项/企业网络营销案例
  • 网站建设 东营远见网络公司/广州知名网络推广公司
  • 模板建网站价格/武汉软件测试培训机构排名