要開始從 Go 應用程序記錄和處理指標,首先需要對其進行檢測。有兩種類型的檢測 - 自動和手動。為了有效地插裝應用程序並產生高質量的指標數據,您必須熟悉這兩種檢測類型。在此主題中,我們提供了如何使用 OpenTelemetry Go Metrics SDK 手動檢測 Go 應用程序的高級概述。
要開始檢測Go應用程序或套件,用戶首先應該安裝OpenTelemetry Metric API和OpenTelemetry Metric SDK包。
go get go.opentelemetry.io/otel/metric /
go.opentelemetry.io/otel/sdk/metric
要開始為Go應用程序記錄測量值,用戶應該配置所有必需的SDK組件,如計量器提供者、計量器、視圖、指標讀取器和導出器。一旦配置了上述組件,用戶就可以開始創建用於記錄測量值的檢測方法。讓我們看看每個組件。
MeterProvider 負責創建計量器(Meters)。由 MeterProvider 的某一實例所創建的所有Meter將與相同的Resource關聯,具有相同的Views,並將產生的指標傳遞給配置的Readers。
import (
// ...
"go.opentelemetry.io/otel/sdk/metric"
// ...
)
//...
provider := metric.NewMeterProvider(
metric.WithResource(...),
metric.WithReader(...),
metric.WithViews(...),
)
有關更多信息,請參閱 OpenTelemetry 規範中的 MeterProvider 部分。
計量器(Meter)負責創建工具(Instruments)。Meter實例始終通過計量器提供者(MeterProvider)來創建。要創建Meter實例,提供一個名稱(使用 Go 模組名稱作為Meter的名稱)、一個可選的版本和給MeterProvider的 Meter 方法的 schema URL 參數。
import (
// ...
"go.opentelemetry.io/otel/metric"
// ...
)
//...
meter := provider.Meter(
"go.opentelemetry.io/otel/metric/example"
metric.WithInstrumentationVersion(...),
metric.WithSchemaURL(...),
)
一旦Meter實例被初始化,它允許我們使用Instruments工廠(Instruments factories)來創建Instruments。以下工廠用於獲得同步或非同步的整數或浮點數據類型的Instruments:
Meter#AsyncInt64 ()
Meter#AsyncFloat64 ()
Meter#SyncInt64 ()
Meter#SyncFloat64 ()Meter實例還用於註冊回調函數,為非同步Instruments記錄觀察結果:Meter#RegisterCallback ([] instrument.Asynchronous {}, func (ctx context.Context) {})
有關Meter creation的更多信息,請參閱計量器創建部分。
Instruments用於報告測量數據 (Measurements)。每個Instruments都有一個名稱、一種工具類型、一個可選的描述和一個測量單位。每個Instrument都與創建它的計量器 (Meter) 關聯。
Instruments可以是同步的或異步的。同步工具應該與應用程序邏輯一致地使用。由同步工具記錄的測量數據可以與上下文 (Context) 關聯。
異步工具允許用戶註冊回調函數,該函數只在需要時被調用。由異步工具記錄的測量數據不能與上下文關聯。
Go Metrics SDK 支持由 OpenTelemetry 規範定義的以下工具類型:
| 工具類型 | 同步 | 異步 |
|---|---|---|
| 計數器 (Counter) | ✓ | ✓ |
| 上下計數器 (UpDownCounter | ✓ | ✓ |
| 直方圖 (Histogram) | ✓ | |
| 量表 (Gauge) | ✓ |
要創建Instrument的實例,選擇符合您需求的工具工廠,然後通過調用相應的工廠方法選擇工具類型並提供所需的參數來創建Instrument。例如,要創建一個同步的整數Counter,請執行以下操作:
import (
// ...
"go.opentelemetry.io/otel/metric/instrument"
// ...
)
// ...
counter, err := meter.SyncInt64().Counter(
"counter",
instrument.WithDescription("..."),
instrument.WithUnit("..."),
)
if err != nil {
// ...
}
要獲得有關Instruments的更詳細信息,請參考 OpenTelemetry 規範中的Instruments部分。
測量數據 (Measurement) 代表由檢測方法產生的數據點。每個Measurement包含一個值、一組可選的Attributes和一個相關的Context(如果適用)。
同步和異步的Instruments以不同的方式記錄測量數據。如上所述,要使用同步工具記錄測量數據,我們應該將其與應用程序邏輯一致地使用。請參見以下由同步浮點數UpDownCounter記錄的測量數據的示例:
import (
// ...
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric/instrument"
// ...
)
// ...
ctx := context.Background()
counter, err := meter.SyncFloat64().UpDownCounter(
"UpDownCounter",
instrument.WithDescription("..."),
instrument.WithUnit("..."),
)
if err != nil {
// ...
}
// ... application logic
attrs := []attribute.KeyValue{
attribute.Key("...").String("..."),
}
counter.Add(ctx, 1, attrs...)
要使用異步工具觀察測量數據,必須在回調中註冊它。以下是使用整數Gaug觀察某些罕見或昂貴操作的測量數據的示例:
import (
// ...
"go.opentelemetry.io/otel/metric/instrument"
// ...
)
// ...
gauge, err := meter.AsyncInt64().Gauge(
"gauge",
instrument.WithDescription("..."),
instrument.WithUnit("..."),
)
if err != nil {
// ...
}
// ... application logic
err = meter.RegisterCallback([]instrument.Asynchronous{gauge}, func(ctx context.Context) {
mesurement := // result of some rare operation
gauge.Observe(ctx, mesurement)
})
if err != nil {
// ...
}
視圖Views允許用戶自定義 SDK 產生的指標。它可以用於匹配指標並修改其名稱、描述、聚合類型和屬性。此外,它還用於過濾由檢測方法產生的某些指標。當與現有的檢測套件合作以修改或過濾產生的指標時,視圖Views通常最為有用,因此我們不會在此手冊中涵蓋視圖Views。
欲了解更多有關視圖Views的信息,請參考 OpenTelemetry 規範中的視圖View部分。
我們已經討論了大部分的 SDK 組件,並知道如何使用Instruments記錄Measurements。現在產生的遙測數據必須被發送到某個代理或觀察性平台。SDK 透過 MetricReader 和 MetricExporter 組件來處理這個問題。
MetricReader 是 Metrics SDK 和導出器之間的接口。它從 SDK 收集已記錄的測量值,並根據需求或定期地將它們交給導出器。MetricReader 總是和 MetricExporter 相關聯。
MetricExporter 是一個特定的協定組件,支援發送或發射由 SDK 產生的遙測數據。
OpenTelemetry Go Metrics SDK 官方支持以下的導出器:
參見一個 MeterProvided 配置的示例,該配置使收集的遙測數據可透過 Prometheus 導出器提取,並定期地發送到一個可以透過 HTTP 以 OTLP 格式接收數據的上游服務。
import (
// ...
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
"go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/sdk/metric"
// ...
)
// ...
// Push-based periodic OTLP exporter
otlpExporter, err := otlpmetrichttp.New(ctx)
if err != nil {
// ...
}
// Pull-based Prometheus exporter
prometheusExporter, err := prometheus.New()
if err != nil {
// ...
}
meterProvider := metric.NewMeterProvider(
metric.WithResource(resources),
metric.WithReader(metric.NewPeriodicReader(otlpExporter)),
metric.WithReader(prometheusExporter),
)
讓我們看一個簡單的 HTTP Go 應用程式的例子,它有一個單獨的 /health 端點,並使用 Go Metrics SDK 進行了檢測。我們使用了兩個同步檢測類型:Counter 和 Histogram,分別記錄進入的請求數和它們的持續時間。記錄的觀察結果將定期使用 OTLP 協議通過 HTTP 導出到配置的上游服務。
檢測套件依賴:
go get go.opentelemetry.io/otel/metric /
go.opentelemetry.io/otel/sdk/metric /
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp
在這個範例中,遙測數據是以 OTLP 格式通過 HTTP 導出的,因此您可以使用任何能夠通過 HTTP 接收OTLP數據格式的工具作為上游服務。一些選項包括:
OTLP 接收器 (HTTP) 的 OpenTelemetry 收集器
要配置 OTLP 導出器,請參考通過環境變量配置 OpenTelemetry 儀表化。
package main
import (
"context"
"log"
"net/http"
"time"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/instrument"
"go.opentelemetry.io/otel/metric/unit"
sdk "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
)
func main() {
ctx := context.Background()
resources := resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String("service"),
semconv.ServiceVersionKey.String("v0.0.0"),
)
// Instantiate the OTLP HTTP exporter
exporter, err := otlpmetrichttp.New(ctx)
if err != nil {
log.Fatalln(err)
}
// Instantiate the OTLP HTTP exporter
meterProvider := sdk.NewMeterProvider(
sdk.WithResource(resources),
sdk.WithReader(sdk.NewPeriodicReader(exporter)),
)
defer func() {
err := meterProvider.Shutdown(context.Background())
if err != nil {
log.Fatalln(err)
}
}()
// Create an instance on a meter for the given instrumentation scope
meter := meterProvider.Meter(
"github.com/.../example/manual-instrumentation",
metric.WithInstrumentationVersion("v0.0.0"),
)
// Create two synchronous instruments: counter and histogram
requestCount, err := meter.SyncInt64().Counter(
"request_count",
instrument.WithDescription("Incoming request count"),
instrument.WithUnit("request"),
)
if err != nil {
log.Fatalln(err)
}
requestDuration, err := meter.SyncFloat64().Histogram(
"duration",
instrument.WithDescription("Incoming end to end duration"),
instrument.WithUnit(unit.Milliseconds),
)
if err != nil {
log.Fatalln(err)
}
http.HandleFunc("/health", func(w http.ResponseWriter, req *http.Request) {
requestStartTime := time.Now()
_, _ = w.Write([]byte("UP"))
elapsedTime := float64(time.Since(requestStartTime)) / float64(time.Millisecond)
// Record measurements
attrs := semconv.HTTPServerMetricAttributesFromHTTPRequest("", req)
requestCount.Add(ctx, 1, attrs...)
requestDuration.Record(ctx, elapsedTime, attrs...)
})
http.ListenAndServe(":8081", nil)
}
手動檢測 Go 應用程式使用 OpenTelemetry Metrics SDK:
依賴:使用者首先需要安裝 OpenTelemetry Metrics API 和 OpenTelemetry Metrics SDK 套件。
Go Metric SDK 組件:
範例:一個簡單的 HTTP Go 應用程式,具有一個 /health 端點,使用 Go Metrics SDK 進行了檢測。遙測數據定期導出到配置的上游服務。
總的來說,這份指南詳細描述了如何手動使用 OpenTelemetry Metrics SDK 對 Go 應用程序進行檢測,從安裝必要的依賴到如何配置和使用各種 SDK 組件,以及如何將遙測數據導出到外部平台。