本文へ移動
cccskills
無料GitHub で公開

aspire-service-defaults

Create a shared ServiceDefaults project for Aspire applications. Centralizes OpenTelemetry, health checks, resilience, and service discovery configuration across all services.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md10.2 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Aspire Service Defaults

When to Use This Skill

Use this skill when:

  • Building Aspire-based distributed applications
  • Need consistent observability (logging, tracing, metrics) across services
  • Want shared health check configuration
  • Configuring HttpClient resilience and service discovery

What is ServiceDefaults?

ServiceDefaults is a shared project that provides common configuration for all services in an Aspire application:

  • OpenTelemetry - Logging, tracing, and metrics
  • Health Checks - Readiness and liveness endpoints
  • Service Discovery - Automatic service resolution
  • HTTP Resilience - Retry and circuit breaker policies

Every service references this project and calls AddServiceDefaults().


Project Structure

src/
  MyApp.ServiceDefaults/
    Extensions.cs
    MyApp.ServiceDefaults.csproj
  MyApp.Api/
    Program.cs  # Calls AddServiceDefaults()
  MyApp.Worker/
    Program.cs  # Calls AddServiceDefaults()
  MyApp.AppHost/
    Program.cs

ServiceDefaults Project

Project File

<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>

Extensions.cs

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;
    }
}

Usage in Services

API Service

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

Worker Service

var builder = Host.CreateApplicationBuilder(args);

// Works for non-web hosts too
builder.AddServiceDefaults();

builder.Services.AddHostedService<MyWorker>();

var host = builder.Build();
host.Run();

Adding Custom Health Checks

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;
}

Adding Custom Trace Sources

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;
}

Production Health Checks

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;
}

Integration with AppHost

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.


Best Practices

PracticeReason
One ServiceDefaults projectConsistent config across all services
Filter health checks from tracesReduces noise in observability data
Tag health checksSeparate liveness from readiness
Use StandardResilienceHandlerBuilt-in retry, circuit breaker, timeout
Add custom trace sourcesCapture domain-specific spans

Resources

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

When the user wants to plan, design, or implement an A/B test or experiment. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," or "hypothesis." For tracking implementation, see analytics-tracking.

日本語の概要は準備中です。原文の説明を表示しています。

ComeOnOliver/skillshub652026年6月24日 更新

Audit and improve web accessibility following WCAG 2.2 guidelines. Use when asked to "improve accessibility", "a11y audit", "WCAG compliance", "screen reader support", "keyboard navigation", or "make accessible".

日本語の概要は準備中です。原文の説明を表示しています。

ComeOnOliver/skillshub652026年6月24日 更新

Audit and improve web accessibility following WCAG 2.1 guidelines. Use when asked to "improve accessibility", "a11y audit", "WCAG compliance", "screen reader support", "keyboard navigation", or "make accessible".

日本語の概要は準備中です。原文の説明を表示しています。

ComeOnOliver/skillshub652026年6月24日 更新

This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.

日本語の概要は準備中です。原文の説明を表示しています。

ComeOnOliver/skillshub652026年6月24日 更新

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics

日本語の概要は準備中です。原文の説明を表示しています。

ComeOnOliver/skillshub652026年6月24日 更新

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates.

日本語の概要は準備中です。原文の説明を表示しています。

ComeOnOliver/skillshub652026年6月24日 更新

ComeOnOliver のスキルをすべて見る

このスキルの問題を報告する