欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

深度长文-我花了10天时间造了个*,你们可能会有兴趣

程序员文章站 2022-04-08 17:32:05
TomatoLog 对日志的处理不敢说强大,但可能是 .NETCore 平台上最简单易用的日志集成组件,具有高度灵活的使用方式,完全可定义配置的可扩展性,使用异步写入,业务完全解耦,客户端的一键安装、一行代码上传日志 ......

介绍

这个项目叫做 tomatolog,托管在 github 项目上,使用的 license 是 mit,请放心试用,目前该项目主要由我个人维护,还有两位大神加入了协作者中。
** tomatolog.server 基于 .netcore2.2
** tomatolog.client 基于 netstandard2.0

项目主页以及组件说明

https://github.com/lianggx/tomatolog

** 中文说明文档:
https://github.com/lianggx/tomatolog/blob/master/readme_zh-cn.md

** 服务器版本:
https://github.com/lianggx/tomatolog/releases

** 客户端组件 v1.0.2:
tomatolog.common(公共代码库)
tomatolog.client(客户端基础实现类)
tomatolog.client.redis(reids客户端,基于 csrediscore 客户端)
tomatolog.client.rabbitmq(rabbitmq客户端)

** 存储插件
tomatolog.tofile(写入文件)
tomatolog.tomongodb(写入mongodb)
tomatolog.toes(写入elasticsearch)

演示代码位于项目目录 examples 下。

1. tomatolog 是干什么的

tomatolog 来源于业务发展的实际需要,在项目中,我们的做法是使用 nlog 将日志写入本地,然后通过 kafka 将日志发送到 es,剩下的就是怎么对日志进行挖掘、展示的问题了。如果需要进行扩展,就需要自行安装其它工具对日志进行操作了;实际上,通过这一系列的操作,你需要用到的是 nlog+kafka+elk,这一系列高度灵活的框架都需要手动安装和调试,这个过程让小白窒息,让老司机迷路。家里的领导常说,能一行代码解决的问题,就不要搞那么复杂,高扩展性是很重要,但是易用性也是非常的重要的。

那么,tomatolog 就是来解决这个问题,tomatolog 对日志的处理不敢说强大,但可能是 .netcore 平台上最简单易用的日志集成组件,具有高度灵活的使用方式,完全可定义配置的可扩展性,使用异步写入,业务完全解耦,客户端的一键安装、一行代码上传日志,目前 tomatolog 没有实现登录验证,需要注意使用环境访问权限问题。下面就使用和功能进行展开介绍。

1.1 tomatolog 的系统架构

千言万语不如一张图

深度长文-我花了10天时间造了个*,你们可能会有兴趣

从图中可以看出,tomatolog 包含三个基础组件,他们分别是:客户端、数据流控制器、服务器;tomatolog 本身不做存储优化,其通过定义一个简单的数据流协议实现日志的收集到存储,这个数据流协议在系统中被定义成为一个实体对象模型 logmessage,位于程序集 tomatolog.common.dll 中:

namespace tomatolog.common.utilities
{
    public class logmessage
    {
        public int eventid { get; set; }
        public string projectname { get; set; }
        public string projectlabel { get; set; }
        public loglevel loglevel { get; set; }
        public string version { get; set; }
        public string ip { get; set; }
        public string[] iplist { get; set; }
        public string machinename { get; set; }
        public string threadid { get; set; }
        public string processid { get; set; }
        public string processname { get; set; }
        public datetime timestamp { get; set; }
        public string username { get; set; }
        public string errormessage { get; set; }
        public string stacktrace { get; set; }
        public object extra { get; set; }
    }
}

上面的所有字段都可以使用配置进行跟踪,可选择将哪些信息写入到日志中,其中,关于服务器主机信息,客户端会自动采集主机信息,无需手动传入,如果这些信息还是不能满足业务需要,没关系,上面的实体类中还定义了扩展字段 "extra" ,该字段接收一切对象,当然,最好就是使用 json 对象,这也比较科学。

服务端在接收到日志信息后,将会根据服务配置对日志进行清洗、筛选、然后是存入指定存储介质中,如果日志触发了服务配置的警报,服务器还将自动发送警报通知。下面,就从使用开始,体验 tomatolog 带来的便利性和舒适的日志操作体验。

2. 部署日志采集服务器

tomatolog 日志服务器目前发布的版本是:1.0.2(目前处于起步阶段,版本迭代速度可能比较快),位于:https://github.com/lianggx/tomatolog/releases,直接下载 tomatolog-1.0.2.zip,解压,得到文件如下:

深度长文-我花了10天时间造了个*,你们可能会有兴趣

此压缩包仅包含程序运行所必须文件,所以必须要在目标机器上安装 .netcore sdk 2.2+,你可以简单的使用命令行或者其它你熟悉的托管程序去启动 tomatolog.server ,比如可以使用 iis、supervisord、docker(需要自行打包); 在本示例中,我选择使用命令行启动它。

在上面文件夹中,我们在第一次使用的使用,只需要关注两个文件即可,他们分别是 appsettings.(development/production).json (服务配置文件)和 tomatolog.server.dll (服务主程序文件),首先,看看服务配置文件

2.1 服务器配置
{
  "logging": {
    "includescopes": false,
    "loglevel": {
      "default": "debug",
      "system": "information",
      "microsoft": "information"
    }
  },
  "tomatolog": {
    "cache-redis": null,
    "config": {
      "sysconfig": "config/sysconfig.json",
      "proconfig": "config/proconfig.json"
    },
    "storage": {
      "type": "tofile", //tofile/toes/tomongodb
      "file": "d:\\tomatolog\\storage",
      "es": "http://127.0.0.1:9200/",
      "mongodb": "mongodb://root:root@127.0.0.1:27017/admin",
      "others":null
    },
    "flow": {
      "type": "rabbitmq", // redis/rabbitmq/kafaka
      "redis": {
        "connection": null,
        "channel": "tomatologchannel"
      },
      "rabbitmq": {
        "host": "127.0.0.1",
        "port": 5672,
        "username": "root",
        "password": "123456",
        "vhost": "tomatolog",
        "exchange": "tomatolog-exchange",
        "exchangetype": "direct",
        "queuename": "tomatolog-queue",
        "routekey": "all",
        "channels": 1 // rabbitmq client instance quantity
      },
      "kafka": null
    }
  }
}

服务配置文件包含一个主节点 tomatolog,下面内置 4 个子节点,分别是:

** cache-redis
该节点指示在服务对日志进行筛选、清洗的过程中,会将策略写入缓存,默认情况下,策略被写入本地缓存,如果指定分布式缓存,则使用分布式缓存,强烈推荐配置分布式缓存,在服务进行重启或者更新的时候,策略将可以被持续计数。

** config
此节点下配置了两个系统配置文件,分别是 sysconfig 和 proconfig,这代表着服务对日志的清洗、过滤、警报的配置,无需改动这两个文件,因为我们提供了更友好的 web 控制台进行配置,后面会有介绍。

** storage
此节点非常重要,决定了日志的存储介质,首先是 type ,可以指定 //tofile/toes/tomongodb 中的任意一种,目前,tomatolog 的存储是通过接口实现的插件进行反射调用,所有的存储插件都存放在程序目录下的 plugins 目录下

深度长文-我花了10天时间造了个*,你们可能会有兴趣

如果你认为有必要重写插件,在存储前做一些其它的工作的话,你还可以通过实现 tomatolog.common 程序集中定义的 ilogwriter 接口,然后将插件放入 plugins 目录下,覆盖 //tofile/toes/tomongodb 中的一种插件,设置 type 指定为你实现的插件名称即可。或者,你还可以自己实现一个全新的插件,如实现了一个将日志存储到 redis 的插件 toredis,则将设置 "type":"toredis",并且将 toredis 需要的配置写入到节点 others 中自行读取实现,因为 ilogwriter 的默认实现 logwriter 抽象类的构造参数接收了一个实体对象

    public class storageoptions
    {
        public storagetype type { get; set; }
        public string file { get; set; }
        public string es { get; set; }
        public string mongodb { get; set; }
        public string others { get; set; }
    }

toredis 插件可以通过继承 logwriter 获得该配置节点。

** flow

flow 节点表示数据流的选择,准备支持 3 中数据流,但是因为精力有限,特别是对 kafka 也不是很熟悉,目前只实现了 redis/rabbitmq 两种方式,目前来看,基本够用,flow 节点下面的子节点就是对数据流节点的配置,选择 redis 就配置 flow.redis ,如果使用 rabbitmq,则配置 flow.rabbitmq 节点。

2.2 启动服务

在服务配置完成后,就可以使用 dotnet tomatolog.server.dll 启动服务程序,可以看到, tomatolog 侦听的端口为:20272.

深度长文-我花了10天时间造了个*,你们可能会有兴趣

在浏览器中输入网址:http://localhost:20272/,查看 web 控制台

深度长文-我花了10天时间造了个*,你们可能会有兴趣

目前可以看到,因为没有产生日志,所以首页是一片空白,但是没有关系,下面介绍另一个强大的功能:配置

2.3 系统全局配置

控制台上还有两个导航按钮 “config”、“project”,点击查看 config

** 警报配置

深度长文-我花了10天时间造了个*,你们可能会有兴趣

enable:是否启用警报通知,值为:true/false
report stage(seconds):警报周期,时间:秒
trigger threshold:触发阈值,和 report stage(seconds) 配合使用,即 xx 秒内发生 x 次后 发送通知,并重置计数器
monitor levels:警报级别,支持 trace;debug;information;warning;error;critical;none,多个 level 以 分号进行分隔。

** 短信通知配置

深度长文-我花了10天时间造了个*,你们可能会有兴趣

此通知配置非常强大,基于 http 请求,不只局限于 sms,所有可以被 http 请求的网关地址都可以配置到这里,通知内容支持系统变量(见下面附录)

** 邮件通知配置

深度长文-我花了10天时间造了个*,你们可能会有兴趣

可以配置邮件通知(推荐测试服启用,跟踪bug),邮件主题和内容支持系统变量(见下面附录),支持 html 邮件内容

** 附录:系统变量

深度长文-我花了10天时间造了个*,你们可能会有兴趣

上面列出了系统支持的所有内置变量,可在 sms 和 email 通知中配置使用,系统变量的使用如上图,必须使用大括号进行包围。

2.4 针对项目的单独配置

除了系统全局配置,tomatolog 还支持针对每个项目进行独立通知设置,方便项目管理和跟踪,项目通知配置和全局配置一致,

深度长文-我花了10天时间造了个*,你们可能会有兴趣

项目通知配置将覆盖全局配置(如果有配置的话)

3. 客户端的使用演示

首先,建立一个演示项目 example ,该项目为 asp.netcore webapi 项目。

3.1 安装客户端组件

接下来在 nuget 上搜索包 tomatolog ,由于服务器配置了使用数据流类型为 rabbitmq,这里选择安装 tomatolog.client.rabbitmq-1.0.2

深度长文-我花了10天时间造了个*,你们可能会有兴趣

3.2 将客户端注入服务中
        public void configureservices(iservicecollection services)
        {
            services.addsingleton<itomatologclient, tomatologclientrabbitmq>(factory =>
            {
                var options = this.configuration.getsection("tomatolog").get<eventrabbitmqoptions>();
                var client = new tomatologclientrabbitmq(options);
                return client;
            });

            services.addmvc().setcompatibilityversion(compatibilityversion.version_2_2);
        }

上面的代码中,读取了客户端配置文件节点 tomatolog 并反序列化为 eventrabbitmqoptions 配置对象,然后使用该配置对 tomatologclientrabbitmq 进行了初始化,关于 eventrabbitmqoptions 在配置文件中的配置如下:

  "tomatolog": {
    "loglevel": "information", // 写入日志级别,大于此级别的日志都将被吸入数据流中
    "projectlabel": "example", // 项目标签,可为 null
    "projectname": "example", // 项目名称,必须
    "sysoptions": { // 是否自动采集主机信息,可配置
      "eventid": true,
      "ip": true,
      "iplist": true,
      "machinename": true,
      "processid": true,
      "processname": true,
      "threadid": true,
      "timestamp": true,
      "username": true
    },
    "tags": null, // 项目 tag ,可 null
    "version": "1.0.0", //  当前项目版本号,可为 null
    "exchange": "tomatolog-exchange", // rabbitmq 中配置的交换机名称
    "exchangetype": "direct", // rabbitmq 交换机类型
    "host": "rabbitmq host ", // rabbitmq 主机地址
    "password": "rabbitmq passworrd", // rabbitmq 连接密码
    "port": 5672, // rabbitmq 连接端口
    "queuename": "rabbitmq queue", // rabbitmq 日志队列名称
    "routekey": "route key", // rabbitmq route key,根据 exchangetype 动态设置
    "username": "rabbitmq username", // rabbitmq 连接用户名
    "vhost": "rabbitmq vhost" // rabbitmq 连接的 vhost
  }

这段配置看似复杂,其实非常简单,所有的一切都可以*配置,在程序中,只需要一行代码初始化即,非常方便。

3.3 将异常写入数据流

在异常发生的时候,将异常写入数据流的操作非常简单,就像下面的代码

** 首先引入命名空间

using tomatolog.client.extensions;

** 处理异常:

        public actionresult<ienumerable<string>> get()
        {
            try
            {
                throw new notsupportedexception("media type");
            }
            catch (exception ex)
            {
                ex.addtomatologasync();
            }
            return new string[] { "value1", "value2" };
        }

我们上面说过,能一行代码做完的事情就不要搞复杂了,使用 ex.addtomatologasync(); 就可以将日志写入到数据流中了,非常的简洁高效。如果需要写入自定义的日志信息,可以通过依赖注入获得日志客户端对象,然后写入自定义日志,比如

        public async task<actionresult<ienumerable<string>>> get()
        {
            await logclient.writelogasync(1029, loglevel.warning, "warning infomation", "warning content", new { lasttime = datetime.now, tips = "warning" });
               
            return new string[] { "value1", "value2" };
        }
3.4 查看服务端收集日志

深度长文-我花了10天时间造了个*,你们可能会有兴趣

可以看到,上面我们一共写入了两条日志,分类为 error 和 warning,查看文件系统上,在项目 example 目录下,有两个文件

深度长文-我花了10天时间造了个*,你们可能会有兴趣

点击列表进入查看,点击单行日志的任意位置,还可以查看详细信息

深度长文-我花了10天时间造了个*,你们可能会有兴趣

3.5 自定义日志查看列

深度长文-我花了10天时间造了个*,你们可能会有兴趣

还支持对日志的搜索和分页,搜索语法支持以下三种类型:

** tofile 存储时:支持直接搜索字符串
** tomongodb 存储时: 支持 mongodb 搜索语法
** toes 存储时:支持 elasticsearch 语法

分页支持:当前日志超过 100 行时(默认显示最新 100 条日志),自动出现 previous/next 分页导航按钮

结束语

tomatolog 设计的基本原则是开放、高可扩展、*、易用,通过简单的封装,让任何一个开发人员都能在 3 分钟内投入使用,享受 tomatolog 带来的便利性,tomatolog 只做简单的存储,可以看到,如果选择存储到 mongodb 或者 es 中的时候,大家还可以通过其它的日志挖掘工具对日志进一步的搜索和处理。

如果您觉得这个项目还不错,请点击 star ,如果希望加入此项目,成为贡献者,请留下您的 github 账号,通过开源,让 .netcore 生态越来越好。

喔~对了,欢迎报告bug!

广州.net微软技术俱乐部

最后,推广一下广州.net微软技术俱乐部,欢迎更多的朋友加入我们 .netcore 这个大家庭、一起学习交流。qq群:651477282。