# 淺談Observability

## Observability的歷史

(又在講古了XD) **Observability**這詞, 最早在[控制理論](https://en.wikipedia.org/wiki/Control_theory)出現, 這是一門關注如何控制動態系統的工程學科, 其中的[Rudolf E. Kálmán在1960的論文](https://www.sciencedirect.com/science/article/pii/S1474667017700948)中提出的.

> Observability to describe mathematical control systems. In control theory, observability is defined as a measure of how well internal states of a system can be inferred from knowledge of its external outputs.

恩...大概就根據一個系統的外部輸出的資訊來推斷內部狀態的能力,甚至可以透過輸出的資訊搭配知識來做出推斷假設與證明. 進而優化再持續性的觀測, 是不能稱為系統具備可觀測性的, 因為這樣子組織會高度依賴少部份人的能力而帶來管理風險.

![https://ithelp.ithome.com.tw/upload/images/20220904/20104930NtEuKNpTjR.png](https://ithelp.ithome.com.tw/upload/images/20220904/20104930NtEuKNpTjR.png align="left")

這也呼應了DevOps的8字環.

![](https://www.tibco.com/sites/tibco/files/media_entity/2021-04/Dev-ops-01.svg align="left")

Kálmán後來有把這論文的理論, 用在軟體系統上, 並且給出了更詳細的要求, 只有滿足了才可稱為具備Observability.

1. 了解應用程式的內部運作
    
2. 了解你的應用程式可以進入任何的系統狀態, 甚至你以前都沒見過也無法預測的新狀態
    
3. 僅透過觀察與存取外部工具來了解軟體的內部運作與系統狀態
    
4. 了解內部狀態, 不需要提供任何新的自定義程式來處理解析它.
    

[Observability Engineering](https://www.oreilly.com/library/view/observability-engineering/9781492076438/)這本書的第一章, 有提出很多小問題來詢問自己是否夠了解自己的系統. 我隨便舉兩三題 1.是否曾經遇過線上問題, 自己都能解釋異常狀況, 沒碰到過排查的死胡同, 最後只能靠通靈跟重開機. 2.如果有用戶抱怨系統很慢, 但你的監控面板顯示99th, 99.9th甚至99.99th的請求都很快, 能找到隱藏的超時嘛?

之類的很多問題XD

**1988年**, SNMPv1定義在[RFC1157](https://www.rfc-editor.org/rfc/rfc1157), 其中提到了大家很熟悉的Monitoring. 其中有**Metric度量指標**,它是一個數字, 跟隨著一些**tag**, 我們就能用這些tag對這些metrics的數字做一些分類和搜尋. 通常這些metric指標都是一次性產生、廉價的存儲空間. 但它們又通常會用Time-Series bucket(時間序列集合)來聚合存放. 現在有很多複雜的應用或組織運作都建立在Metric指標上, 像是Time-Series databases(TSDBs)、一些統計分析、圖形儀表板、運維團隊、On-Call輪轉等等的, 很多方式能展示跟告知團隊. 但這些總有上限, 這上限在這些metric指標都是自己對系統已知的資訊. 平常跑得很正常的系統, 突然壞了, metric指標也不出來時, 大部分的運維團隊就會用low-level的指令來查找問題, 像是strace, tcpdump等等數百條命令來嘗試讓主機來回答問題.

且現在的系統架構往往是

1. 一個應用系統有多組服務來支撐, 換言之系統很複雜
    
2. 有很多種的持久化服務(像是DB, storage systems)
    
3. Infrastructure是很動態地, 像容量就任意的伸縮
    
4. 許多服務是我們有依賴, 但不歸屬我們做管理控制
    
5. 分散式系統是難以被完整預測的
    
    ![](https://i.imgur.com/R7Ckjve.png align="left")
    

還有很多原因, 將導致團隊在治理跟排查上遭遇很大的困難. 若是沒有一個高維度(Dimensionality)和高基數(Cardinality)資料, 貫穿在眾多線索中, 將會非常難在現在這樣複雜的系統架構裡快速地找到問題, 甚至證明假設.

### 基數Cardinality

在關聯式資料庫裡, **Cardinality**指的是資料的唯一性. Low-cardinality表示一列有很多重複的值. 性別/姓名都算是低基數. High-cardinality意味著該列包含很大比例的唯一值. 所以像UniqueID, UUID這樣的值在該列則能稱為高基數.

![](https://i.imgur.com/gI2ZWeT.png align="left")

Cardinality對於Observability是非常重要的, 因為高基數的資料在Debug或了解系統的資料識別上是最有用有效的. 像是UserIDs, ShoppingCartIDs, RequestIDs其他等等的高基數ID. 又或是我們之後要介紹的TraceIDs, SpanIDs, 或是容器ID, 主機名稱都是查詢唯一ID的好方法. 高基數資料的好處除了方便識別外, 也能轉化成低基數的資料, 像是分類分堆, 資料前綴/後綴等等的; 但低基數的資料卻不能反過來轉化成高基數的資料.

但是!! 大部分基於Metrics的工具或服務(像Prometheus), 基本都是處理低基數的資料. 通常低基數的資料都是要是前先決定好的. 但通常很多人事先不太清楚哪些指標做度量的, 或哪些標籤是需要做識別.

### 維度Dimensionality

基數講的是資料的唯一性. 維度講的是該資料所擁有key(屬性)的數量. 在Observability System中, Telemetry(遙測)數據是由任意寬度(Wide)的結構化事件所生成的. 這些事件能被稱為Wide, 是因為它們可以包含上百甚至上千個Key-value pair(或者叫維度Dimensionality).

![](https://i.imgur.com/ienjRfT.png align="left")

圖上的P是特徵, n則是metric資料. 盡可能描述多點特徵. 統計學對於高維度資料有嚴格的定義\[^1\].

像之後要介紹的Prometheus, 其metric資料裡面能含有任意數量的k-v pairs; 結構化Log其內容也是有很多k-v pair來描述其上下文的資訊, 便於觀察了解系統.

### 上下文Context

所有的Signal(之後會解釋), 都有相同的內容. 其實就是在空間上建立資料之間的關聯.

舉例, Prometheus\[^2\]首頁就有這段描述

![https://prometheus.io/](https://i.imgur.com/HzRTuPy.png align="left")

Prometheus就是實現能提供一個高維度資料的模型, 其中也包含了一組任意數量的k-v pair.

在現在這年代, 硬碟容量是很方便被擴充的, 且讀寫速度也遠快於以前. 沒必要省成這樣. 多冗餘些資訊在資料內反而方便之後關聯查詢用. 數據的維度越高, 就越有可能找到系統行為中隱藏或難以捉摸的模式(還是交給數據分析專家幫忙分析好了).

假設我們定義了6個高基數維度的事件, time, app, host, user, endpoint還有status. 我們就可以建立查詢方法來分析這些維度的組合和顯示相關性. 像是可以搜尋所有status是502, time發生在過去半小時內的, 且host是ithome的數據. 或是找所有status是403, 由user是Nathan對著ironman14th這endpoint發生的錯誤, 等等的.

## 今日小總結

Observability相關的工具或服務, 其實不只是上面提到的metrics, 或者是限制遙測資料的基數跟維度. 反而是鼓勵開發團隊為每個可能發生的事件收集豐富的遙測資訊. 將請求的完整上下文也存儲起來, 在某些時候使用或者分析用.

聊到現在, 感覺上Observability就只是Monitoring換了一層包裝的講法, 但不管如何, Observability都是為了給系統帶來更好的Visibility(可見性), 易於Debugging調試, 是一個穩定的系統在維護與發展上的基石.

明天也會繼續講更多Observability. 謝謝各位與隊友們.

## 參考資料

\[^1\]: [What is High Dimensional Data?](https://www.statology.org/high-dimensional-data/) \[^2\]: [Prometheus](https://prometheus.io/) [Observability Whitepaper](https://github.com/cncf/tag-observability/blob/main/whitepaper.md)
