139 строки
3.1 KiB
Ruby
139 строки
3.1 KiB
Ruby
require 'json'
|
|
require 'lightstep'
|
|
require 'opentracing'
|
|
require 'net/http'
|
|
require 'pp'
|
|
require 'uri'
|
|
|
|
$base_url = "http://localhost:8000"
|
|
|
|
$test_tracer = LightStep::Tracer.new(
|
|
component_name: 'lightstep/ruby/example',
|
|
transport: LightStep::Transport::HTTPJSON.new(
|
|
host: 'localhost',
|
|
port: 8000,
|
|
encryption: LightStep::Transport::HTTPJSON::ENCRYPTION_NONE,
|
|
access_token: 'none'
|
|
)
|
|
)
|
|
$noop_tracer = OpenTracing::Tracer.new
|
|
|
|
$prime_work = 982451653
|
|
$logs_memory = ""
|
|
$logs_size_max = (1 << 20)
|
|
$nanos_per_second = 1e9
|
|
|
|
def prepare_logs()
|
|
(0..$logs_size_max-1).each do |x|
|
|
$logs_memory << ("A".ord + x%26).chr
|
|
end
|
|
end
|
|
|
|
prepare_logs()
|
|
|
|
def do_work(n)
|
|
x = $prime_work
|
|
while n != 0 do
|
|
x *= $prime_work
|
|
x %= 4294967296
|
|
n -= 1
|
|
end
|
|
return x
|
|
end
|
|
|
|
def test_body(tracer, control)
|
|
repeat = control['Repeat']
|
|
sleepnano = control['Sleep']
|
|
sleepival = control['SleepInterval']
|
|
work = control['Work']
|
|
logn = control['NumLogs']
|
|
logsz = control['BytesPerLog']
|
|
sleep_debt = 0 # Accumulated nanoseconds
|
|
sleeps = 0
|
|
answer = 0
|
|
|
|
(1..repeat).each do
|
|
span = tracer.start_span('span/test')
|
|
(1..logn).each do
|
|
span.log_event("testlog", $logs_memory[0..logsz])
|
|
end
|
|
answer += do_work(work)
|
|
span.finish()
|
|
sleep_debt += sleepnano
|
|
if sleep_debt <= sleepival
|
|
next
|
|
end
|
|
before = Time.now.to_f
|
|
sleep(sleep_debt / $nanos_per_second)
|
|
elapsed_secs = Time.now.to_f - before
|
|
elapsed = (elapsed_secs * $nanos_per_second).round
|
|
sleeps += elapsed_secs
|
|
sleep_debt -= elapsed
|
|
end
|
|
return sleeps, answer
|
|
end
|
|
|
|
def loop()
|
|
while true do
|
|
uri = URI.parse($base_url + '/control')
|
|
resp = Net::HTTP.get(uri)
|
|
control = JSON.parse(resp)
|
|
|
|
concurrent = control['Concurrent']
|
|
trace = control['Trace']
|
|
|
|
if control['Exit']
|
|
exit(0)
|
|
end
|
|
|
|
tracer = nil
|
|
if trace
|
|
tracer = $test_tracer
|
|
else
|
|
tracer = $noop_tracer
|
|
end
|
|
|
|
before = Time.now.to_f
|
|
|
|
# Note: Concurrency test not implemented
|
|
sleeps, answer = test_body(tracer, control)
|
|
|
|
after = Time.now.to_f
|
|
flush_dur = 0.0
|
|
|
|
if trace
|
|
tracer.flush()
|
|
flush_dur = Time.now.to_f - after
|
|
end
|
|
|
|
elapsed = after - before
|
|
|
|
path = sprintf('/result?timing=%f&flush=%f&s=%f&a=%s', elapsed, flush_dur, sleeps, answer)
|
|
|
|
uri = URI.parse($base_url + path)
|
|
resp = Net::HTTP.get(uri)
|
|
end
|
|
end
|
|
|
|
def backtrace_for_all_threads(signame)
|
|
File.open("/tmp/ruby_backtrace_#{Process.pid}.txt","a") do |f|
|
|
f.puts "--- got signal #{signame}, dump backtrace for all threads at #{Time.now}"
|
|
if Thread.current.respond_to?(:backtrace)
|
|
Thread.list.each do |t|
|
|
f.puts t.inspect
|
|
PP.pp(t.backtrace.delete_if {|frame| frame =~ /^#{File.expand_path(__FILE__)}/},
|
|
f) # remove frames resulting from calling this method
|
|
end
|
|
else
|
|
PP.pp(caller.delete_if {|frame| frame =~ /^#{File.expand_path(__FILE__)}/},
|
|
f) # remove frames resulting from calling this method
|
|
end
|
|
end
|
|
end
|
|
|
|
Signal.trap(29) do
|
|
backtrace_for_all_threads("INFO")
|
|
end
|
|
|
|
loop()
|