ambari+ bigtop 编译、打包、部署步骤总览

Net8将Serilog日志推送ES,附视频

这是一个Serilog的实践Demo,包括了区别记录存放,AOP 日志记录,EF 执行记录,并且将日志推送到Elastic Search。

说在前面的话

自从AI出来之后,学习的曲线瞬间变缓了,学习的路径也有了很大的变化。

与本人来说以前大多数都先知晓理论再找相关的框架官网或博客,然后去实践Demo,再加入到代码中,也就是理论-》实践-》应用-》技能。

而现在,可以在稍微知晓概念之后,直接找AI要Demo先跑起来,应用到代码中去,然后反向结合代码去问AI每一步实现的逻辑与理论,再消化成自己技能,也就是概念-》应用-》理论知识-》技能。

故此次尝试不同的写文思路,从拿到源代码的读者角度,开始思考与实践。

依照惯例,源代码在文末,需要自取~

环境准备

Docker Desktop

VS2022 SDK .NET8

Elastic Search 8.0+ Kibana(Docker)

SqlServer (Docker 或者本地 SqlServer)

Chat Gpt (可选)

效果一览

实现要求

分别记录EF、非EF日志,存放至不同的路径

其中非EF日志以AOP的思想,记录执行方法的前后信息,API接口调用详情与返回结果,

把所有的消息推送至elastic search。

实现效果

Docker中启动 ES 和 SqlServer

再 F5 启动项目

EF 日志存储在 Logs/EFSql 文件夹下

非EF日志存储在 Logs/AuditLogs 文件夹下

所有的日志推送至Elastic Search

从Program 初见端倪

OK,相信你现在已经把代码拉下来了,如果没有想生啃代码,不用跳过此节。

.net 8 与 .net 6 可以使用顶级语句,相对于.net 5 及以前的版本,去掉了Startup作为web的配置程序,也就是上手各大项目的入口, 这里直接看Program 来探究Demo 如何配置Web,来一窥端倪吧!

using Autofac;

using Autofac.Extensions.DependencyInjection;

using Autofac.Extras.DynamicProxy;

using Microsoft.EntityFrameworkCore;

using SampleDemo.Yzh.Net.Logger;

using SampleDemo.Yzh.Net.Repository;

using SampleDemo.Yzh.Net.Service;

using SampleDemo.Yzh.Net.Core;

using Serilog;

using ILogger = Serilog.ILogger;

var builder = WebApplication.CreateBuilder(args);

// Config

builder.Services.AddSingleton(new AppSettings(builder.Configuration));

// Serilog

builder.Host.AddCustomLog();

// EF

builder.Services.AddDbContextPool<TestContext>

    (o => o.UseSqlServer(builder.Configuration.GetConnectionString("NicoLocaldbStr"))

#if DEBUG

    .EnableSensitiveDataLogging()

#endif

    .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddSerilog())

    ));

// Http Info

builder.Services.AddHttpContextAccessor();

// Auto Fac

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());

builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>

{

    // 注册AopDemo拦截器为单例模式

    containerBuilder.RegisterType<AopDemo>().SingleInstance();

    // InterceptedBy指定拦截器

    containerBuilder.RegisterType<ValuesService>().As<IValuesService>().EnableInterfaceInterceptors().InterceptedBy(typeof(AopDemo));

    // 或者在IValuesService 加标签 [Intercept(typeof(AopDemo))]

    //containerBuilder.RegisterType<ValuesService>().As<IValuesService>().EnableInterfaceInterceptors();

    //向 Autofac 容器注册 Log.Logger 这个已经存在的日志记录器实例 ,指定这个实例作为 ILogger 接口的实现 ,此ILogger为 Serilog的ILogger

    //当应用程序中的组件通过依赖注入请求 ILogger 接口的实例时,它们会接收到 Log.Logger 这个单例对象

    containerBuilder.RegisterInstance(Log.Logger).As<ILogger>();

});

builder.Services.AddControllers();

var app = builder.Build();

// Middleware

app.UseMiddleware<ResponseLoggingMiddleware>(); //返回客户端响应的日志记录

app.UseAuthorization();

app.MapControllers();

app.Run();

这里我直接把Program.cs51 行代码全部拉出来,由此来看大致做了些什么。

using 中可以看到 引用了Autofac以及他的扩展包, 引入了Serilog,并且指定了ILogger为 Serilog.ILogger,作用暂且按下不表

builder.Services.AddSingleton(new AppSettings(builder.Configuration))这里将配置以单例的形式封装在AppSettings类中,后续取配置直接从AppSettings类中取即可

builder.Host.AddCustomLog();这里用一个扩展方法,将Serilog的注入写入AddCustomLog()方法中,后续这将是该Demo核心方法,重点看

builder.Services.AddDbContextPool<TestContext>

    (o => o.UseSqlServer(builder.Configuration.GetConnectionString("NicoLocaldbStr"))

#if DEBUG

    .EnableSensitiveDataLogging()

#endif

    .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddSerilog())

    ));

上述代码,以DbContext池化的方式注入EF,并且在Debug模式下开启敏感日志,配置Serilog作为日志的记录工具

builder.Services.AddHttpContextAccessor();添加访问Http请求的信息,用于后续Reponse中间件开发提供HTTP信息

builder.Host.UseServiceProviderFactory以及builder.Host.ConfigureContainer配置Auto Fac,注释详解

app.UseMiddleware< ResponseLoggingMiddleware >();ResponseLoggingMiddleware中间件返回客户端响应的日志记录

再看Serilog拓展

从上文可知,使用了AddCustomLog()这样的一个扩展方法,注入了Serilog,OK! ,Ctrl + F12 进入一探究竟

    public static class CustomLogger

    {

        public static IHostBuilder AddCustomLog(this IHostBuilder builder)

        {

            Log.Logger = new LoggerConfiguration()

                .ReadFrom.Configuration(AppSettings.Configuration)

                .Enrich.FromLogContext()

                // 输出到控制台

                .WriteToConsole()

                // 输出到文件

                .WriteToFile()

                // 输出到Es

                .WriteToElasticsearch()

                .CreateLogger();

            builder.UseSerilog();

            return builder;

        }

    }

.ReadFrom.Configuration(AppSettings.Configuration):指示 Serilog 从应用程序的配置文件(如 appsettings.json)中读取配置信息。这里假设有一个 AppSettings 类,它持有应用程序的配置信息。

.Enrich.FromLogContext():添加从日志上下文中丰富日志事件的能力,例如,可以自动地将关联的 HTTP 请求信息添加到日志中。

.WriteToConsole():配置 Serilog 将日志输出到控制台。

.WriteToFile():配置 Serilog 将日志输出到文件。

.WriteToElasticsearch():配置 Serilog 将日志输出到 Elasticsearch。这对于在 Elasticsearch 中集中管理和分析日志非常有用。

WriteToConsole与WriteToFile 也是拓展方法,那就继续Ctrl + F12 继续下去咯

public static class LoggerConfigurationExtensions

{

    /// <summary>

    /// 输出在控制台

    /// </summary>

    /// <param name="loggerConfiguration"></param>

    /// <returns></returns>

    public static LoggerConfiguration WriteToConsole(this LoggerConfiguration loggerConfiguration)

    {

        // 输出普通日志

        loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>

            lg.FilterRemoveSqlLog().WriteTo.Console());

        // 输出SQL

        loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>

            lg.FilterSqlLog().WriteTo.Console());

        return loggerConfiguration;

    }

    /// <summary>

    /// 写入文件

    /// </summary>

    /// <param name="loggerConfiguration"></param>

    /// <returns></returns>

    public static LoggerConfiguration WriteToFile(this LoggerConfiguration loggerConfiguration)

    {

        // SQL语句写入 

        loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>

            lg.FilterSqlLog()

                .WriteTo.Async(s => s.File(LogContextStatic.Combine(LogContextStatic.EFSql, @"EFSql.txt"), rollingInterval: RollingInterval.Day,

                    outputTemplate: LogContextStatic.FileMessageTemplate, retainedFileCountLimit: 31)));

        // 非SQL写入

        loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>

            lg.FilterRemoveSqlLog()

                .WriteTo.Async(s => s.File(LogContextStatic.Combine(LogContextStatic.AuditLogs, @"AuditLog.txt"), rollingInterval: RollingInterval.Hour,

                outputTemplate: LogContextStatic.FileMessageTemplate, retainedFileCountLimit: 31)));

        return loggerConfiguration;

    }

    /// <summary>

    /// 推送至 ES

    /// </summary>

    /// <param name="loggerConfiguration"></param>

    /// <returns></returns>

    public static LoggerConfiguration WriteToElasticsearch(this LoggerConfiguration loggerConfiguration)

    {

        var esUri = AppSettings.GetValue("ElasticConfiguration:Uri");

        loggerConfiguration = loggerConfiguration.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(

                new Uri(esUri))

        {

            AutoRegisterTemplate = true,

            IndexFormat = "nico-api-log-{0:yyyy.MM.dd}",

            ModifyConnectionSettings = con => con.ServerCertificateValidationCallback((sender, certificate, chain, sslPolicyErrors) => true)

            .BasicAuthentication(

                AppSettings.GetValue("ElasticConfiguration:Es_UserName"),

                AppSettings.GetValue("ElasticConfiguration:Es_Pwd"))

        });

        return loggerConfiguration;

    }

    /// <summary>

    /// 过滤出 SQL语句的日志

    /// </summary>

    /// <param name="lc"></param>

    /// <returns></returns>

    public static LoggerConfiguration FilterSqlLog(this LoggerConfiguration lc)

    {

        return lc.Filter.ByIncludingOnly(e =>

        e.Properties.ContainsKey("SourceContext") &&

        e.Properties["SourceContext"].ToString().Contains("Microsoft.EntityFrameworkCore.Database.Command"));

    }

    /// <summary>

    /// 过滤非 SQL语句的日志

    /// </summary>

    /// <param name="lc"></param>

    /// <returns></returns>

    public static LoggerConfiguration FilterRemoveSqlLog(this LoggerConfiguration lc)

    {

        return lc.Filter.ByExcluding(e =>

        e.Properties.ContainsKey("SourceContext") &&

        e.Properties["SourceContext"].ToString().Contains("Microsoft.EntityFrameworkCore.Database.Command"));

    }

}

注释非常详尽,不再赘述,这里需要解释核心的问题,如何区别的SQL与非SQL的?

日志上下文 (SourceContext):Serilog 允许通过日志事件的属性来进行过滤。在这个例子中,使用了 SourceContext 属性,这是一个常用于标识日志来源的属性。对于由 Entity Framework Core 生成的日志,SourceContext 通常会包含值 "Microsoft.EntityFrameworkCore.Database.Command",这表示日志条目是由 EF Core 在执行数据库命令时产生的。

过滤器 (Filter.ByIncludingOnly):这个方法允许配置日志系统仅包含符合特定条件的日志条目。在这里,条件是日志事件的属性中必须包含 SourceContext,并且其值包含 "Microsoft.EntityFrameworkCore.Database.Command"。这样,只有 EF Core 产生的数据库命令日志会被包括进来。

如果此节看懂了,下面实践绝对难不倒读者。

部署ES

本人在部署ES的时候遇到了很多坑,看到一些大佬的博客也是一笔带过,这里用Docker desktop 一步一步全部覆盖到位,跟着文章步骤走,绝对搞得定。

启动elasticsearch 、 kibana

首先先贴上 ES官方文档启动教程https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html

下载elasticsearch 、 kibana 镜像,本文截至24年7月30日,使用最新的ES版本8.14.3

docker创建网络

docker network create elastic-net

docker中启动ES,并且记住登录的密码,加入集群的Token

docker run --name es01 --net elastic -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -t elasticsearch:8.14.3

启动之后,会在终端显示密码,还有加入集群的Token,待会在启动kibana时要用,如果不小心关掉了,可以在docker desktop中,找到es的容器日志找到。

到这里ES启动完成,接下来启动Kibana

docker中启动kibana,加入集群

docker run --name kib01 --net elastic -p 5601:5601 kibana:8.14.3

http://0.0.0.0/5601可能进不去(改了host文件的原因),用http://localhost/5601即可

将token传入 ,静待部署完成, 就进入了登录界面

账号默认为 elastic 密码(小写) 则为一开始保存的 密码,这里为 _*5O7P+5FKSV7nC_EDEE记得改为你自己的,成功登录之后就进入后台页面

ES后台创建数据集 (DataView)

创建 Data view , 此时需要重点注意 , Index pattern这里需要填对应索引的名称,匹配成功才能在Discover中看到日志

至此 ES 搭建完成,现在要去将 Log 推送到 ES平台来

启动!!!

上文中已经将ES部署好了,现在需要将项目跑起来,将日志推送到ES平台中去。

修改项目配置

数据库使用的是SQL Server , 需要修改为你自己的SQL 链接字符串即可。

    "ConnectionStrings": {

    // SQL Server

    "NicoLocaldbStr": "Data Source=localhost;Initial Catalog=nicolocaldb;User ID=sa;Password=MyStrongPwd!2#;Trust Server Certificate=True"

  }

这里需要加张表

-- SQL Server

CREATE TABLE TestEFTable (

    Id INT PRIMARY KEY IDENTITY(1,1), -- Id 列为主键并设置为自增

    Name NVARCHAR(255) NULL, -- Name 列,允许 NULL,使用 NVARCHAR 类型来支持 Unicode 字符

    LastModifiedAt DATETIMEOFFSET NULL, -- LastModifiedAt 列,允许 NULL,使用 DATETIMEOFFSET 类型

    LastModifiedBy INT NOT NULL -- LastModifiedBy 列,不允许 NULL

);

  "ElasticConfiguration": {

    "Uri": "https://localhost:9200", // ES 地址

    "Es_UserName": "elastic", // 账号

    "Es_Pwd": "_*5O7P+5FKSV7nC_EDEE" // 密码

  }

ES 的配置同样修改为自己的配置。

原神启动!(bushi

F5启动! (以下是操作视频)

https://www.bilibili.com/video/BV1w3vUeWE4n/

总结

稍微总结一下,

Demo集成了Elasticsearch,Serilog,拦截器,autofac,EF。

区分EF 与非EF日志的记录与存放

记录完整的操作视频,包教包会!

源代码仓库[GitHub]https://github.com/OrzCoCo-Y/LogSampleDemo

[Gitee]https://gitee.com/yi_zihao/LogSampleDemo

参考资料

【ChatGPT】

【严架的Maomi 框架】https://maomi.whuanle.cn借鉴了其中HTTP日志记录,取代了自己写中间件

【老八的哲学开源框架】https://github.com/anjoy8/Blog.Core借鉴了其中服务注册

  • 22
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Ambari是Apache软件基金会下的一个子项目,是一个开源的管理和监控Hadoop集群的工具。而Bigtop是一个Apache软件基金会下的开源项目,主要用于构建,测试和部署大数据平台。 Ambari Bigtop大数据平台安装部署指南主要包括以下几个步骤: 1. 准备工作:在开始安装之前,需要确保系统已经安装了合适的操作系统和相关的依赖软件,如Java、SSH等。此外,还需要确定网络环境是否能够正常访问所需的软件源和资源。 2. 下载和安装Ambari:从Ambari官方网站上下载适用于目标操作系统的Ambari软件包。安装Ambari时,需要注意选择合适的数据库和用户认证方式。 3. 配置Ambari服务器:根据实际需求,对Ambari服务器进行配置。一般需要设置主机名和端口号等基本信息,并选择适当的安装选项。 4. 启动Ambari服务器:启动Ambari服务器后,可以通过浏览器访问Ambari web界面,并使用默认的用户名和密码登录。登录成功后,可以进行集群的配置和管理。 5. 创建集群:使用Ambari web界面创建新的集群。在创建集群时,需要指定集群的名称,选择合适的Hadoop分发版本和相应的服务组件。 6. 配置集群:根据需要,配置集群中各个节点的主机名、IP地址、SSH访问等信息,并为各个服务组件分配合适的角色。 7. 安装集群:在配置完成后,可以开始安装集群。Ambari会自动根据所选的服务组件和配置要求,安装相应的软件包并启动服务。 8. 部署集群:安装完成后,可以对集群进行进一步的配置和优化。可以为各个服务组件设置参数,并在需要时添加额外的节点和组件。 9. 监控和管理:Ambari提供了丰富的监控和管理功能,可以用于实时监控集群的运行状态、性能参数等。还可以进行服务的启停、组件的升级等操作。 10. 测试和维护:在部署完成后,还需要进行一些测试和维护工作。可以运行一些测试工具对集群进行测试,以确保其正常运行。同时,定期进行安全和性能优化等维护工作也是非常重要的。 通过遵循Ambari Bigtop大数据平台安装部署指南,用户可以快速搭建和部署大数据平台,实现集群的管理和监控,为大数据处理提供便利和支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牛马程序员24

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值