Private
Public Access
1
0
Files
lua-prometheus-exporter/send-utils.lua

95 lines
3.2 KiB
Lua

local function SendUDP(content)
if content then
helpers.send_udp(options.udpPort, content, options.senderPlayerIndex)
else
error("Missing udpPort or Content")
end
end
---Chunks content into appropriately sized pieces, respecting header lines
---Chunks content greedily to minimize UDP calls
---Fills 200KB buffer as completely as possible, including multiple headers if they fit
---Only prepends header when chunk starts mid-section
---@return table chunks Array of {header=string|nil, content=string}---@param content string
---@param maxSizekB number|nil Default 200KB
local function ChunkContent(content, maxSizekB)
local maxSize = (maxSizekB or 200) * 1024
local len = #content
local chunks = {}
-- 1. Pre-compute headers (O(N))
local headers = {}
local hPos = 1
while true do
local hStart, hEnd, hText = content:find("%%-%-%-(.-)%%-%-%-\n", hPos)
if not hStart then break end
table.insert(headers, {startPos = hStart, text = "---" .. hText .. "---"})
hPos = hEnd + 1
end
local start = 1
local headerIdx = 1
local activeHeaderText = nil
while start <= len do
while headerIdx <= #headers and headers[headerIdx].startPos <= start do
activeHeaderText = headers[headerIdx].text
headerIdx = headerIdx + 1
end
local isAtHeaderStart = (headerIdx > 1 and headers[headerIdx-1].startPos == start)
local needsPrepend = (not isAtHeaderStart) and (activeHeaderText ~= nil)
local overhead = needsPrepend and (#activeHeaderText + 1) or 0
local availableSpace = maxSize - overhead
if availableSpace <= 0 then error("Header exceeds maxSize") end
local target = math.min(start + availableSpace - 1, len)
if target == len then
table.insert(chunks, {header = needsPrepend and activeHeaderText or nil, content = content:sub(start, len)})
break
end
-- Optimized C-level search for newline
local chunkView = content:sub(start, target)
local lastNewline = chunkView:match(".*()\n")
if not lastNewline then
error("Line too long at byte " .. start)
end
local splitPos = start + lastNewline - 1
table.insert(chunks, {header = needsPrepend and activeHeaderText or nil, content = content:sub(start, splitPos)})
start = splitPos + 1
end
return chunks
end
---Sends content in chunks with optional header
---If content starts with header (---<headerline>---), it's automatically repeated in each chunk
---@param content string
---@param maxSizekB number|nil Default 200KB
function SendChunked(content, maxSizekB)
if not content or #content == 0 then
error("Missing or empty content")
end
local maxSize = (maxSizekB or 200) * 1024
-- Content is smaller than maxSize, so send immediately
if #content <= maxSize then
SendUDP(content)
return
end
local chunks = ChunkContent(content, maxSizekB)
for _, chunk in ipairs(chunks) do
if chunk.header then
SendUDP(chunk.header .. "\n" .. chunk.content)
else
SendUDP(chunk.content)
end
end
end