第二章 基础知识(4) - 日志记录

在默认日志级别,Blazor项目中默认提供如下日志记录提供程序:

在服务器上(Blazor Server),日志记录仅发生LogLevel.Information 或更高级别的 Development 环境中的服务器端 .NET 控制台。
在客户端上(Blazor WebAssembly),日志记录仅发生LogLevel.Information 或更高级别的客户端浏览器开发人员工具控制台。

Razor组件日志记录

要在组件中使用日志记录,可以通过注入ILogger<T>或者ILoggerFactory来实现。

ILogger<T>示例

@page "/"
@inject ILogger<Home> Logger<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>Welcome to your new app.
@code{protected override void  OnInitialized(){//这是服务端的组件Logger.LogWarning("OKK");}
}

ILoggerFactory示例

@page "/counter"
@rendermode InteractiveAuto
@inject ILoggerFactory LoggerFactory<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code {private int currentCount = 0;private void IncrementCount(){currentCount++;//这里用的客户端的组件LoggerFactory.CreateLogger<Counter>().LogWarning("OKK");}
}

在这里插入图片描述

客户端日志

对于客户端,并非支持所有ASP.NET Core的日志记录功能。例如,客户端组件无法访问客户端的文件系统或网络,因此无法将日志写入客户端的物理或网络存储。

一、设置日志等级

对于服务端项目的日志配置,默认情况下,可以在项目的appsettings.jsonappsettings.Development.json文件中进行配置。
在这里插入图片描述而在客户端项目中,要进行日志最低等级的配置,需要在Program.cs中,使用WebAssemblyHostBuilder.Logging属性进行日志的设置。

日志级别

  • Trace:0,包含最详细消息的日志,不建议在生产环境下使用此等级。
  • Debug:1,在开发期间用于交互式调查的日志。这些日志应该主要包含对调试有用的信息,没有长期价值。
  • Information:2,跟踪应用的常规流,可能具有长期值。
  • Warning:3,突出显示应用程序流中异常或意外事件,但不会导致应用程序执行停止的日志。
  • Error:4,突出显示由于故障而停止当前执行流的日志。这些应该表明当前活动中的故障,而不是应用程序范围的故障。
  • Critical:5,描述不可恢复的应用程序或系统崩溃,或需要立即注意的灾难性故障的日志。
  • None:6,不进行任何日志记录。

示例-将日志最低等级设置为Warning-Program.cs

......
//设置日志级别
builder.Logging.SetMinimumLevel(LogLevel.Warning);
......

二、客户端Program.cs中输出日志

要在客户端的Program.cs中输出日志,可以使用WebAssemblyHost的服务容器中获取日志工厂ILoggerFactory从而生成日志对象。

  • 需要注意的是,只有在加载首次加载客户端组件时,才会运行Program中的代码。

Program.cs

var builder = WebAssemblyHostBuilder.CreateDefault(args);var host = builder.Build();
var logger = host.Services.GetRequiredService<ILoggerFactory>().CreateLogger<Program>();
logger.LogInformation("Logged after the app is built in the Program file.");await builder.Build().RunAsync();

在这里插入图片描述

三、日志类别

客户端同样支持日志类别,在创建 ILogger 对象时,需要指定日志类别,可以以下几种类别指定方式:

  • ILogger<T>:在注入ILogger接口时,通过泛型T来指定,这种方式需要使用已存在的类型,然后会自动使用T类型的完整空间命名来作为日志类别。
  • CreateLogger<T>()ILoggerFactory的方法,创建ILogger<T>日志对象。
  • CreateLogger(className)ILoggerFactory的方法,创建ILogger日志对象,这里的className可以随便指定,不需要使用存在的类型名称。

示例

@page "/counter"
@rendermode InteractiveAuto
@inject ILogger<Counter> Logger
@inject ILoggerFactory LoggerFactory<PageTitle>Counter</PageTitle><h1>Counter</h1><p role="status">Current count: @currentCount</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code {private int currentCount = 0;private void IncrementCount(){currentCount++;LoggerFactory.CreateLogger("MyLogger").LogWarning("OKK");Logger.LogWarning("OKK");}
}

在这里插入图片描述

四、日志事件ID

Blazor客户端侧同样支持日志事件ID,每个日志都可以指定一个事件ID,一般会将所有日志事件ID作为常量封装到一个类中来使用。

LogEvent.cs

public class LogEvent
{public const int Event1 = 1000;public const int Event2 = 1001;
}

Counter.razor

@page "/counter"
@rendermode InteractiveAuto
@inject ILogger<Counter> Logger......@code {private int currentCount = 0;private void IncrementCount(){currentCount++;Logger.LogInformation(LogEvent.Event1, "Someone has clicked me!");Logger.LogWarning(LogEvent.Event2, "Someone has clicked me!");}
}

在这里插入图片描述

五、日志异常参数

Blazor客户端侧支持日志异常参数的使用。

Counter.razor

@page "/counter"
@rendermode InteractiveAuto
@inject ILogger<Counter> Logger......@code {private int currentCount = 0;private void IncrementCount(){try{currentCount++;throw new OperationCanceledException("Skip 3");}catch (Exception ex){Logger.LogInformation(ex, "Exception (currentCount: {Count})!", currentCount);}}
}

在这里插入图片描述

六、日志筛选函数

指定日志类别与日志级别
在客户端如果希望只输出指定的日志类别和日志级别,可以通过在Program.cs中使用builder.Logging.AddFilter方法来添加过滤器。

Program.cs

......//表示只记录日志类别为MyLoggerClass且日志级别为LogLevel.Information的日志
builder.Logging.AddFilter((provider, category, logLevel)=> category!.Equals("MyLoggerClass") && logLevel == LogLevel.Information);......

Counter.razor

@page "/counter"
@rendermode InteractiveAuto
@inject ILoggerFactory LoggerFactory......@code {private int currentCount = 0;private void IncrementCount(){currentCount++;ILogger _logger = LoggerFactory.CreateLogger("MyLoggerClass");_logger.LogInformation("Information");_logger.LogWarning("Warning");}
}

在这里插入图片描述

七、身份验证日志记录

要开启身份验证的日志记录,可以有如下两种方法:

通过配置文件设置

"Logging": {"LogLevel": {"Microsoft.AspNetCore.Components.WebAssembly.Authentication": "Debug"}
}

通过在Program.cs中添加过滤器

builder.Logging.AddFilter("Microsoft.AspNetCore.Components.WebAssembly.Authentication", LogLevel.Debug);

八、自定义记录器提供程序

有时可能会遇到需要自己定义日志提供程序的需求,要实现自定义的日志提供程序,具体需要进行如下步骤:

创建日志级别字典

using Microsoft.Extensions.Logging;public class CustomLoggerConfiguration
{public int EventId { get; set; }public Dictionary<LogLevel, LogFormat> LogLevels { get; set; } = new(){[LogLevel.Information] = LogFormat.Short,[LogLevel.Warning] = LogFormat.Short,[LogLevel.Error] = LogFormat.Long};public enum LogFormat{Short,Long}
}

实现ILogger接口,自定义日志提供程序

public sealed class CustomLogger : ILogger
{private readonly string name;private readonly Func<CustomLoggerConfiguration> getCurrentConfig;public CustomLogger(string name,Func<CustomLoggerConfiguration> getCurrentConfig) =>(this.name, this.getCurrentConfig) = (name, getCurrentConfig);public IDisposable BeginScope<TState>(TState state) => default!;public bool IsEnabled(LogLevel logLevel) =>getCurrentConfig().LogLevels.ContainsKey(logLevel);public void Log<TState>(LogLevel logLevel,EventId eventId,TState state,Exception? exception,Func<TState, Exception?, string> formatter){if (!IsEnabled(logLevel)){return;}CustomLoggerConfiguration config = getCurrentConfig();if (config.EventId == 0 || config.EventId == eventId.Id){switch (config.LogLevels[logLevel]){case LogFormat.Short:Console.WriteLine($"{name}: {formatter(state, exception)}");break;case LogFormat.Long:Console.WriteLine($"[{eventId.Id, 2}: {logLevel, -12}] {name} - {formatter(state, exception)}");break;default:// No-opbreak;}}}
}

实现自定义日志提供程序的配置类

using System.Collections.Concurrent;
using Microsoft.Extensions.Options;[ProviderAlias("CustomLog")]
public sealed class CustomLoggerProvider : ILoggerProvider
{private readonly IDisposable onChangeToken;private CustomLoggerConfiguration config;private readonly ConcurrentDictionary<string, CustomLogger> loggers =new(StringComparer.OrdinalIgnoreCase);public CustomLoggerProvider(IOptionsMonitor<CustomLoggerConfiguration> config){this.config = config.CurrentValue;onChangeToken = config.OnChange(updatedConfig => this.config = updatedConfig);}public ILogger CreateLogger(string categoryName) =>loggers.GetOrAdd(categoryName, name => new CustomLogger(name, GetCurrentConfig));private CustomLoggerConfiguration GetCurrentConfig() => config;public void Dispose(){loggers.Clear();onChangeToken.Dispose();}
}

ILoggingBuilder添加扩展方法

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Configuration;public static class CustomLoggerExtensions
{public static ILoggingBuilder AddCustomLogger(this ILoggingBuilder builder){builder.AddConfiguration();builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, CustomLoggerProvider>());LoggerProviderOptions.RegisterProviderOptions<CustomLoggerConfiguration, CustomLoggerProvider>(builder.Services);return builder;}
}

Program.cs中,添加日志提供程序。

builder.Logging.ClearProviders().AddCustomLogger();

使用第三方日志提供程序

这里以NLog的使用为例,由于浏览器存在访问权限等原因,这里只在服务端(Blazor Server)上使用。

一、安装NLog包

要在 ASP.NET Core 6 中使用 NLog,首先要安装 NLog 的扩展包,然后再进行一些基本的配置,就可以实现 NLog 与.NET Core 6 的集成了。
首先到Nuget中,下载对应的依赖库:

  • 选择NLog.Extensions.Logging程序包,这个是微软参与开发的插件,也是微软官方网站上推荐的,兼容性也最好。

在这里插入图片描述

二、添加配置文件

NLog包安装完成之后,还需要配置才可使用,NLog使用的是NLog.config配置文件。
在项目中填加新项,选择Web配置文件,命名为NLog.config。
在这里插入图片描述NLog.config

<?xml version="1.0" encoding="utf-8"?>
<nlogxmlns="http://www.nlog-project.org/schemas/NLog.xsd"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"autoReload="true"internalLogLevel="Warn"internalLogFile="nlog.txt"><targets><target xsi:type="File" name="allfile" fileName="nlog-all-${shortdate}.log" layout="${longdate}|${logger}|${uppercase:${level}}|${message} ${exception}" /><target xsi:type="File" name="ownFile-web" fileName="nlog-own-${shortdate}.log" layout="${longdate}|${logger}|${uppercase:${level}}| ${message} ${exception}"/></targets><rules><logger name="*" minlevel="Trace" writeTo="allfile" /><logger name="Microsoft.*" minlevel="Trace" final="true" /><logger name="*" minlevel="Trace" writeTo="ownFile-web" /></rules>
</nlog>

三、注册NLog

NLog的包和配置文件完成之后,可以在Program类中注册NLog日志提供程序。
NLog要使用ILoggerFactory来提供注入服务,这里我们在统一的Program类中注册NLog。
AddNLog([string path])ILoggingBuilder的扩展方法,为Blzor框架添加NLog日志提供程序。

Program.cs

......//清除掉所有的日志服务
builder.Logging.ClearProviders();
//添加NLog日志服务
builder.Logging.AddNLog();......

这里试了一下,如果不清除掉所有的日志服务,直接添加NLog服务,可以保留其他日志提供程序的日志记录。

四、使用NLog

Home.razor

@page "/"
@inject ILoggerFactory LoggerFactory<PageTitle>Home</PageTitle><h1>Hello, world!</h1>Welcome to your new app.@code{protected override void OnInitialized(){ILogger _logger = LoggerFactory.CreateLogger<Home>();_logger.LogInformation("Information");_logger.LogWarning("Warning");}
}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

泛微E9开发 控制日期浏览按钮的可选日期范围

控制日期浏览按钮的可选日期范围 1、需求说明2、实现方法3、扩展知识点控制日期浏览按钮的可选日期范围格式参数说明演示 1、需求说明 控制日期浏览按钮的可选日期范围为2024/07/01~2024/07/31&#xff0c;如下图所示 2. 控制日期浏览按钮的可选日期范围在当前时间的前一周~当…

生成多个ssh访问不同git

如果&#xff0c;你的git代码仓库&#xff0c;比如说腾讯云coding&#xff0c;通过ssh秘钥访问&#xff0c;一直用的好好的&#xff0c;有一天&#xff0c;你又增加一个aliyun云效的代码仓库&#xff0c;又配置了aliyun云效的秘钥并且&#xff0c;根据aliyun云效的官方文档上传…

Django 更新数据 save()方法

1&#xff0c;添加模型 Test/app11/models.py from django.db import modelsclass Post(models.Model):title models.CharField(max_length200)content models.TextField()pub_date models.DateTimeField(date published)class Book(models.Model):title models.CharFie…

【Linux】多线程_2

文章目录 九、多线程2. 线程的控制 未完待续 九、多线程 2. 线程的控制 主线程退出 等同于 进程退出 等同于 所有线程都退出。为了避免主线程退出&#xff0c;但是新线程并没有执行完自己的任务的问题&#xff0c;主线程同样要跟进程一样等待新线程返回。 pthread_join 函数…

力扣喜刷刷--day1

1.无重复字符的最长子串 知识点&#xff1a;滑动窗口 基本概念 窗口&#xff1a;窗口是一个连续的子序列&#xff0c;可以是固定长度或可变长度。滑动&#xff1a;窗口在数据序列上移动&#xff0c;可以是向左或向右。边界&#xff1a;窗口的起始和结束位置。 应用场景 字符…

基于Python的51job招聘数据采集与可视化项目实践

项目背景与目标 在当今竞争激烈的就业市场中&#xff0c;深入分析招聘信息对于求职者和企业都具有重要意义。基于Python的51job招聘数据采集与可视化项目旨在通过自动化手段高效获取大量招聘信息&#xff0c;并对这些数据进行深度分析和展示。 51job作为中国领先的招聘网站&…

干货:高水平论文写作思路与方法

前言:Hello大家好,我是小哥谈。高水平论文的写作需要扎实的研究基础和严谨的思维方式。同时,良好的写作技巧和时间管理也是成功的关键。本篇文章转载自行业领域专家所写的一篇文章,希望大家阅读后可以能够有所收获。🌈 目录 🚀1.依托事实/证据,通过合理的逻辑,…

【深度学习基础】环境搭建 linux系统下安装pytorch

目录 一、anaconda 安装二、创建pytorch1. 创建pytorch环境&#xff1a;2. 激活环境3. 下载安装pytorch包4. 检查是否安装成功 一、anaconda 安装 具体的安装说明可以参考我的另外一篇文章【环境搭建】Linux报错bash: conda: command not found… 二、创建pytorch 1. 创建py…

C++ 是否变得比 C 更流行了?

每年都会出现一种新的编程语言。创造一种新语言来解决计算机科学中的挑战的诱惑很难抗拒。一些资料表明&#xff0c;目前有多达 2,500 种语言&#xff0c;这并不奇怪&#xff01; 对于我们嵌入式软件开发人员来说&#xff0c;这个列表并不长。事实上&#xff0c;我们可以用一只…

【Java算法】二分查找 下

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【算法工作坊】算法实战揭秘 一.山脉数组的峰顶索引 题目链接&#xff1a;852.山脉数组的峰顶 ​ 算法原理 这段代码实现了一个查找山峰数组中峰值索引的算法。山峰数组是一个先递增后递减的数组&…

解决安卓tv 蓝牙遥控器配对后输入法弹不出来的问题

t972在蓝牙配对后,自带的LatinIME 输入法会出现弹不出来的现象。 经过分析,主要为蓝牙的kl 文件适配存在问题。解决如下: 1.新建 kl文件Vendor_2b54_Product_1600.kl 放到 /vendor/usr/keylayout/下 内容: #for bl remote add by jason 20240709 key 113 VOLUME_MUTE …

来一场栈的大模拟(主要是单调栈)

一.栈模拟 二.单调栈求最大矩形面积 通常&#xff0c;直方图用于表示离散分布&#xff0c;例如&#xff0c;文本中字符的频率。 现在&#xff0c;请你计算在公共基线处对齐的直方图中最大矩形的面积。 图例右图显示了所描绘直方图的最大对齐矩形。 输入格式 输入包含几个测…

Java内存区域与内存溢出异常(补充)

2.2.5 方法区 方法区(Method Area)与Java堆一样&#xff0c;是各个线程共享的内存区域&#xff0c;它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。虽然《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分&#xff0c;但是它却有一…

【C++】开源:坐标转换和大地测量GeographicLib库配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍坐标转换和大地测量GeographicLib库配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关…

“郑商企航”暑期社会实践赴美丽美艳直播基地开展调研

马常旭文化传媒网讯&#xff08;记者张明辉报道&#xff09;导读&#xff1a;2024 年 7 月 3 日&#xff0c;商学院暑期社会实践团“郑商企航”在河南省郑州市新密市岳村镇美丽美艳直播基地&#xff0c;展开了一场意义非凡的考察活动&#xff0c;团队成员深度调研了直播基地的产…

关于string的‘\0‘与string,vector构造特点加部分特别知识点的讨论

目录 前言&#xff1a; 问题一&#xff1a;关于string的\0问题讨论 问题二&#xff1a;C标准库中的string内存是分配在堆上面吗&#xff1f; 问题三&#xff1a;string与vector的capacity大小设计的特点 问题四&#xff1a;string的流提取问题 问题五&#xff1a;迭代器失…

c++内存管理(上)

目录 引入 分析 说明 C语言中动态内存管理方式 C内存管理方式 new/delete操作内置类型 new和delete操作自定义类型 引入 我们先来看下面的一段代码和相关问题 int globalVar 1; static int staticGlobalVar 1; void Test() { static int staticVar 1; int localVar 1…

MySQL:TABLE_SCHEMA及其应用

MySQL TABLE_SCHEMA及其应用 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/ar…

(2)滑动窗口算法练习:无重复字符的最长子串

无重复字符的最长子串 题目链接&#xff1a;3. 无重复字符的最长子串 - 力扣&#xff08;LeetCode&#xff09; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的最长子串的长度。 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是"a…

二战架构师,拿下

前言 已经许久更新文章了&#xff0c;并不是因为我懒了&#xff0c;而是在备考系统架构师考试。个人感觉还是比较幸运的&#xff0c;低分飘过。现阶段任务也算完成了&#xff0c;记录一下感受。 什么是软考 软考&#xff0c;全称“计算机技术与软件专业技术资格&#xff08…