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