事件)
Vector Lua Transform 完全指南使用 Lua 5.4 編程式處理日志與指標(biāo)事件【免費下載鏈接】vectorA high-performance observability data pipeline.項目地址: https://gitcode.com/GitHub_Trending/vect/vector本指南以 Vector 官方的luatransform 組件文檔為核心系統(tǒng)講解如何用嵌入式 Lua 5.4 引擎對日志log與指標(biāo)metric事件進(jìn)行編程式處理。你將掌握version、hooks、source、search_dirs、timers、metric_tag_values全部配置項的含義與用法理解 Vector 數(shù)據(jù)模型到 Lua 數(shù)據(jù)類型的映射規(guī)則并通過 6 個官方示例和源碼級原理剖析獲得可直接投入生產(chǎn)管道pipeline的完整實戰(zhàn)能力。Lua Transform 是什么luatransform 是 Vector 內(nèi)置的一個通用數(shù)據(jù)處理組件它內(nèi)嵌一個完整的 Lua 5.4 運行時允許你直接用 Lua 腳本改寫流過管道的每一個事件。與專注于聲明式轉(zhuǎn)換的remaptransform 相比luatransform 提供的是近乎無限自由度的編程能力凡是remap表達(dá)式語言覆蓋不到的邊角場景復(fù)雜字符串解析、外部 Lua 庫調(diào)用、周期性聚合、按需構(gòu)造新事件等都可以用 Lua 腳本來實現(xiàn)。根據(jù)官方組件元數(shù)據(jù)website/cue/reference/components/transforms/lua.cue開發(fā)狀態(tài)stable穩(wěn)定輸出方式stream流式逐事件處理是否有狀態(tài)true腳本中可以持有跨事件的全局狀態(tài)配合定時器可實現(xiàn)聚合統(tǒng)計。在輸入輸出類型上luatransform 同時接受日志與全部類型的指標(biāo)counter、distribution、gauge、histogram、set、summary但不支持 trace 事件源碼 lib/vector-core/src/event/lua/event.rs 中會明確報錯Trace are not supported。官方性能警告優(yōu)先使用 remap官方文檔在support.warnings中給出了明確的性能指引luatransform 比remaptransform 慢約 60%只要情況允許強(qiáng)烈建議優(yōu)先使用remap。luatransform 僅用于remap無法覆蓋的邊界場景不應(yīng)作為默認(rèn)首選。若remap無法滿足你的用例請?zhí)峤?issue 反饋。因此在架構(gòu)選型時請遵循先remap后lua的原則能用 VRLVector Remap Language表達(dá)的邏輯盡量用remap組件完成只有確實需要通用編程能力時才引入lua??焖偕鲜肿钚】蛇\行配置luatransform 采用版本化配置version字段當(dāng)前推薦使用 API 版本2。最小配置只需提供一個process鉤子。以下配置為每個事件添加一個processed_by字段并輸出transforms: my_lua_transform: type: lua inputs: - my_source version: 2 hooks: process: | function (event, emit) event.log.processed_by lua emit(event) end要點version: 2是必填項官方通過generate_config生成的默認(rèn)骨架即為version: 2加空的hooks.process見 src/transforms/lua/mod.rshooks.process是必填鉤子接收(event, emit)兩個參數(shù)event是待處理事件emit是用于向外輸出事件的回調(diào)函數(shù)事件被修改后必須調(diào)用emit(event)否則該事件會被丟棄。配置參數(shù)完整參考luatransform 的全部配置項定義在 website/cue/reference/components/transforms/generated/lua.cue 與 Rust 結(jié)構(gòu)體 src/transforms/lua/v2/mod.rs 中匯總?cè)缦聟?shù)類型必填默認(rèn)值說明versionstring1/2是無Transform API 版本。1已棄用且將在未來版本移除應(yīng)使用2hooks.processstringLua 源碼或函數(shù)名是無每個事件進(jìn)入時調(diào)用的鉤子簽名function (event, emit)hooks.initstringLua 源碼或函數(shù)名否無首個事件到來時、process之前調(diào)用一次簽名function (emit)hooks.shutdownstringLua 源碼或函數(shù)名否無transform 停止時調(diào)用一次簽名function (emit)sourcestringLua 源碼否無初始化腳本可 import 外部依賴、定義鉤子函數(shù)等search_dirsarraystring否[]require加載 Lua 模塊時的搜索目錄未設(shè)置時使用配置文件所在目錄timersarrayobject否[]周期性執(zhí)行的定時器列表每個包含interval_seconds與handlermetric_tag_valuesstringsingle/full否single指標(biāo)標(biāo)簽值在 Lua 中的暴露形式versionAPI 版本選擇version字段保證了向后兼容性。兩個版本的行為差異明顯版本 1已棄用只支持日志事件配置項僅source與search_dirs整個腳本直接作為每個事件的處理器執(zhí)行見 src/transforms/lua/v1/mod.rs。構(gòu)建時會打印棄用警告DEPRECATED The lua transform API version 1 is deprecated. Please convert your script to version 2.版本 2推薦支持日志與指標(biāo)引入hooks生命周期機(jī)制與timers定時器配置使用#[serde(deny_unknown_fields)]嚴(yán)格校驗見 src/transforms/lua/v2/mod.rs。hooks生命周期鉤子hooks是 v2 的核心機(jī)制包含三個可選/必填的鉤子hooks.process必填對每個進(jìn)入的事件調(diào)用。它既可以寫內(nèi)聯(lián) Lua 閉包也可以寫source中定義的函數(shù)名。無論是閉包還是函數(shù)簽名都是function (event, emit)——event為正在處理的事件emit為事件輸出回調(diào)。官方默認(rèn)示例function (event, emit) event.log.field value -- 設(shè)置字段值 event.log.another_field nil -- 刪除字段 event.log.first, event.log.second nil, event.log.first -- 重命名字段 -- 非常重要發(fā)射處理后的事件。 emit(event) endhooks.init可選在首個事件到來時、process之前調(diào)用一次簽名function (emit)。可用于初始化全局狀態(tài)如計數(shù)器、連接池、加載配置等。測試用例lua_runs_init_hooksrc/transforms/lua/v2/mod.rs驗證了init鉤子可以通過emit在管道啟動階段就構(gòu)造并輸出新事件。hooks.shutdown可選transform 停止時調(diào)用一次簽名function (emit)。常用于沖刷殘留狀態(tài)——例如把尚未上報的計數(shù)最終輸出為指標(biāo)事件。source初始化腳本source用于注入一段啟動代碼典型用途是定義被hooks引用的具名函數(shù)通過require加載外部 Lua 模塊。官方示例給出了兩種典型寫法-- 寫法一定義鉤子與定時器所需的全部函數(shù) function init() count 0 end function process() count count 1 end function timer_handler(emit) emit(make_counter(counter)) counter 0 end function shutdown(emit) emit(make_counter(counter)) end function make_counter(value) return metric { name event_counter, kind incremental, timestamp os.date(!*t), counter { value value } } end-- 寫法二從外部文件加載含鉤子與定時器定義的模塊 require(custom_module)需要說明的是source并非必填——如果所有鉤子都以內(nèi)聯(lián)方式寫在hooks中就不需要source見 website/cue/reference/components/transforms/generated/lua.cue 的說明。search_dirs模塊搜索目錄search_dirs指定require加載 Lua 模塊時的絕對路徑搜索列表。如果未設(shè)置則默認(rèn)使用配置文件所在的目錄。這一默認(rèn)行為由源碼default_config_paths()實現(xiàn)它讀取全局的CONFIG_PATHS對文件型配置取其所在目錄、對目錄型配置直接使用該目錄見 src/transforms/lua/v2/mod.rs。構(gòu)建時每個目錄會被格式化為{dir}/?.lua追加到 Lua 的package.path中并保留原有路徑見 src/transforms/lua/v2/mod.rs。示例search_dirs: - /etc/vector/lua隨后即可在腳本中require(custom_module)。測試用例lua_load_filesrc/transforms/lua/v2/mod.rs演示了從search_dirs指定目錄加載script2.lua模塊并調(diào)用其導(dǎo)出函數(shù)的完整鏈路。timers定時器timers允許配置一個或多個周期性任務(wù)每個定時器包含兩個必填字段字段類型必填說明interval_secondsuint是執(zhí)行間隔秒文檔示例值為2handlerstring是定時器觸發(fā)時調(diào)用的函數(shù)名或內(nèi)聯(lián)閉包簽名function (emit)timers: - interval_seconds: 5 handler: timer_handler定時器在源碼中通過RuntimeTransform::timer_handler驅(qū)動每個定時器持有一個唯一的數(shù)值 IDhandler 以RegistryKey形式注冊在 Lua 虛擬機(jī)中見 src/transforms/lua/v2/mod.rs。定時器 handler 可以借助emit周期性輸出新事件——這是實現(xiàn)每 N 秒上報一次聚合指標(biāo)的官方推薦路徑。metric_tag_values指標(biāo)標(biāo)簽的暴露形式Vector 的指標(biāo)標(biāo)簽可能對應(yīng)多個值多值標(biāo)簽或空值。該配置控制 Lua 腳本中event.metric.tags的形態(tài)single默認(rèn)標(biāo)簽值以單個字符串暴露與舊版本行為一致。多值標(biāo)簽只顯示最后一個賦值空值被忽略full所有標(biāo)簽以字符串或 null 組成的數(shù)組形式暴露可完整看到每一個值。源碼中該配置映射為MetricTagMode::Single / Full兩種模式見 src/transforms/lua/v2/mod.rs并在事件轉(zhuǎn)換為 Lua 值時生效見 lib/vector-core/src/event/lua/metric.rs。注意metric_tag_values取值非法如auto會在配置解析階段直接被拒絕對應(yīng)測試rejects_auto_metric_tag_valuessrc/transforms/lua/mod.rs。事件數(shù)據(jù)模型事件在 Lua 中長什么樣官方文檔明確process鉤子的第一個參數(shù)event在 Lua 中表現(xiàn)為一個table其結(jié)構(gòu)與 Vector 的數(shù)據(jù)模型完全一致。以 lib/vector-core/src/event/lua/event.rs 的實現(xiàn)為準(zhǔn)日志事件事件表頂層含log鍵其值為日志字段表指標(biāo)事件事件表頂層含metric鍵其值為指標(biāo)表包含name、namespace、timestamp、interval_ms、tags、kind以及按類型區(qū)分的counter/gauge/set/distribution/aggregated_histogram/aggregated_summary/sketch等子表trace 事件不支持轉(zhuǎn)換時報錯。Vector 類型與 Lua 類型映射表官方文檔給出了完整的類型映射關(guān)系這是編寫腳本時必須遵守的契約Vector 類型Lua 類型說明Stringstring—Integerinteger—Floatnumber—Booleanboolean—TimestamptableLua 沒有專用時間戳類型按os.date/os.time的約定用表表示Null空字符串Lua 中把字段設(shè)為nil表示刪除#長度運算符對含 null 的序列行為不符合預(yù)期因此 Null 編碼為空字符串Maptable—Arraysequence序列是表的特例索引從 1 開始Lua 慣例時間戳的特殊約定時間戳在 Lua 中是一個包含以下字段的表{ year, month, day, hour, min, sec, nanosec, yday, wday, isdst }從 Lua 回傳 Vector 時yday、wday、isdst三個字段可以省略相比標(biāo)準(zhǔn)os.time表示Vector 額外支持通過nanosec字段表達(dá)亞秒精度。源碼 lib/vector-core/src/event/lua/util.rs 驗證了這一約定timestamp_to_table會把DateTimeUtc完整寫出全部 9 個字段反向的table_to_timestamp讀取year/month/day/hour/min/sec并以nanosec缺省為 0補(bǔ)齊納秒。Null 值的編碼細(xì)節(jié)映射表中Null → 空字符串是一條容易踩坑的規(guī)則在 Lua 中向表的字段寫入nil意味著刪除該字段同時#運算符無法正確處理含空值的序列。因此 Vector 用空字符串表示語義上的 Null 值避免與 Lua 的nil刪除語義沖突。測試lua_non_coercible_valuesrc/transforms/lua/v2/mod.rs驗證了向字段寫入nil后該字段確實被刪除。官方實戰(zhàn)示例全解析組件文檔共提供了 6 個官方示例覆蓋日志與指標(biāo)事件最常見的操作模式。以下逐一給出完整配置、輸入輸出與要點分析。示例 1添加、重命名、刪除日志字段version: 2 hooks: process: | function (event, emit) -- 添加根級字段 event.log.field new value -- 添加嵌套字段 event.log.nested {} event.log.nested.field nested value -- 重命名字段 event.log.renamed_field event.log.field_to_rename event.log.field_to_rename nil -- 刪除字段 event.log.field_to_remove nil emit(event) end輸入事件field_to_rename: old value field_to_remove: remove me輸出事件field: new value nested: field: nested value renamed_field: old value要點字段的增刪改通過簡單的表賦值/置nil完成event.log直接對應(yīng)日志的頂層字段空間重命名的慣用法是新字段 舊字段舊字段 nil。對應(yīng)的單元測試有l(wèi)ua_add_field、lua_read_field、lua_remove_fieldsrc/transforms/lua/v2/mod.rs。示例 2添加、重命名、刪除指標(biāo)標(biāo)簽version: 2 hooks: process: | function (event, emit) -- 添加標(biāo)簽 event.metric.tags.tag new value -- 重命名標(biāo)簽 event.metric.tags.renamed_tag event.log.tag_to_rename event.metric.tags.tag_to_rename nil -- 刪除標(biāo)簽 event.metric.tags.tag_to_remove nil emit(event) end輸入指標(biāo)一個logins增量計數(shù)器kind: incremental name: logins counter: value: 2.0 tags: tag_to_rename: old value tag_to_remove: remove me輸出指標(biāo)kind: incremental name: logins counter: value: 2.0 tags: tag: new value renamed_tag: old value要點指標(biāo)事件通過event.metric訪問kind字段取incremental或absolute指標(biāo)值位于按類型命名的子表如counter.value中。多值標(biāo)簽的讀寫形態(tài)由metric_tag_values控制見上文。示例 3完全丟棄一個事件version: 2 hooks: process: | function (event, emit) -- 不調(diào)用 emit 函數(shù)即可徹底丟棄事件 end輸入任何事件輸出為空null。要點不調(diào)用emit(event)即丟棄事件這是實現(xiàn)過濾語義的最直接方式。測試lua_drop_eventsrc/transforms/lua/v2/mod.rs專門驗證了輸出流為空的行為。示例 4遍歷日志字段version: 2 hooks: process: | function (event, emit) -- 刪除所有值為 - 的字段 for f, v in pairs(event) do if v - then event[f] nil end end emit(event) end輸入value_to_remove: - value_to_keep: keep輸出value_to_keep: keep要點日志事件表可直接用pairs()遍歷逐字段過濾清洗。測試lua_pairssrc/transforms/lua/v2/mod.rs展示了for k,v in pairs(event.log)的完整遍歷改寫模式。示例 5解析時間戳source 具名函數(shù)version: 2 hooks: process: process source: | timestamp_pattern (%d%d%d%d)-- (%d%d):(%d%d):(%d%d).?(%d*) function parse_timestamp(str) local year, month, day, hour, min, sec, millis string.match(str, timestamp_pattern) local ms 0 if millis and millis ~ then ms tonumber(millis) end return { year tonumber(year), month tonumber(month), day tonumber(day), hour tonumber(hour), min tonumber(min), sec tonumber(sec), nanosec ms * 1000000 } end function process(event, emit) event.log.timestamp parse_timestamp(event.log.timestamp_string) emit(event) end輸入timestamp_string: 2020-04-07 06:26:02.643輸出timestamp_string: 2020-04-07 06:26:02.643 timestamp: 2020-04-07 06:26:02.643要點這是hooks.process引用source中具名函數(shù)的標(biāo)準(zhǔn)用法。parse_timestamp返回的表嚴(yán)格遵循上文的時間戳約定含nanosec字段Vector 會將其正確轉(zhuǎn)換為內(nèi)部時間戳類型。示例 6統(tǒng)計日志數(shù)量init timers shutdown 組合這是最能體現(xiàn) v2 生命周期機(jī)制的示例用全局計數(shù)統(tǒng)計處理過的日志數(shù)每 5 秒把累計數(shù)作為指標(biāo)事件輸出一次并在關(guān)閉時沖刷剩余計數(shù)。version: 2 hooks: init: init process: process shutdown: shutdown timers: - interval_seconds: 5 handler: timer_handler source: | function init() count 0 end function process() count count 1 end function timer_handler(emit) emit(make_counter(count)) count 0 end function shutdown(emit) emit(make_counter(count)) end function make_counter(value) return metric { name event_counter, kind incremental, timestamp os.date(!*t), counter { value value } } end輸入任意日志事件示例輸入為{}。輸出名為event_counter、kindincremental的計數(shù)指標(biāo)示例輸出counter.value為1.0。要點init在首個事件前初始化全局變量countprocess每處理一個事件即自增計數(shù)且不需要調(diào)用emit該鉤子只做計數(shù)不轉(zhuǎn)發(fā)原始日志timer_handler每 5 秒構(gòu)造一個event_counter增量計數(shù)指標(biāo)并通過emit輸出隨后清零shutdown在停止時把剩余計數(shù)最后一次沖刷出去保證數(shù)據(jù)不丟失make_counter展示了在 Lua 中從零構(gòu)造指標(biāo)事件的完整寫法name、kind、timestamp、counter.value均為必填語義字段timestamp使用os.date(!*t)生成符合約定的時間戳表。源碼實現(xiàn)原理深入 Lua 運行時嵌入式 Lua 5.4 引擎與安全標(biāo)準(zhǔn)庫transform 通過mluacrate 創(chuàng)建 Lua 5.4 虛擬機(jī)并以StdLib::ALL_SAFE加載安全標(biāo)準(zhǔn)庫集合不包含調(diào)試庫等潛在危險模塊以支持加載 C 模塊見 src/transforms/lua/v2/mod.rs。所有鉤子init/process/shutdown與定時器 handler 都會被編譯為mlua::Function并注冊為RegistryKey保證在整個生命周期內(nèi)可被反復(fù)調(diào)用src/transforms/lua/v2/mod.rs。自動垃圾回收GC控制Lua 的垃圾回收在高事件速率下可能不會自動及時觸發(fā)導(dǎo)致類似內(nèi)存泄漏的 RAM 增長模式。為此源碼實現(xiàn)了每 16 次調(diào)用強(qiáng)制 GC 一次的機(jī)制GC_INTERVAL: usize 16見 src/transforms/lua/v2/mod.rs。該間隔大于 1是因為 GC 本身開銷較大不宜在每次處理后執(zhí)行。每次 GC 都會通過內(nèi)部事件LuaGcTriggered上報當(dāng)前used_memorysrc/internal_events/lua.rs。事件的雙向轉(zhuǎn)換Vector → Lua日志事件經(jīng) lib/vector-core/src/event/lua/log.rs 轉(zhuǎn)換為字段表指標(biāo)事件經(jīng) lib/vector-core/src/event/lua/metric.rs 轉(zhuǎn)換為包含name、namespace、timestamp、interval_ms、tags、kind及類型子表的結(jié)構(gòu)化表Lua → Vector事件表必須且只能包含頂層log或metric鍵之一否則報Event should contain either log or metric key at the top level轉(zhuǎn)換錯誤lib/vector-core/src/event/lua/event.rs。由于 Lua 腳本可任意改寫事件Vector 無法靜態(tài)推導(dǎo)輸出 schema——源碼中outputs()會重置輸出類型定義Definition::default_for_namespace即下游組件不再假定任何字段結(jié)構(gòu)src/transforms/lua/v2/mod.rs。錯誤處理與可觀測性運行時錯誤通過內(nèi)部事件體系上報主要包含三類src/internal_events/lua.rsLuaScriptError腳本運行時報錯如error(this is an error)對應(yīng)component_errors_total計數(shù)與ComponentEventsDropped事件錯誤碼如syntax_error、runtime_error、callback_error等LuaBuildError配置/源碼構(gòu)建期錯誤錯誤碼細(xì)分到invalid_hook_init、invalid_hook_process、invalid_timer_handler、runtime_error_gc等 13 種LuaGcTriggered將 GC 觸發(fā)時的used_memory寫入 gauge 指標(biāo)lua_memory_used_bytes。因此你可以在internal_metrics源中訂閱lua_memory_used_bytes指標(biāo)組件遙測定義見 website/cue/reference/components/transforms/lua.cue監(jiān)控 Lua 運行時內(nèi)存水位。學(xué)習(xí)資源建議官方文檔專門為 Lua 新手預(yù)留了指引編寫有實質(zhì)業(yè)務(wù)邏輯的 transform 需要具備 Lua 基礎(chǔ)。由于 Lua 本身簡單易學(xué)閱讀官方書籍《Programming in Lua》的前幾章或查閱 Lua 參考手冊即可滿足絕大多數(shù)場景。官方文檔原文website/cue/reference/components/transforms/lua.cue亦明確指出在動手編寫復(fù)雜腳本前先掌握 Lua 的表table、函數(shù)、pairs/ipairs迭代與string庫等核心概念。最佳實踐小結(jié)優(yōu)先remap約 60% 的性能差距意味著能不用 Lua 就不用僅當(dāng)remap無法表達(dá)時才選用lua始終使用version: 2v1 已棄用并將被移除且不支持指標(biāo)事件與鉤子/定時器機(jī)制利用source組織代碼把可復(fù)用的具名函數(shù)、外部require模塊放入sourcehooks中只寫函數(shù)名引用便于閱讀與復(fù)用嚴(yán)格遵守類型映射時間戳用含nanosec的約定表、Null 用空字符串、數(shù)組索引從 1 開始不要遺漏emit需要向下游傳遞事件時務(wù)必調(diào)用emit(event)emit可多次調(diào)用以實現(xiàn)事件復(fù)制測試lua_duplicate_event驗證了單事件雙發(fā)射的合法性見 src/transforms/lua/v2/mod.rs用定時器做周期性聚合全局狀態(tài) timersshutdown沖刷是統(tǒng)計類 transform 的標(biāo)準(zhǔn)實現(xiàn)模式關(guān)注lua_memory_used_bytes通過 internal_metrics 觀測 Lua 內(nèi)存配合內(nèi)置的自動 GC 機(jī)制保障長期運行的穩(wěn)定性。【免費下載鏈接】vectorA high-performance observability data pipeline.項目地址: https://gitcode.com/GitHub_Trending/vect/vector創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考