首页 编程语言 一个简单的 C# 异步日志记录器

一个简单的 C# 异步日志记录器

Clearcove.Logging是一个非常简单的日志库,旨在通过直接许可条款满足大多数日志记录需求。

介绍

我知道你在想什么——代码世界真的需要另一个日志库吗?

如果你在.NET中寻找一个日志库,那么你有很多选择。有NLog,Log4Net,Enterprise Logging,erilog and Common.Logging,这些只是我现在暂时能想到的。我们不难找到一些由才华横溢的开发人员编写的日志库,他们花费了大量时间和精力创建了一些功能强大且功能丰富的软件。

那么,这个问题是否还需要解决呢?

背景

几个月前,我进入了一个日志库市场。我是一个商业桌面应用程序的创建者,该商业桌面应用程序通过互联网分发。因此,我有三个硬性需求:

  1. 异步写入日志条目。我看到过有太多的应用程序因为是同步日志记录,因而出现了严峻的性能问题。
  2. 库应该尽可能小。我不希望我的用户就为了一个简单的日志功能就得下载和加载1 MB的DLL。越小越好。
  3. 我不想增加应用程序许可的复杂性。目前,我的客户必须同意我的许可条款。添加具有单独许可条款的第三方组件可能意味着需要额外的工作来评估我的产品。也许这有点偏执,但我只是想保持简单。

我认为这些都是非常简单的要求,但事实证明,我找不到任何符合我需求的产品。特别是,我发现许多日志库的许可条款是我无法接受的,因为我不想被迫分发“另一个”许可证。

所以我决定自己来写日志库——Clearcove.Logging。它只有83行代码,非常轻巧。完整的实现放在一个单独的.cs文件中,以便在不必导入库的情况下重用。代码是用VS 2017编写的,但我曾试图编写可与早期版本兼容的代码。日志库以.NET 2.0为目标,为了吸引更多的用户。

我认为这种日志记录方法是一个很好的选择,是因为:

  1. 应用程序没有复杂的日志记录需求
  2. 这是一个小程序,让你从简化的部署中受益
  3. 许可复杂性必须保持在最低限度

那么它是怎样工作的?

使用代码

首先,我要知道我想记录什么信息。我想要一个简单的API,可以用来记录时间戳、记录器名称、线程ID和消息等信息。我对Log4Net API非常熟悉,并且从中借鉴了很多。

要声明和使用记录器,可以使用如下语法:

var log = new Logger(typeof(Program));    // Class level declaration.

log.Error("My error message", exception); // Logging from within a method.

log.Info("My info message");

如果你以前使用过其他日志记录库,那么你可能熟悉这种语法。

数据封装

接下来,我要将我的日志条目表示为一个简单的对象。这样做的主要原因是我希望我的记录器能够提升日志记录事件。有时我会在创建单元和集成测试时使用这些事件,因为我发现它们可以提供帮助。这只是个人喜好。如果你对提升日志记录事件不感兴趣,则可以简化此代码。

日志记录事件封装在LogMessageInfo 对象中,该对象的实现方式如下:

public sealed class LogMessageInfo{

public readonly DateTime Timestamp;

public readonly string ThreadId;

public readonly string Level;

public readonly string Logger;

public readonly string Message;

}

编写日志条目

上面用于API实现和数据封装部分的代码虽然冗长但非常简单。但是,异步日志记录略有差别。例如,如果抛出导致应用程序关闭的异常,那么会发生什么情况?我们如何知道所有日志条目将按照接收到的顺序编写?有若干方法可以解决这个问题。 Clearcove.Logger 就是其中一种简单但不优雅的方式:

static void Main(string[] args){

           var targetLogFile = new FileInfo("./MyApp.log");

Logger.Start(targetLogFile); // Loggers will complains if you skip initialization try { Run(args); } finally { Logger.ShutDown(); // Removing this line may result in lost log entries. } }

这是一个Clearcove.Logging 背离其他实现,例如Log4Net的示例。我们必须告诉我们的记录器何时开始记录以及何时停止记录。在尝试将任何日志条目写入日志文件之前,我们必须执行这个操作。将Logger.ShutDown() 调用放在finally语句中应该使我们的记录器有机会在应用程序关闭之前将所有待处理的日志条目写入日志文件。当然,也有日志条目不写入的情况。例如,如果机器没电了。如果其中有些边缘情况是你所关心的,则可能需要考虑同步日志记录。

Clearcove.Logging 通过使用单个System.Thread.Timer 实例来实现异步日志写入。我们没有设置线程计时器的周期,因此计时器只会触发一次。在所有待处理日志条目被成功写入日志文件后,计时器将重置,等到下一个间隔触发。这种行为类似于在计时器上设置一段时间,但会阻止计时器在间隔延迟的情况下被多次触发。

最后,通过简单调用File.AppendAllText将日志条目写入文件。这种调用可能不是多次写入日志文件最有效的方法,但是出于保持代码尽可能简单的前提。

好了。一个非常简单的日志实现完成了,它完全能够满足大多数应用程序的日志需求。而且非常适合我,帮助我解决了所有的日志记录问题,同时将依赖关系降到最低。

进一步的工作

记录器简单的好处之一是它很容易理解,并且可以快速定制以满足你的需求。例子包括滚动日志文件,同步日志记录,外部配置等。这些功能的实现就留给大家练习吧。玩的开心!

此记录器实现的一个很大的缺点是它只是.NET。我打算尽快发布这个日志记录库的Java实现。

另外,请注意,一些CodeProject用户可能会在下面发布增强功能。我会尝试在不增加复杂性的情况下合并更改,但如果你发现此记录器不怎么满足你的需求,则可能需要阅读下面的注释。

兴趣点

让我陷入混乱的一件事是希望简化软件许可。我努力想使得Clearcove.Logger 免费,而不增加许可复杂性。根据我的研究,我相信Ms-PL是最宽容的许可证。不但简单,易于阅读和理解,并且重要的是要求你的二进制发行版“在遵循本许可证的许可下”发布。在我看来,这个陈述是一个开放的解释,给了我们很大的灵活性。当然,我的看法是,一方面软件应该尽可能免费,另一方面应该仍然给予用户需要的保护。如果你有更加开放的许可建议,请告诉我。

下载源代码 – 7.7 KB

站心网

Clearcove.Logging是一个非常简单的日志库,旨在通过直接许可条款满足大多数日志记录需求。介绍我知道你在..

为您推荐

mysql分表简单介绍

一、Mysql分表的原因1、当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会停在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询时间。2、mysql中有一种机制是表锁定..

一个简单的大转盘抽奖程序(附.NetCore Demo源码)

最近闲下来在做一些demo,现在讲一下做的一个简单的大转盘抽奖demo,前端lottery,layui,后端.net core,sqlsugar,数据库用的mysql1.前端实现:前端用的是基于开源的lottery,其中有些改动的,使得前端可以自适应pc端..

简单优雅的Java ORM

Java的ORM框架有很多,但由于Java语言的限制大部分都不够优雅也不够简单,所以作者只能另辟蹊径造轮子了。照旧先看示例代码了解个大概,然后再解释实现原理。一、ORM示例Insertpublic CompletableFuture<Void> inser..

Dapper使用教程

假如你喜欢原生的Sql语句,又喜欢ORM的简单,那你一定会喜欢上Dapper这款ROM。Dapper的优势: 1、Dapper是一个轻型的ORM类。代码就一个SqlMapper.cs文件,编译后就40K的一个很小的Dll. 2、Dapper很快。Dapper的速度..

.NET Core 日志配置,NLog配置示例

.NET Core内置的日志组件附带了以堆日志提供程序,输出到控制台,输出,系统事件。在Program.cs组件配置里可以配置,如下。Console和Debug是默认配置。publicstaticIHostBuilderCreateHostBuilder(string[]args)=>Ho..

.NET Core记录请求处理时间的中间件

以下是一个示例的 .NET Core 中间件,用于记录请求处理时间的情况:using Microsoft.AspNetCore.Http;using Microsoft.Extensions.Logging;using System;using System.Diagnostics;using System.Threading.Tasks;pub..

介绍Js简单的递归排列组合

最近在开发SKU模块的时候,遇到这样一个需求,某种商品有N(用未知数N来表示是因为规格的数组由用户制定且随时可以编辑的,所以对程序来说,它是一个未知数)类规格,每一类规格又有M个规格值,各种规格值的组合便是..

.NET官方日志库Microsoft.Extensions.Logging用法

.NET中的 Microsoft.Extensions.Logging 是一个通用的日志记录接口,它提供了一个日志记录框架,允许你通过多种日志记录提供程序(如控制台、文件、数据库等)记录日志。以下是 Microsoft.Extensions.Logging 的基本..

使用C#的Socket实现最简单的TCP通信示例代码

使用C#实现TCP通信有多个类可以使用,最简单的是直接使用TcpListener+TcpClient类,但有时候这两个类并不方便做更底层的一些配置。而使用Socket类可以做一些比较底层的TCP配置。这里给出使用Socket实现最简单的TCP通..

简单了解Docker的概念和作用

什么是Docker?Docker是一个基于轻量级虚拟化技术的容器,整个项目基于Go语言开发,并采用了Apache 2.0协议。Docker可以将我们的应用程序打包封装到一个容器中,该容器包含了应用程序的代码、运行环境、依赖库、配置..

.NET Core NLog日志存入数据库配置

要将 NLog 配置为将日志记录到数据库,您需要提供以下信息:数据库连接字符串表名称日志记录级别日志记录格式可以使用 NLog 配置文件或代码来配置数据库日志记录。使用 NLog 配置文件要使用 NLog 配置文件配置数据库..

通过Linux命令分析Nginx日志得知百度蜘蛛的爬行情况

前言做网站的目的就是将自己的信息展示给目标用户,最直接的就是通过搜索引擎搜索展示。针对搜索引擎也需要优化,也就是我们说的SEO优化,新站长可能会特别关注蜘蛛爬行的次数、频率等,而做好网站SEO优化的第一步就..

在C#中通过Windows API读写INI文件的简单实现代码

摘要INI文件是比较常用的配置文件格式,在C#中,没有提供对INI文件直接读写的类库,要想实现INI文件的读写,需要借助Windows API GetPrivateProfileString和WritePrivateProfileString两个方法来实现。INI写入字符串..

.NET Core日志库Serilog用法教程

在.NET Core应用开发中,日志记录是不可或缺的一部分。它能够帮助我们追踪应用的运行情况、诊断问题以及进行性能优化。然而,传统的日志框架往往功能单一、配置繁琐,难以满足复杂应用的需求。幸运的是,Serilog作为..

Visual Studio自带的Git工具简单使用方法

写程序必然需要版本控制,哪怕是个人项目也是必须的,VS2015开始默认提供了对Git的支持。考虑到现在Git很火,作为微软系的程序员也不得不学一点防身,以免被开源世界的家伙们嘲笑,但是我相信用惯了SVN和TFS的童鞋们..

简单、小巧、灵活的C++11单头文件的命令行参数解析库

概述命令行参数解析,在写一些命令行的程序时需要用到,args.hxx类似于Python的argparse,但在C++中,它具有静态类型检查,并且速度更快(也允许完全嵌套的组逻辑,而Python的argparse没有),支持自定义类型解析,..

DBSync 简单易用的免费数据库同步工具使用图文教程

关于数据库同步,网上的技术方案很多,但大多是高实时的日志方案,涉及Binlog、CDC、消息处理等模块,不仅实施过程复杂,而且适用范围窄。但在现实中,很多场合的实时性要求并不高,秒级、分钟级的同步就足够,有些..

Zoraxy 简单好用的反向代理的创新工具

在当今的网络世界中,反向代理服务器扮演着至关重要的角色,它不仅能够提高网站的访问速度,还能增强安全性和隐私保护。然而,设置和管理一个反向代理服务器往往需要专业的技术知识。Zoraxy的问世,为这一领域带来了..

快速简单的开源JavaScript存储库localForage使用方法

什么是 localForage?Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.localForage 是一个快速且简单的 JavaScript 存储库,其通过使用异步存储对例如:Inde..

发表回复

返回顶部