require 'rack' require './postfix_exporter' require 'socket' class Settings def initialize environment @environment = environment.to_s.to_sym end attr_reader :environment alias :env :environment def development?() :development == environment end def production?() :production == environment end def test?() :test == environment end end settings = Settings.new ENV['RACK_ENV'] collector = Collector.new settings: settings collector.start showqpath = '/var/spool/postfix/public/showq' prometheus = collector.prometheus metrics = OpenStruct.new( queued: prometheus.gauge( :postfix_queued, docstring: "Queued mails per queue and sender/recipient", labels: %i[queue sender recipient]), ) def determine_domain str case str when /@([^.]+\.(?:(?:co|ac)\.)?[^.]+)\.?\z/ $1 when /\.([^.]+\.(?:(?:co|ac)\.)?[^.]+)\?.\z/ "any.#$1" when 'MAILER-DAEMON' 'MAILER-DAEMON' else 'any' end end run lambda {|env| req = Rack::Request.new env case req.path when "/metrics" showq = '' UNIXSocket.open showqpath do |s| while '' != (r = s.read) showq += r end end showq = showq.split( "\x00\x00").map do |x| y = x.split "\x00" y.push '' if y.length.odd? Hash[*y] end showq.group_by do |e| {queue: e['queue_name'], sender: determine_domain( e['sender']), recipient: determine_domain( e['recipient'])} end.each do |labels, entries| metrics.queued.set entries.length, labels: labels if labels and labels[:queue] end [200, {"Content-Type" => "text/plain"}, [Prometheus::Client::Formats::Text.marshal( prometheus)]] else [404, {"Content-Type" => "text/plain"}, ["Not found\nYou want to try /metrics?\n"]] end }