Opentelemetry Metrics SDK


Metrics SDK

目標

本文檔包含兩個部分,在第一部分中列出了實現OpenTelemetry Metric SDK的默認需求。實現者需要根據這些規則來實現OpenTelemetry API。

在第二部分中,以OpenTelemetry-Go Metric SDK為例描述了SDK模型的架構細節,給出所需要實現的內容,以此作為對實現者的指導,而不需要強制跨語言精確地去復制這種模型體系結構。

期望

SDK實現者在實現OpenTelemetry API時應該遵守該語言的最佳實踐和運行時環境。實現者應該遵循 OpenTelemetry library guidelines給出的有關安全和性能的規定。

SDK 術語

Metrics SDK提供了一種Metrics API的實現,包含如下術語(本文后續將直接采用如下術語,不作翻譯):

  • Meter:支持OpenTelemetry Metric API的接口,與Resources 和Instrumentation Library綁定在一起
  • MeterProvider:通過給定的Instrumentation Library獲取Meter實例的接口

這些術語用於描述API和SDK的邊界,但它們都是API級別的結構。我們可以使用API級別的術語來描述SDK和API之間的邊界,但從API的角度看,SDK是不透明的,且沒有結構。

本文給出了默認OpenTelemetry SDK的主要組件的內部結構,通過術語來解釋每個組件在將metric數據從輸入(API級別的事件)導出到輸出(metric呈現格式)中所扮演的角色。我們使用Export Pipeline來描述SDK級別的功能。

export pipeline中有三個數據流會經過的主要組件,按順序為:

  1. Accumulator:接收API通過Instrument獲取的metric事件,並根據活動的Instrument和Label Set對計算出一個Accumulation
  2. Processor:從Accumulator接收Accumulations ,並轉換為ExportRecordSet
  3. Exporter:接收ExportRecordSet,並轉換為某種協議(如grpc),將其發送出去

Controller 組件在export pipeline中協調Accumulator、Processor和Exporter。

Metrics API規范定義了如下術語:

  • Metric Instrument:開發者用於操作工具的API對象
  • Synchronous Instrument:用戶通過應用程序上下文調用的metric Instrument
  • Asynchronous Instrument:通過從SDK的回調調用的metric Instrument
  • Metric Descriptor:描述一個metric Instrument
  • Metric Event:單個記錄到或觀察到的(Instrument, Label Set, Measurement)
  • Collection Interval: Accumulator.Collect()調用的周期
  • Label: 描述metric Event屬性的key-value
  • Label Set: 包含唯一的keys的key-values集
  • Measurement: 來自synchronous instrument的證書或浮點數
  • Observation: 來自asynchronous instrument的證書或浮點數

Resource SDK 定義了如下術語:

  • Resource: 描述進程的一組具有唯一keys的key-value集
  • Instrumentation Library:與一個工具包關聯的名稱和版本

下面為架構中重要的數據類型:

  • Aggregator: 以一種有用的方式匯總一個或多個measurements
  • Aggregator Snapshot: 在采集期間拷貝synchronous instrument aggregator的副本
  • AggregatorSelector: 選擇分配給metric instrument 的Aggregator
  • Accumulation: 包含Instrument, Label Set, Resource, 和Aggregator snapshot, 由Accumulator生成
  • Aggregation: 由特定的aggregator聚合一個或多個事件產生的結果, 由Processor生成
  • AggregationKind: 描述了Aggregation支持的API類型 (e.g., Sum)
  • ExportKind: Delta, Cumulative, 或Pass-Through的一種
  • ExportKindSelector: 為一個metric Instrument選擇ExportKind
  • ExportRecord: 包含Instrument, Label Set, Resource, Timestamp(s), 和Aggregation
  • ExportRecordSet: 一些列的export records.

術語SDK instrument 指Instrument的底層實現。

數據流圖表

從外部看, Metrics SDK 實現了MeterMeterProvider接口,從內部看, Metrics SDK為每個metric數據封裝了一個export pipeline,包含四個重要組件。

Accumulator組件是將metric event並發地傳遞給Aggregator的地方,這是負責SDK性能的組件。Accumulator 負責bound 和unbound Instrument,更新和同步拷貝Aggregator 狀態,調用Observer Instrument以及喚醒采集周期。

Processor 組件是exporter pipeline中可定制的組件。Processor 負責通過一個獨立的AggregationSelector接口為特定的Instrument選擇Aggregators ,用於減少維數,以及用於在DELTA和CUMULATIVE數據表示之間進行轉換。Processor 接口支持任意協議獨立的數據轉換,且可以將Processor連接在一起,形成更復雜的export pipelines。

Exporter 組件將處理的數據轉換為特定的協議,並將其轉發到某處。根據 library guidelines,exporter應該包含最小的功能,定制時最好通過Processors來表示。

Controller 組件協調在一個采集間隔內的采集動作,處理和導出采集間隔內的metric數據,確保對export pipeline的訪問是同步的。

要求

下面列出了針對OpenTelemetry SDK主要組件的要求。

上面展示了一個抽象的數據流圖,將本文檔使用的標准組件名與數據路徑做了映射。上圖並非要說明SDK的整體架構,僅命名了一個export pipeline的過程,並將組件放到了上下文中。

SDK要求這些組件使用標准名稱,這樣做有助於在OpenTelemetry中構建一致性。每個SDK都應該包含這些組件,以及下面列出的接口,盡管每個SDK的實際組織可能會因可用的庫和源語言的性能特征而有所不同。例如,一個SDK可能為每個instrument實現了一個Accumulator,或者可以為每個采集周期使用一個Accumulator(假設支持多采集周期)。

SDK

SDK封裝了OpenTelemetry Metric export pipeline,實現了Meter接口,並管理SDK instrument,Resource和Instrumentation Library 元數據。

MeterProvider
Shutdown

該方法為provider提供了一種清理環境的方法。

每個MeterProvider實例只能調用一次Shutdown,在調用Shutdown之后,將不允許獲得Meter。對於這些調用,SDK應該返回一個有效的無操作Meter。

Shutdown應該提供一種方式來讓調用者知道是否成功,失敗或超時。

當出現超時時,Shutdown應該結束或中止。Shutdown可以被實現為一個阻塞API,或異步API,通過回調或事件通知調用者。語言庫作者可以決定是否配置shutdown的超時時間。

SDK:Instrument注冊

OpenTelemetry SDK負責確保單個Meter的實現不會報告具有相同名稱但不同定義的多個Instrument。為了實現該要求,如果一個Meter已經注冊了一個相同名稱的metric,則SDK必須拒絕在該Meter重復注冊該Instrument。該要求甚至適用於嘗試注冊一個具有相同定義的Instrument。我們假設單個instrumentation library可以使用單個Instrument定義,而不是依賴SDK的重復注冊。

不同的Meter具有不同的instrumentation library名稱,允許在不同的instrumentation library中注冊相同名稱的Instrument,這種情況下,SDK必須將它們認為是不同的Instruments。

SDK負責實現API規范中包含的metric名稱的語法要求。

SDK: RecordBatch() 函數

TODO: Add functional requirements for RecordBatch().

SDK: Collect() 函數

SDK負責實現Collect()函數,該函數會調用一個或多個Accumulators。本規范刻意避免在SDK和Accumulator之間建立特定關系;還有一個實現細節,即一個SDK是否會維護一個Accumulator,或每個Instrument對應一個Accumulator,或介於兩者之間的某些配置。

SDK Collect()函數必須通過活動的synchronous instruments以及所有注冊的asynchronous instruments的Accumulations來調用Processor。

SDK必須允許在評估asynchronous instrument回調期間使用synchronous metric instruments。但通過asynchronous instrument回調來使用synchronous instruments是有副作用的,這種情況下,SDK應該在處理asynchronous instrument之后再處理synchronous instruments,這樣synchronous measurements會作為asynchronous observations采集間隔的一部分進行處理。

Accumulator

下圖展示了API和Accumulator之間的關系,以及synchronous instruments的細節。

對於一個synchronous instrument,Accumulator會:

  1. 將每個活動的Label Set 映射到一條記錄中,該記錄由兩個相同類型的Aggregator實例組成
  2. 在映射中輸入新記錄,如果需要,調用AggregationSelector
  3. 更新當前的Aggregator 實例,用以響應並發API事件
  4. 在當前Aggregator 實例上調用Aggregator.SynchronizedMove:a)拷貝其值到Aggregator快照實例中;b)將當前的Aggregator重置為0狀態
  5. 調用Processor.Process。處理每一個生成的Accumulation (即Instrument, Label Set, Resource, 和Aggregator snapshot)

Accumulator必須提供選項來將一個Resource與它生成的Accumulations進行關聯。

Synchronous metric instruments可以同步使用,除非源語言不支持該特性。SDK Accumulator 組件應該注意同步產生的性能壓力。

Accumulator可能會使用排他鎖定來維護synchronous instruments的更新。在調用Aggregator 時,Accumulator不應該持有排他鎖,因為Aggregators可能具有更高的同步期望。

Accumulator: Collect()函數

Accumulator必須實現Collect方法來為活動的instruments構建和處理當前的Accumulation值,即在上一次采集之后會更新這些值。Collect方法必須調用Processor來處理對應調用之前的所有metric events的Accumulations。

必須在Collect期間使用Aggregator上的同步移動操作來計算Accumulations。該操作會同步拷貝當前的Aggregator,並將其重置為0狀態,這樣Aggregator會在當前采集周期處理結束之后,下次采集周期開始時立即開始累加事件。一個Accumulation 定義為同步拷貝的Aggregator與Label Set, Resource, 和metric Descriptor的組合。

TODO: Are there more Accumulator functional requirements?

Processor

TODO Processor functional requirements

Controller

TODO Controller functional requirements

Aggregator

TODO Aggregator functional requirements

如果可能的話,Sum Aggregator應該使用原子操作。

模型實現

本模型實現基於OpenTelemetry-Go SDK,本節為實現者提供指南。

Accumulator: Meter實現

為了構造一個Accumulator,需要提供Processor和options

// NewAccumulator constructs a new Accumulator for the given
// Processor and options.
func NewAccumulator(processor export.Processor, opts ...Option) *Accumulator

// WithResource sets the Resource configuration option of a Config.
func WithResource(res *resource.Resource) Option

Controller會使用Collect()方法來調用Accumulator,對采集進行協調。

// Collect traverses the list of active instruments and exports
// data.  Collect() may not be called concurrently.
//
// During the collection pass, the Processor will receive
// one Process(Accumulation) call per current aggregation.
//
// Returns the number of accumulations that were exported.
func (m *Accumulator) Collect(ctx context.Context) int
實現與用戶級別的Metric API匹配的SDK級別的API

該接口位於SDK和API的邊界處,包含3個方法:

// MeterImpl is the interface an SDK must implement to supply a Meter
// implementation.
type MeterImpl interface {
        // RecordBatch atomically records a batch of measurements.
        RecordBatch(context.Context, []label.KeyValue, ...Measurement)

        // NewSyncInstrument returns a newly constructed
        // synchronous instrument implementation or an error, should
        // one occur.
        NewSyncInstrument(descriptor Descriptor) (SyncImpl, error)

        // NewAsyncInstrument returns a newly constructed
        // asynchronous instrument implementation or an error, should
        // one occur.
        NewAsyncInstrument(
                descriptor Descriptor,
                runner AsyncRunner,
        ) (AsyncImpl, error)
}

這些方法覆蓋了實現OpenTelemetry Metric API所需的所有入口。

RecordBatch是一個直接由Accumulator實現的用戶級別的API。另外兩個instrument構造器用於創建同步和異步SDK instruments。

用戶通常對Metric API Meter 接口感興趣,該接口通過Metric API MeterProvider 接口獲得。可以通過封裝SDK Meter實現來構建Meter接口。

// WrapMeterImpl constructs a named `Meter` implementation from a
// `MeterImpl` implementation.  The `instrumentationName` is the
// name of the instrumentation library.
func WrapMeterImpl(impl MeterImpl, instrumentationName string, opts ...MeterOption) Meter

該方法的選項:

  • 可以為命名的Meter添加instrumentation library版本

instrument注冊:

// NewUniqueInstrumentMeterImpl returns a wrapped metric.MeterImpl with
// the addition of uniqueness checking.
func NewUniqueInstrumentMeterImpl(impl metric.MeterImpl) metric.MeterImpl {
訪問instrument descriptor

API Descriptor 方法根據API級別的構造定義了instrument ,包括名稱,instrument類型,描述和度量單位。在實現SDK時必須提供方式來訪問傳遞給constructor的Descriptor。

// InstrumentImpl is a common interface for synchronous and
// asynchronous instruments.
type InstrumentImpl interface {
        // Descriptor returns a copy of the instrument's Descriptor.
        Descriptor() Descriptor
}
Synchronous SDK instrument

Synchronous SDK instrument 支持直接和綁定調用規范。

// SyncImpl is the implementation-level interface to a generic
// synchronous instrument (e.g., ValueRecorder and Counter instruments).
type SyncImpl interface {
        // InstrumentImpl provides Descriptor().
        InstrumentImpl

        // Bind creates an implementation-level bound instrument,
        // binding a label set with this instrument implementation.
        Bind(labels []label.KeyValue) BoundSyncImpl

        // RecordOne captures a single synchronous metric event.
        RecordOne(ctx context.Context, number Number, labels []label.KeyValue)
}

// BoundSyncImpl is the implementation-level interface to a
// generic bound synchronous instrument
type BoundSyncImpl interface {

        // RecordOne captures a single synchronous metric event.
        RecordOne(ctx context.Context, number Number)

        // Unbind frees the resources associated with this bound instrument.
        Unbind()
}
Asynchronous SDK instrument

Asynchronous SDK instrument 支持單觀察者和匹配觀測者調用規范。用於執行Observer回調的接口會傳遞給constructor,這樣asynchronous instruments就不需要其他API級別的訪問方法。

// AsyncImpl is an implementation-level interface to an
// asynchronous instrument (e.g., Observer instruments).
type AsyncImpl interface {
        // InstrumentImpl provides Descriptor().
        InstrumentImpl
}

傳遞給asynchronous SDK instrument constructor 的異步"runner"接口(AsyncRunner)同時支持單個批量調用規范。

Export pipeline細節

TODO: define AggregatorSelector, Aggregator, Accumulation, ExportKind, ExportKindSelector, Aggregation, AggregationKind ExportRecord, ExportRecordSet

Processor細節

TODO: define the Processor interface

Basic Processor

TODO: define how ExportKind conversion works (delta->cumulative required, cumulative->delta optional), Memory option (to not forget prior collection state).

Reducing Processor

TODO: Label filter, LabelFilterSelector

Controller 細節

TODO: Push, Pull

Aggregator Implementations

TODO: Sum, LastValue, Histogram, MinMaxSumCount, Exact, and Sketch.

Pending issues

ValueRecorder instrument default aggregation

TODO: The default SDK behavior for ValueRecorder instruments is still in question. Options are: LastValue, Histogram, MinMaxSumCount, and Sketch.

Spec issue 636 OTEP 117 OTEP 118

Standard sketch histogram aggregation

TODO: T.B.D.: DDSketch considered a good choice for ValueRecorder instrument default aggregation.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM