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.Now.Date : DateTime.Now.Date.AddDays(days.Value);
var endDate = days == null ? DateTime.Now : DateTime.Now.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, endDate);
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 日志服务器进行交互,获取和分析应用程序的日志数据。让我详细解释一下:
类的结构和依赖
public class AppLogEntryService(IConfiguration configuration, ILogger<AppLogEntryService> logger)
: IAppLogEntryService
- 使用了 C# 12 的主构造函数语法
- 依赖注入了
IConfiguration(配置服务)和ILogger(日志服务) - 实现了
IAppLogEntryService接口
核心方法解析
1. GetSeqConnection() - 建立 Seq 连接
private SeqConnection GetSeqConnection()
这个私有方法负责创建与 Seq 日志服务器的连接:
- 从配置中读取
LogApiHost(Seq 服务器地址) - 根据环境(生产环境或非生产环境)选择不同的 API Key
- 非生产环境使用
LogApiKey,生产环境使用LogSeq:ApiKey - 返回配置好的
SeqConnection对象
2. GetPageAsync() - 分页获取日志事件
public async Task<ResultSetPart?> GetPageAsync(...)
这个方法提供日志事件的分页查询功能:
- 参数说明:
filter: 过滤条件startAtId: 起始IDafterId: 在某个ID之后pageSize: 页面大小(默认20条)
- 调用 Seq API 的
Events.PageAsync方法获取数据 render: true表示渲染日志消息模板
3. GetLatestAccessNumberAsync() - 获取访问统计
public async Task<List<AccessSummary>> GetLatestAccessNumberAsync(int? days)
这个方法用于统计网站的访问量:
- 时间范围:根据
days参数确定查询的时间范围 - 过滤条件:
- 只统计
Dpz.Core.Web程序的日志 - 只统计来自请求日志中间件的日志
- 排除 WebSocket 相关的路径(如
/chathub,/notification等)
- 只统计
- SQL 查询:使用 Seq 的查询语言按天分组统计访问次数
- 返回数据:包含日期和访问次数的
AccessSummary列表
关键特性
- 环境区分:根据配置环境使用不同的 API Key
- 异常处理:在统计方法中包含了完整的异常处理
- 资源管理:使用
using语句确保连接正确释放 - 灵活过滤:支持多种过滤条件来精确查询所需的日志数据
底部的 SQL 注释
文件末尾的注释展示了一个更复杂的 Seq 查询示例,用于获取响应时间最长的 20 个请求,这可能是性能监控的一部分。
这个服务类是一个典型的日志分析服务,为应用程序提供了日志查询和访问统计的功能。
评论加载中...