热门看点:基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)
最近好几天都忙着写代码,没更新文章,近期给博客增加了一些功能,本文一次性介绍~
新增的功能如下:
(相关资料图)
PS:其实前面两篇关于日志收集工具介绍的文章也是为了给本文做铺垫
系统监控这块包括日志收集、性能监测和系统状态监测。
日志收集和性能监测我交给了ExceptionLess和Sentry,这俩开源的工具可以很好的完成这些工作,详情可以看我之前写的这俩篇文章:
Sentry的安装、配置、使用ExceptionLess的安装、配置、使用然后状态监测我是基于GitHub上的一个开源项目来魔改的:CLRStats
这个组件可以实时查看CPU、GC、线程的状态,不过原版的实现是作为一个中间件嵌入AspNetCore项目,并且访问的地址只能用Basic认证,不适用。
于是我把代码clone下来之后魔改了一下,变成一个可以调用的服务,并且重新写了API接口,终于方便起来了~
这个接口拿到的数据是这样的,后续在管理后台里面做成可视化图表也比较方便。
{"server":{"machineName":"machineName","systemDateTime":"7/26/202211:30:22PM"},"application":{"cpu":{"usagePercent":0},"gc":{"gen0CollectCount":24,"gen1CollectCount":23,"gen2CollectCount":22,"heapMemory":38328872,"heapMemoryFormat":"36M","isServerGC":true},"thread":{"availableCompletionPortThreads":1000,"availableWorkerThreads":32766,"usedCompletionPortThreads":0,"usedWorkerThreads":1,"usedThreadCount":29,"maxCompletionPortThreads":1000,"maxWorkerThreads":32767}}}
具体代码就不复制粘贴了,我把它放在StarBlog.Contrib项目中,作为一个独立的组件方便调用。
访问统计虽然前面这篇文章有介绍访问统计的实现:基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计
不过只是单纯讲了通过中间件实现访问记录,这些数据存在数据库之后并没有被利用起来
现在就实现了一些简单的统计,目前主要实现了总览数据(总访问、今日、昨日访问)、趋势数据、指定日期统计,这几个功能。
逻辑代码在StarBlog.Web/Services/VisitRecordService.cs中
总览数据代码在这PS:我发现FreeSQL的ISelect对象在链式操作时候的行为很奇怪,我知道是懒加载,但是已经执行了.Count()似乎还没执行,下一行调用的代码甚至会把前面的筛选条件加上,无奈我之内在方法内又写了一个嵌套的方法……
也就是这个GetQuerySet,这点让我这种用习惯DjangoORM的人觉得很不适应 = =..
这个接口计算总访问量、今日访问量、昨日访问量,方便做对比(受知乎的创作者中心启发)
publicobjectOverview(){ISelect趋势数据GetQuerySet()=>_repo.Where(a=>!a.RequestPath.StartsWith("/Api"));returnnew{TotalVisit=GetQuerySet().Count(),TodayVisit=GetQuerySet().Where(a=>a.Time.Date==DateTime.Today).Count(),YesterdayVisit=GetQuerySet().Where(a=>a.Time.Date==DateTime.Today.AddDays(-2).Date).Count(),};}
也就是统计最近n天的访问量
PS:C#的日期处理还是比较舒服的
publicobjectTrend(intdays=7){return_repo.Where(a=>!a.RequestPath.StartsWith("/Api")).Where(a=>a.Time.Date>DateTime.Today.AddDays(-days).Date).GroupBy(a=>a.Time.Date).ToList(a=>new{time=a.Key,date=$"{a.Key.Month}-{a.Key.Day}",count=a.Count()});}按日期统计
这个简单粗暴不用多说
publicobjectStats(DateTimedate){vardata=_repo.Where(a=>a.Time.Date==date.Date&&!a.RequestPath.StartsWith("/Api"));returnnew{Count=data.Count()};}
注意这里面所有的统计我都过滤了以/Api开头的地址,因为我只需要统计博客前台的访问量就行了。
配置管理博客还是有很多需要配置的东西,比如说Host
之前我是写在appsettings.json文件里的,按理说也可以,修改这文件之后也能hot reload,不过问题是没法实现在管理后台中修改并保存
所以我打算实现一个配置管理的功能
一开始是把目光瞄准了KV数据库,甚至要求找一个嵌入式的、C#实现的开源项目,叠了这么多buff,果然没找到合适的
(不过前几天好像看到有个大佬发了篇文章介绍用C#手写一个KV数据库的,大赞!)
于是还是用博客本身的数据来实现好了,也不难
老规矩,继续写Service:StarBlog.Web/Services/ConfigService.cs
这里只把关键代码放出来,完整代码可以看GitHub
publicclassConfigService{privatereadonlyIConfiguration_conf;privatereadonlyIBaseRepository_repo;publicConfigItem?GetByKey(stringkey){varitem=_repo.Where(a=>a.Key==key).First();if(item==null){//尝试读取初始化配置varsection=_conf.GetSection($"StarBlog:Initial:{key}");if(!section.Exists())returnnull;item=newConfigItem{Key=key,Value=section.Value,Description="Initial"};item=AddOrUpdate(item);}returnitem;}publicConfigItemAddOrUpdate(ConfigItemitem){return_repo.InsertOrUpdate(item);}publicint?Update(stringkey,stringvalue,string?description=default){varitem=GetByKey(key);if(item==null)returnnull;item.Value=value;if(description!=null)item.Description=description;return_repo.Update(item);}publicstringthis[stringkey]{get{varitem=GetByKey(key);returnitem==null?"":item.Value;}set{varitem=GetByKey(key)??newConfigItem{Key=key};item.Value=value;AddOrUpdate(item);}}}
这个ConfigService实现了索引器,可以比较方便的实现配置的读取和保存
比如这样
varconf=xxx;//注入ConfigService//读取配置Console.WriteLine(conf["host"]);//修改配置conf["host"]="http://dealiaxy.com";
同时我也写了几个接口,可以通过HTTP的方式管理配置,代码就不放了~
初始化在我的设计中,这个功能是依赖于配置管理的
所以把配置管理做完之后,我的初始化页面也做出来了
看起来是这样的
也就是首次运行本项目的时候,会进入这个页面,目前的初始化配置就只有创建管理、设置Host两个,后续应该会慢慢增加其他的
后台是通过is_init这个字段来判断是否有初始化的
直接上Controller代码
[HttpGet]publicIActionResultInit([FromServices]ConfigServiceconf){if(conf["is_init"]=="true"){_messages.Error("已经完成初始化!");returnRedirectToAction(nameof(Index));}returnView(newInitViewModel{Host=conf["host"]});}[HttpPost]publicIActionResultInit([FromServices]ConfigServiceconf,[FromServices]IBaseRepositoryuserRepo,InitViewModelvm){if(!ModelState.IsValid)returnView();//保存配置conf["host"]=vm.Host;conf["is_init"]="true";//创建用户//todo这里暂时存储明文密码,后期要换成MD5加密存储userRepo.Insert(newUser{Id=Guid.NewGuid().ToString(),Name=vm.Username,Password=vm.Password});_messages.Success("初始化完成!");returnRedirectToAction(nameof(Index));}
同时还要实现一个View页面,这个就比较简单,代码不放了
相关阅读
-
世界热推荐:今晚7:00直播丨下一个突破...
今晚19:00,Cocos视频号直播马上点击【预约】啦↓↓↓在运营了三年... -
NFT周刊|Magic Eden宣布支持Polygon网...
Block-986在NFT这样的市场,每周都会有相当多项目起起伏伏。在过去... -
环球今亮点!头条观察 | DeFi的兴衰与...
在比特币得到机构关注之后,许多财务专家预测世界将因为加密货币的... -
重新审视合作,体育Crypto的可靠关系才能双赢
Block-987即使在体育Crypto领域,人们的目光仍然集中在FTX上。随着... -
简讯:前端单元测试,更进一步
前端测试@2022如果从2014年Jest的第一个版本发布开始计算,前端开发... -
焦点热讯:刘强东这波操作秀
近日,刘强东发布京东全员信,信中提到:自2023年1月1日起,逐步为...