C#使用log4net结合sqlite数据库记录日志

0 前言

为什么要把日志存到数据库里?

因为结构化的数据库存储的日志信息,可以写专门的软件读取历史日志信息,通过各种条件筛选,可操作性极大增强,有这方面需求的开发人员可以考虑。

为什么选择SQLite?

轻量级数据库,免安装,数据库的常用的基本功能都有,可以随程序迁移到不同的电脑上使用。

1 安装包

两个包:

  • log4net
  • System.Data.SQLite

第二个包也可以使用Microsoft.Data.Sqlite,查到的资料显示如果环境使用的是 .NET Core 或 .NET 5+,建议使用Microsoft.Data.Sqlite。但是我并没有测试第二个包,可能使用上有区别。

2 下载Sqlite

如果本地没有sqlite环境的话,需要先下载。官网下载链接

进去之后直接找各自环境对应的版本,如果是windows环境的话,直接下载下图中标记的tool,中间那个下载链接是下载sqlite3.dll,不过我并不清楚如何使用,有知道的大佬可以在评论区交流一下。

tool解压之后有如下几个文件,双击打开sqlite3.exe即可。

3 Sqlite常用命令

打开是一个命令行界面,可以使用.help查看常用的命令及解释。

.help

创建数据库文件使用.open xxx,这条语句,如果发现数据库文件存在,就会直接打开,如果不存在,就会先创建再打开。

.open test.db

在目录内可以看到创建的数据库文件。(划重点,这个文件拷到程序中就可以直接使用sqlite数据库,充分体现了轻量级的魅力)

.databases可以查询所有数据库文件

.tables可以查询所有表(我还未创建,所以目前还没有表)

sql语句请自行查询相关资料。

查询的数据以标准格式显示。

.header on
.mode column
SELECT * FROM COMPANY;

当然sqlite也有可视化的软件,但是我目前没用到,所以没有下载安装,需要的话可以自行查询。

4 创建日志相关基本表

使用命令创建日志表,包含id(使用自增,当然可以换成uuid或者其它形式)、日期、线程号、级别(info、error这些)、记录者、具体记录的信息、异常信息。具体内容要对应log4net的配置。

CREATE TABLE Log (
  Id INTEGER PRIMARY KEY AUTOINCREMENT,
  Date DATETIME,
  Thread VARCHAR(255),
  Level VARCHAR(50),
  Logger VARCHAR(255),
  Message TEXT,
  Exception TEXT
);

5 log4net配置

更换数据库连接。sql语句的内容一定要对应数据库基本表的字段。

<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>

  <log4net>
    <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
      <bufferSize value="1" />
      <connectionType value="System.Data.SQLite.SQLiteConnection, System.Data.SQLite" />
      <connectionString value="Data Source=./database/logs.db;Version=3;" />
      <commandText value="INSERT INTO Log (Date, Thread, Level, Logger, Message, Exception) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />
      
      <parameter>
        <parameterName value="@log_date" />
        <dbType value="DateTime" />
        <layout type="log4net.Layout.RawTimeStampLayout" />
      </parameter>
      <parameter>
        <parameterName value="@thread" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%thread" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@log_level" />
        <dbType value="String" />
        <size value="50" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%level" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@logger" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%logger" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@message" />
        <dbType value="String" />
        <size value="4000" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%message" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@exception" />
        <dbType value="String" />
        <size value="2000" />
        <layout type="log4net.Layout.ExceptionLayout" />
      </parameter>
    </appender>

    <root>
      <level value="ALL" />
      <appender-ref ref="AdoNetAppender" />
    </root>
  </log4net>
</configuration>

6 日志记录

把生成的db文件拷到程序里,这个文件就是记录文件的数据库了,其它的都不重要。当然,如果想查看数据库的话,也可以把sqlite3.exe拷过来。

读取log4net的配置建议写在AssemblyInfo.cs,这样程序启动时会默认加载配置文件。

//Log4net配置
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]

具体程序如下:

private static readonly ILog log = LogManager.GetLogger(typeof(Form1));

log.Info("这是一条info语句");
log.Warn("这是一条warn语句");
log.Error("这是一条错误语句", new Exception("测试异常"));

查看日志是否正常写入数据库。

7 使用C#程序查询sqlite

程序如下(不过感觉GetString(index)这种方式有点别扭吧,有没有GetString(key)的这种形式,欢迎大佬们补充)

// 构建连接字符串
string connectionString = "Data Source=./database/SoftWareBaseLog.db;Version=3;";

// 创建 SQLite 连接
using (var connection = new SQLiteConnection(connectionString))
{
    connection.Open();

    // 创建 SQL 命令
    string sql = "SELECT Message FROM Log where Level='ERROR'";
    using (var command = new SQLiteCommand(sql, connection))
    {
        // 执行命令并读取数据
        using (var reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                string msg = reader.GetString(0);
                Console.WriteLine(msg);
            }
        }
    }
}

8 实时显示日志

现在所有日志都写到数据库里了,那要是还想实时显示到界面上,当然也有很多方式实现,不过我这里建议实时显示可以使用log4net的自有功能。

比如我想使用winform中的listbox来实时显示日志,可以建立一个Appender(附加),继承于log4net的AppenderSkeleton,这是一个抽象类,有一个抽象方法。

具体的,可以参考以下程序,这里会显示所有的日志,如果需要过滤的话,可以在这个基础上改。另外,一定一定一定要给this.Layout赋值,这是日志在界面上的显示方式,如果没有写的话,就会收获一个报错:“A layout must be set”,去网上搜这条内容,不一定能找到解决方案。

public class ListBoxAppender : AppenderSkeleton
{
    private ListBox _ListBox;

    public ListBoxAppender(ListBox box)
    {
        _ListBox = box;
        this.Layout = new PatternLayout("%date [%thread] %-5level %logger - %message%newline");
    }

    protected override void Append(LoggingEvent loggingEvent)
    {
        // 获取日志信息
        string logMessage = RenderLoggingEvent(loggingEvent);

        // 更新 UI 控件
        if (_ListBox.InvokeRequired)
        {
            _ListBox.Invoke(new Action(() => AppendText(logMessage)));
        }
        else
        {
            AppendText(logMessage);
        }
    }

    private void AppendText(string text)
    {
        _ListBox.Items.Add(text);
    }
}

只需要给log4net配置一次就可以使用,这样,每次调用日志记录,界面上的lbxLog控件就可以一直显示最新的日志信息。

// 添加自定义 Appender
var listBoxAppender = new ListBoxAppender(lbxLog);
log4net.Config.BasicConfigurator.Configure(listBoxAppender);

但是,我并不建议使用log4net直接操作控件显示日志信息,在多线程短时间写较多日志的情况下,可能会导致软件卡死,更佳的方式是增加缓存机制。

如果这篇文章对你有帮助的话,请为我点一个大大的赞吧,非常感谢!!

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

node和npm

背景&#xff08;js&#xff09; 1、为什么js能操作DOM和BOM? 原因&#xff1a;每个浏览器都内置了DOM、BOM这样的API函数 2、浏览器中的js运行环境&#xff1f; v8引擎&#xff1a;负责解析和执行js代码 内置API&#xff1a;由运行环境提供的特殊接口&#xff0c;只能在所…

Java面向对象编程高阶(一)

Java面向对象编程高阶&#xff08;一&#xff09; 一、关键字static1、static修饰属性2、静态变量与实例变量的对比3、static修饰方法4、什么时候将属性声明为静态的&#xff1f;5、什么时候将属性声明为静态的&#xff1f;6、代码演示 一、关键字static static用来修饰的结构…

从0到1学习node.js(npm)

文章目录 一、NPM的生产环境与开发环境二、全局安装三、npm安装指定版本的包四、删除包 五、用npm发布一个包六、修改和删除npm包1、修改2、删除 一、NPM的生产环境与开发环境 类型命令补充生产依赖npm i -S uniq-S 等效于 --save -S是默认选项npm i -save uniq包的信息保存在…

首席数据官和首席数据分析官

根据分析人士的预测&#xff0c;首席数据官&#xff08;CDO&#xff09;和首席数据分析官&#xff08;CDAO&#xff09;必须更有效地展示他们对企业和AI项目的价值&#xff0c;以保障其在高管层的地位。Gartner的最新报告指出&#xff0c;CDO和CDAO在AI时代需要重新塑造自身定位…

HDFS异常org.apache.hadoop.hdfs.protocol.NSQuotaExceededException

HDFS异常org.apache.hadoop.hdfs.protocol.NSQuotaExceededException 异常信息&#xff1a; Hive:org.apache.hadoop.hdfs.protocol.NSQuotaExceededException: The NameSpace quota (directories and files) of directory /xxxdir is exceeded: quota10000 file count15001N…

【Python】为Pandas加速(适合Pandas中级开发者)

非常好的一篇文章&#xff0c;解决问题的方式和思路层层递进&#xff0c;透彻深刻。 Pandas是个好工具&#xff0c;好工具要用正确高效的方式使用&#xff0c;才能发挥出万钧之力。 英文水平较高可直接阅读原文。Fast, Flexible, Easy and Intuitive: How to Speed Up Your p…

linux创建自定义服务部署项目

1.进入linux单元服务文件夹 cd /etc/systemd/system/ 2.创建一个文件以.service结尾的文件 C#(.Net Core)、 Java、Python等语言&#xff0c;都可以通过linux自定义服务来部署项目&#xff0c;实现守护进程、实现开机自启 2.1例如创建my.service文件 这里以部署python项目为…

新华三H3CNE网络工程师认证—OSPF路由协议

OSPF是典型的链路状态路由协议&#xff0c;是目前业内使用非常广泛的IGP协议之一。本博客将对OSPF路由协议进行总结。 OSPF目前针对IPv4协议使用的是OSPFVersion2(RFC2328)&#xff1b; 针对IPv6协议使用OSPFVersion3(RFC2740)。如无特殊说明本章后续所指的OSPF均为OSPF Versi…

HBase2.4.17 修改znode后master初始化失败

正常运行的hbase服务&#xff0c;修改zookeeper.znode.parent后&#xff0c;重启。hbase master服务可以启动成功&#xff0c;但是仅有meta表上线&#xff0c;且hbase:meta表中元数据丢失。仅残留table:state列的值&#xff0c;其他列的值全部丢失。 有大佬知道是怎么回事嘛

(二十四)、在 k8s 中部署自己的 jar 镜像(以 springcloud web 项目为例)

文章目录 1、环境陈述2、前期准备2.1、将一个 SpringCloud 微服务运行 以 jar 方式运行2.2、为 SpringCloud 项目生成 Docker 镜像2.3、推送镜像2.4、从宿主机访问 k8s(minikube) 发布的 redis 服务2.5、k8s(minikube) 部署mysql 3、本期关键3.1、打 jar 包需要修改的地方3.2、…

Anchor DETR:Transformer-Based目标检测的Query设计

写在前面 文中指出之前DETR-like算法存在以下问题&#xff1a; 之前DETR-liked检测算法里&#xff0c;object query是一组可学习的嵌入表示&#xff08;就是一组256-d的向量&#xff09;&#xff0c;缺乏明确的物理意义&#xff0c;不能解释它们会关注什么地方。每个object q…

禾川SV-X2E A伺服驱动器参数设置——脉冲型

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff01;人工智能学习网站 前言&#xff1a; 大家好&#xff0c;我是上位机马工&#xff0c;硕士毕业4年年入40万&#xff0c;目前在一家自动化公司担任…

PHPOK 4.8.338 后台任意文件上传漏洞(CVE-2018-12941)复现

PHPOK企业站(简称PHPOK&#xff09;建设系统是一套基于PHP和MySQL构建的高效企业网站建设方案之一&#xff0c;全面针对企业网&#xff08;以展示为中心&#xff09;进行合理的设计规划。 PHPOK是一套开源免费的建站系统&#xff0c;可以在遵守LGPL协议的基础上免费使用。系统具…

浅析正交投影矩阵和透视投影矩阵的推导

先上矩阵的内容。在opengl中&#xff0c;分别通过glOrtho函数和glFrustum函数得到正交投影矩阵和透视投影矩阵。 glOrtho 函数描述生成正交投影矩阵。 (左、 下、 近) 和 (右、 上、 近) 参数分别指定近剪裁平面上映射到窗口左下角和右上角的点&#xff0c;假定眼睛位于 (0、0…

Vue104 vue3 组合式API的优势 对比配置式API

笔记 1.Options API 存在的问题 使用传统OptionsAPI中&#xff0c;新增或者修改一个需求&#xff0c;就需要分别在data&#xff0c;methods&#xff0c;computed里修改 。 2.Composition API 的优势 我们可以更加优雅的组织我们的代码&#xff0c;函数。让相关功能的代码更…

三方接口调用设计方案

在为第三方系统提供接口的时候&#xff0c;肯定要考虑接口数据的安全问题&#xff0c;比如数据是否被篡改&#xff0c;数据是否已经过时&#xff0c;数据是否可以重复提交等问题 在设计三方接口调用的方案时&#xff0c;需要考虑到安全性和可用性。以下是一种设计方案的概述&am…

Jenkins + GitLab + Docker实现自动化部署(Java项目)

部署Jenkins 因为Jenkins需要用到git、jdk、maven&#xff0c;后两者我们采取挂载的方式&#xff0c;git采用直接在容器中安装的方式&#xff0c;所以我们要做一个增强版的Jenkins镜像&#xff0c;编写Dockerfile文件 #使用jenkins 镜像作为基础镜像 FROM jenkins/jenkins:lt…

Spring Boot框架下租房管理系统的设计与实现

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

springboot098基于web的网上摄影工作室的开发与实现(论文+源码)_kaic

网上摄影工作室 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了网上摄影工作室的开发全过程。通过分析网上摄影工作室管理的不足&#xff0c;创建了一个计算机管理网上摄影工作室的方案。文章介绍了网上摄影工…

Kubernetes实战——DevOps集成SpringBoot项目

目录 一、安装Gitlab 1、安装并配置Gitlab 1.1 、下载安装包 1.2、安装 1.3、修改配置文件 1.4、更新配置并重启 2、配置 2.1、修改密码 2.2、禁用注册功能 2.3、取消头像 2.4、修改中文配置 2.5、配置 webhook 3、卸载 二、安装镜像私服Harbor 1、下载安装包 2、…