diff --git a/README.adoc b/README.adoc index 950d8aa..15ff147 100644 --- a/README.adoc +++ b/README.adoc @@ -4,6 +4,16 @@ postfix_exporter Collects continuesly events from postfix and dovecot via journald. Exports the collected event-counters and the currently count of queued messages. +queue_exporter +============== + +If you only want to check the count of mails in queue, use the `queue_exporter` in the subdirectory. +It has lesser dependencies and a smaller footprint: + +* No journald, no ffi, no puma +* ffi and puma need a compiler, which you do not need to install +* Instead of puma, use simple rackup, which provides a simpler webserver. + Usage ----- diff --git a/queue_exporter/Gemfile b/queue_exporter/Gemfile new file mode 100644 index 0000000..75f2ee1 --- /dev/null +++ b/queue_exporter/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem 'prometheus-client' +gem 'rack' diff --git a/queue_exporter/Gemfile.lock b/queue_exporter/Gemfile.lock new file mode 100644 index 0000000..99d073c --- /dev/null +++ b/queue_exporter/Gemfile.lock @@ -0,0 +1,15 @@ +GEM + remote: https://rubygems.org/ + specs: + prometheus-client (4.0.0) + rack (3.0.0) + +PLATFORMS + x86_64-linux + +DEPENDENCIES + prometheus-client + rack + +BUNDLED WITH + 2.3.9 diff --git a/queue_exporter/config.ru b/queue_exporter/config.ru new file mode 100644 index 0000000..1d390d0 --- /dev/null +++ b/queue_exporter/config.ru @@ -0,0 +1,48 @@ +require 'rack' +require 'socket' + +showqpath = '/var/spool/postfix/public/showq' +prometheus = Prometheus::Client.registry +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 +} diff --git a/queue_exporter/gemset.nix b/queue_exporter/gemset.nix new file mode 100644 index 0000000..ff4b29d --- /dev/null +++ b/queue_exporter/gemset.nix @@ -0,0 +1,22 @@ +{ + prometheus-client = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "11k1r8mfr0bnd574yy08wmpzbgq8yqw3shx7fn5f6hlmayacc4bh"; + type = "gem"; + }; + version = "4.0.0"; + }; + rack = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1772yq480iffns36zisgsnaxf6cr6r7m8v7y14cwlpaqbnzdnyhr"; + type = "gem"; + }; + version = "3.0.0"; + }; +} diff --git a/queue_exporter/queue_exporter.service.erb b/queue_exporter/queue_exporter.service.erb new file mode 100644 index 0000000..0cbb345 --- /dev/null +++ b/queue_exporter/queue_exporter.service.erb @@ -0,0 +1,16 @@ +<% require 'pathname'; path = Pathname.new( __FILE__).expand_path.dirname %> +[Unit] +Description=Postfix Queue exporter +Documentation=https://git.denkn.at/deac/postfix_exporter +After=network.target + +[Service] +Restart=always +User=postfix_exporter +WorkingDirectory=<%=path%> +ExecStart=<%=`which bundle`.chomp%> exec rackup --bind 'tcp://[::]:9124' --environment production --tag queue_exporter +ExecReload=/bin/kill -USR1 $MAINPID +KillMode=mixed + +[Install] +WantedBy=multi-user.target diff --git a/queue_exporter/shell.nix b/queue_exporter/shell.nix new file mode 100644 index 0000000..ffbf975 --- /dev/null +++ b/queue_exporter/shell.nix @@ -0,0 +1,21 @@ +with (import {}); +let + env = bundlerEnv { + name = "queue_exporter-bundler-env"; + inherit ruby; + gemfile = ./Gemfile; + lockfile = ./Gemfile.lock; + gemset = ./gemset.nix; + }; +in stdenv.mkDerivation { + name = "queue-exporter"; + buildInputs = [ pkgs.ruby env env.gems.rack ]; + #buildPhase = '' + # echo "Build queue_exporter + # mkdir -p "$out/lib" + # for f in ${pkgs.systemd}/lib/libsystemd* + # do + # ln -s "$f" "$out/lib/" + # done + #''; +}