基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)

系列文章

  • 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客?

  • 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目

  • 基于.NetCore开发博客项目 StarBlog - (3) 模型设计

  • 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入

  • 基于.NetCore开发博客项目 StarBlog - (5) 开始搭建Web项目

  • 基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列表

  • 基于.NetCore开发博客项目 StarBlog - (7) 页面开发之文章详情页面

  • 基于.NetCore开发博客项目 StarBlog - (8) 分类层级结构展示

  • 基于.NetCore开发博客项目 StarBlog - (9) 图片批量导入

  • 基于.NetCore开发博客项目 StarBlog - (10) 图片瀑布流

  • 基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计

  • 基于.NetCore开发博客项目 StarBlog - (12) Razor页面动态编译

  • 基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能

  • 基于.NetCore开发博客项目 StarBlog - (14) 实现主题切换功能

  • 基于.NetCore开发博客项目 StarBlog - (15) 生成随机尺寸图片

  • 基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)

前言

最近好几天都忙着写代码,没更新文章,近期给博客增加了一些功能,本文一次性介绍~

新增的功能如下:

  • 系统监控:sentry、exceptionless、CLRStats

  • 访问统计

  • 配置管理

  • 初始化

系统监控

PS:其实前面两篇关于日志收集工具介绍的文章也是为了给本文做铺垫

系统监控这块包括日志收集、性能监测和系统状态监测。

日志收集和性能监测我交给了ExceptionLess和Sentry,这俩开源的工具可以很好的完成这些工作,详情可以看我之前写的这俩篇文章:

  • Sentry的安装、配置、使用

  • ExceptionLess的安装、配置、使用

然后状态监测我是基于GitHub上的一个开源项目来魔改的:CLRStats

这个组件可以实时查看CPU、GC、线程的状态,不过原版的实现是作为一个中间件嵌入AspNetCore项目,并且访问的地址只能用Basic认证,不适用。

于是我把代码clone下来之后魔改了一下,变成一个可以调用的服务,并且重新写了API接口,终于方便起来了~

这个接口拿到的数据是这样的,后续在管理后台里面做成可视化图表也比较方便。

{"server": {"machineName": "machineName","systemDateTime": "7/26/2022 11:30:22 PM"},"application": {"cpu": {"usagePercent": 0},"gc": {"gen0CollectCount": 24,"gen1CollectCount": 23,"gen2CollectCount": 22,"heapMemory": 38328872,"heapMemoryFormat": "36 M","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的人觉得很不适应 = =..

这个接口计算总访问量、今日访问量、昨日访问量,方便做对比(受知乎的创作者中心启发)

public object Overview() {ISelect<VisitRecord> GetQuerySet() => _repo.Where(a => !a.RequestPath.StartsWith("/Api"));return new {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#的日期处理还是比较舒服的

public object Trend(int days = 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()});
}

按日期统计

这个简单粗暴不用多说

public object Stats(DateTime date) {var data = _repo.Where(a => a.Time.Date == date.Date && !a.RequestPath.StartsWith("/Api"));return new { Count = data.Count() };
}

注意这里面所有的统计我都过滤了以/Api开头的地址,因为我只需要统计博客前台的访问量就行了。

配置管理

博客还是有很多需要配置的东西,比如说Host

之前我是写在appsettings.json文件里的,按理说也可以,修改这文件之后也能hot reload,不过问题是没法实现在管理后台中修改并保存

所以我打算实现一个配置管理的功能

一开始是把目光瞄准了KV数据库,甚至要求找一个嵌入式的、C#实现的开源项目,叠了这么多buff,果然没找到合适的

(不过前几天好像看到有个大佬发了篇文章介绍用C#手写一个KV数据库的,大赞!)

于是还是用博客本身的数据来实现好了,也不难

老规矩,继续写Service:StarBlog.Web/Services/ConfigService.cs

这里只把关键代码放出来,完整代码可以看GitHub

public class ConfigService {private readonly IConfiguration _conf;private readonly IBaseRepository<ConfigItem> _repo;public ConfigItem? GetByKey(string key) {var item = _repo.Where(a => a.Key == key).First();if (item == null) {// 尝试读取初始化配置var section = _conf.GetSection($"StarBlog:Initial:{key}");if (!section.Exists()) return null;item = new ConfigItem { Key = key, Value = section.Value, Description = "Initial" };item = AddOrUpdate(item);}return item;}public ConfigItem AddOrUpdate(ConfigItem item) {return _repo.InsertOrUpdate(item);}public int? Update(string key, string value, string? description = default) {var item = GetByKey(key);if (item == null) return null;item.Value = value;if (description != null) item.Description = description;return _repo.Update(item);}public string this[string key] {get {var item = GetByKey(key);return item == null ? "" : item.Value;}set {var item = GetByKey(key) ?? new ConfigItem { Key = key };item.Value = value;AddOrUpdate(item);}}
}

这个ConfigService实现了索引器,可以比较方便的实现配置的读取和保存

比如这样

var conf = xxx; // 注入 ConfigService
// 读取配置
Console.WriteLine(conf["host"]);
// 修改配置
conf["host"] = "http://dealiaxy.com";

同时我也写了几个接口,可以通过HTTP的方式管理配置,代码就不放了~

初始化

在我的设计中,这个功能是依赖于配置管理的

所以把配置管理做完之后,我的初始化页面也做出来了

看起来是这样的

dd9ead44b2620cba8234a2063fa6f5e1.png
image

也就是首次运行本项目的时候,会进入这个页面,目前的初始化配置就只有创建管理、设置Host两个,后续应该会慢慢增加其他的

后台是通过is_init这个字段来判断是否有初始化的

直接上Controller代码

[HttpGet]
public IActionResult Init([FromServices] ConfigService conf) {if (conf["is_init"] == "true") {_messages.Error("已经完成初始化!");return RedirectToAction(nameof(Index));}return View(new InitViewModel {Host = conf["host"]});
}[HttpPost]
public IActionResult Init([FromServices] ConfigService conf, [FromServices] IBaseRepository<User> userRepo, InitViewModel vm) {if (!ModelState.IsValid) return View();// 保存配置conf["host"] = vm.Host;conf["is_init"] = "true";// 创建用户// todo 这里暂时存储明文密码,后期要换成MD5加密存储userRepo.Insert(new User {Id = Guid.NewGuid().ToString(),Name = vm.Username,Password = vm.Password});_messages.Success("初始化完成!");return RedirectToAction(nameof(Index));
}

同时还要实现一个View页面,这个就比较简单,代码不放了

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

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

相关文章

堪比JMeter的.Net压测工具 - Crank 入门篇

1. 前言 Crank 是.NET 团队用来运行基准测试的基准测试基础架构&#xff0c;包括&#xff08;但不限于&#xff09;来自TechEmpower Web 框架基准测试的场景,是2021年.NET Conf 大会上介绍的一项新的项目&#xff0c;其前身是Benchmarks。 Crank目标之一是为开发人员提供一种工…

【GlobalMapper精品教程】016:按照指定字段批量生成不同用地类型的矢量图层

Globalmapper中可以很方便的根据指定的字段,对矢量数据进行批量提取,生成不同类型的多个矢量数据,本文以土地利用现状数据为例,基于DLMC,提取出不同用地类型的矢量图层。 参考阅读:【ArcGIS遇上Python】ArcGIS Python按照指定字段批量筛选不同类型的图斑(以土地利用数据…

javascript闭包—围观大神如何解释闭包

闭包的概念已经出来很长时间了&#xff0c;网上资源一大把&#xff0c;本着拿来主意的方法来看看。 这一篇文章 学习Javascript闭包&#xff08;Closure&#xff09; 是大神阮一峰的博文&#xff0c;作者循序渐进&#xff0c;讲的很透彻。下面一一剖析。 1.变量的作用域 变量的…

298. Binary Tree Longest Consecutive Sequence

题目&#xff1a;Given a binary tree, find the length of the longest consecutive sequence path. The path refers to any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The longest consecutive path need to…

Educational Codeforces Round 37 (Rated for Div. 2)

Educational Codeforces Round 37 (Rated for Div. 2) A.Water The Garden 题意&#xff1a;Max想给花园浇水。花园可被视为长度为n的花园床&#xff0c;花园内共有k个水龙头&#xff0c;分别在花园的xi&#xff08;0≤xi<n&#xff09;处&#xff0c;在j秒内花园的[xi-(j-1…

详解 .Net6 Minimal API 的使用方式

随着 .Net6 的发布&#xff0c;微软也改进了对之前 ASP.NET Core 构建方式&#xff0c;使用了新的 Minimal API 模式。以前默认的方式是需要在 Startup 中注册 IOC 和中间件相关&#xff0c;但是在 Minimal API 模式下你只需要简单的写几行代码就可以构建一个 ASP.NET Core的We…

.NET 20周年专访 - 张善友:.NET 技术是如何赋能并改变世界的

点击蓝字关注我们今年是 .NET 发布20周年&#xff0c;值此20周年之际&#xff0c;微软 Reactor 特别策划了 .NET 20周年系列主题专访。我们邀请了数位中国 .NET 领域的技术专家以及社区名人&#xff0c;来聊聊他们与 .NET 的情缘、认识 .NET 的契机、选择 .NET 的理由&#xff…

【ArcGIS错误异常100问】之005:ArcGIS字段计算器python中文编码问题解决

问题描述&#xff1a; 现因工作的需要&#xff0c;对照2017最新版&#xff1a;《土地利用现状分类》&#xff08;GBT 21010-2017&#xff09;&#xff0c;需根据DLMC对DLBM进行批量修改&#xff0c;如旱地是0103&#xff0c;其他林地是0307等&#xff0c;共计19种用地类型。 问…

【ArcGIS微课1000例】0055:根据图层创建自定义图例符号案例教程

在利用ArcGIS作图时,有时候需要根据线状或面状图层自己的矢量形状去创建图例项目符号,本文讲解根据图层创建自定义图例符号。 本实验使用的数据为配套案例数据包中的0055.rar中的水库数据。 文章目录 1. 添加“新建图例图面形状”工具2. 根据图层形状创建符号3. 绘制形状符号…

jQuery 3.3.1已经发布,开发团队正在准备4.0版本

\看新闻很累&#xff1f;看技术新闻更累&#xff1f;试试下载InfoQ手机客户端&#xff0c;每天上下班路上听新闻&#xff0c;有趣还有料&#xff01;\\\jQuery 3.3.1已经发布&#xff0c;其中包含了许多新特性也提出要移除几个之前的特性&#xff0c;移除一些特性是为了jQuery …

C#.NET版本、Visual Studio版本对应关系

C#版本.NET版本Visual Studio版本发布日期特性C# 1.0.NET Framework 1.0Visual Studio .NET 20022002-02-13委托、事件C# 1.1.NET Framework 1.1Visual Studio .NET 20032003-04-24APM&#xff08;异步编程模型&#xff09;C# 2.0.NET Framework 2.0Visual Studio 20052005-11-…

真魔法!图形化管理 Kafka 超轻量的自动化工具

Kafka Magic[1] 是一个用于处理 Apache Kafka 集群的 GUI 工具。它可以查找和显示消息、在 Topic 之间转换和移动消息、查看和更新模式、管理 Topic 以及自动化复杂任务。Kafka Magic 通过方便的用户界面促进 Topic 管理、QA 和集成测试。Kafka Magic Community Edition 可免费…

前端工程构建工具——Yeoman

一、Yeoman 简介 通常在开发新项目时我们都需要配置工程环境&#xff0c;开发目录&#xff0c;需要下载一些库、框架文件&#xff08;如 jQuery、Backbone 等&#xff09;&#xff0c;配置编译环境&#xff08;Less、Sass、Coffeescript等&#xff09;&#xff0c;甚至还要配置…

【FME实战教程】001:FME2020中文安装图文教程(附安装包下载)

文章目录1. 安装license2. 安装FME Desktop3. 安装中文语言4. FME软件下载地址1. 安装license 打开软件安装包中的fme-flexnet-win-x64.msi&#xff0c;如下图所示&#xff1a; 点击Next。 点击Next。 单击install。 点击finish&#xff0c;完成。 &#xff08;1&#xff09;修…

算法导论 第三部分——基本数据结构——第14章:数据结构的扩张

本章通过扩张红黑树构造出两种数据结构&#xff1a;动态顺序统计和区间树。 1、动态顺序统计&#xff1a;查找倒数第i小的数据 复杂度为 lg(n) 为什么是扩张红黑树而不是搜索二叉树或者二叉树&#xff1f; 相对于搜索二叉树&#xff0c;红黑树的平衡性更好&#xff0c;高度在l…

/hgfs下无共享文件夹?/mnt下没有hgfs文件夹?vmhgfs-fuse:找不到命令?

前言&#xff1a;最近在使用linux的过程中&#xff0c;需要在宿主操作系统与客户操作系统间建立共享文件夹&#xff0c;遇到了些许问题&#xff0c;在网上参考了许多文章与各种尝试后&#xff0c;现得以解决&#xff0c;分享如下。1、系统环境&#xff1a;宿主操作系统&#xf…

GraphQL入门有

本文将从GraphQL是什么&#xff0c;为什么要使用GraphQL&#xff0c;使用GraphQL创建简单例子&#xff0c;以及GraphQL实战&#xff0c;四个方面对GraphQL进行阐述。说得不对的地方&#xff0c;希望大家指出斧正。 github项目地址&#xff1a;https://github.com/Charming2015/…

对话庄表伟:开源第一课

庄表伟目前就职于华为的开源管理中心。自2014年开源社成立之初&#xff0c;他便友情参与了开源社的筹办工作。2017年&#xff0c;开源社转型为完全由个人成员组成的组织&#xff0c;庄表伟就以个人身份加入了开源社。作为开源社理事&#xff0c;当被问到“为什么要参选”时&…

【FME实战教程】002:FME完美实现CAD数据转shp案例教程(以三调土地利用现状数据为例)

FME完美实现CAD数据转shp案例教程&#xff08;以三调土地利用数据为例&#xff09; 文章目录1. cad数据预览2. 转换过程3. shp数据预览1. cad数据预览 2. 转换过程 &#xff08;1&#xff09;打开FME Desktop2020中文软件&#xff0c;点击【新建】。 &#xff08;2&#xff09…

Linux学习之01_基础命令介绍

初学Linux&#xff0c;还在摸索中&#xff0c;在这个过程中希望能记录下学习到的东西&#xff0c;参考的的书籍为《鸟哥的Linux私房菜》 在这里学到的主要命令有这几个&#xff1a; data cal bc man shutdown sync 1、基础命令操作 data----显示日期与实践的命令 cal----显示日…