OpenTememetry Demo 專案是如何做到的呢 ?
上圖是 OTel 範例專案的數據流程圖,從圖中可以得知重要元件有 OTel Demo Application、OTel Collector、Prometheus、Jaeger 及 Grafana。以下就針對這些元件做簡單說明
OTel Demo是由 10 多種不同的程式語言開發的微服務架構應用程式,在 Day18 的介紹中有提到蒐集遙測數據方式有自動跟手動兩種,以 .NET 開發的 Cart Service 為例,其是使用自動(automatic)採集,再將蒐集好的資料使用 HTTP、grpc Protocol 傳遞到 OTel collector。
在 .NET 專案 Program.cs 可以在程式碼中可以看到使用 AddOpenTelemetry()
方法後加上 AddAspNetCoreInstrumentation
與 AddRedisInstrumentation
自動蒐集 dotnet 應用程式與 Redis 的遙測資料
Action<ResourceBuilder> appResourceBuilder =
resource => resource
.AddDetector(new ContainerResourceDetector());
builder.Services.AddOpenTelemetry()
.ConfigureResource(appResourceBuilder)
.WithTracing(tracerBuilder => tracerBuilder
.AddRedisInstrumentation(
cartStore.GetConnection(),
options => options.SetVerboseDatabaseStatements = true)
.AddAspNetCoreInstrumentation()
.AddGrpcClientInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter());
設定檔 : otelcol-config.yml、otelcol-observability.yml
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
exporters:
otlp:
endpoint: "jaeger:4317"
tls:
insecure: true
otlp/logs:
endpoint: "dataprepper:21892"
tls:
insecure: true
otlphttp/prometheus:
endpoint: "http://prometheus:9090/api/v1/otlp"
tls:
insecure: true
service:
pipelines:
traces:
exporters: [otlp, logging, spanmetrics]
metrics:
exporters: [otlphttp/prometheus, logging]
logs:
exporters: [otlp/logs, logging]
OTel Collector 詳細配置設定介紹請參考 : 官網
當需要自定義 Span 屬性時,該如何設定呢 ?
在 Cart Service 中有幾個自定義屬性
Name | Type | Description |
---|---|---|
app.cart.items.count | number | Number of unique items in cart |
app.product.id | string | Product ID for cart item |
app.product.quantity | string | Quantity for cart item |
在 .NET 中我們可以使用 Activity
類別,設定其 tag 進行自定義屬性設定,將重要資訊透過設定在既有的請求上,將屬性一直往後傳遞下去
例如 : cart.items.count
var activity = Activity.Current;
activity?.SetTag("app.user.id", request.UserId);
activity?.AddEvent(new("Fetch cart"));
var cart = await _cartStore.GetCartAsync(request.UserId);
var totalCart = 0;
foreach (var item in cart.Items)
{
totalCart += item.Quantity;
}
activity?.SetTag("app.cart.items.count", totalCart);
例如 : 清空購物車時,紀錄 UserId。當遇到異常的狀況時亦可將錯誤資訊記錄下來,如下所示
public override async Task<Empty> EmptyCart(EmptyCartRequest request, ServerCallContext context)
{
var activity = Activity.Current;
activity?.SetTag("app.user.id", request.UserId);
activity?.AddEvent(new("Empty cart"));
try
{
if (await _featureFlagHelper.GenerateCartError())
{
await _badCartStore.EmptyCartAsync(request.UserId);
}
else
{
await _cartStore.EmptyCartAsync(request.UserId);
}
}
catch (RpcException ex)
{
Activity.Current?.RecordException(ex);
Activity.Current?.SetStatus(ActivityStatusCode.Error, ex.Message);
throw;
}
return Empty;
}
關於資料蒐集的重要觀念之前已介紹過,可以參考下列章節回顧
最後關於 Demo 範例專案內容可以參考官網 OpenTelemetry Document 文件,內有更豐富的資源提供參考,詳細說明就整理到這邊不在追述。
OpenTelemetry Demo Documentation