分類程式碼研究室

協作者:cphoenix@

本程式碼研究室將說明 Triage 公用程式:

  • 內容。
  • 執行方式,包括指令列選項。
  • 如何新增及測試設定規則,以偵測 Fuchsia 快照中的問題。

本文件參考的來源檔案和範例請見:

什麼是 Triage?

分類可讓您掃描 Fuchsia 快照 (snapshot.zip 檔案),找出預先定義的條件。

「分類」系統可讓您輕鬆設定新條件,提高試用的實用性,讓所有使用者受益。

必要條件

在開始本程式碼研究室之前,請先確認您已完成以下操作:

  • 開始使用
  • 使用 fx build 建立了 Fuchsia 版本。

透過指令列執行 Triage

  • 如要執行 Triage,請執行下列操作:
fx triage

這個指令會使用 fx snapshot 指令下載新的 snapshot.zip 檔案。這個指令會執行來源樹狀結構中的預設規則:

  • //src/diagnostics/config/triage/*.triage

如要分析特定 snapshot.zip 檔案,請使用 --data

  • 您最多只能指定一個 --data 引數。
  • --data 的引數也可以是包含未壓縮快照的目錄路徑。
  • 如果您在執行 fx triage 時未指定 --data 選項,系統會執行新的 fx snapshot 並分析其檔案。
fx triage --data my/foo/snapshot.zip

如要使用特定設定檔或特定目錄中的所有 *.triage 檔案,請使用 --config

  • 您可以使用多個 --config 引數。
  • 如果使用 --config 引數,系統不會自動載入預設規則。
fx triage --config my/directory --config my/file.triage

新增分類規則

本程式碼研究室的其餘部分將說明如何在 Triage 中設定新行為。

總覽

分類透過下列步驟,將診斷資料的大量資料壓縮為有用的資訊:

  1. 使用設定檔的 select 區段中的「選取器」字串,選取 inspect.json 檔案中的值。
  2. 執行計算和比較以產生新值,如設定檔的 eval 區段指定。
  3. 依據設定檔 act 區段中的項目執行動作。
    1. 如果錯誤狀況 (布林值運算式) 為 true,系統就會發出警告。
    2. 向使用者顯示值。
  4. 透過 test 區段中的項目,支援對動作和運算進行單元測試。

尋找程式碼研究室的範例檔案

前往來源樹狀結構中的 examples/diagnostics/triage 目錄。下列指令是用來從該目錄執行:

fx triage --config . --data snapshot

使用未經修改的程式碼研究室檔案在範例目錄中執行這個指令,即可列印預先提供動作的一行內容:

Warning: 'always_triggered' in 'rules' detected 'Triage is running': 'always_true' was true

檢查.json

本程式碼研究室包含包含檢查資料的 inspect.json 檔案,讓運動能夠預測。這個檔案位於 snapshot/inspect.json 下的範例目錄中。

Rules.triage

剪輯程式會使用從一或多個 .triage 檔案載入的設定。本程式碼研究室會使用範例目錄中的 rules.triage 檔案。

.triage 檔案使用 JSON5,這比 JSON 容易寫入及讀取:

  • 在最後一個清單項目後方加上半形逗號是不錯的方式。
  • 大部分的金鑰 (包括所有有效的分類名稱) 不需要包裝在引號中。
  • /* 多行 */ 和 // 單行註解。

為「Inspect」的值新增選取器

範例目錄中的 inspect.json 檔案表示系統有幾個問題。您將設定分類系統來偵測這些問題。

這個步驟會設定 Triage,從 inspect.json 檔案的資料擷取值。

rules.triage 檔案包含名為 select 的鍵/值部分。每個鍵 (名稱) 都可以在其他設定項目的主體中使用。每個值都是選取器字串。實際上,select 部分 (以及下方所述的 eval 部分) 中的每個項目都會定義變數。

選取器字串是以半形冒號分隔的字串,可在「檢查資料」中的位置尋找所需值。

select: {
    disk_total: "INSPECT:bootstrap/fshost:root/data_stats/stats:total_bytes",
    // "data_stat" is an intentional typo to fix later in the codelab.
    disk_used: "INSPECT:bootstrap/fshost:root/data_stat/stats:used_bytes",
}

檢查元件發布的資料會整理成包含值 (屬性) 的節點樹狀結構。inspect.json 檔案是這些樹狀結構的陣列,每個樹狀結構都有識別來源元件的預留位置。

INSPECT: 和第二個冒號之間的選取器字串部分應與 inspect.json 檔案的其中一個路徑名稱字串相符。

第二個和第三個半形冒號之間的部分是以 / 分隔的節點名稱清單。

最後一個冒號後面的部分是屬性名稱。

上述選取器字串表示的元件 moniker 符合 bootstrap/fshost 字串,且其檢查樹狀結構包含 root/data_stat/stats 路徑。同時也表示該元件「檢查樹狀結構」中 root 節點的 stats 子節點中的 used_bytes 屬性。

將上方的選取器放入規則.triage 檔案的「select」部分。

產生選取器

手動輸入選取器很容易出錯,因此可以使用 fx triage --select 輸出有效的選取器。

fx triage --data snapshot --select total_bytes
INSPECT:bootstrap/fshost:root/data_stats/stats:total_bytes

可使用多個 --select 參數。程式會產生快照診斷資料的所有可能選取器,然後透過所有 --select 參數篩選 (grep)。

新增計算

inspect.json 檔案中選擇值後,您需要執行一些邏輯,並可能會進行一些算術,確認這些值是否代表值得標記的條件。

複製以下一行內容並新增至 rules.triage 檔案的 eval 區段,以便計算磁碟已滿:

eval: {
    ....
    disk_percentage: "disk_used / disk_total",
}

eval 項目使用一般的中置數學運算式。詳情請參閱「詳細資料」一節。

新增動作

在設定檔的「act」部分中,新增動作,以便在磁碟已滿 98% 時顯示警告。使用下列程式碼:

act: {
    ...
    disk_full: {
        type: "Warning",
        trigger: "disk_percentage > 0.98",
        print: "Disk reached 98% full",
    },
}

請注意:

  • 「觸發條件」是評估為布林值的運算式。這可能是布林類型選取器或運算的名稱,或任何適當的數學運算式。
  • 如要進一步瞭解比較方式,請參閱「詳細資料」一節。
  • 如要瞭解其他支援的動作,請參閱設定參考資料

新增度量

act: {
    ...
    disk_display: {
        type: "Gauge",
        value: "disk_percentage",
        format: "percentage",
    }
}

標準一律會顯示提供的值。

format 為選用欄位。「percentage」值會告訴輸出格式化工具預期 0 到 1 之間的值,並以百分比顯示。

實際演練

下列指令將對本機設定檔執行 Triage。

fx triage --config . --data snapshot

您會收到類似以下的錯誤訊息:

[ERROR] In config 'rules': No value found matching selector
bootstrap/fshost:root/data_stat/stats:used_bytes

選取器規則中有錯字。分類找不到評估規則所需的值。事實上,正確的選取器是「data_stats」而不是「data_stat」。 請在選取器規則中修正錯誤,然後再試一次。

fx triage --config . --data snapshot

怎麼了?沒有,對吧?我們該如何得知 inspect.json 檔案中是否沒有任何問題,還是規則中的錯誤呢?

測試規則

您可以為動作新增測試。建議您為每項測試指定值,以及這些值是否會觸發規則。

如要測試新增的規則,請將以下內容新增至 rules.triage 檔案的 test 區段中:

test: {
    ....
    is_full: {
        yes: ["disk_full"],
        values: {
            disk_used: 98,
            disk_total: 100,
        }
    }
}

values 區段中的鍵應為 evalselect 項目的名稱。提供的值會覆寫項目所選或計算的值。

您也可以測試不應觸發動作的條件:

test: {
    ....
    not_full: {
        no: ["disk_full"],
        values: {
            disk_used: 97,
            disk_total: 100,
        }
    }
}

如要執行測試,只要執行 Triage 即可。它會在每次執行時自動自我測試。

fx triage --config . --data snapshot

哎呀!這表示應該出現錯誤:

Test is_full failed: trigger 'disk_percentage > 0.98' of action disk_full returned Bool(false), expected true

修正規則

您希望在磁碟已滿 98% 以上時觸發,但這與您的寫入內容不符,且測試發現問題。將動作中的 > 修改為 >=

        trigger: "disk_percentage >= 0.98",

再次執行 Triage。錯誤應該會消失,並改為顯示 inspect.json 檔案實際上代表磁碟已滿的警告訊息。

Warning: 'disk_full' in 'rules' detected 'Disk is 98% full': 'disk98' was true

記錄檔掃描

您可以編寫運算式,測試記錄檔中的一行 (syslog.txt、klog.txt、Bootlog.txt) 是否與規則運算式相符。看起來會像這樣:

    eval: {
        syslog_has_not_found: "SyslogHas('ERROR.*not found')",
        ...
    }
    act: {
        something_not_found: {
            trigger: "SyslogHas('ERROR.*not found')",
            ...
        }
    }

這些函式可分為 SyslogHas()、KlogHas()、BootlogHas()。如果缺少記錄檔 (例如,某些快照不含 bootlog.txt),系統會將其視為空白檔案的處理方式。

如要測試這一點,您可以在測試中加入如下所示的項目:

test: {
    test_error: {
        yes: [error_scan],
        syslog: "ERROR: file Foo not found\nSecond line OK",
    }
}

註解.json

快照內含檔案 annotations.json,其中包含建構、主面板、運作時間等相關資訊。

您可以使用函式 Annotation() 搭配單一字串參數 (這是檔案中的 JSON 物件索引鍵),從這個檔案中擷取值。例如:

eval: {
    using_chromebook: "Annotation('build.board') == 'chromebook-x64'",
}

使用多個設定檔

您可以新增任意數量的 Triage 設定檔,甚至使用某個檔案中定義的變數。這類應用程式有許多:

  • 一個檔案用於儲存磁碟相關變數和動作,另一個檔案用於相關網路相關變數和動作。
  • 用於定義產品專屬編號的檔案。
  • 為特定工程師或團隊分別建立檔案。

新增包含以下內容的「product.triage」檔案:

{
    eval: {
        max_components: "4",
    },
}

請注意:

  • .triage 檔案中可能會省略空白區段。這個檔案不含任何 selectacttest 項目。
  • 雖然 JSON 中的數值沒有加上引號,但 4 是數學運算式字串,因此必須加上引號。

將下列項目新增至 rules.triage 檔案:

select: {
    ...
    actual_components: "INSPECT:bootstrap/archivist:root/event_stats:components_started",
}

這樣就能擷取裝置上正在使用的元件數量。

eval: {
    ...
    too_many_components: "actual_components > product::max_components",

這樣會比較實際元件與產品的理論最高值。

最後,新增動作:

act: {
    ...
    component_overflow: {
        type: "Warning",
        trigger: "too_many_components",
        print: "Too many components!",
    },
}

很抱歉,這部裝置嘗試使用過多元件,因此在執行「fx triage」時觸發這項警告。

在實際工作環境中,您可以將數個「product.triage」檔案保存在不同的目錄中,也可以引導 Triage 透過「--config」指令列引數使用其中一個檔案。

測試與命名空間

測試只會使用測試所在檔案中的指標,以及測試所提供的值。如果運算式 (評估觸發條件或測試觸發條件) 使用「a::b」等命名空間值,這些值必須由測試值中的「a::b」項目提供。

test: {
    component_max_ok: {
        no: [
            "component_overflow",
        ],
        values: {
            actual_components: 17,
            "product::max_components": 17,
        },
    },
},

詳細說明

名稱

名稱 (選取器、運算式、動作和測試以及設定檔的基礎名稱) 可以是任何字母或底線,後接任意數量的字母、數字或底線。

以底線開頭的名稱在日後的行程版本中可能會具有特殊意義。這類影片未禁止使用,但最好避免使用。

每個 .triage 檔案的名稱會建立其命名空間。系統不允許從不同目錄載入兩個名稱相同的 .triage 檔案。

數學運算式

  • 變數可以是 64 位元浮點、帶正負號 64 位元 int 或布林值。
  • 算術運算式會使用 + - * / // 運算子,其具備一般順序和作業優先順序。
  • 除法運算子 / 會產生浮點值。
  • 除法運算子 // 會產生 int 值,將結果截斷至 0,即使有浮點引數也一樣。(請注意,這與 Python 3 不同,其中 // 會向下截斷。)
  • + - * 會保留其運算元的類型 (混合升級為浮點值)。
  • 比較運算子為 > >= < <= == !=
  • 比較項目包含布林值結果類型,可用來觸發動作。
  • 您可以在單一 eval 規則中合併計算和比較項目。
  • 您可以使用括號。
  • 您可以使用 evalselect 項目的鍵名做為變數。
  • 在所有位置均可選用空格,但除了 filename::variable 命名空間變數之外,其餘所有位置均可使用空格。

預先定義的函式

Triage 提供預先定義的函式,可用於 eval 運算式:

  • Max(value1, value2, value3...) 會傳回最大值,並將類型促銷設為浮點值。
  • Min(value1, value2, value3...) 會傳回最小值,並將類型促銷設為浮點值。
  • And(value1, value2, value3...) 會使用布林引數,並傳回值的邏輯 AND。
  • Or(value1, value2, value3...) 會使用布林引數,並傳回值的邏輯 OR。
  • Not(value) 會使用一個布林引數,並傳回其邏輯 NOT。
  • 如果對應的記錄檔有行比對器,也就是包含規則運算式運算式的字串,則 SyslogHas(matcher)KlogHas(matcher)BootlogHas(matcher) 會傳回 true。
  • Annotation(key) 會傳回 annotation.json 檔案中的對應值。
  • Option(value1, value2, value3...) 會傳回第一個實用的值,以便支援選取器遷移作業和預設值:第一個非空白清單、非遺漏值 (如有);或者提供空白清單 (如有)。
  • 如果值是錯誤指示,Missing(value) 會傳回 true。
  • Days()Hours()Minutes()Seconds()Millis()Micros()Nanos() 會計算值以與單調時間戳記進行比較。
  • Now() 會傳回診斷資料建立時的約略時間戳記。
  • StringMatches(value, regex) 會將特定規則運算式套用至指定值,如有相符項目,則傳回 true。規則運算式語法受 Rust 規則運算式 Crate 支援。

功能程式設計

分類可對值向量套用函式。向量的格式是 "[expr, expr, expr...]"。部分選取器會傳回多元素向量。

Triage 提供 Map()Fold()Filter()Count() 函式來處理向量,Fn() 用於定義要套用地圖、折疊和套用篩選條件的函式或 lambda,而 Apply() 可將 Fn() 套用至引數。

詳情請參閱設定 fx 分類

其他資訊

如需最新功能和選項,請參閱 fx triage;分類功能會不斷改善!