lib/skylight/instrumenter.rb in skylight-0.1.5.alpha2 vs lib/skylight/instrumenter.rb in skylight-0.1.5

- old
+ new

@@ -1,10 +1,11 @@ require 'thread' module Skylight class Instrumenter - KEY = :__skylight_current_trace + KEY = :__skylight_current_trace + LOCK = Mutex.new include Util::Logging def self.current_trace Thread.current[KEY] @@ -12,69 +13,66 @@ def self.current_trace=(trace) Thread.current[KEY] = trace end + def self.instance + @instance + end + def self.start!(config = Config.new) - new(config).start! + return @instance if @instance + + LOCK.synchronize do + return @instance if @instance + @instance = new(config).start! + end end + def self.stop! + LOCK.synchronize do + return unless @instance + @instance.shutdown + @instance = nil + end + end + attr_reader :config, :gc def initialize(config) if Hash === config config = Config.new(config) end @gc = config.gc - @lock = Mutex.new @config = config @worker = config.worker.build - @started = false @subscriber = Subscriber.new(config) end def start! - # Quick check - return self if @started return unless config - @lock.synchronize do - # Ensure that the instrumenter has not been started now that the lock - # has been acquired. - return self if @started + t { "starting instrumenter" } + @config.validate! + @config.gc.enable + @worker.spawn + @subscriber.register! - t { "starting instrumenter" } - @config.validate! - @config.gc.enable - @worker.spawn - @subscriber.register! - - @started = true - end - self rescue Exception => e error "failed to start instrumenter; msg=%s", e.message nil end def shutdown - @lock.synchronize do - return unless @started - @subscriber.unregister! - @worker.shutdown - end + @subscriber.unregister! + @worker.shutdown end def trace(endpoint = 'Unknown') - # Ignore everything unless the instrumenter has been started - unless @started - return yield - end - # If a trace is already in progress, continue with that one if trace = Instrumenter.current_trace t { "already tracing" } return yield(trace) end @@ -96,17 +94,37 @@ process(built) else if built && built.spans.empty? debug "trace invalid -- dropping; spans=0" elsif built - debug "trace invalid -- dropping; spans=%d; started_at=%d", built.spans, built.spans[-1].started_at + debug "trace invalid -- dropping; spans=%d; started_at=%d", + built.spans.length, built.spans[-1].started_at else debug "trace invalid -- dropping; trace=nil" end end rescue Exception => e error e end + end + end + + def instrument(cat, *args) + cat = cat.to_s + + unless cat =~ CATEGORY_REGEX + warn "invalid skylight instrumentation category; value=%s", cat + return yield + end + + cat = "other.#{cat}" unless cat =~ TIER_REGEX + + return yield unless sp = @subscriber.instrument(cat, *args) + + begin + yield sp + ensure + @subscriber.done end end private