Permalink
Browse files

Initial commit. Spikey.

  • Loading branch information...
0 parents commit caa6aba52939e28341071188fa5d49c1b6c144bc Yehuda Katz committed Nov 29, 2009
@@ -0,0 +1,20 @@
+This is just a spike. Please do not use.
+
+This is mostly an experiment to see how low-memory I can make a simple process launcher/watcher.
+
+Goals:
+* No dependencies other than Ruby
+* Extremely low memory consumption
+* Simple DSL
+
+TODO:
+* Everything
+
+Current status:
+* Pros
+** Uses under 2MB of RAM on Ruby 1.8.7
+* Cons
+** Only supports watching single processes for life
+** No support for any other kinds of watches
+** In other words... this is not even alpha quality
+** So don't use it.
@@ -0,0 +1,14 @@
+$:.push "lib"
+require "prometheus"
+
+r = Prometheus::Reactor.new do
+ start_process "vm_stat 1" do
+ check running, :every => 1
+
+ check memory_usage, :below => 150.mb, :every => 5 do
+ must_pass 3, :of => 5
+ end
+ end
+end
+
+r.start
@@ -0,0 +1,47 @@
+require "prometheus/dsl"
+require "prometheus/checks"
+require "prometheus/core_ext"
+
+module Prometheus
+ class CheckList < Array
+ def sort_by_next_tick
+ sort! {|a,b| a.next_tick <=> b.next_tick }
+ end
+
+ def insert(check)
+ self << check.tick
+ sort_by_next_tick
+ end
+ end
+
+ class Reactor
+ include Prometheus::DSL
+
+ attr_reader :processes
+
+ def initialize(&block)
+ $start = Time.now.to_i
+ @checks = CheckList.new
+ instance_eval(&block)
+ end
+
+ def start
+ @processes.each do |process|
+ process.checks.each {|c| @checks.insert(c) }
+ end
+
+ checks, start = @checks, $start
+
+ loop do
+ GC.start
+
+ check = checks.shift
+ check.run
+ checks.insert(check)
+ sleep_time = checks.first.next_tick - (Time.now.to_i - start)
+
+ sleep sleep_time if sleep_time > 0
+ end
+ end
+ end
+end
@@ -0,0 +1,23 @@
+module Prometheus
+ class Check
+ def initialize(process, options)
+ @process, @options = process, options
+ end
+
+ def tick
+ @next_tick = (Time.now.to_i - $start) + options[:every]
+ self
+ end
+
+ attr_reader :pass, :total, :options, :next_tick
+ def must_pass(number, hash)
+ @pass, @total = number, hash[:of]
+ end
+
+ def run
+ end
+ end
+end
+
+require "prometheus/checks/running"
+require "prometheus/checks/memory_usage"
@@ -0,0 +1,11 @@
+module Prometheus
+ module Checks
+ class MemoryUsage < Check
+ extend DSL::Evaluator
+
+ def run
+ puts "Checking if memory usage for #{@process} is bigger than #{@options[:below]}"
+ end
+ end
+ end
+end
@@ -0,0 +1,42 @@
+module Prometheus
+ module Checks
+ class Running < Check
+ extend DSL::Evaluator
+
+ def run
+ if @started && check_pid
+ puts "#{@process} is alive"
+ else
+ puts "#{@process} is dead; starting it"
+ start
+ end
+ end
+
+ def start
+ read, write = IO.pipe
+
+ pid = fork do
+ read.close
+ Process.setsid
+ exit if fork
+ write.puts Process.pid.to_s
+ Dir.chdir "/"
+ ::File.umask 0000
+ STDIN.reopen "/dev/null"
+ STDOUT.reopen "/dev/null", "a"
+ STDERR.reopen "/dev/null", "a"
+ exec @process.to_s
+ end
+
+ @pid = read.readline.to_i
+ @started = true
+ end
+
+ def check_pid
+ @pid && Process.kill(0, @pid)
+ rescue Errno::ESRCH
+ false
+ end
+ end
+ end
+end
@@ -0,0 +1,9 @@
+class Fixnum
+ def seconds
+ self
+ end
+
+ def mb
+ self
+ end
+end
@@ -0,0 +1,37 @@
+module Prometheus
+ module DSL
+ module Evaluator
+ def evaluate(*args, &block)
+ new(*args).tap {|e| e.instance_eval(&block) }
+ end
+ end
+
+ def start_process(name, &block)
+ @processes ||= []
+ @processes << DSLProcess.evaluate(name, &block)
+ end
+
+ class DSLProcess
+ extend Evaluator
+
+ def running() Checks::Running end
+ def memory_usage() Checks::MemoryUsage end
+
+ def initialize(name)
+ @name = name
+ @checks = []
+ end
+
+ attr_accessor :checks
+
+ def to_s
+ @name
+ end
+
+ def check(type, options, &block)
+ block ||= proc {}
+ @checks << type.evaluate(self, options, &block)
+ end
+ end
+ end
+end

0 comments on commit caa6aba

Please sign in to comment.