aspire-service-defaults by aaronontheweb/dotnet-skills
npx skills add https://github.com/aaronontheweb/dotnet-skills --skill aspire-service-defaults在以下情况下使用此技能:
ServiceDefaults 是一个共享项目,为 Aspire 应用程序中的所有服务提供通用配置:
每个服务都引用此项目并调用 AddServiceDefaults()。
src/
MyApp.ServiceDefaults/
Extensions.cs
MyApp.ServiceDefaults.csproj
MyApp.Api/
Program.cs # 调用 AddServiceDefaults()
MyApp.Worker/
Program.cs # 调用 AddServiceDefaults()
MyApp.AppHost/
Program.cs
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<IsAspireSharedProject>true</IsAspireSharedProject>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
</ItemGroup>
</Project>
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
namespace Microsoft.Extensions.Hosting;
public static class Extensions
{
private const string HealthEndpointPath = "/health";
private const string AlivenessEndpointPath = "/alive";
/// <summary>
/// 添加通用的 Aspire 服务:OpenTelemetry、健康检查、
/// 服务发现和 HTTP 弹性策略。
/// </summary>
public static TBuilder AddServiceDefaults<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder.ConfigureOpenTelemetry();
builder.AddDefaultHealthChecks();
builder.Services.AddServiceDiscovery();
builder.Services.ConfigureHttpClientDefaults(http =>
{
// 弹性策略:重试、断路器、超时
http.AddStandardResilienceHandler();
// 服务发现:将服务名称解析为地址
http.AddServiceDiscovery();
});
return builder;
}
public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
// 日志记录
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
builder.Services.AddOpenTelemetry()
// 指标
.WithMetrics(metrics =>
{
metrics
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation();
})
// 追踪
.WithTracing(tracing =>
{
tracing
.AddSource(builder.Environment.ApplicationName)
.AddAspNetCoreInstrumentation(options =>
// 从追踪中排除健康检查
options.Filter = context =>
!context.Request.Path.StartsWithSegments(HealthEndpointPath) &&
!context.Request.Path.StartsWithSegments(AlivenessEndpointPath))
.AddHttpClientInstrumentation();
});
builder.AddOpenTelemetryExporters();
return builder;
}
private static TBuilder AddOpenTelemetryExporters<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
// 如果配置了端点(Aspire 仪表板、Jaeger 等),则使用 OTLP 导出器
var useOtlp = !string.IsNullOrWhiteSpace(
builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
if (useOtlp)
{
builder.Services.AddOpenTelemetry().UseOtlpExporter();
}
return builder;
}
public static TBuilder AddDefaultHealthChecks<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder.Services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
return builder;
}
/// <summary>
/// 映射健康检查端点。在 UseRouting() 之后调用。
/// </summary>
public static WebApplication MapDefaultEndpoints(this WebApplication app)
{
// 仅在开发环境中公开 - 请参阅下面的安全说明
if (app.Environment.IsDevelopment())
{
// 就绪性:所有健康检查必须通过
app.MapHealthChecks(HealthEndpointPath);
// 存活状态:仅包含 "live" 标签的检查
app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("live")
});
}
return app;
}
}
var builder = WebApplication.CreateBuilder(args);
// 添加所有服务默认配置
builder.AddServiceDefaults();
// 添加您的服务
builder.Services.AddControllers();
var app = builder.Build();
// 映射健康端点
app.MapDefaultEndpoints();
app.MapControllers();
app.Run();
var builder = Host.CreateApplicationBuilder(args);
// 也适用于非 Web 主机
builder.AddServiceDefaults();
builder.Services.AddHostedService<MyWorker>();
var host = builder.Build();
host.Run();
public static TBuilder AddDefaultHealthChecks<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder.Services.AddHealthChecks()
// 基本存活状态
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"])
// 数据库就绪性
.AddNpgSql(
builder.Configuration.GetConnectionString("postgres")!,
name: "postgres",
tags: ["ready"])
// Redis 就绪性
.AddRedis(
builder.Configuration.GetConnectionString("redis")!,
name: "redis",
tags: ["ready"])
// 自定义检查
.AddCheck<MyCustomHealthCheck>("custom", tags: ["ready"]);
return builder;
}
对于 Akka.NET 或自定义 ActivitySources:
public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing
.AddSource(builder.Environment.ApplicationName)
// Akka.NET 追踪
.AddSource("Akka.NET")
// 自定义源
.AddSource("MyApp.Orders")
.AddSource("MyApp.Payments")
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation();
});
return builder;
}
对于生产环境,保护健康端点或使用不同的路径:
public static WebApplication MapDefaultEndpoints(this WebApplication app)
{
// 始终为 Kubernetes 探针映射,但请考虑:
// - 使用仅内部端口
// - 添加授权
// - 速率限制
app.MapHealthChecks("/health", new HealthCheckOptions
{
// 仅返回状态,不返回详细信息
ResponseWriter = (context, report) =>
{
context.Response.ContentType = "text/plain";
return context.Response.WriteAsync(report.Status.ToString());
}
});
app.MapHealthChecks("/alive", new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("live"),
ResponseWriter = (context, report) =>
{
context.Response.ContentType = "text/plain";
return context.Response.WriteAsync(report.Status.ToString());
}
});
return app;
}
AppHost 自动配置 OTLP 端点:
// AppHost/Program.cs
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres");
var redis = builder.AddRedis("redis");
var api = builder.AddProject<Projects.MyApp_Api>("api")
.WithReference(postgres)
.WithReference(redis);
builder.Build().Run();
服务自动接收 OTEL_EXPORTER_OTLP_ENDPOINT,将遥测数据发送到 Aspire 仪表板。
| 实践 | 原因 |
|---|---|
| 一个 ServiceDefaults 项目 | 所有服务间配置一致 |
| 从追踪中过滤健康检查 | 减少观测数据中的噪音 |
| 标记健康检查 | 将存活状态与就绪性分开 |
| 使用 StandardResilienceHandler | 内置重试、断路器、超时 |
| 添加自定义追踪源 | 捕获特定领域的跨度 |
每周安装数
79
代码仓库
GitHub 星标数
491
首次出现
2026年1月29日
安全审计
安装于
claude-code61
codex50
opencode49
github-copilot48
gemini-cli47
kimi-cli44
Use this skill when:
ServiceDefaults is a shared project that provides common configuration for all services in an Aspire application:
Every service references this project and calls AddServiceDefaults().
src/
MyApp.ServiceDefaults/
Extensions.cs
MyApp.ServiceDefaults.csproj
MyApp.Api/
Program.cs # Calls AddServiceDefaults()
MyApp.Worker/
Program.cs # Calls AddServiceDefaults()
MyApp.AppHost/
Program.cs
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<IsAspireSharedProject>true</IsAspireSharedProject>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
</ItemGroup>
</Project>
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
namespace Microsoft.Extensions.Hosting;
public static class Extensions
{
private const string HealthEndpointPath = "/health";
private const string AlivenessEndpointPath = "/alive";
/// <summary>
/// Adds common Aspire services: OpenTelemetry, health checks,
/// service discovery, and HTTP resilience.
/// </summary>
public static TBuilder AddServiceDefaults<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder.ConfigureOpenTelemetry();
builder.AddDefaultHealthChecks();
builder.Services.AddServiceDiscovery();
builder.Services.ConfigureHttpClientDefaults(http =>
{
// Resilience: retries, circuit breaker, timeouts
http.AddStandardResilienceHandler();
// Service discovery: resolve service names to addresses
http.AddServiceDiscovery();
});
return builder;
}
public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
// Logging
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
builder.Services.AddOpenTelemetry()
// Metrics
.WithMetrics(metrics =>
{
metrics
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation();
})
// Tracing
.WithTracing(tracing =>
{
tracing
.AddSource(builder.Environment.ApplicationName)
.AddAspNetCoreInstrumentation(options =>
// Exclude health checks from traces
options.Filter = context =>
!context.Request.Path.StartsWithSegments(HealthEndpointPath) &&
!context.Request.Path.StartsWithSegments(AlivenessEndpointPath))
.AddHttpClientInstrumentation();
});
builder.AddOpenTelemetryExporters();
return builder;
}
private static TBuilder AddOpenTelemetryExporters<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
// Use OTLP exporter if endpoint is configured (Aspire Dashboard, Jaeger, etc.)
var useOtlp = !string.IsNullOrWhiteSpace(
builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
if (useOtlp)
{
builder.Services.AddOpenTelemetry().UseOtlpExporter();
}
return builder;
}
public static TBuilder AddDefaultHealthChecks<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder.Services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
return builder;
}
/// <summary>
/// Maps health check endpoints. Call after UseRouting().
/// </summary>
public static WebApplication MapDefaultEndpoints(this WebApplication app)
{
// Only expose in development - see security note below
if (app.Environment.IsDevelopment())
{
// Readiness: all health checks must pass
app.MapHealthChecks(HealthEndpointPath);
// Liveness: only "live" tagged checks
app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("live")
});
}
return app;
}
}
var builder = WebApplication.CreateBuilder(args);
// Add all service defaults
builder.AddServiceDefaults();
// Add your services
builder.Services.AddControllers();
var app = builder.Build();
// Map health endpoints
app.MapDefaultEndpoints();
app.MapControllers();
app.Run();
var builder = Host.CreateApplicationBuilder(args);
// Works for non-web hosts too
builder.AddServiceDefaults();
builder.Services.AddHostedService<MyWorker>();
var host = builder.Build();
host.Run();
public static TBuilder AddDefaultHealthChecks<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder.Services.AddHealthChecks()
// Basic liveness
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"])
// Database readiness
.AddNpgSql(
builder.Configuration.GetConnectionString("postgres")!,
name: "postgres",
tags: ["ready"])
// Redis readiness
.AddRedis(
builder.Configuration.GetConnectionString("redis")!,
name: "redis",
tags: ["ready"])
// Custom check
.AddCheck<MyCustomHealthCheck>("custom", tags: ["ready"]);
return builder;
}
For Akka.NET or custom ActivitySources:
public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing
.AddSource(builder.Environment.ApplicationName)
// Akka.NET tracing
.AddSource("Akka.NET")
// Custom sources
.AddSource("MyApp.Orders")
.AddSource("MyApp.Payments")
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation();
});
return builder;
}
For production, protect health endpoints or use different paths:
public static WebApplication MapDefaultEndpoints(this WebApplication app)
{
// Always map for Kubernetes probes, but consider:
// - Using internal-only ports
// - Adding authorization
// - Rate limiting
app.MapHealthChecks("/health", new HealthCheckOptions
{
// Only return status, not details
ResponseWriter = (context, report) =>
{
context.Response.ContentType = "text/plain";
return context.Response.WriteAsync(report.Status.ToString());
}
});
app.MapHealthChecks("/alive", new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("live"),
ResponseWriter = (context, report) =>
{
context.Response.ContentType = "text/plain";
return context.Response.WriteAsync(report.Status.ToString());
}
});
return app;
}
The AppHost automatically configures OTLP endpoints:
// AppHost/Program.cs
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres");
var redis = builder.AddRedis("redis");
var api = builder.AddProject<Projects.MyApp_Api>("api")
.WithReference(postgres)
.WithReference(redis);
builder.Build().Run();
Services receive OTEL_EXPORTER_OTLP_ENDPOINT automatically, sending telemetry to the Aspire Dashboard.
| Practice | Reason |
|---|---|
| One ServiceDefaults project | Consistent config across all services |
| Filter health checks from traces | Reduces noise in observability data |
| Tag health checks | Separate liveness from readiness |
| Use StandardResilienceHandler | Built-in retry, circuit breaker, timeout |
| Add custom trace sources | Capture domain-specific spans |
Weekly Installs
79
Repository
GitHub Stars
491
First Seen
Jan 29, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code61
codex50
opencode49
github-copilot48
gemini-cli47
kimi-cli44
FastAPI开发工作流:构建生产就绪Python后端,含异步、SQLAlchemy与API文档
204 周安装
知识综合工具:企业搜索最后一公里,多源信息去重与可信答案生成
1,000 周安装
智能OCR文字识别工具 - 支持100+语言,高精度提取图片/PDF/手写文本
1,100 周安装
DeerFlow AI智能体平台HTTP API使用指南 - 集成Claude与LangGraph实现多智能体协作
1,100 周安装
Blueprint构建计划生成器:将目标转化为AI编码代理可执行的逐步开发计划
1,200 周安装
Obsidian知识库管理指南:命名规范、链接语法与高效工作流程
1,300 周安装
Android 整洁架构指南:模块化设计、依赖注入与数据层实现
1,300 周安装