安装MiniProfiler

  • Install-Package MiniProfiler.AspNetCore.Mvc

在startup.cs 中配置服务ConfigureServices

  1. services.AddMiniProfiler(options =>
  2. {
  3. options.RouteBasePath = "/profiler";//注意这个路径要和下边 index.html 脚本配置中的一致,
  4. (options.Storage as MemoryCacheStorage).CacheDuration = TimeSpan.FromMinutes(10);
  5. }

最后,调用下中间件即可:

  1. app.UseMiniProfiler();

在 Swagger 中配置 MiniProfiler

MiniProfiler - 图1 MiniProfiler - 图2

  1. <script async="async" id="mini-profiler" src="/profiler/includes.min.js?v=4.0.138+gcc91adf599"
  2. data-version="4.0.138+gcc91adf599" data-path="/profiler/"
  3. data-current-id="4ec7c742-49d4-4eaf-8281-3c1e0efa748a" data-ids="" data-position="Left"
  4. data-authorized="true" data-max-traces="15" data-toggle-shortcut="Alt+P"
  5. data-trivial-milliseconds="2.0" data-ignored-duplicate-execute-types="Open,OpenAsync,Close,CloseAsync">
  6. </script>
  7. <!-- HTML for static distribution bundle build -->
  8. <!DOCTYPE html>
  9. <html lang="en">
  10. <head>
  11. <meta charset="UTF-8">
  12. ........
  13. ........
  • 具体的参数请自行研究吧,基本都能看懂,比如版本,/profiler的路径,position的位置显示(我是左边),authorized的是否权限max-traces最多显示多少条(15)等等。

  • 然后我们修改下中间件去调用我们这个 index.html 页面:

  1. app.UseSwaggerUI(c =>
  2. {
  3. typeof(ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version =>
  4. {
  5. c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{ApiName} {version}");
  6. });
  7. // 将swagger首页,设置成我们自定义的页面,记得这个字符串的写法:程序集名.index.html
  8. c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("Blog.Core.index.html");
  9. });
  • 最后,记得一定要配置了使用静态资源文件的中间件:
  1. app.UseStaticFiles();

在接口中使用 MiniProfiler

  1. public async Task<object> Get(int id, int page = 1, string bcategory = "技术博文")
  2. { ......// 你可以用这种包括的形式
  3. using (MiniProfiler.Current.Step("开始加载数据:"))
  4. {
  5. if (redisCacheManager.Get<object>("Redis.Blog") != null)
  6. {
  7. // 也可以直接这么写
  8. MiniProfiler.Current.Step("从Redis服务器中加载数据:");
  9. blogArticleList = redisCacheManager.Get<List<BlogArticle>>("Redis.Blog");
  10. }
  11. else
  12. {
  13. MiniProfiler.Current.Step("从MSSQL服务器中加载数据:");
  14. blogArticleList = await blogArticleServices.Query(a => a.bcategory == bcategory);
  15. redisCacheManager.Set("Redis.Blog", blogArticleList, TimeSpan.FromHours(2));
  16. }
  17. }
  18. ......
  19. }

MiniProfiler - 图3

切面 MiniFilter 分析

  • 很简单,只需要在 AOP 日志记录中,配置 MiniProfiler 即可
  1. try
  2. {
  3. // 就是这里!!
  4. MiniProfiler.Current.Step($"执行Service方法:{invocation.Method.Name}() -> ");
  5. invocation.Proceed();
  6. }
  7. catch (Exception e)
  8. {
  9. //执行的 service 中,捕获异常
  10. dataIntercept += ($"方法执行中出现异常:{e.Message + e.InnerException}");
  11. }

在Swagger中展示 Sql 执行日志

如果想要开启这个 SQL AOP的功能,请参考我的源代码,主要是通过 SqlSugar 的 相关功能来实现,发现主分支,已经没有了 DbContext 上下文了,因为目前我采用了事务工作单元的形式,所以不用上下文来处理了,统一使用 ISqlsugarClient 的形式了,最新版的Sqlsugar也可以通过注入的形式,直接把AOP给配置进去,

  • 查看 SqlsugarSetup.cs 类:
  1. BaseDBConfig.MutiConnectionString.Item1.ForEach(m =>
  2. {
  3. listConfig.Add(new ConnectionConfig()
  4. {
  5. ConfigId = m.ConnId.ObjToString().ToLower(),
  6. ConnectionString = m.Connection,
  7. DbType = (DbType)m.DbType,
  8. IsAutoCloseConnection = true,
  9. IsShardSameThread = false,
  10. AopEvents = new AopEvents
  11. {
  12. OnLogExecuting = (sql, p) =>
  13. {
  14. if (Appsettings.app(new string[] { "AppSettings", "SqlAOP", "Enabled" }).ObjToBool())
  15. {
  16. Parallel.For(0, 1, e =>
  17. {
  18. MiniProfiler.Current.CustomTiming("SQL:", GetParas(p) + "【SQL语句】:" + sql);
  19. LogLock.OutSql2Log("SqlLog", new string[] { GetParas(p), "【SQL语句】:" + sql });
  20. });
  21. }
  22. }
  23. },
  24. MoreSettings = new ConnMoreSettings()
  25. {
  26. IsAutoRemoveDataCache = true
  27. },
  28. // 从库
  29. SlaveConnectionConfigs = listConfig_Slave,
  30. //InitKeyType = InitKeyType.SystemTable
  31. }
  32. );
  33. });

结合AOP+MiniProfiler实现异常可视化

  1. // 这个是AOP中
  2. try
  3. {
  4. MiniProfiler.Current.Step($"执行Service方法:{invocation.Method.Name}() -> ");
  5. invocation.Proceed();
  6. }
  7. catch (Exception e)
  8. {
  9. //执行的 service 中,收录异常
  10. MiniProfiler.Current.CustomTiming("Errors:", e.Message);
  11. //执行的 service 中,捕获异常
  12. dataIntercept += ($"方法执行中出现异常:{e.Message + e.InnerException}");
  13. }
  14. //这个是全局异常处理中
  15. public void OnException(ExceptionContext context)
  16. {
  17. //...................不重要内容...............
  18. MiniProfiler.Current.CustomTiming("Errors:", json.Message);
  19. //采用log4net 进行错误日志记录
  20. _loggerHelper.Error(json.Message, WriteLog(json.Message, context.Exception));
  21. }

MiniProfiler - 图4

参考资料