天天看點

OpenTelemetry Log規範解讀前言初衷&宗旨日志架構演進特性字段類型LogModel定義LogModel示例總結參考

前言

OpenTelemetry作為目前可觀察性的标準方案,近年來的發展速度非常快,目前OpenTelemetry Trace規範v1.0版本已經釋出,Metrics v1.0也将在幾個月後釋出。相對最慢的當屬Log規範,但在衆多公司的參與下,Log規範的第一個版本已經在半年前釋出,且經過了幾次更新,也在朝着v1.0的方向快速前進。

本文主要介紹OpenTelemetry Log規範,這一規範來自于Google、Microsoft、AWS、Splunk、DataDog、ES、Fluntd等衆多優秀的公司和項目成員,其中有很多點是我們在平時開發、運維需要關注的知識和經驗,值得大家一觀。

初衷&宗旨

官方定義的宗旨如下:

  • 日志模型能夠表達各種來源的日志:應用程式、機器事件、系統日志、容器日志等。
  • 能夠将現有的大部分日志格式映射到日志模型,并且日志模型也可以很容易的轉換成各種日志格式。
  • 通過日志資料模型和語義的定義,能夠指導日志系統如何記錄、傳輸、存儲和了解日志。

從OpenTelemetry的頂層宗旨來看,日志模型的定義最主要還是規範化,能夠将Metrics、Tracing、Logging的common schema統一,這樣可以做到3者的無縫打通。當然,為了盡可能的通用,模型的定義會參考衆多的日志格式,表達資訊的方式需要盡肯能靈活。

日志架構演進

OpenTelemetry Log規範解讀前言初衷&宗旨日志架構演進特性字段類型LogModel定義LogModel示例總結參考

傳統架構下Logs、Traces、Metrics都是單獨産生并收集的,在OpenTelemetry的規劃中,所有的資料都會通過OpenTelemetry的Collector進行采集并傳輸到統一的後端進行關聯。好處非常明顯:

  1. 應用隻需要一個SDK就可以做所有可觀測性上的事情,依賴更少、資源消耗也更小
  2. 采集端隻需要一個,部署和運維代價更低
  3. 資料格式統一,資料關聯更容易

上面的圖展示的是終極目标,但目前OpenTelemetry Collector對于Log的支援還比較弱,估計未來1-2年還是要用其他的日志采集去支撐。

特性

  1. LogModel(日志模型)應該支援任意類型的日志能夠明确的轉換成該類型,對于兩種相同含義不同格式的日志,轉換到LogModel後應該是完全等價的。
  2. 從其他日志類型映射到LogModel是有一定意義的,LogModel必須能夠表示出其他日志類型的語義。
  3. 将類型A的日志換成到LogModel,然後再由LogModel轉換到類型B。這種場景應該和從類型A直接轉換到類型B是一緻的,即轉換過程中不應該丢失/增加資料。
  4. LogModel在傳輸和存儲的效率上需盡可能的高,主要是對于CPU和記憶體的使用盡可能低,即序列化/反序列化盡可能高效以及存儲空間盡可能低。

從表達能力上看,LogModel需要能夠表達至少以下3種的日志/Event:

  1. 系統日志:即作業系統/硬體産生的日志,一個最典型的代表是Syslog。
  2. 三方應用日志:一些流行的三方軟體的日志格式,例如Apache日志、MySQL慢日志等。
  3. 應用日志:業務應用産生的日志,這些日志一般由程式員列印,在需要的時候可以适當修改源碼來适應新的LogModel。

字段類型

LogModel隻定義日志(Record)的邏輯表現形式,與具體的實體格式和編碼形式無關,每個Record包含兩種字段類型:

  1. 具有特定類型和含義的頂級字段(Top-Level)
  2. 具體的字段,通常以KeyValue對的形式,根據不同的Top-Level名稱,對應的字段會有不同的類型

LogModel定義

字段名 描述 必選
Timestamp 日志時間戳
TraceId 關聯請求的TraceId
SpanId 關聯請求的SpanId
TraceFlags W3C trace flag.
SeverityText 日志等級的可讀描述.
SeverityNumber 日志等級.
ShortName 用于辨別日志類型的短語.
Body 具體的日志内容.
Resource Log關聯的Resource.
Attributes 額外關聯屬性.

字段詳細解釋

uint64,納秒

位元組數組,具體可以參考:

W3C Trace Context

位元組數組,如果SpanId出現,則TraceId必須出現。

單位元組,具體可參考:

日志等級的可讀描述,如果不設定,則按照

SeverityNumber

的預設Mapping規則映射。

SeverityNumber

和Syslog中的日志等級比較像,OpenTelemetry定義了6大類、24種日志等級,基本上可以包含所有類型日志的等級定義。

SeverityNumber range 通用等級 含義
1-4 TRACE A fine-grained debugging event. Typically disabled in default configurations.
5-8 DEBUG A debugging event.
9-12 INFO An informational event. Indicates that an event happened.
13-16 WARN A warning event. Not an error but is likely more important than an informational event.
17-20 ERROR An error event. Something went wrong.
21-24 FATAL A fatal error such as application or system crash.

SeverityNumber

SeverityText

可通過Mapping的方式自動映射,是以在日志産生的時候,可以不填寫

SeverityText

字段,以介紹序列化/反序列化和傳輸代價。映射關系如下:

Short Name
1
2 TRACE2
3 TRACE3
4 TRACE4
5
6 DEBUG2
7 DEBUG3
8 DEBUG4
9
10 INFO2
11 INFO3
12 INFO4
13
14 WARN2
15 WARN3
16 WARN4
17
18 ERROR2
19 ERROR3
20 ERROR4
21
22 FATAL2
23 FATAL3
24 FATAL4

一般用一個特定的詞來辨別日志類型,通常不要超過50個位元組,例如:

ProcessStarted

日志内容為Any類型,Any類型,可以是 int、string、bool、float,也可以是一個數組或是Map。

Key/Value對清單,參考OpenTelemetry的

通用Resource定義

這裡包括主機名、程序号、服務名等資訊,可以用于關聯Metrics、Tracing。

Key/Value對清單,Key始終是 string,Value是Any類型。具體可以參考Tracing中

Attributes的定義

LogModel示例

Example 1

{
  "Timestamp": 1586960586000, // JSON needs to make a decision about
                              // how to represent nanoseconds.
  "Attributes": {
    "http.status_code": 500,
    "http.url": "http://example.com",
    "my.custom.application.tag": "hello",
  },
  "Resource": {
    "service.name": "donut_shop",
    "service.version": "semver:2.0.0",
    "k8s.pod.uid": "1138528c-c36e-11e9-a1a7-42010a800198",
  },
  "TraceId": "f4dbb3edd765f620", // this is a byte sequence
                                 // (hex-encoded in JSON)
  "SpanId": "43222c2d51a7abe3",
  "SeverityText": "INFO",
  "SeverityNumber": 9,
  "Body": "20200415T072306-0700 INFO I like donuts"
}      

Example 2

{
  "Timestamp": 1586960586000,
  ...
  "Body": {
    "i": "am",
    "an": "event",
    "of": {
      "some": "complexity"
    }
  }
}      

Example 3

{
   "Timestamp": 1586960586000,
   "Attributes":{
      "http.scheme":"https",
      "http.host":"donut.mycie.com",
      "http.target":"/order",
      "http.method":"post",
      "http.status_code":500,
      "http.flavor":"1.1",
      "http.user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36",
   }
}      

總結

從上述的規範可以看出,OpenTelemetry的Log模型主要追求以下幾點:

  1. 作為Metrics、Traces、Logs三大可觀測性資料的終極細節性資料,Log需要能夠表達足夠詳細的資訊
  2. 如果Log在Trace場景中,需要包裹TraceID、SpanID,以便和Traces關聯,同時借助Resource資訊可以更好的和Traces、Metrics關聯
  3. Log的性能需要盡可能的高,因為日志是資料量最大的可觀測性資料,而且不會做采樣,一定要確定對應用的性能影響盡可能的小
  4. 相容性要好,因為目前有太多的日志系統,且都存在了很久也有很明确的存在意義,是以需要能夠保證這些不同類型的Log可以和OpenTelemetry Log進行無縫轉換

整體上這個模型還是非常适合現代的IT系統,但想要把這套标準成功實施下來還有很多工作要做,包括日志采集、解析、傳輸工具,相容其他很多已有系統、環境等。不過好在Fluentd也在CNCF項目下,未來可能會成為OpenTelemetry的日志采集核心,配合Collector一起工作。

參考

  1. https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/overview.md
  2. https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md
  3. https://www.w3.org/TR/trace-context/#trace-id
  4. https://docs.datadoghq.com/tracing/connect_logs_and_traces/java/?tab=log4j2
  5. https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/overview.md#resources
  6. https://github.com/open-telemetry/opentelemetry-specification/tree/master/specification/trace/semantic_conventions

繼續閱讀