网站建设的具体实施方案,网上编程课的哪家好,外发加工平台,晋州做网站#x1f680; ABP vNext Sentry ELK Stack#xff1a;打造高可用异常跟踪与日志可视化平台 #x1f389; #x1f4da; 目录 #x1f680; ABP vNext Sentry ELK Stack#xff1a;打造高可用异常跟踪与日志可视化平台 #x1f389;技术选型系统架构图依赖安装与多环… ABP vNext Sentry ELK Stack打造高可用异常跟踪与日志可视化平台 目录 ABP vNext Sentry ELK Stack打造高可用异常跟踪与日志可视化平台 技术选型系统架构图依赖安装与多环境配置 安全日志配置 appsettings.Development.jsonappsettings.Production.jsonElasticsearch 索引模板 程序启动与 DI 注册 ⚙️日志增强与异常捕获 ️自定义 TenantLogEnricher全局异常订阅器 APM 事务监控示例 HealthChecks 与 UI 日志生命周期管理 (ILM) 容器化部署示例 Kubernetes 部署示例 ☸️ 技术选型
️ 工具功能适用场景ABP vNext模块化应用框架多租户、多模块Serilog.NET 结构化日志库支持多种 SinkSentry异常与性能链路监控异常聚合、Trace 分析Elasticsearch日志索引引擎大规模写入与检索Kibana日志可视化面板仪表盘和图表展示HealthChecks UI可视化健康检查服务可用性与探针监控 系统架构图 #mermaid-svg-U9fnFivafD2fg5Ug {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-U9fnFivafD2fg5Ug .error-icon{fill:#552222;}#mermaid-svg-U9fnFivafD2fg5Ug .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-U9fnFivafD2fg5Ug .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-U9fnFivafD2fg5Ug .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-U9fnFivafD2fg5Ug .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-U9fnFivafD2fg5Ug .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-U9fnFivafD2fg5Ug .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-U9fnFivafD2fg5Ug .marker{fill:#333333;stroke:#333333;}#mermaid-svg-U9fnFivafD2fg5Ug .marker.cross{stroke:#333333;}#mermaid-svg-U9fnFivafD2fg5Ug svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-U9fnFivafD2fg5Ug .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-U9fnFivafD2fg5Ug .cluster-label text{fill:#333;}#mermaid-svg-U9fnFivafD2fg5Ug .cluster-label span{color:#333;}#mermaid-svg-U9fnFivafD2fg5Ug .label text,#mermaid-svg-U9fnFivafD2fg5Ug span{fill:#333;color:#333;}#mermaid-svg-U9fnFivafD2fg5Ug .node rect,#mermaid-svg-U9fnFivafD2fg5Ug .node circle,#mermaid-svg-U9fnFivafD2fg5Ug .node ellipse,#mermaid-svg-U9fnFivafD2fg5Ug .node polygon,#mermaid-svg-U9fnFivafD2fg5Ug .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-U9fnFivafD2fg5Ug .node .label{text-align:center;}#mermaid-svg-U9fnFivafD2fg5Ug .node.clickable{cursor:pointer;}#mermaid-svg-U9fnFivafD2fg5Ug .arrowheadPath{fill:#333333;}#mermaid-svg-U9fnFivafD2fg5Ug .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-U9fnFivafD2fg5Ug .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-U9fnFivafD2fg5Ug .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-U9fnFivafD2fg5Ug .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-U9fnFivafD2fg5Ug .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-U9fnFivafD2fg5Ug .cluster text{fill:#333;}#mermaid-svg-U9fnFivafD2fg5Ug .cluster span{color:#333;}#mermaid-svg-U9fnFivafD2fg5Ug div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-U9fnFivafD2fg5Ug :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 写日志 写入 上报 捕获 探针 ABP vNext App Serilog Logging Elasticsearch Sink Elasticsearch Kibana Dashboard Sentry SDK Sentry Dashboard IExceptionSubscriber HealthChecks UI 依赖安装与多环境配置
dotnet add package Sentry.AspNetCore
dotnet add package Serilog.Sinks.Elasticsearch
dotnet add package Serilog.Enrichers.Environment
dotnet add package Serilog.Enrichers.Thread
dotnet add package Serilog.Enrichers.CorrelationId
dotnet add package Volo.Abp.Serilog
dotnet add package AspNetCore.HealthChecks.UI// Program.cs - 配置读取顺序
var builder WebApplication.CreateBuilder(args);builder.Configuration.AddJsonFile(appsettings.json, optional: false, reloadOnChange: true).AddJsonFile($appsettings.{builder.Environment.EnvironmentName}.json, optional: true).AddEnvironmentVariables();安全日志配置
appsettings.Development.json
{Sentry: {Dsn: ${SENTRY_DSN},TracesSampleRate: 1.0,Debug: true},Serilog: {MinimumLevel: { Default: Debug },WriteTo: [ { Name: Console } ]}
}appsettings.Production.json
{Sentry: {Dsn: ${SENTRY_DSN},TracesSampleRate: 0.2,SendDefaultPii: true,AttachStacktrace: true,Debug: false,DiagnosticsLevel: Error},Serilog: {Using: [ Serilog.Sinks.Elasticsearch ],MinimumLevel: {Default: Information,Override: { Microsoft: Warning }},WriteTo: [{Name: Elasticsearch,Args: {NodeUris: http://elasticsearch:9200,AutoRegisterTemplate: true,AutoRegisterTemplateVersion: ESv7,IndexFormat: abp-logs-{0:yyyy.MM.dd}}}],Enrich: [ FromLogContext, WithMachineName, WithThreadId ]}
}秘钥注入 .NET 默认支持用环境变量 SENTRY__DSN双下划线表示冒号覆盖 Sentry:Dsn。 export SENTRY__DSNhttps://xxxxsentry.io/projectElasticsearch 索引模板
curl -X PUT localhost:9200/_template/abp-logs-template -H Content-Type: application/json -d
{index_patterns: [abp-logs-*],settings: { number_of_shards: 3 },mappings: {properties: {TenantId: { type: keyword },Module: { type: keyword },Timestamp: { type: date },Level: { type: keyword },Message: { type: text }}}
}程序启动与 DI 注册 ⚙️
var builder WebApplication.CreateBuilder(args);// 1. CorrelationId 中间件
builder.Services.AddCorrelationId();// 2. Sentry SDK
builder.Services.AddSentry(o
{o.Dsn builder.Configuration[Sentry:Dsn];o.TracesSampleRate 0.2;o.AttachStacktrace true;o.Debug false;
});// 3. Serilog 注册
builder.Host.UseSerilog((ctx, lc)
{lc.ReadFrom.Configuration(ctx.Configuration).Enrich.WithCorrelationId().Enrich.WithMachineName().Enrich.WithEnvironmentUserName().Enrich.WithProcessId().Enrich.WithTenantLogEnricher();
});// 4. 全局异常订阅
builder.Services.AddSingletonIExceptionSubscriber, GlobalExceptionSubscriber();// 5. HealthChecks UI
builder.Services.AddHealthChecks().AddSqlServer(builder.Configuration.GetConnectionString(Default), name: SQL).AddRedis(builder.Configuration[Redis:Configuration], name: Redis).AddHealthChecksUI().AddSqlServerStorage(builder.Configuration.GetConnectionString(HealthChecksUI:Storage));var app builder.Build();// 6. 中间件顺序
app.UseCorrelationId();
app.UseSerilogRequestLogging();
app.UseSentryTracing();
app.UseRouting();app.UseEndpoints(endpoints
{endpoints.MapHealthChecks(/health, new HealthCheckOptions{ResponseWriter UIResponseWriter.WriteHealthCheckUIResponse});endpoints.MapHealthChecksUI(options { options.UIPath /health-ui; });endpoints.MapControllers();
});app.Run();日志增强与异常捕获 ️
自定义 TenantLogEnricher
public class TenantLogEnricher : ILogEventEnricher
{public void Enrich(LogEvent logEvent, ILogEventPropertyFactory factory){var tenantId CurrentTenant.Id?.ToString() ?? host;var moduleName Assembly.GetEntryAssembly()?.GetName().Name ?? unknown;logEvent.AddPropertyIfAbsent(factory.CreateProperty(TenantId, tenantId));logEvent.AddPropertyIfAbsent(factory.CreateProperty(Module, moduleName));}
}全局异常订阅器
public class GlobalExceptionSubscriber : IExceptionSubscriber
{private readonly ILoggerGlobalExceptionSubscriber _logger;public GlobalExceptionSubscriber(ILoggerGlobalExceptionSubscriber logger) _logger logger;public Task HandleAsync(ExceptionNotificationContext context){// 业务异常也记录级别 Warning_logger.LogWarning(context.Exception, 业务异常{Message}, context.Exception.Message);// 全部异常上报到 SentrySentrySdk.CaptureException(context.Exception);return Task.CompletedTask;}
}APM 事务监控示例
using var tx SentrySdk.StartTransaction(OrderProcess, order.process);
try
{// … 业务逻辑 …tx.Finish(SpanStatus.Ok);
}
catch (Exception)
{tx.Finish(SpanStatus.InternalError);throw;
}HealthChecks 与 UI
// healthchecks-settings.json
{HealthChecksUI: {HealthChecks: [{Name: ABP Core,Uri: http://localhost:5000/health}],EvaluationTimeOnSeconds: 30,MinimumSecondsBetweenFailureNotifications: 60,Storage: {ConnectionString: Server...;DatabaseHealthChecks;User Id...;}}
}已在 Program.cs 中通过 .AddSqlServerStorage(...) 完成持久化配置。 日志生命周期管理 (ILM)
# 创建 ILM 策略
PUT _ilm/policy/abp-logs-policy
{policy: {phases: {hot: { actions: { rollover: { max_age: 7d, max_size: 50gb } } },warm: { actions: { forcemerge: { max_num_segments: 1 } } },delete: { actions: { delete: { min_age: 30d } } }}}
}# 创建 Alias 并激活 Rollover
PUT /abp-logs-write
{aliases: { abp-logs: {} }
}在 appsettings.Production.json 中将 IndexFormat 修改为:
IndexFormat: abp-logs-write-{0:yyyy.MM.dd}容器化部署示例
version: 3.8
services:elasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:7.17.10ports: [9200:9200]environment:- discovery.typesingle-nodekibana:image: docker.elastic.co/kibana/kibana:7.17.10ports: [5601:5601]depends_on: [elasticsearch]logstash: # 可选集中化管道image: docker.elastic.co/logstash/logstash:7.17.10ports: [5044:5044]volumes:- ./logstash/pipeline/:/usr/share/logstash/pipeline/depends_on: [elasticsearch]app:image: yourorg/abp-sentry-elk-demo:latestports: [5000:80]environment:- ASPNETCORE_ENVIRONMENTProduction- SENTRY__DSN${SENTRY__DSN}depends_on: [elasticsearch]#mermaid-svg-eNYRannNnSFHQ4nD {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-eNYRannNnSFHQ4nD .error-icon{fill:#552222;}#mermaid-svg-eNYRannNnSFHQ4nD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eNYRannNnSFHQ4nD .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-eNYRannNnSFHQ4nD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eNYRannNnSFHQ4nD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eNYRannNnSFHQ4nD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eNYRannNnSFHQ4nD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eNYRannNnSFHQ4nD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eNYRannNnSFHQ4nD .marker.cross{stroke:#333333;}#mermaid-svg-eNYRannNnSFHQ4nD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eNYRannNnSFHQ4nD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eNYRannNnSFHQ4nD .cluster-label text{fill:#333;}#mermaid-svg-eNYRannNnSFHQ4nD .cluster-label span{color:#333;}#mermaid-svg-eNYRannNnSFHQ4nD .label text,#mermaid-svg-eNYRannNnSFHQ4nD span{fill:#333;color:#333;}#mermaid-svg-eNYRannNnSFHQ4nD .node rect,#mermaid-svg-eNYRannNnSFHQ4nD .node circle,#mermaid-svg-eNYRannNnSFHQ4nD .node ellipse,#mermaid-svg-eNYRannNnSFHQ4nD .node polygon,#mermaid-svg-eNYRannNnSFHQ4nD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eNYRannNnSFHQ4nD .node .label{text-align:center;}#mermaid-svg-eNYRannNnSFHQ4nD .node.clickable{cursor:pointer;}#mermaid-svg-eNYRannNnSFHQ4nD .arrowheadPath{fill:#333333;}#mermaid-svg-eNYRannNnSFHQ4nD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eNYRannNnSFHQ4nD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eNYRannNnSFHQ4nD .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-eNYRannNnSFHQ4nD .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-eNYRannNnSFHQ4nD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eNYRannNnSFHQ4nD .cluster text{fill:#333;}#mermaid-svg-eNYRannNnSFHQ4nD .cluster span{color:#333;}#mermaid-svg-eNYRannNnSFHQ4nD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eNYRannNnSFHQ4nD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} AppCluster 写日志 写日志 LoggingStack Kibana Elasticsearch Logstash App1 App2 Kubernetes 部署示例 ☸️
apiVersion: v1
kind: Secret
metadata:name: sentry-secret
stringData:DSN: https://xxxxsentry.io/project
---
apiVersion: apps/v1
kind: Deployment
metadata:name: abp-elk-app
spec:replicas: 3strategy:type: RollingUpdaterollingUpdate:maxSurge: 1maxUnavailable: 0selector:matchLabels:app: abp-elktemplate:metadata:labels:app: abp-elkspec:containers:- name: appimage: yourorg/abp-sentry-elk-demo:latestenv:- name: ASPNETCORE_ENVIRONMENTvalue: Production- name: SENTRY__DSNvalueFrom:secretKeyRef:name: sentry-secretkey: DSNports:- containerPort: 80