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

界面开发框架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实践教程图集

相关文章:

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

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

多卡训练核心技术详解

多卡训练核心技术详解 多卡训练 主要围绕分布式环境初始化、模型并行化、数据分片和梯度同步展开。下面结合您的代码,详细解释这些核心部分: 并行执行命令 torchrun --nproc_per_node=5 TokenLossMulCard.py 1. 分布式环境初始化 def init_distributed():init_process_…...

深度学习全面掌握指南

一、引言 深度学习是机器学习的一个分支&#xff0c;它通过构建多层神经网络来模拟人类大脑的信息处理方式&#xff0c;从而实现对复杂数据的自动特征提取和模式识别。近年来&#xff0c;深度学习在计算机视觉、自然语言处理、语音识别等领域取得了巨大的突破&#xff0c;引发…...

magic-api配置Git插件教程

一、配置gitee.com 1&#xff0c;生成rsa密钥&#xff0c;在你的电脑右键使用管理员身份运行&#xff08;命令提示符&#xff09;&#xff0c;执行下面命令 ssh-keygen -t rsa -b 2048 -m PEM一直按回车键&#xff0c;不需要输入内容 找到 你电脑中的~/.ssh/id_rsa.pub 文件…...

算法打卡第11天

36.有效的括号 &#xff08;力扣20题&#xff09; 示例 1&#xff1a; **输入&#xff1a;**s “()” **输出&#xff1a;**true 示例 2&#xff1a; **输入&#xff1a;**s “()[]{}” **输出&#xff1a;**true 示例 3&#xff1a; **输入&#xff1a;**s “(]”…...

【决策分析】基于Excel的多变量敏感性分析解决方案

在Excel中实现多变量敏感性分析&#xff08;3个及以上变量&#xff09;需要结合更灵活的工具和方法&#xff0c;因为Excel内置的数据表功能仅支持最多双变量分析。以下是针对多变量场景的解决方案&#xff0c;按复杂度和实用性排序&#xff1a; 方法1&#xff1a;场景管理器 摘…...

php:5.6-apache Docker镜像中安装 gd mysqli 库 【亲测可用】

Dockerfile 代码如下&#xff1a; FROM php:5.6-apache# 使用Debian归档源 RUN echo "deb http://archive.debian.org/debian stretch main contrib non-free" > /etc/apt/sources.list && \echo "deb http://archive.debian.org/debian-security s…...

小程序跳转H5或者其他小程序

1. h5跳转小程序有两种情况 &#xff08;1&#xff09;从普通浏览器打开的h5页面跳转小程序使用wx-open-launch-weapp可以实现h5跳转小程序 <wx-open-launch-weappstyle"display:block;"v-elseid"launch-btn":username"wechatYsAppid":path…...

【AI赋能,视界升级】智微智能S134 AI OPS,重构智慧大屏未来

智慧教室中&#xff0c;教师通过电子白板&#xff0c;4K高清课件、3D教学模型同步呈现&#xff0c;后排学生也能看清画面细节&#xff0c;课堂变得趣味十足&#xff1b;智能会议室里&#xff0c;会议内容、多人云会议多屏投放依旧畅通清晰&#xff0c;会议纪要自动生成Word/PPT…...

外网访问可视化工具 Grafana (Linux版本)

Grafana 是一款强大的可视化监控指标的展示工具&#xff0c;可以将不同的数据源数据以图形化的方式展示&#xff0c;不仅通用而且非常美观。它支持多种数据源&#xff0c;如 prometheus 等&#xff0c;也可以通过插件和 API 进行扩展以满足各种需求。 本文将详细介绍如何在本地…...

ass字幕嵌入mp4带偏移

# 格式转化文件&#xff0c;包含多种文件的互相转化&#xff0c;主要与视频相关 from pathlib import Path import subprocess import random import os import reclass Utils(object):staticmethoddef get_decimal_part(x: float) -> float:s format(x, .15f) # 格式化为…...

WPF响应式UI的基础:INotifyPropertyChanged

INotifyPropertyChanged 1 实现基础接口2 CallerMemberName优化3 数据更新触发策略4 高级应用技巧4.1 表达式树优化4.2 性能优化模式4.3 跨平台兼容实现 5 常见错误排查 在WPF的MVVM架构中&#xff0c; INotifyPropertyChanged是实现数据驱动界面的核心机制。本章将深入解析属…...

JavaScript字符串方法全面指南:从基础到高级应用

在JavaScript开发中&#xff0c;字符串(String)是最常用的数据类型之一&#xff0c;用于存储和操作文本数据。JavaScript提供了丰富的内置方法来处理字符串&#xff0c;掌握这些方法能极大提高开发效率。本文将全面介绍JavaScript中的字符串方法&#xff0c;按照"先总后分…...

浅谈 JavaScript 性能优化

文章目录 概要一、代码执行优化1. 减少全局变量访问2. 避免不必要的计算3. 优化循环操作 二、内存管理优化1. 减少内存泄漏2. 对象池与内存复用 三、渲染性能优化1. 避免强制同步布局2. 减少 DOM 操作3. 优化动画与合成 四、网络加载优化1. 代码压缩与 Tree Shaking2. 按需加载…...

React从基础入门到高级实战:React 生态与工具 - 构建与部署

React 构建与部署 引言 在现代Web开发中&#xff0c;构建与部署是项目从开发到上线的关键环节。对于React开发者而言&#xff0c;掌握构建优化和部署策略不仅能提升应用的性能&#xff0c;还能确保项目的稳定性和安全性。随着React应用的复杂性不断增加&#xff0c;合理的构建…...

Kafka性能调优三剑客:深度解析buffer_memory、linger_ms和batch_size

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 持续学习&#xff0c;不断…...

5分钟学会网络服务搭建,飞凌i.MX9352 + Linux 6.1实战示例

在“万物互联”的技术浪潮下&#xff0c;网络服务已成为连接物理世界与数字世界的核心纽带&#xff0c;它不仅赋予了终端设备“开口说话”的能力&#xff0c;更构建了智能设备的开发范式。 本文就将以飞凌嵌入式OK-MX9352-C开发板&#xff08;搭载了在工业物联网领域广泛应用的…...

网络安全-等级保护(等保) 3-2-2 GB/T 28449-2019 第7章 现场测评活动/第8章 报告编制活动

################################################################################ GB/T 28449-2019《信息安全技术 网络安全等级保护测评过程指南》是规定了等级测评过程&#xff0c;是纵向的流程&#xff0c;包括&#xff1a;四个基本测评活动:测评准备活动、方案编制活…...

74道TypeScript高频题整理(附答案背诵版)

1.简述什么是TypeScript &#xff1f; TypeScript是一种由Microsoft开发和维护的开源编程语言。它是JavaScript的一个超集&#xff0c;意味着它扩展了JavaScript的功能&#xff0c;包括添加了类型系统和对ES6的新特性的支持。TypeScript的设计目标是帮助开发者捕捉代码中的错误…...

PostgreSQL 临时表空间

PostgreSQL 临时表空间 PostgreSQL 使用临时表空间来存储查询执行过程中产生的临时数据&#xff0c;与 Oracle 类似但实现方式有所不同。 一、临时表空间基本概念 PostgreSQL 的临时表空间主要用于存储&#xff1a; 排序操作&#xff08;ORDER BY、GROUP BY、DISTINCT&…...

N2语法 状態

1&#xff0c;&#xff5e;てならない  接続&#xff1a;て型  意味&#xff1a;…得不得了(强调自然产生的情感&#xff0c;可接自发动词)  例文&#xff1a;     お腹が痛くてならない。     心配でならない。     両親に会いたくてならない。&#xff08;非常…...

从Node.js到Go:如何从NestJS丝滑切换并爱上Sponge框架

引言 各位 NestJS 老司机们&#xff0c; 不得不说&#xff0c;用装饰器开发 API 简直像在键盘上跳华尔兹——Controller 转个圈&#xff0c;Get 踮个脚&#xff0c;Injectable 优雅谢幕&#xff0c;三下五除二就能搭出个像模像样的后端服务。TypeScript 的类型检查就像个贴心管…...

海思 35XX MIPI读取YUV422

1.项目背景&#xff1a; 使用海思芯片&#xff0c;接收FPGA发送的MIPI数据&#xff0c;不需要ISP处理&#xff0c;YUV图像格式为YUV422。 2.移植MIPI驱动 修改IMX347的驱动远吗&#xff0c;将I2C读写的部分注释&#xff0c;其他的不用再做修改。 int imx347_slave_i2c_init(ot…...

sass三大循环语法

for for 指令可以在限制的范围内重复输出格式&#xff0c;每次按要求&#xff08;变量的值&#xff09;对输出结果做出变动。这个指令包含两种格式&#xff1a;for $var from through &#xff0c;或者 for v a r f r o m < s t a r t > t o < e n d > &#xff…...

第1章 Redis 概述

一、Redis 简介 Redis,Remote Dictionary Server,远程字典服务,由意大利人Salvatore Sanfilippo(又名Antirez)开发,是一个使用ANSI C 语言编写&#xff64;支持网络&#xff64; 可基于内存亦可持久化的日志型&#xff64;NoSQL 开源内存数据库,其提供多种语言的API&#xff61…...

硬件工程师笔记——二极管Multisim电路仿真实验汇总

目录 1 二极管基础知识 1.1 工作原理 1.2 二极管的结构 1.3 PN结的形成 1.4 二极管的工作原理详解 正向偏置 反向偏置 multisim使用说明链接 2 二极管特性实验 2.1 二极管加正向电压 2.2 二极管加反向电压 2.3 二极管两端的电阻 2.4 交流电下二级管工作 2.5 二极…...

30V/3A,云岑CP8335B,完美替换EUP3484

1 FEATURES ● Wide Input Voltage Range: 6V ~ 30V ● Low RDS(ON) for Internal Switches (Top/Bottom): 90mΩ/65 mΩ ● 3A output current capability ● 500kHz Switching Frequency Minimize the External Components ● Internal 1.5-ms Soft-Start ● 0.6V/0.8V/0.925…...

基于大模型预测的FicatIII-IV期股骨头坏死综合治疗研究报告

目录 一、引言 1.1 研究背景与目的 1.2 国内外研究现状 1.3 研究意义和创新点 二、FicatIII-IV 期股骨头坏死概述 2.1 疾病定义与分期 2.2 病因与病理机制 2.3 临床症状与诊断方法 三、大模型预测原理与方法 3.1 大模型简介 3.2 数据收集与预处理 3.3 模型训练与优…...

promptfoo:让语言模型评测不再“靠感觉”——一站式 LLM 自动化测评神器深度解读

大家好&#xff0c;这里是你们喜闻乐见、永远不低调的 AI 技术博主。这篇分享&#xff0c;我要隆重介绍一个我愿称之为“LLM 测试自动化福音”的神器——promptfoo。 如果你做 LLM&#xff08;大模型&#xff09;落地开发&#xff0c;调教 prompt 拼死拼活&#xff0c;一上线用…...

LINUX安装运行jeelowcode后端项目(idea启动)

参考 LINUX安装运行jeelowcode后端项目&#xff08;命令行&#xff09;-CSDN博客 IntelliJ IDEA下载地址&#xff08;社区版、付费版&#xff09;-CSDN博客 软件已安装好&#xff0c;数据库也初始化完毕。 步骤1&#xff1a;打开项目目录步骤2&#xff1a;配置JDK步骤3&…...