社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Elasticsearch

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

dotNET跨平台 • 1 月前 • 37 次点击  

 

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


技术架构概览

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

一、配置文件设置

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

{
  "Elasticsearch":{
    "Url":"https://es-host:9200",
    "Username":"username",
    "Password":"password"
},
"Logging":{
    "LogLevel":{
      "Default":"Information"
    }
},
"AllowedHosts":"*"
}

二、创建 Elasticsearch 服务类

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

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<boolIndexAsync<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();

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

        return result;
    }
}

三、注册服务

在 Program.cs 中注册 HttpClient 和 ElasticsearchService

builder.Services.AddHttpClient();

四、定义日志实体类

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

public classApiLogEntity
{
    publicstring Name { getset; }
    publicstring Ip { getset; }
    publicstring Url { getset; }
    publicstring ReqMethod { getset; }
    public DateTime OpTime { getset; }
    publicstring Account { getset; }
    publicint StatusCode { getset; }
    publicstring ResponseBody { getset; }
}

五、编写日志记录中间件

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




    
public classRequestLoggingMiddleware
{
    privatereadonly RequestDelegate _next;
    privatereadonly ILogger _logger;
    privatereadonly ElasticsearchService _esService;

    public RequestLoggingMiddleware(RequestDelegate next, ILogger 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;
        }
    }
}

注册中间件:

app.UseMiddleware();

六、测试接口

1. 写入日志文档

  • • 请求路径:POST /search/index
  • • Body 示例:
{
  "title": "Test Document",
  "description": "Elasticsearch integration with HttpClient"
}

 




如果你觉得这篇文章对你有帮助,欢迎点赞、收藏并分享给更多开发者!让我们一起学习,共同进步!



Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/183519
 
37 次点击