网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using Dpz.Core.Public.ViewModel.AppLogs;
using Seq.Api;
using Seq.Api.Model.Events;

namespace Dpz.Core.Service.RepositoryServiceImpl;

public class AppLogEntryService(IConfiguration configuration, ILogger<AppLogEntryService> logger)
    : IAppLogEntryService
{
    private SeqConnection GetSeqConnection()
    {
        var logApiHost = configuration["LogApiHost"];
        if (string.IsNullOrEmpty(logApiHost))
            throw new Exception("configuration no LogApiHost node");
        var apiKey = configuration["LogSeq:ApiKey"];
        if (string.IsNullOrEmpty(apiKey))
            throw new Exception("configuration no LogSeq.Apikey node");
        var connection =
            configuration["AgileConfig:env"] != "PROD"
                ? new SeqConnection(logApiHost, configuration["LogApiKey"])
                : new SeqConnection(logApiHost, apiKey);
        return connection;
    }

    public async Task<ResultSetPart?> GetPageAsync(
        string? filter = null,
        string? startAtId = null,
        string? afterId = null,
        int pageSize = 20
    )
    {
        using var connection = GetSeqConnection();

        var part = await connection.Events.PageAsync(
            filter: filter,
            startAtId: startAtId,
            afterId: afterId,
            render: true,
            count: pageSize
        );

        return part;
    }

    public async Task<List<AccessSummary>> GetLatestAccessNumberAsync(int? days)
    {
        var startDate =
            days == null ? DateTime.UtcNow.Date : DateTime.UtcNow.Date.AddDays(days.Value);
        var endDate = days == null ? DateTime.UtcNow : DateTime.UtcNow.Date;
        using var connection = GetSeqConnection();
        var filters = new List<string>
        {
            "Program = 'Dpz.Core.Web'",
            "SourceContext = 'Serilog.AspNetCore.RequestLoggingMiddleware'",
            "RequestPath <> '/chathub'",
            "RequestPath <> '/chatHub'",
            "RequestPath <> '/notification'",
            "RequestPath <> '/notification/negotiate'",
            "RequestPath <> '/chathub/negotiate'",
            "RequestPath <> '/chat/init'",
        };
        var filter = string.Join(" and ", filters);

        try
        {
            var query = $"""
                select count(@Id) from stream
                where {filter}
                group by time(1d)
                """;
            var part = await connection.Data.QueryAsync(query, startDate, DateTime.Now.AddHours(8));
            var list = part
                .Slices.Select(x => new AccessSummary
                {
                    Date = Convert.ToDateTime(x.Time).ToString("yyyy/MM/dd"),
                    Count = Convert.ToInt32(x.Rows.FirstOrDefault()?.FirstOrDefault() ?? 0),
                })
                .ToList();

            return list;
        }
        catch (Exception e)
        {
            logger.LogError(e, "get latest access number fail");
            return new List<AccessSummary>();
        }
    }
}




// select
// 	@Id,
// 	ToIsoString(@Timestamp) as time,
// 	Elapsed,
// 	@Message
// from stream
// where SourceContext='Serilog.AspNetCore.RequestLoggingMiddleware'
// 	and SourceContext = 'Serilog.AspNetCore.RequestLoggingMiddleware'
// 	and RequestPath <> '/chathub'
// 	and RequestPath <> '/chatHub'
// 	and RequestPath <> '/notification'
// 	and RequestPath <> '/notification/negotiate'
// 	and RequestPath <> '/chathub/negotiate'
// 	and RequestPath <> '/chat/init'
// 	and RequestPath <> '/robotChat'
//  order by Elapsed desc limit 20
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码定义了一个名为 AppLogEntryService 的服务类,主要用于与 Seq 日志管理系统进行交互。Seq 是一个用于集中管理和查询日志的工具。该服务实现了 IAppLogEntryService 接口,提供了两个主要功能:获取日志分页和获取最新的访问统计。

以下是代码的主要功能和结构的详细解释:

1. 构造函数

public AppLogEntryService(
    IConfiguration configuration,
    ILogger<AppLogEntryService> logger)
  • 构造函数接受两个参数:IConfigurationILogger<AppLogEntryService>
  • IConfiguration 用于读取应用程序的配置设置(如日志 API 的主机和 API 密钥)。
  • ILogger<AppLogEntryService> 用于记录日志。

2. GetSeqConnection 方法

private SeqConnection GetSeqConnection()
  • 该方法用于创建并返回一个 SeqConnection 对象,该对象用于与 Seq API 进行交互。
  • 它从配置中读取 LogApiHostLogSeq:ApiKey,并根据环境(是否为生产环境)选择合适的 API 密钥。
  • 如果配置中缺少必要的节点,会抛出异常。

3. GetPageAsync 方法

public async Task<ResultSetPart?> GetPageAsync(string? filter = null, string? startAtId = null,
    string? afterId = null, int pageSize = 20)
  • 该方法用于获取日志的分页数据。
  • 它接受可选的过滤条件、起始 ID、后续 ID 和页面大小作为参数。
  • 使用 GetSeqConnection 方法建立与 Seq 的连接,并调用 PageAsync 方法获取日志数据。
  • 返回一个 ResultSetPart 对象,包含分页的日志信息。

4. GetLatestAccessNumberAsync 方法

public async Task<List<AccessSummary>> GetLatestAccessNumberAsync(int? days)
  • 该方法用于获取最近访问的统计信息,返回一个 AccessSummary 对象的列表。
  • 它接受一个可选的参数 days,表示要查询的天数。
  • 根据 days 参数计算起始日期,并构建一组过滤条件,排除特定的请求路径。
  • 使用 SQL 查询语法从 Seq 中获取访问计数,并按天分组。
  • 结果被转换为 AccessSummary 对象的列表,包含日期和访问计数。
  • 如果在查询过程中发生异常,会记录错误并返回一个空的列表。

总结

AppLogEntryService 类提供了与 Seq 日志系统的交互功能,允许用户分页获取日志和获取最近的访问统计信息。通过使用配置和日志记录,它确保了服务的灵活性和可维护性。

loading