tokuhirom
5/10/2016 - 1:13 AM

process_exporter for prometheus' textfile exporter

process_exporter for prometheus' textfile exporter

class ProcessExporter
        def initialize(filter=nil)
                unless filter.nil?
                        @filter = /#{filter}/
                end
        end

        def run
                Dir.glob("/proc/*/stat") do |file|
                        next unless File.file?(file)

                        stat = File.read(file).split(/ /)
                        cmdline = File.read(file.sub(/\/stat$/, '/cmdline'))
                        name = stat[1].sub(/^\(/, '').sub(/\)$/, '')

                        unless @filter.nil?
                                next unless cmdline =~ @filter || name =~ @filter
                        end

                        # http://man7.org/linux/man-pages/man5/proc.5.html
                        w = ProcessExporter::Writer.new(name, cmdline)
                        w.write('process_pid', stat[0], 'process id', 'counter')
                        w.write('process_ppid', stat[3], 'parentprocess id', 'counter')
                        w.write('process_utime', stat[13], 'Amount of time that this process has been scheduled in user mode, measured in clock ticks', 'counter')
                        w.write('process_stime', stat[13], 'Amount of time that this process has been scheduled in kernel mode, measured in clock ticks', 'counter')
                        w.write('process_nice', stat[18], 'The nice value', 'counter')
                        w.write('process_threads', stat[19], 'The number of threads', 'counter')
                        w.write('process_starttime', stat[21], 'The time the process started after system boot', 'counter')
                        w.write('process_vsize', stat[22], 'Virtual memory size in bytes', 'counter')
                        w.write('process_rss', stat[23], 'Resident Set Size: number of pages the process has in real memory', 'counter')
                end
        end

        class Writer
                def initialize(name, cmdline)
                        @name=name
                        @cmdline=cmdline
                end

                # label_value can be any sequence of UTF-8 characters, but the backslash, the double-quote, and the line-feed characters have to be escaped as \\, \", and \n
                def escape(s)
                        s.gsub(/\\/, '\\\\').gsub(/"/, '\\"').gsub(/\n/, "\\n")
                end

                def write(label, value, help, type)
                        puts "# HELP #{label} #{help}"
                        puts "# TYPE #{label}"
                        puts "#{label}{name=\"#{escape @name}\",cmdline=\"#{escape @cmdline}\"} #{escape value}"
                end
        end
end

# TODO: optparse
ProcessExporter.new(ARGV[0]).run