欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

.NET使用?OpenTelemetry?Traces?追蹤應(yīng)用程序的方法

 更新時間:2024年06月06日 08:59:40   作者:敏杰的學(xué)習(xí)園地  
OpenTelemetry Traces是OpenTelemetry提供的一種遙測數(shù)據(jù)類型,用于記錄和描述在分布式系統(tǒng)中的單個操作或工作單元的生命周期,這篇文章主要介紹了.NET中使用OpenTelemetry Traces追蹤應(yīng)用程序,需要的朋友可以參考下

上一次我們講了 OpenTelemetry Logs。今天繼續(xù)來說說 OpenTelemetry Traces。
在今天的微服務(wù)和云原生環(huán)境中,理解和監(jiān)控系統(tǒng)的行為變得越來越重要。在當(dāng)下我們實現(xiàn)一個功能可能需要調(diào)用了 N 個方法,涉及到 N 個服務(wù)。方法之間的調(diào)用如蜘蛛網(wǎng)一樣。分布式追蹤這個時候就至關(guān)重要。它可以把我們程序的調(diào)用鏈可視化。這對于運維人員監(jiān)控程序狀態(tài),開發(fā)人員 trouble shooting 都非常用幫助。

什么是 OpenTelemetry Traces

OpenTelemetry Traces 是 OpenTelemetry 提供的一種遙測數(shù)據(jù)類型,用于記錄和描述在分布式系統(tǒng)中的單個操作或工作單元的生命周期。
在 OpenTelemetry 中,一個 Trace 可以被視為由一系列相關(guān)的事件組成的時間線,這些事件被稱為 Spans。每個 Span 可以包含多個屬性、注釋和事件,用于描述在該 Span 的生命周期中發(fā)生的特定操作或事件。
例如,一個 HTTP 請求可以被表示為一個 Span,其中包含了請求的開始時間、結(jié)束時間、HTTP 方法、URL、狀態(tài)碼等信息。如果這個請求還調(diào)用了其他的服務(wù)或數(shù)據(jù)庫,那么這些調(diào)用也可以被表示為與原始請求 Span 相關(guān)聯(lián)的子 Span

注意:Span 是 OpenTelemetry 定義的概念,在 .NET 中使用 Activity 表示一個 Span

以上的話呢比較官方,是我用 chatGPT 生成的。還是直接用代碼來演示一下效果大家好理解。

示例:追蹤 Http 與 Database

在日常的開發(fā)活動中,http 與 database 操作基本就是涵蓋了 99% 的場景。很多時候我們希望監(jiān)控應(yīng)用程序?qū)γ總€請求的響應(yīng)速度,以及其中數(shù)據(jù)庫操作的耗時。這是一個非常非常常見的需求。以下使用一個用戶登錄接口來演示。

安裝依賴

<PackageReference Include="Npgsql" Version="8.0.3" />
	<PackageReference Include="Npgsql.OpenTelemetry" Version="8.0.3" />
	<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.8.1" />
	<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.8.1" />
	<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.8.1" />

使用 nuget 安裝以上包。

注入服務(wù)

var otel = builder.Services.AddOpenTelemetry();
// Configure OpenTelemetry Resources with the application name
otel.ConfigureResource(resource => resource
    .AddService(builder.Environment.ApplicationName));
otel.WithTracing(tracing =>
{
    tracing
    .AddAspNetCoreInstrumentation()
    .AddNpgsql()
    .AddOtlpExporter(otlpOptions =>
    {
        otlpOptions.Protocol = OtlpExportProtocol.HttpProtobuf;
        otlpOptions.Endpoint = new Uri("http://192.168.0.1:5341/ingest/otlp/v1/traces");
    });
});

跟 Logs 類似,我們使用 WithTracing 擴展方法來對 Traces 進行配置。

  • 調(diào)用 AddAspNetCoreInstrumentation 方法來添加對 AspNetCore 框架的跟蹤支持。這將自動跟蹤應(yīng)用程序中的HTTP請求和響應(yīng),并生成相應(yīng)的跟蹤數(shù)據(jù)。
  • 調(diào)用 AddNpgsql 方法來添加對 Npgsql 庫的跟蹤支持。這將自動跟蹤應(yīng)用程序中使用 Npgsql 庫進行的數(shù)據(jù)庫操作,并生成相應(yīng)的跟蹤數(shù)據(jù)。
  • 我們調(diào)用 AddOtlpExporter 方法來添加一個 OTLP(OpenTelemetry Protocol)導(dǎo)出器。這個導(dǎo)出器將把跟蹤數(shù)據(jù)發(fā)送到指定的 OTLP 接收端。在這里,我們將跟蹤數(shù)據(jù)發(fā)送到"http://192.168.0.201:5341/ingest/otlp/v1/traces"這個地址。

登錄代碼

public class UserRepository
{
    private readonly string _connectionString = "Host=127.0.0.1;Username=postgres;Password=123456";
    public async Task<User> GetUserAsync(string username, string password)
    {
        using var conn = new NpgsqlConnection(_connectionString);
        conn.Open();
        using var cmd = new NpgsqlCommand("SELECT * FROM t_users WHERE username = @username AND password = @password", conn);
        cmd.Parameters.AddWithValue("username", username);
        cmd.Parameters.AddWithValue("password", password);
        using var reader = await cmd.ExecuteReaderAsync();
        if (reader.Read())
        {
            return new User
            {
                Id = reader.GetString(0),
                Username = reader.GetString(1),
                Password = reader.GetString(2),
                // 其他字段...
            };
        }
        return null;
    }
}
public class User
{
    public string Id { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    // 其他字段...
}
    [HttpPost]
    public async Task<string> Login([FromBody] LoginModel model)
    {
        var user = await new UserRepository().GetUserAsync(model.Username, model.Password);
        if (user != null)
        {
            return "ok";
        }
        return "error";
    }

平平無奇的代碼,簡單演示一下用用戶名密碼進行登錄。在這里我想指出的一個點是:

其中并沒有任何 Trace 的代碼會侵入到我們的業(yè)務(wù)中。

在 Seq 中查看 Trace

以上就是所有的關(guān)鍵代碼。讓我們運行程序使用 postman 調(diào)用登錄接口。打開 Seq 界面進行查看。

Trace 的信息已經(jīng)到了 Seq 里??梢钥吹秸麄€ POST Account 接口耗時 326ms,其中 postgres 耗時 42 ms。點擊每一行都有更詳細(xì)的屬性。比如 postgres 里包含了 connection string,sql statement 等非常有用的信息。

示例:自定義 Trace 內(nèi)容

以上示例能是使用現(xiàn)成的庫進行 Trace。雖然絕大多數(shù)情況下已經(jīng)夠用了。但是有的時候我們想更加詳細(xì)的對我們的程序進行追蹤,那么就需要自己來定義 Span(Activity)來實現(xiàn)了。以下就讓我們通過一個獲取天氣的接口來演示如何自定義 Activity。

添加 Trace 的 source

otel.WithTracing(tracing =>
{
    tracing
    .AddSource("MyTraceSample")
    ....
});

編寫接口

    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly ILogger<WeatherForecastController> _logger;
        private readonly  ActivitySource _source;
        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
            _source = new ActivitySource("MyTraceSample", "1.0.0");
        }
        [HttpGet]
        public async Task<string> Get([FromQuery]string city)
        {
            _logger.LogInformation("Hello WeatherForecast");
            using (var activity = _source.StartActivity("CallWeatherForecast")) {
                activity?.AddTag("city", city);
                await Task.Delay(100);
                await GetWeatherInfoFromWebservice();
                await FormatWeatherInfo();
            }
            return "24°c";
        }
        async Task GetWeatherInfoFromWebservice()
        {
            using (var activity = _source.StartActivity("GetWeatherInfoFromWebservice"))
            {
                await Task.Delay(200);
            }
        }
        async Task FormatWeatherInfo()
        {
            using (var activity = _source.StartActivity("FormatWeatherInfo"))
            {
                await Task.Delay(300);
            }
        }
    }

在 Controller 的 Get 方法可以接受一個 city 的參數(shù),然后調(diào)用 GetWeatherInfoFromWebservice 模擬從其他服務(wù)獲取數(shù)據(jù),再調(diào)用 FormatWeatherInfo 方法來模擬對獲取的天氣數(shù)據(jù)進行格式化。每個方法中都加入了 Task.Delay 來模擬耗時。
首先我們會實例化一個 ActivitySource。然后在每個需要追蹤的方法最頂上調(diào)用 _source.StartActivity 得到一個 Activity 實例。這時候 Activity 就開始計時了。但是為啥沒有 Stop 呢?
顯然是 using 幫我們調(diào)用了。 以上代碼可能對業(yè)務(wù)代碼侵入的比較嚴(yán)重,那么可以使用 AOP 技術(shù)進行解耦。這里就不展開了。

在 Seq 中查看自定義的 Trace

運行程序,使用 postman 進行調(diào)用。然后打開 Seq 界面查看 Trace。

通過以上圖片可以清晰看到:GET WeatherForecast 接口調(diào)用了 CallWeatherForecast , CallWeatherForecast 又調(diào)用了 GetWeatherInfoFromWebservice 與 FormatWeatherInfo。以及這些方法與整個 http 請求的耗時??梢哉f是非常非常直觀。

點擊 CallWeatherForecast 這一行,還可以看到我們設(shè)置的 tag 的內(nèi)容。

總結(jié)

以上我們可以看到如果你想對 http 接口以及 database 操作進行追蹤,只需要簡單的幾行代碼就可以完成而且全程無侵入。如果你想對程序進行更細(xì)致的追蹤還可以使用自定義的 Activity 進行擴展,整個過程也毫無難度。希望這篇內(nèi)容對想要學(xué)習(xí) .NET 程序可觀測的同學(xué)有所幫助。

到此這篇關(guān)于.NET 中使用 OpenTelemetry Traces 追蹤應(yīng)用程序的文章就介紹到這了,更多相關(guān).NET  OpenTelemetry Traces 追蹤應(yīng)用程序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論