首頁

目前文章總數:157 篇

  

最後更新:2024年 12月 07日

0078. 配置 Microsoft .NET Aspire - 測試容器與實體容器的兼容切換流程

日期:2024年 11月 23日

標籤: .Net Aspire Asp.NET Core Asp.NET Core Web MVC Redis Web MySQL Docker

摘要:C# 學習筆記


範例所需: 1. Visual Studio 2022 Asp.net Core 版本 17.10.0 以上 (才支援 .Net Aspire)
      2. Windows Docker Desktop (本篇範例需要使用)
範例檔案:本篇範例代碼
相關參考:1. .Net Aspire 官方文件
     2. 如何通過 Microsoft .NET Aspire 建立可觀察、具生產導向的分散式應用程式並與現有系統無縫整合
解決問題:1. 如何使用 Aspire 切換實體機器與容器
      2. 示範將專案加入,轉變為可觀察、追蹤的遙測專案
基本介紹:本篇分為四大部分。
第一部分:.Net Aspire 範例專案介紹
第二部分:Redis 測試容器 & 實體切換
第三部分:Mysql 測試容器 & 實體切換
第四部分:Aspire 追蹤資訊 - 添加遙測專案






第一部分:.Net Aspire 範例專案介紹

Step 1:功能概述

打開範例專案後,專案分成以下 5 個:

1. Aspire Host 主程式,此為專案的啟動點,進行管理、監控
2. MinIo Form 程式 加入現有 WindowsForm 專案,補充說明用
3. Mysql Web 網站 Asp.net Core Web MVC 專案,用於說明容器化、實體切換
4. Redis Web 網站 Asp.net Core Web MVC 專案,用於說明容器化、實體切換
5. Aspire 預設設定 此專案為 Aspire 預設的 OpenTelemetry 配置,使其他專案參考可以加入可觀察、監控



Step 2:專案相依性

5 個專案相依如下,可以知道每個專案要可觀察、監控都需要參考 Aspire 預設設定 專案:



Step 3:Aspire Host 專案架構

專案建立後,如何加入到 Aspire Host 可參考上篇:如何通過 Microsoft .NET Aspire 建立可觀察、具生產導向的分散式應用程式並與現有系統無縫整合

Aspire Host 專案分成以下:

1. 設定檔 Appsettings.json 可以依照設定檔案,動態配置監控的專案
2. 主程式 Aspire 主程式的配置,可透過當前配置,讓開發者決定使用的連線配置



Step 4:Aspire Host 設定檔

以下為 Aspire 的設定檔案

1. ServiceSettings 控制 3 個專案是否啟動
2. ConnectionStrings 使用的 Redis、Mysql 連線字串,對應的專案也必須有相同的 Key、Value 以便於切換
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Aspire.Hosting.Dcp": "Warning"
    }
  },
  "ServiceSettings": {
    "MinIOFormExample": false,
    "StartRedisConnectionExample": true,
    "StartMysqlConnectionExample": true
  },
  "ConnectionStrings": {
    "RedisDb": "127.0.0.1:1582,abortConnect=false,defaultDatabase=0",
    "MySqlConnection": "Server=127.0.0.1;Port=3306;Database=testdb;User=root;Password=1qaz@WSX;"
  }
}


Step 5:Aspire Host 主程式

以下為 Aspire 的主程式,取得設定檔、依照設定檔案配置決定啟動的專案、使用的 Redis 、 Mysql 連線對象

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

var builder = DistributedApplication.CreateBuilder(args);

// 1. 取得服務啟動設定
var serviceSettings = builder.Configuration
    .GetSection("ServiceSettings")
    .Get<Dictionary<string, bool>>();

// 若無配置檔案 - 可直接關閉
if (serviceSettings == null)
    return;

#region 2. 依照設定啟動服務 - 並且監控

// 方法處理 MinIO 服務
HandleMinIOForm(builder, serviceSettings);

// 方法處理 Redis Web測試網站
HandleRedisConnection(builder, serviceSettings);

// 方法處理 Mysql Web測試網站
HandleMysqlConnection(builder, serviceSettings);
    
#endregion 

builder.Build().Run();

// 方法:2-1. 處理 MinIO 表單
void HandleMinIOForm(IDistributedApplicationBuilder builder, Dictionary<string, bool> settings)
{
    // 權限開啟才啟動觀察
    if (settings.TryGetValue("MinIOFormExample", out bool startMinIO) && startMinIO)
    {       
        builder.AddProject<Projects.MinIOFormExample>("minioformexample");
    }
}

// 方法:2-2. 處理 Redis 連接
void HandleRedisConnection(IDistributedApplicationBuilder builder, Dictionary<string, bool> settings)
{
    // 權限開啟才啟動觀察
    if (settings.TryGetValue("StartRedisConnectionExample", out bool startRedis) && startRedis)
    {
        // 示意 - 若環境為 Development 時,啟動開發環境的 Redis 連接
        if (builder.Environment.IsDevelopment())
        {
            var redis = builder.AddConnectionString("RedisDb");
            builder.AddProject<Projects.RedisConnectionWebExample>("redisconnectionexample")
                   .WithReference(redis);
        }
        else// 示意 - 若其他情況下,可以使用容器化的 Redis 連接
        {
            var redis = builder.AddRedis("RedisDb");
            builder.AddProject<Projects.RedisConnectionWebExample>("redisconnectionexample")
                   .WithReference(redis);
        }
    }
}

// 方法:2-3. 處理 Mysql 連接
void HandleMysqlConnection(IDistributedApplicationBuilder builder, Dictionary<string, bool> settings)
{
    // 權限開啟才啟動觀察
    if (settings.TryGetValue("StartMysqlConnectionExample", out bool startRedis) && startRedis)
    {
        // 示意 - 若環境為 Development 時,啟動開發環境的 Mysql 連接
        if (builder.Environment.IsDevelopment())
        {
            var mysql = builder.AddConnectionString("MySqlConnection");
            builder.AddProject<Projects.MysqlConnectionWebExample>("mysqlconnectionexample")
                   .WithReference(mysql);
        }
        else// 示意 - 若其他情況下,可以使用容器化的 Mysql 連接
        {
            var mysql = builder.AddMySql("MySqlConnection");
            builder.AddProject<Projects.MysqlConnectionWebExample>("mysqlconnectionexample")
                   .WithReference(mysql);
        }
    }
}


Step 6:示範控制關閉專案 - 1

若要關閉整個專案的啟動,可以直接將 Appsettings.json 切換為 False
※這裡為了示意,實務上應要依照 Develop、Staging、Production 建立對應的 Appsettings.{Enviroment}.json 實體檔案

   "MinIOFormExample": false,


Step 7:示範控制關閉專案 - 2

接著啟動 Aspire.Host 專案後,可以觀察到 Minio 這個專案不會被加入 Aspire 的資源





第二部分:Redis 測試容器 & 實體切換

Step 1:Redid Web 專案架構

Redid Web 專案分成以下 4 點:

1. 設定檔 Appsettings.json 需要與 Aspire.Host 一致,兩者才能動態傳遞
2. 主程式 啟動主程式,依賴注入 StackExchange.Redis 、連線資源
3. Html 檢視 提供驗證當前 Redis 專案,連線到的服務
4. 控制器 連線 Redis Server 邏輯,並回傳檢視當前的連線對象(容器 或 實體服務)



Step 2:Redid Web 設定檔

設定檔的 Key : ConnectionStrings 與 Aspire Host 上的設定檔相同,兩者才可配對到

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "RedisDb": "127.0.0.1:6379,abortConnect=false,defaultDatabase=0"
  }
}


Step 3:Redid Web 主程式

簡單的注入 Redis 連線配置,啟動時仍取 RedisDb 的 Value 做設定

using StackExchange.Redis;

var builder = WebApplication.CreateBuilder(args);

//... 略

// 注入Redis連接字符串
var redisConnectionString = builder.Configuration.GetSection("ConnectionStrings:RedisDb").Value;

builder.Services.AddSingleton<IConnectionMultiplexer>(provider =>
{        
    return ConnectionMultiplexer.Connect(ConfigurationOptions.Parse(redisConnectionString));
});

var app = builder.Build();

//... 略

app.Run();


Step 4:Redid Web Html 檢視

會從控制器將當前的Redis 連線字串Redis 連線狀態 顯示於畫面。

@{
    ViewData["Title"] = "Redis 測試頁面";
}

<div class="text-center">
    <h1>Redis 連線字串</h1>
    <p>@ViewBag.ConnectionString</p>
    <h1>Redis 連線狀態</h1>
    <p>@ViewBag.Message</p>
</div>


Step 5:Redid Web 控制器

分成主要的 3 種控制器,用於取得顯示畫面、連接字串、連線狀態

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly IConnectionMultiplexer _redis;
    public HomeController(ILogger<HomeController> logger,
        IConnectionMultiplexer redisDb)
    {
        _logger = logger;
        _redis = redisDb;
    }

    /// <summary>
    /// 1. 取得頁面
    /// </summary>        
    public IActionResult Index()
    {
        ViewBag.ConnectionString = RedisConnectionStr();
        ViewBag.Message = RedisConnection();
        return View();
    }

    /// <summary>
    /// 2. 獲取連接字串
    /// </summary>        
    private string RedisConnectionStr()
    {
        _logger.LogInformation(_redis.Configuration);
        return _redis.Configuration ?? string.Empty;
    }

    /// <summary>
    /// 3. 獲取連線狀態
    /// </summary>        
    private string RedisConnection()
    {
        var message = string.Empty;
        try
        {
            var db = _redis.GetDatabase();
            // 使用 PING 命令來檢查連線
            var response = db.Execute("PING");
            if (response.ToString() == "PONG")
            {
                message = "成功連線到 Redis 伺服器!";
            }
            else
            {
                message = "無法確認連線狀態,回應:" + response;
            }
        }
        catch (RedisConnectionException ex)
        {
            message = "無法連線到 Redis 伺服器:" + ex.Message;
        }
        catch (Exception ex)
        {
            message = "發生錯誤:" + ex.Message;
        }
        finally
        {
            // 關閉連接
            if (_redis != null)
            {
                _redis.Close();
            }
        }
        _logger.LogDebug(message);
        return message;
    }
}


Step 6:Redid Web 容器、實體連線切換示範 - 1

現在模擬情境,在 開發 階段,都共用一個固定的 Redis 實體機器,Port:1582
部署 階段,都會啟用一個容器做持久化
※開發階段的 Redis 服務如下圖:

Step 7:Redid Web 容器、實體連線切換示範 - 2

開啟 Aspire Host 專案 -> 檢視 Program.cs 代碼
加入以下 C# 代碼,當為開發環境時,使用 1582 這台機器的 Reids
否則都是使用產生容器化的 Redis 連接

// 方法:2-2. 處理 Redis 連接
void HandleRedisConnection(IDistributedApplicationBuilder builder, Dictionary<string, bool> settings)
{
    // 權限開啟才啟動觀察
    if (settings.TryGetValue("StartRedisConnectionExample", out bool startRedis) && startRedis)
    {
        // 示意 - 若環境為 Development 時,啟動開發環境的 Redis 連接
        if (builder.Environment.IsDevelopment())
        {
            var redis = builder.AddConnectionString("RedisDb");
            builder.AddProject<Projects.RedisConnectionWebExample>("redisconnectionexample")
                   .WithReference(redis);
        }
        else// 示意 - 若其他情況下,可以使用容器化的 Redis 連接
        {
            var redis = builder.AddRedis("RedisDb");
            builder.AddProject<Projects.RedisConnectionWebExample>("redisconnectionexample")
                   .WithReference(redis);
        }
    }
}


Step 8:Redid Web 容器、實體連線切換示範 - 實體

我們啟動 Debug 模式,將 Aspire Host 啟動後,出現以下:



Step 9:Redid Web 容器、實體連線切換示範 - 容器

為了測試容器是否正常,可以將對應代碼註解,再次將 Aspire Host 啟動後,出現以下:
成功切換成 Redis 容器連線

// 示意 - 若環境為 Development 時,啟動開發環境的 Redis 連接
//if (builder.Environment.IsDevelopment())
//{
//    var redis = builder.AddConnectionString("RedisDb");
//    builder.AddProject<Projects.RedisConnectionWebExample>("redisconnectionexample")
//           .WithReference(redis);
//}



Step 10:Aspire Host Nuget 套件 - 補充

若要使用容器化,需要在 Aspire Host 專案上 Nuget 安裝 Aspire.Hosting.Redis 套件
並且此容器化的套件要在 Debug 模式下使用,一定要先啟用 Windwos Desktop Docker



第三部分:Mysql 測試容器 & 實體切換

Step 1:Mysql Web 專案架構

Redid Web 專案分成以下 4 點:

1. 設定檔 Appsettings.json 需要與 Aspire.Host 一致,兩者才能動態傳遞
2. 主程式 啟動主程式,依賴注入 Mysql 、連線資源
3. Html 檢視 提供驗證當前 Mysql 專案,連線到的服務
4. 控制器 連線 Mysql Server 邏輯,並回傳檢視當前的連線對象、資料(容器 或 實體服務)



Step 2:Mysql Web 設定檔

設定檔的 Key : ConnectionStrings 與 Aspire Host 上的設定檔相同,兩者才可配對到

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MySqlConnection": "Server=127.0.0.1;Port=3306;Database=testdb;User=root;Password=1qaz@WSX;"    
  }
}


Step 3:Mysql Web 主程式

簡單的注入 Mysql 連線配置,啟動時仍取 MySqlConnection 的 Value 做設定

using MySql.Data.MySqlClient;

var builder = WebApplication.CreateBuilder(args);

//... 略

// 依賴注入 MySQL 連線服務
builder.Services.AddTransient<MySqlConnection>(sp =>
{
    // 讀取 ConnectionString,並設定 MySQL DbContext
    var connectionString = builder.Configuration.GetConnectionString("MySqlConnection");
    return new MySqlConnection(connectionString);
});

var app = builder.Build();

//... 略

app.Run();


Step 4:Mysql Web Html 檢視

會從控制器將當前的MySql 連線字串MySql 當前資料 顯示於畫面。

@{
    ViewData["Title"] = "Mysql 測試頁面";
}

<div class="text-center">
    <h1>MySql 連線字串</h1>
    <p>@ViewBag.ConnectionString</p>
    <h1>MySql 當前資料</h1>
    <p>@ViewBag.Message</p>
</div>


Step 5:Mysql Web 控制器

分成主要的 3 種控制器,用於取得顯示畫面、連接字串、資料

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly MySqlConnection _mySqlConnection;
    public HomeController(ILogger<HomeController> logger,
        MySqlConnection mysql)
    {
        _logger = logger;
        _mySqlConnection = mysql;
    }

    /// <summary>
    /// 1. 取得頁面
    /// </summary>        
    public IActionResult Index()
    {
        ViewBag.ConnectionString = MysqlConnectionStr();
        ViewBag.Message = MysqlGetTableData();
        return View();
    }

    /// <summary>
    /// 2. 獲取連接字串
    /// </summary>        
    private string MysqlConnectionStr()
    {
        _logger.LogInformation(_mySqlConnection.ConnectionString);
        return _mySqlConnection.ConnectionString ?? string.Empty;
    }

    /// <summary>
    /// 3. 獲取連線資料
    /// </summary>        
    private string MysqlGetTableData()
    {
        var message = string.Empty;
        
        try
        {
            _mySqlConnection.Open();
            var collectionData = new List<TestAspireTable>();
            var command = new MySqlCommand("SELECT SeqNo, Comment FROM testaspiretable", _mySqlConnection);
            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    // 讀取資料
                    var newItem = new TestAspireTable();
                    newItem.SeqNo = int.Parse(reader["SeqNo"].ToString());
                    newItem.Comment = reader["Comment"].ToString();
                    collectionData.Add(newItem);
                }
            }
            // 關閉連接
            _mySqlConnection.Close();
           
            // Json 序列化參數
            var options = new JsonSerializerOptions
            {
                Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
                WriteIndented = true
            };
            message = JsonSerializer.Serialize(collectionData, options);
        }
        catch (Exception ex)
        {
            message = "發生錯誤:" + ex.Message;
        }
        _logger.LogDebug(message);
        return message;
    }

    /// <summary>
    /// 測試 Mysql 連線的資料表
    /// </summary>
    private class TestAspireTable
    {
        public int SeqNo { get; set; }
        public string Comment { get; set; } = string.Empty;
    }
}


Step 6:Mysql Web 容器、實體連線切換示範 - 1

現在模擬情境,在 開發 階段,都共用一個固定的 Mysql 實體機器,Port:3306
部署 階段,都會啟用一個容器做持久化
※開發階段的 Mysql 服務如下圖:

Step 7:Mysql Web 容器、實體連線切換示範 - 2

開啟 Aspire Host 專案 -> 檢視 Program.cs 代碼
加入以下 C# 代碼,當為開發環境時,使用 3306 這台機器的 Mysql 資料庫
否則都是使用產生容器化的 Mysql 連接

// 方法:2-3. 處理 Mysql 連接
void HandleMysqlConnection(IDistributedApplicationBuilder builder, Dictionary<string, bool> settings)
{
    // 權限開啟才啟動觀察
    if (settings.TryGetValue("StartMysqlConnectionExample", out bool startRedis) && startRedis)
    {
        // 示意 - 若環境為 Development 時,啟動開發環境的 Mysql 連接
        if (builder.Environment.IsDevelopment())
        {
            var mysql = builder.AddConnectionString("MySqlConnection");
            builder.AddProject<Projects.MysqlConnectionWebExample>("mysqlconnectionexample")
                   .WithReference(mysql);
        }
        else// 示意 - 若其他情況下,可以使用容器化的 Mysql 連接
        {
            var mysql = builder.AddMySql("MySqlConnection");
            builder.AddProject<Projects.MysqlConnectionWebExample>("mysqlconnectionexample")
                   .WithReference(mysql);
        }
    }
}


Step 8:Mysql Web 容器、實體連線切換示範 - 實體

我們啟動 Debug 模式,將 Aspire Host 啟動後,出現以下:



Step 9:Mysql Web 容器、實體連線切換示範 - 容器

為了測試容器是否正常,可以將對應代碼註解,再次將 Aspire Host 啟動後,出現以下:
成功切換成 Mysql 容器連線

// 示意 - 若環境為 Development 時,啟動開發環境的 Mysql 連接
//if (builder.Environment.IsDevelopment())
//{
//    var mysql = builder.AddConnectionString("MySqlConnection");
//    builder.AddProject<Projects.MysqlConnectionWebExample>("mysqlconnectionexample")
//           .WithReference(mysql);
//}



Step 10:Aspire Host Nuget 套件 - 補充

若要使用容器化,需要在 Aspire Host 專案上 Nuget 安裝 Aspire.Hosting.MySql 套件
並且此容器化的套件要在 Debug 模式下使用,一定要先啟用 Windwos Desktop Docker



第四部分:Aspire 內建追蹤資訊

Step 1:將專案增加追蹤 - 預設無追蹤

Aspire Host 空專案,即使把專案做關聯,但不會自動加入追蹤,追蹤還需要做些配置

Step 2:將專案增加追蹤 - 新增專案

對整個專案滑鼠右鍵 -> 加入 -> 新增專案

Step 3:將專案增加追蹤 - Aspire 服務預設值

添加 .NET Aspire 服務預設值 專案

建立專案名稱:

Step 4:將專案增加追蹤 - 建立完成

建立完成後會有 Extension.cs ,為了便於閱讀,這邊將代碼做英文翻譯成中文如下:

namespace Microsoft.Extensions.Hosting
{
    // 新增常見的 .NET Aspire 服務:服務發現、彈性、運行狀況檢查和 OpenTelemetry。
    // 您的解決方案中的每個服務項目都應引用該項目。
    // 要了解有關使用此項目的更多信息,請參閱 https://aka.ms/dotnet/aspire/service-defaults
    public static class Extensions
    {
        public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)
        {
            builder.ConfigureOpenTelemetry();

            builder.AddDefaultHealthChecks();

            builder.Services.AddServiceDiscovery();

            builder.Services.ConfigureHttpClientDefaults(http =>
            {
                // 預設開啟 彈性處理程序
                http.AddStandardResilienceHandler();

                // 預設開啟 服務發現
                http.AddServiceDiscovery();
            });

            // 取消以下註釋內容可限制"允許"的服務發現方案。
            // builder.Services.Configure<ServiceDiscoveryOptions>(options =>
            // {
            //     options.AllowedSchemes = ["https"];
            // });

            return builder;
        }

        /// <summary>
        /// 配置分散式追蹤和指標收集,允許應用程式的監控和可觀察性。
        /// </summary>        
        public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
        {
            builder.Logging.AddOpenTelemetry(logging =>
            {
                logging.IncludeFormattedMessage = true;
                logging.IncludeScopes = true;
            });

            builder.Services.AddOpenTelemetry()
                .WithMetrics(metrics =>
                {
                    metrics.AddAspNetCoreInstrumentation()
                        .AddHttpClientInstrumentation()
                        .AddRuntimeInstrumentation();
                })
                .WithTracing(tracing =>
                {
                    tracing.AddAspNetCoreInstrumentation()
                        // 取消註釋以下行以啟用 gRPC 檢測(需要 OpenTelemetry.Instrumentation.GrpcNetClient 套件)
                        //.AddGrpcClientInstrumentation()
                        .AddHttpClientInstrumentation();
                });

            builder.AddOpenTelemetryExporters();

            return builder;
        }

        private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
        {
            var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);

            if (useOtlpExporter)
            {
                builder.Services.AddOpenTelemetry().UseOtlpExporter();
            }

            // 取消註解以下行以啟用 Azure Monitor 匯出器(需要 Azure.Monitor.OpenTelemetry.AspNetCore 套件)
            //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
            //{
            //    builder.Services.AddOpenTelemetry()
            //       .UseAzureMonitor();
            //}

            return builder;
        }

        /// <summary>
        /// 健康檢查
        /// </summary>        
        public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)
        {
            builder.Services.AddHealthChecks()
                // 新增預設的"健康檢查"以確保自己的應用程式能夠回應
                .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);

            return builder;
        }

        public static WebApplication MapDefaultEndpoints(this WebApplication app)
        {
            // 將運行狀況檢查端點新增至非開發環境中的應用程式會產生安全隱患。
            // 在非開發環境中啟用這些端點之前,請參閱 https://aka.ms/dotnet/aspire/healthchecks 以了解詳細資訊。
            if (app.Environment.IsDevelopment())
            {
                // 所有的運行"健康檢查"必須通過,此應用程式才能在啟動後視為準備好接受傳輸流量
                app.MapHealthChecks("/health");

                // 只有標有「live」標籤的"健康檢查"通過,此應用程式才會被視為處於 live 狀態
                app.MapHealthChecks("/alive", new HealthCheckOptions
                {
                    Predicate = r => r.Tags.Contains("live")
                });
            }

            return app;
        }
    }
}



Step 5:將專案增加追蹤 - Redis Web 加入追蹤

開啟 Redis Web 的 Program.cs 將以下代碼添加
完成對 .Net Aspire 預設值服務的參考 & 依賴注入

using StackExchange.Redis;

var builder = WebApplication.CreateBuilder(args);

// 1. [加入結構化、計量、追蹤] Aspire 要能可觀察此專案,需要增加以下服務
builder.AddServiceDefaults();

// 略...

var app = builder.Build();

// 略...

//// 2. [加入結構化、計量、追蹤] Aspire 要能可觀察此專案,需要增加以下服務
app.MapDefaultEndpoints();

app.Run();


Step 6:將專案增加追蹤 - Mysql Web 加入追蹤

開啟 Mysql Web 的 Program.cs 將以下代碼添加
完成對 .Net Aspire 預設值服務的參考 & 依賴注入

using StackExchange.Redis;

var builder = WebApplication.CreateBuilder(args);

// 1. [加入結構化、計量、追蹤] Aspire 要能可觀察此專案,需要增加以下服務
builder.AddServiceDefaults();

// 略...

var app = builder.Build();

// 略...

//// 2. [加入結構化、計量、追蹤] Aspire 要能可觀察此專案,需要增加以下服務
app.MapDefaultEndpoints();

app.Run();


Step 7:驗證成果 - 實現追蹤

再次開啟追蹤,可以發現下拉式選單,已經上述的 2 個專案加入,可以進行追蹤



Step 8:驗證成果 - 觀察追蹤1

照下面步驟,我們測試當 API 錯誤時,追蹤的變化

Step 9:驗證成果 - 觀察追蹤2

透過觀察,追蹤 的好處是讓生產環境的維護 IT、開發人員更好追蹤錯誤

Step 10:最後補充 - 英體資源一定要充足

若本機、部署環境機器資源配置過低,很容易發生以下錯誤:
錯誤資訊:未預期的錯誤


原因是因為本機記憶體過少、導致並不是每次啟動應用程式都會正常,這是因為 Aspire Host 依賴所有專案,並且啟用追蹤,需要大量硬體資源