昨天大概了解了Client架構後
這幾天來逐步了解一下 三本柱在OTel中的規範
三本柱裡面, 唯一沒有直接統一的API套件來做client遵守的就只有Log.
因為Log, 從古至今, 太多種套件跟格式了.
與其給一套全新統一的套件, 不如想辦法整合集成, 並加以豐富其內容.
這是OTel對於Logs這遙測資料生態的期許.
in logging space we need to support existing legacy of logs and logging libraries, while offering improvements and better integration with the rest of observability world where possible.
開發者聽到Log大概都想到自己程式寫出去的Application Logs.
運維同仁聽到Log, 搞不好大部份想到的是System Logs.
其實都是Log, 只是來源的不同, 來源不同格式通常也不同.
由OS生成的Log, 我們無法控制其格式與其包含的訊息.
常見的就Linux的Syslog和Widnows Event Log.
上圖是Linux Mint的syslog & kernel log與其內容
幾乎system log不會包含任何有關request的上下文資訊.
這log資訊對開發人員來說難以識別跟使用.
運維同仁也很難識別, 幾乎都依靠時間跟主機還有經驗來猜測.
但這個層級的log,
我們也是能想辦法拿到一些resouce context資訊並且冗餘到application內;
或者透過log agent來蒐集時, 並且添加進去.
Resouce context像是hostname, ip address, pod name或是container name.
Infrastructure 是基於OS之上的基礎設施服務所產生的Log.
像是Kubernetes, Kafka, MySQL等等都是.
但還是跟system logs一樣缺少request context資訊.
但還是可以去增添resouce context進去, pod, node或container name.
就我們專案常用的Log套件, 像是Log4j(怕), NLog, Go的zap這類的.
輸出的管道就多了, 有stdout, file或其他(像是Windows Event Logs for applications)
這裡太多變化了XD
小弟去年也有介紹一點, 分布式可觀測性 Structured Log
這裡面不管哪種格式, 都缺少request context, 但是可以增添resource context, 這裡除了上面的resource屬性外, 還能有程式級別的屬性(app name, version, db name等等的).
也能透過該改專案內的程式, 把request context的資訊添加到log描述中;
但我相信, 在線的系統甚至老專案, 沒人敢這樣做, 搞不好連套件版本都不支持.
通常已經在線上的跑系統, 想加入上述的resource context, 或者request context所需的trace/span ID.
最常見的作法可能是先把已經存在的log/file, 給轉成structed log格式.
這部份能參考小弟去年用的FluetBit系列, 透過FluentBit的Modify Filter加上resource context.
透過Log collector agent(FluentBIt)來讀取file, 解析log, 收集log, 並且送到OTel Collector(日後會介紹).
如果log格式本身就是具備很好解析的格式, 像上面的2,3點.
那也能考慮使用OTel Collector內建的parser.
直接把log讀進OTel collector處理即可.
上面兩種作法, 有點難處在trace_id與span_id的產生, 還有之前提到的一些k-v pair的夾帶資訊
最後一種是直接修改程式, 為我們用的Logging library提供OTel logging sdk擴充,始其將之格式甚至傳輸協議都改成滿足OTLP OpenTelemetry Protocol的形式傳輸
因為OTel沒有定義標準的log api或者直接提供官方的log library.
所以實際有提供的涵蓋範圍如下圖虛線.
目的還是增強常見的log library.
希望透過OTel SDK
能達成這樣的架構
讓三本柱都在Collector內集中處理, 讓設定也集中管理.
OTlp Log and Event Record Definition
Field Name | Description |
---|---|
Timestamp | Time when the event occurred. |
ObservedTimestamp | Time when the event was observed. |
TraceId | Request trace id (hex-encoded). |
SpanId | Request span id (hex-encoded). |
TraceFlags | W3C trace flag. |
SeverityText | The severity text (also known as log level). |
SeverityNumber | Numerical value of the severity. |
Body | The body of the log record. |
Resource | Describes the source of the log. |
InstrumentationScope | Describes the scope that emitted the log. |
Attributes | Additional information about the event. |
以及對應的proto檔opentelemetry/proto/logs/v1/logs.proto
重要的就是其中的TraceId, SpanId,以及TraceFlags, 但三個都是optional, 可加可不加.
少加了就少點資料能操作.
不管是什麼格式, 盡量加上traceId,與SpanId
Syslog RFC5424格式
[opentelemetry trace_id="102981ABCD2901" span_id="abcdef1010" trace_flags="01"]
Plain Text格式
host:192.168.0.1 trace_id:102981ABCD2901 span_id:abcdef1010 time:[01/Jan/2010:10:11:23 -0400] req:GET /health HTTP/1.0 status:200
JSON格式
{
"timestamp":1581385157.14429,
"body":"Incoming request",
"trace_id":"102981ABCD2901",
"span_id":"abcdef1010"
}
m...越早被廣泛使用的東西, 到如今月難改動, 甚至導入.
只能想辦法墊個數層, 做轉化.
但重點還是規範, 要在Log model中紀錄什麼?
OTel的log data model給了一個很好的範例.
還沒提到, 但在Log加入traceId的好處
OpenTelemetry Logging Overview
原來雷N大都是一過時間就發布,好厲害,剛剛快截稿時,還在想 雷N大怎麼沒有po文,
要來學習雷N大的精神才是。
這樣才能多將近一天的Buffer XD