diff --git a/prometheus-exporter/control.lua b/prometheus-exporter/control.lua new file mode 100644 index 0000000..ca280e2 --- /dev/null +++ b/prometheus-exporter/control.lua @@ -0,0 +1,83 @@ +-- Config +local steps_per_tick = 1 -- process 1 surfaceƗforce per tick +local flush_interval_ticks = 60 * 15 -- flush every n ticks + +-- State +local queue = {} +local buffer = {} +local last_flush_tick = 0 + +-- Initialize queue with all surfaceƗforce pairs +local function prepare_queue() + queue = {} + for surface_name, _ in pairs(game.surfaces) do + for force_name, _ in pairs(game.forces) do + table.insert(queue, {surface_name = surface_name, force_name = force_name}) + end + end +end + +-- Process a few items from the queue each tick +local function process_queue() + for i = 1, steps_per_tick do + local entry = table.remove(queue, 1) + if not entry then break end + + local surface_name, force_name = entry.surface_name, entry.force_name + local force = game.forces[force_name] + + -- Items + local item_stats = force.get_item_production_statistics(surface_name) + for item, count in pairs(item_stats.input_counts) do + table.insert(buffer, string.format( + "production{type=\"item\",surface=\"%s\",force=\"%s\",name=\"%s\"} %d", + surface_name, force_name, item, count + )) + end + for item, count in pairs(item_stats.output_counts) do + table.insert(buffer, string.format( + "consumption{type=\"item\",surface=\"%s\",force=\"%s\",name=\"%s\"} %d", + surface_name, force_name, item, count + )) + end + + -- Fluids + local fluid_stats = force.get_fluid_production_statistics(surface_name) + for fluid, count in pairs(fluid_stats.input_counts) do + table.insert(buffer, string.format( + "production{type=\"fluid\",surface=\"%s\",force=\"%s\",name=\"%s\"} %d", + surface_name, force_name, fluid, count + )) + end + for fluid, count in pairs(fluid_stats.output_counts) do + table.insert(buffer, string.format( + "consumption{type=\"fluid\",surface=\"%s\",force=\"%s\",name=\"%s\"} %d", + surface_name, force_name, fluid, count + )) + end + end +end + +-- Flush buffer to file periodically +local function maybe_flush() + if #queue == 0 and game.tick - last_flush_tick >= flush_interval_ticks then + if #buffer > 0 then + helpers.write_file("metrics.prom", table.concat(buffer, "\n"), false) + buffer = {} + end + last_flush_tick = game.tick + prepare_queue() + end +end + +-- Main tick handler +script.on_event(defines.events.on_tick, function() + process_queue() + maybe_flush() +end) + +-- Bootstrap +script.on_init(function() + last_flush_tick = game.tick + prepare_queue() +end) diff --git a/prometheus-exporter/info.json b/prometheus-exporter/info.json new file mode 100644 index 0000000..fb5d20f --- /dev/null +++ b/prometheus-exporter/info.json @@ -0,0 +1,9 @@ +{ + "name": "prometheus-exporter", + "version": "0.0.1", + "title": "Prometheus Exporter for Factorio", + "author": "Bjorn Pijnacker", + "factorio_version": "2.0", + "dependencies": ["base >= 2.0"], + "description": "Exports certain production and consumption metrics to Prometheus format, to be used by Prometheus/Grafana monitoring stack" +} \ No newline at end of file