首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >ASP.NET Core 中简单使用 HttpClient 集成 Elasticsearch 实现日志记录与查询

ASP.NET Core 中简单使用 HttpClient 集成 Elasticsearch 实现日志记录与查询

作者头像
郑子铭
发布2025-07-12 15:36:19
发布2025-07-12 15:36:19
13400
代码可运行
举报
运行总次数:0
代码可运行

在开发中,将系统日志集中管理并支持实时搜索是提升运维效率的重要手段。本文将介绍如何在 ASP.NET Core 项目中通过 HttpClientElasticsearch 进行集成,实现日志的自动记录、索引和查询功能。

技术架构概览

  • ASP.NET Core:构建 Web API 服务
  • HttpClient:与 Elasticsearch REST 接口通信
  • Elasticsearch:用于日志数据的存储与检索
  • 中间件(Middleware):拦截请求并记录日志
  • Basic Auth:保障 Elasticsearch 安全访问

一、配置文件设置

首先,在 appsettings.json 中配置 Elasticsearch 的地址和认证信息:

代码语言:javascript
代码运行次数:0
运行
复制
{
  "Elasticsearch":{
    "Url":"https://es-host:9200",
    "Username":"username",
    "Password":"password"
},
"Logging":{
    "LogLevel":{
      "Default":"Information"
    }
},
"AllowedHosts":"*"
}

二、创建 Elasticsearch 服务类

创建 ElasticsearchService.cs 类,封装对 Elasticsearch 的基本操作,如写入文档和查询数据:

代码语言:javascript
代码运行次数:0
运行
复制
public classElasticsearchService
{
    privatereadonly HttpClient _client;
    privatereadonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web);

    public ElasticsearchService(HttpClient client, IConfiguration config)
    {
        var uri = config["Elasticsearch:Url"];
        var username = config["Elasticsearch:Username"];
        var password = config["Elasticsearch:Password"];

        client.BaseAddress = new Uri(uri);
        var byteArray = Encoding.ASCII.GetBytes($"{username}:{password}");
        client.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

        _client = client;
    }

    public async Task<bool> IndexAsync<T>(T document, string indexName, string? id = null)
    {
        var url = id != null ? $"/{indexName}/_doc/{id}" : $"/{indexName}/_doc";
        var content = new StringContent(JsonSerializer.Serialize(document, _jsonOptions), Encoding.UTF8, "application/json");

        var response = await _client.PostAsync(url, content);
        return response.IsSuccessStatusCode;
    }

    public async Task<List<T>> SearchAsync<T>(object query, string indexName)
    {
        var content = new StringContent(JsonSerializer.Serialize(query, _jsonOptions), Encoding.UTF8, "application/json");

        var response = await _client.PostAsync($"/{indexName}/_search", content);
        response.EnsureSuccessStatusCode();

        var json = await response.Content.ReadAsStringAsync();
        usingvar doc = JsonDocument.Parse(json);

        var hits = doc.RootElement.GetProperty("hits").GetProperty("hits");
        var result = new List<T>();

        foreach (var hit in hits.EnumerateArray())
        {
            var source = hit.GetProperty("_source").GetRawText();
            var obj = JsonSerializer.Deserialize<T>(source, _jsonOptions);
            if (obj != null) result.Add(obj);
        }

        return result;
    }
}

三、注册服务

Program.cs 中注册 HttpClientElasticsearchService

代码语言:javascript
代码运行次数:0
运行
复制
builder.Services.AddHttpClient<ElasticsearchService>();

四、定义日志实体类

创建一个用于记录请求日志的实体类 ApiLogEntity

代码语言:javascript
代码运行次数:0
运行
复制
public classApiLogEntity
{
    publicstring Name { get; set; }
    publicstring Ip { get; set; }
    publicstring Url { get; set; }
    publicstring ReqMethod { get; set; }
    public DateTime OpTime { get; set; }
    publicstring Account { get; set; }
    publicint StatusCode { get; set; }
    publicstring ResponseBody { get; set; }
}

五、编写日志记录中间件

通过自定义中间件拦截请求,并将日志写入 Elasticsearch:

代码语言:javascript
代码运行次数:0
运行
复制
public classRequestLoggingMiddleware
{
    privatereadonly RequestDelegate _next;
    privatereadonly ILogger<RequestLoggingMiddleware> _logger;
    privatereadonly ElasticsearchService _esService;

    public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger, ElasticsearchService esService)
    {
        _next = next;
        _logger = logger;
        _esService = esService;
    }

    public async Task Invoke(HttpContext context)
    {
        // 判断是否启用日志记录
        if (!App.Configuration["AppLogEntity"].ToBool())
        {
            await _next(context);
            return;
        }

        var request = context.Request;

        if (!request.Path.Value.Contains("api"))
        {
            await _next(context);
            return;
        }

        request.EnableBuffering();
        var originalBodyStream = context.Response.Body;
        awaitusingvar responseBody = new MemoryStream();
        context.Response.Body = responseBody;

        try
        {
            await _next(context);

            context.Response.Body.Seek(0, SeekOrigin.Begin);
            var responseText = awaitnew StreamReader(context.Response.Body).ReadToEndAsync();
            context.Response.Body.Seek(0, SeekOrigin.Begin);

            var entity = new ApiLogEntity
            {
                Name = Environment.MachineName,
                Ip = context.Connection.RemoteIpAddress?.ToString(),
                Url = request.Path + request.QueryString,
                ReqMethod = request.Method,
                OpTime = DateTime.Now,
                Account = "wx-" + App.User.FindFirst("UserID")?.Value,
                StatusCode = context.Response.StatusCode,
                ResponseBody = responseText
            };

            await _esService.IndexAsync(entity, "jltlogs");
        }
        finally
        {
            await responseBody.CopyToAsync(originalBodyStream);
            context.Response.Body = originalBodyStream;
        }
    }
}

注册中间件:

代码语言:javascript
代码运行次数:0
运行
复制
app.UseMiddleware<RequestLoggingMiddleware>();

六、测试接口

1. 写入日志文档

  • • 请求路径:POST /search/index
  • • Body 示例:
代码语言:javascript
代码运行次数:0
运行
复制
{
  "title": "Test Document",
  "description": "Elasticsearch integration with HttpClient"
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 技术架构概览
  • 一、配置文件设置
  • 二、创建 Elasticsearch 服务类
  • 三、注册服务
  • 四、定义日志实体类
  • 五、编写日志记录中间件
  • 六、测试接口
    • 1. 写入日志文档
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档