Commit 637827f1 authored by Jurriaan Pruis's avatar Jurriaan Pruis
Browse files

Added API

parent 2a4fe0c6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ module FnordMetric

end

require "fnordmetric/api"
require "fnordmetric/inbound_stream"
require "fnordmetric/worker"
require "fnordmetric/widget"

lib/fnordmetric/api.rb

0 → 100644
+37 −0
Original line number Diff line number Diff line
require 'securerandom'
class FnordMetric::API
  @@opts = nil
  def initialize opts
    @@opts = FnordMetric.default_options opts
    connect
  end
  
  def connect
    @redis = @@opts[:redis] if @@opts[:redis]
    @redis = Redis.connect(:url => @@opts[:redis_url])
  end
  
  def event event_data
    push_event get_next_uuid, event_data
  end

  def disconnect
    @redis.quit
  end
  
  private 
  
  def push_event(event_id, event_data)    
    prefix = @@opts[:redis_prefix]
    @redis.hincrby "#{prefix}-testdata",             "events_received", 1
    @redis.hincrby "#{prefix}-stats",             "events_received", 1
    @redis.set     "#{prefix}-event-#{event_id}", event_data
    @redis.lpush   "#{prefix}-queue",             event_id       
    @redis.expire  "#{prefix}-event-#{event_id}", @@opts[:event_queue_ttl]
    event_id
  end
  
  def get_next_uuid
    SecureRandom.uuid
  end
end
 No newline at end of file
+5 −22
Original line number Diff line number Diff line
require 'securerandom'
class FnordMetric::InboundStream < EventMachine::Connection 

  @@opts = nil

  def self.start(opts)
@@ -13,18 +11,6 @@ class FnordMetric::InboundStream < EventMachine::Connection
    EM.defer{ next_event }
  end

  def push_event(event_id, event_data)    
    prefix = @@opts[:redis_prefix]
        
    @redis.hincrby "#{prefix}-stats",             "events_received", 1
    @redis.set     "#{prefix}-event-#{event_id}", event_data
    @redis.lpush   "#{prefix}-queue",             event_id       
    @redis.expire  "#{prefix}-event-#{event_id}", @@opts[:event_queue_ttl]
    
    @events_buffered -= 1
    close_connection?
  end
  
  def next_event
    read_next_event
    push_next_event
@@ -39,20 +25,18 @@ class FnordMetric::InboundStream < EventMachine::Connection

  def push_next_event
    return true if @events.empty?
    push_event(get_next_uuid, @events.pop) 
    @api.event event_data
    @events_buffered -= 1
    close_connection?
    EM.next_tick(&method(:push_next_event))    
  end

  def get_next_uuid
    SecureRandom.uuid
  end

  def close_connection?
    @redis.quit unless @streaming || (@events_buffered!=0) 
    @api.disconnect unless @streaming || (@events_buffered!=0) 
  end

  def post_init
    @redis = Redis.connect(:url => @@opts[:redis_url])
    @api = API.new(@@opts)
    @events_buffered = 0
    @streaming = true
    @buffer = ""
@@ -63,5 +47,4 @@ class FnordMetric::InboundStream < EventMachine::Connection
    @streaming = false
    close_connection?
  end

end

spec/api_spec.rb

0 → 100644
+107 −0
Original line number Diff line number Diff line
require ::File.expand_path('../spec_helper.rb', __FILE__)

describe FnordMetric::Event do

  include FnordMetric

  before(:all) do
    @now = Time.utc(1992,01,13,5,23,23).to_i   
    @redis = Redis.new
    @redis_wrap = RedisWrap.new(@redis)

    @namespace = "fnordmetric-test-ns1234-api" 
    @timeline = "#{@namespace}-timeline"

    @opts = {         
      :namespace_prefix => "#{@namespace}",
      :redis_prefix => "fnordmetric-test",
      :redis => @redis
    }  
    @api = API.new @opts
  end

  describe "finding events using API" do

    before(:each) do        
      @redis.keys("fnordmetric-test-*").each { |k| @redis.del(k) }     
    end

    it "should find all events" do
      create_event({:_type => "foo", :_time => @now})
      create_event({:_type => "foo", :_time => @now})
      Event.all(@opts).length.should == 2
    end

    it "should find all events and return event objects" do
      create_event({:_type => "foo", :_time => @now})
      Event.all(@opts).first.should be_a(FnordMetric::Event)
    end

    it "should find all events and returnevent objects with time" do
      create_event({:_type => "Fn0rd", :blah => :blubb, :_time => @now})
      events = Event.all(@opts) 
      events.first.time.to_i.should == @now
    end

    it "should find an event and return a event object" do
      event_id = create_event({:_type => "Fn0rd", :_time => @now})
      event = Event.find(event_id, @opts)
      event.should be_a(FnordMetric::Event)
      event.type.should == "Fn0rd"
    end

    it "should find an event and return a event object with data" do
      event_id = create_event({:_type => "Fn0rd", :blah => :blubb, :_time => @now})
      event = Event.find(event_id, @opts)  
      event.data(:blah).should == "blubb"
    end

    it "should find an event and return a event object with id" do
      event_id = create_event({:_type => "Fn0rd", :blah => :blubb, :_time => @now})
      event = Event.find(event_id, @opts) 
      event.id.should == event_id
    end

    it "should find all in the correct order" do
      create_event({:_type => "foo", :_time => @now-17})
      create_event({:_type => "foo", :_time => @now-23})
      create_event({:_type => "foo", :_time => @now-42})
      create_event({:_type => "foo", :_time => @now-5})
      Event.all(@opts).length.should == 4
    end

    it "should find all events since a given time, including that exact time" do
      create_event({:_type => "foo", :_time => @now-42})
      create_event({:_type => "foo", :_time => @now-23})
      create_event({:_type => "foo", :_time => @now-17})
      create_event({:_type => "foo", :_time => @now-5})
      Event.all(@opts).length.should == 4
      Event.all(@opts.merge(:since => @now-42)).length.should == 4
      Event.all(@opts.merge(:since => @now-23)).length.should == 3
      Event.all(@opts.merge(:since => @now-22)).length.should == 2
      Event.all(@opts.merge(:since => @now-17)).length.should == 2
      Event.all(@opts.merge(:since => @now-16)).length.should == 1
      Event.all(@opts.merge(:since => @now-5)).length.should == 1
    end

    it "should find a maximum number of events" do
      create_event( {:_type => "foo", :_time => @now-42})
      create_event( {:_type => "foo", :_time => @now-23})
      create_event( {:_type => "foo", :_time => @now-17})
      create_event( {:_type => "foo", :_time => @now-5})
      Event.all(@opts).length.should == 4
      Event.all(@opts.merge(:limit => 2)).length.should == 2
    end



    def create_event(event_data)
      event_id = @api.event event_data.to_json
      @redis_wrap.zadd(@timeline, event_data.delete(:_time), event_id)
      event_id
    end

  end


end