github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/helpers/fluentbit/crio.lua (about) 1 _G.JSON = { 2 escape = "\\", 3 comma = ",", 4 colon = ":", 5 null = "null", 6 quotes = '"', 7 left_brace = '{', 8 right_brace = '}', 9 left_square_bracket = '[', 10 right_square_bracket = ']' 11 } 12 JSON._trim = function(target) return target and string.gsub(target, "^%s*(.-)%s*$", "%1") end 13 -- parse json key or value from stringify json 14 -- @return string(metadata),string(rest string) 15 JSON._parse = function(str) 16 local chStack, index, lastCh = {}, 1 17 while index <= #str do 18 local ch = string.sub(str, index, index) 19 if JSON.quotes == ch then 20 if ch == lastCh then 21 table.remove(chStack, #chStack) 22 lastCh = #chStack > 0 and chStack[#chStack] or nil 23 else 24 lastCh = ch 25 table.insert(chStack, lastCh) 26 end 27 elseif JSON.escape == ch then 28 str = string.sub(str, 1, index - 1) .. string.sub(str, index + 1) 29 end 30 if JSON.quotes ~= lastCh then 31 if JSON.left_brace == ch then 32 table.insert(chStack, JSON.right_brace) 33 lastCh = ch 34 elseif JSON.left_square_bracket == ch then 35 table.insert(chStack, JSON.right_square_bracket) 36 lastCh = ch 37 elseif JSON.right_brace == ch or JSON.right_square_bracket == ch then 38 assert(lastCh == ch, str .. " : " .. index .. " unexpected " .. ch .. "<->" .. lastCh) 39 table.remove(chStack, #chStack) 40 lastCh = #chStack > 0 and chStack[#chStack] or nil 41 elseif JSON.comma == ch or JSON.colon == ch then 42 if not lastCh then return string.sub(str, 1, index - 1), string.sub(str, index + 1) end 43 end 44 end 45 index = index + 1 46 end 47 return string.sub(str, 1, index - 1), string.sub(str, index + 1) 48 end 49 -- stringify json to lua table 50 JSON.toJSON = function(str) 51 str = JSON._trim(str) 52 -- handle string 53 -- return plain string, not stringify json 54 if JSON.quotes == string.sub(str, 1, 1) and JSON.quotes == string.sub(str, -1, -1) then 55 return string.sub( 56 JSON._parse(str), 2, -2) 57 end 58 if 4 == #str then 59 -- handle boolean and nil 60 local lower = string.lower(str) 61 if "true" == lower then 62 return true 63 elseif "false" == lower then 64 return false 65 elseif JSON.null == lower then 66 return nil 67 end 68 end 69 -- handle number 70 local n = tonumber(str) 71 if n then return n end 72 -- handle array 73 if JSON.left_square_bracket == string.sub(str, 1, 1) and JSON.right_square_bracket == string.sub(str, -1, -1) then 74 local rest = string.gsub(str, "[\r\n]+", "") 75 rest = string.sub(rest, 2, -2) 76 local arr, index, val = {}, 1 77 while #rest > 0 do 78 val, rest = JSON._parse(rest) 79 if val then 80 val = JSON.toJSON(val) 81 arr[index] = val 82 index = index + 1 83 end 84 end 85 return arr 86 end 87 -- handle table 88 if JSON.left_brace == string.sub(str, 1, 1) and JSON.right_brace == string.sub(str, -1, -1) then 89 local rest = string.gsub(str, "[\r\n]+", "") 90 rest = string.sub(rest, 2, -2) 91 local key, val 92 local tbl = {} 93 while #rest > 0 do 94 key, rest = JSON._parse(rest) 95 val, rest = JSON._parse(rest) 96 if key and #key > 0 and val then 97 key = JSON.toJSON(key) 98 val = JSON.toJSON(val) 99 if key and val then tbl[key] = val end 100 end 101 end 102 return tbl 103 end 104 -- parse error 105 return nil 106 end 107 -- https://docs.fluentbit.io/manual/pipeline/filters/lua 108 -- Maybe you have to update the following function to match your real log format. 109 -- Log example: 110 -- 2023-03-31T15:35:48.917244985+00:00 stdout F {"level":"INFO","timestamp":"2023-03-31T15:35:48.917Z","caller":"logger/console.go:138","message":"ignored proxy module [auth]","service":"auth","request-trace-id":"__internal__","pod-info":{"ip":"10.128.2.66","uid":"368a8103-2c54-4e3b-8b37-627aa06544a9","name":"omc-auth-ss-0","namespace":"xxx","node":"worker3.dev","node-ip":"172.29.13.164","software":{"build-date":"2023-03-28 07:11:01","app-version":"1.0.0-dev","dev-kit-version":"go1.20.2","git-commit":"8bd57509da035bc4e19fab5e2fe9a2d960373de4","mode":"dev/linux/amd64"}}} 111 -- fluentbit log match and extract regexpr: 112 -- ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<log>.*)$ 113 function nest_to_json(tag, timestamp, record) 114 local str_json = record["log"] 115 local json = JSON.toJSON(str_json) 116 if not json then 117 return 0, timestamp, record 118 end 119 local tbl = {} 120 for k, v in pairs(json) do 121 if k and "pod-info" == k and "table" == type(v) then 122 for k1, v1 in pairs(v) do 123 tbl[k1] = v1 124 end 125 elseif k and "timestamp" == k or "@timestamp" == k then 126 tbl["app@ts"] = v 127 else 128 tbl[k] = v 129 end 130 end 131 -- crio log flag 132 tbl["stream"] = record["stream"] 133 return 2, timestamp, tbl 134 end