Exceptionless(二) - 使用进阶

作者:markjiang7m2
原文地址:https://www.cnblogs.com/markjiang7m2/p/11100563.html
官网地址:http://letyouknow.net

在上一篇文章Exceptionless - .Net Core开源日志框架中就说到如何对Exceptionless进行本地化部署,不过我也跟大家说了,仅限于能用的阶段。那今天我就继续来探讨一下如何再用好。

后台运行服务

上次我就是直接通过脚本 Start-ElasticSearch.ps1启动ElasticSearch和Kibana服务,但是大家也能看到,服务是运行起来了,同时还有两个命令窗口,如果一个不小心把窗口关闭了,服务也就关闭了,而且一旦服务器重启了,这两个服务也不会自动启动。
我这里先暂时把Kibana扔一边去,来看看ElasticSearch服务。ElasticSearch是直接有脚本支持将ElasticSearch安装为Windows服务,在后台运行。

640?wx_fmt=png

就是这个 elasticsearch-service.bat脚本,支持一下参数:

  • install 将Elasticsearch作为服务安装

  • remove 删除已安装的Elasticsearch服务(并在启动时停止服务)

  • start 启动Elasticsearch服务(如果已安装)

  • stop 停止Elasticsearch服务(如果启动)

  • manager 启动一个GUI来管理已安装的服务

安装
命令行,进入到 elasticsearch-service.bat所在的目录,然后执行下面的脚本

elasticsearch-service.bat install

启动

640?wx_fmt=png

这个时候我们可以直接在浏览器访问 9200端口看看服务是否正常

640?wx_fmt=png

继续使用上次部署好的Exceptionless
(如何使用IIS部署Exceptionless Web服务,请看Exceptionless - .Net Core开源日志框架)

因为我是直接用回之前ElasticSearch的节点,而且也没有清空数据,所以可以直接用之前注册的账号重新登录

640?wx_fmt=png

也是成功的,ElasticSearch服务已经运行在后台了。

自动启动
通过ElasticSearch提供的GUI可以将服务设置为自动启动

elasticsearch-service.bat manager

StartupType选择为 Automatic,再点击OK保存

640?wx_fmt=png

这样,即使服务器重启了,我们的ElasticSearch服务也会自动启动

其实,有玩过Windows服务的朋友一定知道,上面的一些操作在Windows自带的服务管理器也能完成

同时按下"WIN+R" 打开服务的命令运行窗口。在服务运行窗口中输入services.msc

在列表中也可以找到ElasticSearch服务,双击打开属性窗口,跟刚刚的GUI操作就是一样的了

640?wx_fmt=png

再看Web.config

上次我只是改了Exceptionless的端口设置,其实这里面还包含很多配置信息

<add name="RedisConnectionString" connectionString="localhost:6379,abortConnect=false" />	
<add name="ElasticSearchConnectionString" connectionString="http://localhost:9200" />

官方是建议大家安装和配置Redis,这样就可以同时运行多个实例,并且重启不会丢失状态,强烈建议在Linux上运行Redis 3.0+版本, RedisConnectionString就是Redis的连接串

ElasticSearchConnectionString是必须的,指向ElasticSearch服务,如果有多个节点,则使用 ,隔开

<!-- Exceptionless Web 基础Url -->	
<add key="BaseURL" value="http://localhost:50001/#" />	
<!-- 是否启用ssl -->	
<add key="EnableSSL" value="false" />	
<!-- 	
Dev: Use this mode when debugging. (Outbound emails will not be sent)	
QA: Use this mode when deployed to staging. (Outbound emails restricted)	
Production: Use this mode when deployed to production.	
-->	
<add key="WebsiteMode" value="Production" />	
<!-- Controls whether users can signup. -->	
<add key="EnableAccountCreation" value="true" />	
<!-- Controls whether daily summary emails are sent -->	
<add key="EnableDailySummary" value="true" />

网站模式WebsiteMode主要是限制邮件发送,默认值是Dev,不发送邮件,所以我这里设置为Production

邮件发送配置,记得跟上面的WebsiteMode一起配置

<add key="SmtpHost" value="smtp.qq.com" />	
<add key="SmtpPort" value="25" />	
<add key="SmtpEncryption" value="SSL" />	
<add key="SmtpUser" value="xxx@qq.com" />	
<add key="SmtpPassword" value="xxx" />

我在案例中使用的是自己的qq邮箱。我在qq邮箱中已经开启了SMTP服务,并且也通过一个控制台应用程序测试可以发送邮件。
但是在Exceptionless这里一样的设置就是不行,在Web中点击发送邮件,log记录错误如下:
ERROR MailMessageJob Job run "MailMessageJob" failed: 由于意外的数据包格式,握手失败。 System.IO.IOException: 由于意外的数据包格式,握手失败。

清除Url
我们现在使用的Url都会带有 #!,例如

http://localhost:50001/#!/type/error/dashboard

可以按照下面步骤清除字符 #!

  • 首先保证你的IIS是否已经安装了重写模块,可通过双击IIS中的 模块查看是否包含了 RewriteModule

  • 更新 Web.config文件

    • 释放出在 system.webServer中的 rewrite节点

    • 删除 BaseURL值中的 /#

    • 注释了在 system.webServer\modules中的 <removename="RewriteModule"/>标签

  • 修改 app.config.77fc9ddd679d37dc.js文件中 USE_HTML5_MODE的值为 true

进程外运行作业
默认情况下,所有作业都在当前的Web进程中运行。如果发现事件处理开始变慢的时候,可以启动并扩展多个作业实例。通过在进程外运行作业,可以确保所有作业是否正常运行。

  • 首先是要配置安装Redis,这样可以保证Exceptionless与作业之间能够进行通信

  • 更新 Web.config中的 RunJobsInProcess值为 false

  • 更新作业的配置,有两种方法可选:

    • 使用环境变量进行配置Exceptionless。新增环境变量Exceptionless{SETTING NAME} (例如: ExceptionlessBaseURL, ExceptionlessElasticSearchConnectionString)。这是官方推荐的方法,因为它更简单,而且当部署到azure时非常好用

    • 打开AppData\jobs文件夹,然后按照在根目录中 Web.config的配置,再重新配置每个作业的 xxx.exe.config

  • 在每个作业文件夹中都有一个 run.bat文件,双击它就会运行这个作业。当然,也可以将这些作业全部设置为Windows服务在后台运行

更多设置
除了上面提到的设置,Exceptionless还支持很多自定义配置,下面是全部的设置列表,大家可根据自己的需要进行定制
列表按照这个格式进行排列:设置项 (数据类型,默认值)

EnableSSL (bool)	
BaseURL (string)	
InternalProjectId (string, "54b56e480ef9605a88a13153")	
WebsiteMode (WebsiteMode, "Dev")	
AppScope (string, String.Empty)	
TestEmailAddress (string)	
AllowedOutboundAddresses (List<string>, "exceptionless.io")	
RunJobsInProcess (bool, true)	
BotThrottleLimit (int, 25)	
ApiThrottleLimit (int, Int32.MaxValue)	
EventSubmissionDisabled (bool)	
MaximumEventPostSize (long, 1000000)	
MaximumRetentionDays (int, 180)	
EnableDailySummary (bool)	
MetricsServerName (string, "127.0.0.1")	
MetricsServerPort (int, 8125)	
EnableMetricsReporting (bool)	
RedisConnectionString (string)	
EnableRedis (bool)	
DisableSnapshotJobs (bool)	
DisableIndexConfiguration (bool)	
ElasticSearchConnectionString (string)	
ElasticSearchNumberOfShards (int, 1)	
ElasticSearchNumberOfReplicas (int)	
EnableElasticsearchTracing (bool)	
LdapConnectionString (string)	
EnableActiveDirectoryAuth (bool)	
EnableSignalR (bool, true)	
Version (string)	
EnableIntercom (bool)	
IntercomAppSecret (string)	
EnableAccountCreation (bool, true)	
MicrosoftAppId (string)	
MicrosoftAppSecret (string)	
FacebookAppId (string)	
FacebookAppSecret (string)	
GitHubAppId (string)	
GitHubAppSecret (string)	
GoogleAppId (string)	
GoogleAppSecret (string)	
GoogleGeocodingApiKey (string)	
EnableBilling (bool)	
StripeApiKey (string)	
StorageFolder (string)	
AzureStorageConnectionString (string)	
EnableAzureStorage (bool)	
BulkBatchSize (int, 1000)	
SmtpHost (string)	
SmtpPort (int, 587)	
SmtpEnableSsl (bool, true)	
SmtpUser (string)	
SmtpPassword (string)

更多日志类型

Exceptionless除了支持记录Exception,也可以记录LogMessage、Broken Links 、Feature Usages

LogMessage
LogMessage支持多种级别的日志信息

  • Other

  • Trace

  • Debug

  • Info

  • Warn

  • Error

  • Fatal

  • Off

用法也很简单,直接在你想要记录日志的地方直接加一句

ExceptionlessClient.Default.CreateLog("日志信息", LogLevel.Debug).AddTags("tag1", "tag2").Submit();

所以我们在应用的过程中,可以添加一个统一的接口

public interface ILogger	
{	void Debug(string message, params string[] tags);	void Error(string message, params string[] tags);	void Fatal(string message, params string[] tags);	void Info(string message, params string[] tags);	void Off(string message, params string[] tags);	void Other(string message, params string[] tags);	void Trace(string message, params string[] tags);	void Warn(string message, params string[] tags);	
}
using Exceptionless;	
using Exceptionless.Logging;
public class ExceptionlessLogger : ILogger	
{	public void Debug(string message, params string[] tags)	{	ExceptionlessClient.Default.CreateLog(message, LogLevel.Debug).AddTags(tags).Submit();	}	public void Error(string message, params string[] tags)	{	ExceptionlessClient.Default.CreateLog(message, LogLevel.Error).AddTags(tags).Submit();	}	public void Fatal(string message, params string[] tags)	{	ExceptionlessClient.Default.CreateLog(message, LogLevel.Fatal).AddTags(tags).Submit();	}	public void Info(string message, params string[] tags)	{	ExceptionlessClient.Default.CreateLog(message, LogLevel.Info).AddTags(tags).Submit();	}	public void Off(string message, params string[] tags)	{	ExceptionlessClient.Default.CreateLog(message, LogLevel.Off).AddTags(tags).Submit();	}	public void Other(string message, params string[] tags)	{	ExceptionlessClient.Default.CreateLog(message, LogLevel.Other).AddTags(tags).Submit();	}	public void Trace(string message, params string[] tags)	{	ExceptionlessClient.Default.CreateLog(message, LogLevel.Trace).AddTags(tags).Submit();	}	public void Warn(string message, params string[] tags)	{	ExceptionlessClient.Default.CreateLog(message, LogLevel.Warn).AddTags(tags).Submit();	}	
}

然后在 Startup.csConfigureServices方法注入 ExceptionlessLogger

public void ConfigureServices(IServiceCollection services)	
{	services.AddSingleton<ILogger, ExceptionlessLogger>();	services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);	
}

这样就可以更方便地使用了

public class ValuesController : ControllerBase	
{	public ILogger _logger;	public ValuesController(ILogger logger)	{	_logger = logger;	}	// GET api/values/{id}	[HttpGet("{id}")]	public ActionResult<string> Get(int id)	{	try	{	_logger.Info("Test msg", "tag1", "tag2");	throw new Exception();	}	catch (Exception ex)	{	ex.ToExceptionless().AddTags("tag1", "tag2").Submit();	}	return $"value {id}";	}	
}

Broken Links
记录404找不到请求的日志

像我这里没有添加favicon.ico图标,使用Chrome浏览器会自动请求这个资源,因此,Exceptionless就记录了这样的日志

640?wx_fmt=png

也可以直接在Api服务中调用如下面语句添加这种类型的日志

ExceptionlessClient.Default.CreateNotFound("404 not found").SetType("404").SetSource($"api/values/{id}");

Feature Usages
类似的也可以添加Feature Usages日志

ExceptionlessClient.Default.CreateFeatureUsage("Feature 1").SetSource($"api/values/{id}").SetType("FeatureType").Submit();

事件

上面所说的所有日志类型,最终都会通过事件进行记录,Exceptionless也支持我们直接记录一个事件

例子如下:

var dataDic = new Exceptionless.Models.DataDictionary();	
dataDic.Add("key", "value");	
ExceptionlessClient.Default.SubmitEvent(new Exceptionless.Models.Event	
{	Count = 1,	Date = DateTime.Now,	Data = dataDic,	Geo = "geo",	Message = "message",	ReferenceId = "referencelId",	Source = "source",	Tags = new Exceptionless.Models.TagSet() { "tags" },	Type = "type"	
});

Exceptionless同时也支持我们捕获事件提交过程和事件提交后的事件,这样我们就可以在过程中做一些操作,例如可以忽略 404的请求,或者针对某些特殊日志返回某些信息

为了代码的整洁,可以将Exceptionless的配置单独放到一个cs文件中

添加一个 ExceptionlessBuilderExtensions

public static class ExceptionlessBuilderExtensions	
{	public static IApplicationBuilder UseExceptionless(this IApplicationBuilder app, IConfiguration configuration)	{	ExceptionlessClient.Default.Configuration.ApiKey = configuration["Exceptionless:ApiKey"];	ExceptionlessClient.Default.Configuration.ServerUrl = configuration["Exceptionless:ServerUrl"];	ExceptionlessClient.Default.SubmittingEvent += OnSubmittingEvent;	app.UseExceptionless();	return app;	}	private static void OnSubmittingEvent(object sender, EventSubmittingEventArgs e)	{	if (e.Event.IsNotFound())	{	e.Cancel = true;//取消事件提交	return;	}	// 修改日志信息	if (e.Event.Source == "sourceA")	{	e.Event.AddTags("systemLog");	}	//TODO:	}	private static void OnSubmittedEvent(object sender, EventSubmittedEventArgs e)	{	// 做点什么东西	if (e.Event.Source == "sourceA")	{	//TODO:	}	}	
}

然后修改 Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)	
{	……	app.UseExceptionless(Configuration);	……	
}

Exceptionless 日志查询

Exceptionless Web站点已经帮我们做好项目、时间、日志类型的分类,大家可以很直观地进行操作查询。
我这里要关注的是 Filter查询

前面记录日志的时候,有添加了 tagType等信息,这时候就可以使用Filter进行查询了。
语法:

[FilterType]:[value1] {or} {[value2]}

or是用于查询多个该类型值的日志时使用

例如:tag:tag1

640?wx_fmt=png

列几个可能比较常用的

  • source:"my log source" or "my log source"

  • type:error

  • level:Error

  • ip:127.0.0.1

如果是要同时输入多种类型的条件:

[FilterType]:[value] {OR|AND} {[FilterType]:[value]}

例如:tag:tag1 OR ip:127.0.0.1

更多的语法可以看官网说明
https://github.com/exceptionless/Exceptionless/wiki/Filtering-Searching

总结

在这篇文章中,我基本就是顺着Exceptionless Self Hosting的介绍做了一遍,不过有一些东西因为没有实际环境,所以也没有去做,然后我这个也只是一个Demo,暂时也没有做相关的压力测试,所以也不知道这货真正在生产环境大量用起来的时候会有一些什么表现,会不会踩到什么坑。欢迎大家在留言区跟我一起交流。今天就先跟大家介绍到这里,希望大家能持续关注我们。

参考文献
本文在编写过程中引用或参考了以下文章中的部分内容,如有侵权,请联系修改或删除。
https://www.cnblogs.com/edisonchou/p/exceptionlessdeploymentonproductionenv_introduction.html
https://www.cnblogs.com/ants/p/8580890.html

640?wx_fmt=jpeg


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315220.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ozon Tech Challenge 2020 (Div.1 + Div.2) F. Kuroni and the Punishment 随机化

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你nnn个数&#xff0c;每次操作可以选择将某个数1,−11,-11,−1&#xff0c;求最少进行多少次操作使得所有数都为正数且gcd>1gcd>1gcd>1。 思路&#xff1a; 考虑gcd2gcd2gcd2的情况&#xff0…

【洛谷P4841】城市规划【指数型生成函数】【麦克劳林级数】【多项式对数】

传送门 题意&#xff1a;求NNN个点的带标号无向连通简单图的个数。 N≤130000N \leq 130000N≤130000 这个问题的主要矛盾在于连通 这个并不好表示&#xff0c;但可以用这个表示出不要求连通的方案数 由于带标号&#xff0c;先构造答案的EGF f(x)∑i0∞aii!xif(x)\sum_{i0}…

基于 Kong 和 Kubernetes 的 WebApi 多版本解决方案

前言大家好&#xff0c;很久没有写博客了&#xff0c;最近半年也是比较的忙&#xff0c;所以给关注我的粉丝们道个歉。去年和朱永光大哥聊的时候提了一下我们的这个方案&#xff0c;他说让我有空写篇博客讲一下&#xff0c;之前是非常的忙&#xff0c;所以这次趁着有些时间就写…

CodeCraft-20 (Div. 2) D. Nash Matrix 构造 + dfs

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给定一个n∗nn*nn∗n的矩阵&#xff0c;每个点上面都有一个xi,yix_i,y_ixi​,yi​&#xff0c;表示这个点到xi,yix_i,y_ixi​,yi​这个点停下&#xff0c;当xi−1,yi−1x_i-1,y_i-1xi​−1,yi​−1的时候代表…

【HAOI2018】染色【反向二项式反演】【NTT卷积】

传送门 题意&#xff1a;NNN个位置染MMM种颜色&#xff0c;恰好出现SSS次的颜色数量恰好为kkk时的愉悦度为wkw_kwk​,求所有方案的愉悦度之和。对100453580910045358091004535809取模。 N≤1e7N \leq 1e7N≤1e7,M≤1e5M \leq 1e5M≤1e5,S≤150S \leq 150S≤150 本题的恶心之处…

从严治码-别人在项目中下毒,我该怎么治?

01 从软考说起从4月份开始&#xff0c;由于备考《系统集成项目管理工程师》的原因&#xff0c;博客没有持续更新&#xff0c;在上半年考试结束之后&#xff0c;又对项目进行了一些收尾的工作。下面就这段时间的学习作一个记录和总结吧。在学习的过程中&#xff0c;提炼了一些自…

CodeCraft-20 (Div. 2) C. Primitive Primes 思维 + 数论

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你两个长度分别为n,mn,mn,m的多项式&#xff0c;将他们乘起来&#xff0c;问系数modp0\bmod p 0modp0的项的指数是多少&#xff0c;两个多项式所有项的系数gcd1gcd1gcd1。 n,m<1e6n,m<1e6n,m<1e6…

【LOJ166】拉格朗日插值2【拉格朗日插值】【NTT卷积】

传送门 题意&#xff1a;给定n,m,f(0),f(1),......,f(n)n,m,f(0),f(1),... ...,f(n)n,m,f(0),f(1),......,f(n)&#xff0c;求f(m),f(m1),......f(mn)f(m),f(m1),... ...f(mn)f(m),f(m1),......f(mn) 模998244353998244353998244353 n≤100000,m≤1e8,n<mn \leq 100000,m \…

学习MVVM设计模式后第一次用于生产

WPF的MVVM设计模式从winform转变到WPF的过程&#xff0c;难点主要还是在MVVM的设计模式。当然&#xff0c;如果依然采用winform的涉及方式&#xff0c;在每个控件背后绑定事件的方式运用在wpf中&#xff0c;依然可行&#xff0c;但是假如GUI改版&#xff0c;其背后绑定的特别为…

剑指 Offer 14- II. 剪绳子 II

给你一根长度为 n 的绳子&#xff0c;请把绳子剪成整数长度的 m 段&#xff08;m、n都是整数&#xff0c;n>1并且m>1&#xff09;&#xff0c;每段绳子的长度记为 k[0],k[1]...k[m - 1] 。请问 k[0]*k[1]*...*k[m - 1] 可能的最大乘积是多少&#xff1f;例如&#xff0c;…

Educational Codeforces Round 108 (Rated for Div. 2) D. Maximum Sum of Products 思维 + dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你两个长度为nnn的数组a,ba,ba,b&#xff0c;你可以至多反转一段连续区间&#xff0c;求∑i1nai∗bi\sum _{i1}^n a_i*b_i∑i1n​ai​∗bi​最大是多少。 n<5e3n<5e3n<5e3 思路&#xff1a; 首…

【CF1215E】Marbles【状压DP】

传送门 题意&#xff1a;给一个长为NNN的序列aaa&#xff0c;每次操作交换两个相邻位置&#xff0c;求最少操作次数使得所有相同的值连成一片。 N≤400000N \leq 400000N≤400000,ai≤20a_i \leq20ai​≤20 我们发现aia_iai​很小&#xff0c;盲猜单独考虑 我们重新确认一个…

netcore mvc快速开发系统(菜单,角色,权限[精确到按钮])开源

基于netcore2.0 mvc 开发的 快速搭建具有如下特色的后台管理系统用户管理菜单管理角色管理权限管理[精确到按钮]&#xff09;代码生成器代码克隆到本地 用vs2017或以上版本 打开工程。项目结构如下&#xff1a;找到DbModel下面的初始化db脚本里面包含4张表的schema和初始化数据…

剑指 Offer 25. 合并两个排序的链表

输入两个递增排序的链表&#xff0c;合并这两个链表并使新链表中的节点仍然是递增排序的。 示例1&#xff1a; 输入&#xff1a;1->2->4, 1->3->4 输出&#xff1a;1->1->2->3->4->4 限制&#xff1a; 0 < 链表长度 < 1000 思路&#xff1a;和…

Codeforces Round #720 (Div. 2) C. Nastia and a Hidden Permutation 交互

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你一个序列ppp长度nnn&#xff0c;每次可以执行两个种询问&#xff1a; t1max(min(x,pi),min(x1,pj))t1\ \ max(min(x,p_i),min(x1,p_j))t1 max(min(x,pi​),min(x1,pj​)) t2min(max(x,pi),max(x1,pj))t…

【NOIP2018】赛道修建【二分】【树形dp】【multiset】【贪心】

传送门 题意&#xff1a;给一棵带边权的树&#xff0c;求MMM条没有公共边的路径的最小长度的最大值。 N≤50000N \leq50000N≤50000 抛开NOIP不谈&#xff0c;其实这题本身出的很好 显然二分 问题转化成了“最多可以找多少条长度不小于kkk的路径” 递归处理 对于每个结点…

asp.net core 系列之Startup

这篇文章简单记录 ASP.NET Core中 &#xff0c;startup类的一些使用。一.前言在 Startup类中&#xff0c;一般有两个方法&#xff1a;ConfigureServices 方法: 用来配置应用的 service 。 Configure 方法&#xff1a;创建应用的请求处理管道它们都在应用启动时&#xff0c;被AS…

可持久化Splay 学习笔记

可持久化Splay是怎么回事呢&#xff1f;Splay相信大家都很熟悉&#xff0c;但是可持久化Splay是怎么回事呢&#xff0c;下面就让小编带大家一起了解吧。   可持久化Splay&#xff0c;其实就是将Splay持久化一下&#xff0c;大家可能会很惊讶Splay怎么可以持久化呢&#xff1f…

译 | .NET Core 基础架构进化之路(一)

原文&#xff1a;Matt Mitchell翻译&#xff1a;Edi Wang随着 .NET Core 3.0 Preview 6 的推出&#xff0c;我们认为简要了解一下我们基础设施系统的历史以及过去一年左右所做的重大改进会很有用。如果您对构建基础结构感兴趣&#xff0c;或者想要了解我们如何构建与 .NET Core…

【洛谷P4705】玩游戏【二项式定理】【NTT卷积】【生成函数】【分治NTT】【函数求导】【多项式对数】

传送门 题意&#xff1a;给定长度为N,MN,MN,M的序列a,ba,ba,b和ttt&#xff0c;随机选取x∈[1,N],y∈[1,M]x \in[1,N],y\in[1,M]x∈[1,N],y∈[1,M],对于i1,2,...,t,i 1,2,...,t,i1,2,...,t,求(axby)i(a_xb_y)^i(ax​by​)i的期望 N,M,t≤100000N,M,t \leq100000N,M,t≤100000 …