lightstep 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/Makefile +23 -0
- data/README.md +56 -0
- data/Rakefile +6 -0
- data/benchmark/bench.rb +60 -0
- data/benchmark/threading/thread_test.rb +53 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/circle.yml +7 -0
- data/example.rb +34 -0
- data/examples/fork_children/main.rb +54 -0
- data/examples/rack/hello.rb +22 -0
- data/lib/lightstep.rb +35 -0
- data/lib/lightstep/global_tracer.rb +27 -0
- data/lib/lightstep/span.rb +148 -0
- data/lib/lightstep/tracer.rb +309 -0
- data/lib/lightstep/transport/base.rb +22 -0
- data/lib/lightstep/transport/callback.rb +25 -0
- data/lib/lightstep/transport/http_json.rb +111 -0
- data/lib/lightstep/transport/nil.rb +9 -0
- data/lib/lightstep/version.rb +3 -0
- data/lightstep-tracer.gemspec +25 -0
- data/scripts/version.rb +5 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 842c2598853d8cd0b169c367beb6fb16b3cc54f3
|
4
|
+
data.tar.gz: 19a192a4a00afb358410c6ff8953858dbb7837e5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e2c209b4d660be14a771f96676c0ab76f5c2b39a3e731b756a6cc4a2f7259a25030933aa525d08c1b76bdf47aed90133ffdbb1b75f716be4b9092f17205af693
|
7
|
+
data.tar.gz: d5087a55948bfdd293e4d275e290428f47857ba75909df2e3f2b6a54f1817cb1a0f04608831dcc73a8e179a635a5ea68d8ddd6cb7b2d5dbe9bc64799d6ea04c8
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 LightStep
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Makefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
.PHONY: build test benchmark publish
|
2
|
+
|
3
|
+
build:
|
4
|
+
gem build lightstep-tracer.gemspec
|
5
|
+
|
6
|
+
test:
|
7
|
+
bundle exec rake spec
|
8
|
+
ruby example.rb
|
9
|
+
ruby examples/fork_children/main.rb
|
10
|
+
|
11
|
+
benchmark:
|
12
|
+
ruby benchmark/bench.rb
|
13
|
+
ruby benchmark/threading/thread_test.rb
|
14
|
+
|
15
|
+
bump-version:
|
16
|
+
ruby -e 'require "bump"; Bump::Bump.run("patch")'
|
17
|
+
make build # rebuild after version increment
|
18
|
+
git tag `ruby scripts/version.rb`
|
19
|
+
|
20
|
+
publish: build test benchmark
|
21
|
+
git push
|
22
|
+
git push --tags
|
23
|
+
gem push lightstep-`ruby scripts/version.rb`.gem
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# lightstep-tracer-ruby
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/lightstep-tracer.svg)](https://badge.fury.io/rb/lightstep-tracer) [![Circle CI](https://circleci.com/gh/lightstep/lightstep-tracer-ruby.svg?style=shield)](https://circleci.com/gh/lightstep/lightstep-tracer-ruby) [![MIT license](http://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT) [![Code Climate](https://codeclimate.com/github/lightstep/lightstep-tracer-ruby/badges/gpa.svg)](https://codeclimate.com/github/lightstep/lightstep-tracer-ruby)
|
4
|
+
|
5
|
+
The LightStep distributed tracing library for Ruby.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'lightstep'
|
12
|
+
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install lightstep
|
21
|
+
|
22
|
+
|
23
|
+
## Getting started
|
24
|
+
|
25
|
+
require 'lightstep'
|
26
|
+
|
27
|
+
# Initialize the singleton tracer
|
28
|
+
LightStep.configure(component_name: 'lightstep/ruby/example', access_token: 'your_access_token')
|
29
|
+
|
30
|
+
# Create a basic span and attach a log to the span
|
31
|
+
span = LightStep.start_span('my_span')
|
32
|
+
span.log(event: 'hello world', count: 42)
|
33
|
+
|
34
|
+
# Create a child span (and add some artificial delays to illustrate the timing)
|
35
|
+
sleep(0.1)
|
36
|
+
child = LightStep.start_span('my_child', child_of: span)
|
37
|
+
sleep(0.2)
|
38
|
+
child.finish
|
39
|
+
sleep(0.1)
|
40
|
+
span.finish
|
41
|
+
|
42
|
+
## Thread Safety
|
43
|
+
|
44
|
+
The LightStep Tracer is threadsafe. For increased performance, you can add the
|
45
|
+
`concurrent-ruby-ext` gem to your Gemfile. This will enable C extensions for
|
46
|
+
concurrent operations.
|
47
|
+
|
48
|
+
**The LightStep Tracer is not inherently Fork-safe**. When forking, you should
|
49
|
+
`disable` the Tracer before forking, then `enable` it in the child Process
|
50
|
+
and parent Process after forking. See the `fork_children` example for more.
|
51
|
+
|
52
|
+
## Development
|
53
|
+
|
54
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `make test` to run the tests.
|
55
|
+
|
56
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
data/Rakefile
ADDED
data/benchmark/bench.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'lightstep'
|
6
|
+
|
7
|
+
rng = Random.new
|
8
|
+
|
9
|
+
# Run a quick profile on logging lots of spans
|
10
|
+
tracer = LightStep::Tracer.new(
|
11
|
+
component_name: 'lightstep/ruby/spec',
|
12
|
+
transport: LightStep::Transport::Nil.new
|
13
|
+
)
|
14
|
+
|
15
|
+
Benchmark.bm(32) do |x|
|
16
|
+
x.report('Random.bytes.unpack') do
|
17
|
+
for i in 1..10_000; rng.bytes(8).unpack('H*')[0]; end
|
18
|
+
end
|
19
|
+
x.report('Random.bytes.each_byte.map') do
|
20
|
+
for i in 1..10_000; rng.bytes(8).each_byte.map { |b| b.to_s(16) }.join; end
|
21
|
+
end
|
22
|
+
x.report('SecureRandom.hex') do
|
23
|
+
for i in 1..10_000; SecureRandom.hex(8); end
|
24
|
+
end
|
25
|
+
|
26
|
+
x.report('start_span(100)') do
|
27
|
+
for i in 0..100; tracer.start_span('my_span').finish; end
|
28
|
+
end
|
29
|
+
x.report('start_span(1000)') do
|
30
|
+
for i in 0..1000; tracer.start_span('my_span').finish; end
|
31
|
+
end
|
32
|
+
x.report('start_span(10000)') do
|
33
|
+
for i in 0..10_000; tracer.start_span('my_span').finish; end
|
34
|
+
end
|
35
|
+
|
36
|
+
x.report('log_event(100)') do
|
37
|
+
span = tracer.start_span('my_span')
|
38
|
+
for i in 0..100; span.log(event: 'event', i: i); end
|
39
|
+
span.finish
|
40
|
+
end
|
41
|
+
x.report('log_event(1000)') do
|
42
|
+
span = tracer.start_span('my_span')
|
43
|
+
for i in 0..1000; span.log(event: 'event', i: i); end
|
44
|
+
span.finish
|
45
|
+
end
|
46
|
+
x.report('log_event(10000)') do
|
47
|
+
span = tracer.start_span('my_span')
|
48
|
+
for i in 0..10_000; span.log(event: 'event', i: i); end
|
49
|
+
span.finish
|
50
|
+
end
|
51
|
+
|
52
|
+
x.report('inject(10000)') do
|
53
|
+
span = tracer.start_span('my_span')
|
54
|
+
for i in 0..10_000
|
55
|
+
carrier = {}
|
56
|
+
tracer.inject(span, LightStep::Tracer::FORMAT_TEXT_MAP, carrier)
|
57
|
+
end
|
58
|
+
span.finish
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'lightstep'
|
3
|
+
|
4
|
+
LightStep.configure(component_name: 'lightstep/ruby/example', access_token: '{your_access_token}')
|
5
|
+
|
6
|
+
puts 'Starting...'
|
7
|
+
|
8
|
+
mutex = Mutex.new
|
9
|
+
done = false
|
10
|
+
span_count = 0
|
11
|
+
percent_done = 0
|
12
|
+
total_time = 0
|
13
|
+
|
14
|
+
watchThread = Thread.new do
|
15
|
+
loop do
|
16
|
+
sleep(0.5)
|
17
|
+
mutex.lock
|
18
|
+
time_per_span = (1e6 * (total_time.to_f / span_count.to_f)).round(2)
|
19
|
+
puts "#{span_count} spans #{percent_done}% done #{total_time.round(2)} seconds (#{time_per_span} us/span)"
|
20
|
+
is_done = done
|
21
|
+
mutex.unlock
|
22
|
+
Thread.exit if is_done
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
thread = Thread.new do
|
27
|
+
count = 0
|
28
|
+
total_time = 0
|
29
|
+
for j in 1..1000
|
30
|
+
start = Time.now
|
31
|
+
for i in 1..100
|
32
|
+
span = LightStep.start_span('my_span')
|
33
|
+
span.log(event: 'hello world', count: i)
|
34
|
+
span.finish
|
35
|
+
count += 1
|
36
|
+
end
|
37
|
+
delta = Time.now - start
|
38
|
+
|
39
|
+
mutex.lock
|
40
|
+
percent_done = (100.0 * (count / 100_000.0)).ceil
|
41
|
+
span_count = count
|
42
|
+
total_time += delta
|
43
|
+
mutex.unlock
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
thread.join
|
48
|
+
mutex.lock
|
49
|
+
done = true
|
50
|
+
mutex.unlock
|
51
|
+
watchThread.join
|
52
|
+
|
53
|
+
puts 'Done!'
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'lightstep'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/circle.yml
ADDED
data/example.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.command_name 'example.rb'
|
4
|
+
SimpleCov.start
|
5
|
+
require 'lightstep'
|
6
|
+
|
7
|
+
access_token = '{your_access_token}'
|
8
|
+
|
9
|
+
LightStep.configure(component_name: 'lightstep/ruby/example', access_token: access_token)
|
10
|
+
|
11
|
+
puts 'Starting operation...'
|
12
|
+
span = LightStep.start_span('my_span')
|
13
|
+
thread1 = Thread.new do
|
14
|
+
for i in 1..10
|
15
|
+
sleep(0.15)
|
16
|
+
puts "Logging event #{i}..."
|
17
|
+
span.log(event: 'hello world', count: i)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
thread2 = Thread.new do
|
21
|
+
current = 1
|
22
|
+
for i in 1..16
|
23
|
+
child = LightStep.start_span('my_child', child_of: span)
|
24
|
+
sleep(0.1)
|
25
|
+
current *= 2
|
26
|
+
child.log(event: "2^#{i}", result: current)
|
27
|
+
child.finish
|
28
|
+
end
|
29
|
+
end
|
30
|
+
[thread1, thread2].each(&:join)
|
31
|
+
span.finish
|
32
|
+
|
33
|
+
puts 'Done!'
|
34
|
+
puts "https://app.lightstep.com/#{access_token}/trace?span_guid=#{span.guid}&at_micros=#{span.start_micros}"
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# A simple, manual test ensuring that tracer instances still report after a
|
2
|
+
# Process.fork. Currently this requires the tracer instance to be explicitly
|
3
|
+
# disabled before the fork and reenabled afterward.
|
4
|
+
|
5
|
+
require 'bundler/setup'
|
6
|
+
require 'lightstep'
|
7
|
+
|
8
|
+
LightStep.configure(
|
9
|
+
component_name: 'lightstep/ruby/examples/fork_children',
|
10
|
+
access_token: '{your_access_token}'
|
11
|
+
)
|
12
|
+
|
13
|
+
puts 'Starting...'
|
14
|
+
(1..20).each do |k|
|
15
|
+
puts "Explicit reset iteration #{k}..."
|
16
|
+
|
17
|
+
# NOTE: the tracer is disabled and reenabled on either side of the fork
|
18
|
+
LightStep.disable
|
19
|
+
pid = Process.fork do
|
20
|
+
LightStep.enable
|
21
|
+
10.times do
|
22
|
+
span = LightStep.start_span("my_forked_span-#{Process.pid}")
|
23
|
+
sleep(0.0025 * rand(k))
|
24
|
+
span.finish
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Also renable the parent process' tracer
|
29
|
+
LightStep.enable
|
30
|
+
|
31
|
+
10.times do
|
32
|
+
span = LightStep.start_span("my_process_span-#{Process.pid}")
|
33
|
+
sleep(0.0025 * rand(k))
|
34
|
+
span.finish
|
35
|
+
end
|
36
|
+
|
37
|
+
# Make sure redundant enable calls don't cause problems
|
38
|
+
10.times do
|
39
|
+
LightStep.disable
|
40
|
+
LightStep.enable
|
41
|
+
LightStep.disable
|
42
|
+
LightStep.disable
|
43
|
+
LightStep.enable
|
44
|
+
LightStep.enable
|
45
|
+
span = LightStep.start_span("my_toggle_span-#{Process.pid}")
|
46
|
+
sleep(0.0025 * rand(k))
|
47
|
+
span.finish
|
48
|
+
end
|
49
|
+
|
50
|
+
puts "Parent, pid #{Process.pid}, waiting on child pid #{pid}"
|
51
|
+
Process.wait
|
52
|
+
end
|
53
|
+
|
54
|
+
puts 'Done!'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'lightstep'
|
3
|
+
|
4
|
+
require 'rack'
|
5
|
+
require 'rack/server'
|
6
|
+
|
7
|
+
LightStep.configure(
|
8
|
+
component_name: 'lightstep/ruby/examples/rack',
|
9
|
+
access_token: '{your_access_token}'
|
10
|
+
)
|
11
|
+
|
12
|
+
class HelloWorldApp
|
13
|
+
def self.call(env)
|
14
|
+
span = LightStep.start_span('request')
|
15
|
+
span.log event: 'env', env: env
|
16
|
+
resp = [200, {}, ["Hello World. You said: #{env['QUERY_STRING']}"]]
|
17
|
+
span.finish
|
18
|
+
resp
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Rack::Server.start app: HelloWorldApp
|
data/lib/lightstep.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
# LightStep Tracer
|
4
|
+
module LightStep
|
5
|
+
extend SingleForwardable
|
6
|
+
|
7
|
+
# Base class for all LightStep errors
|
8
|
+
class Error < StandardError; end
|
9
|
+
|
10
|
+
# Returns the singleton instance of the Tracer.
|
11
|
+
def self.instance
|
12
|
+
LightStep::GlobalTracer.instance
|
13
|
+
end
|
14
|
+
|
15
|
+
def_delegator :instance, :configure
|
16
|
+
def_delegator :instance, :start_span
|
17
|
+
def_delegator :instance, :disable
|
18
|
+
def_delegator :instance, :enable
|
19
|
+
def_delegator :instance, :flush
|
20
|
+
|
21
|
+
# Convert a time to microseconds
|
22
|
+
def self.micros(time)
|
23
|
+
(time.to_f * 1E6).floor
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns a random guid. Note: this intentionally does not use SecureRandom,
|
27
|
+
# which is slower and cryptographically secure randomness is not required here.
|
28
|
+
def self.guid
|
29
|
+
@_rng ||= Random.new
|
30
|
+
@_rng.bytes(8).unpack('H*')[0]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'lightstep/tracer'
|
35
|
+
require 'lightstep/global_tracer'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module LightStep
|
4
|
+
# GlobalTracer is a singleton version of the LightStep::Tracer.
|
5
|
+
#
|
6
|
+
# You should access it via `LightStep.instance`.
|
7
|
+
class GlobalTracer < Tracer
|
8
|
+
private
|
9
|
+
def initialize
|
10
|
+
end
|
11
|
+
|
12
|
+
public
|
13
|
+
include Singleton
|
14
|
+
|
15
|
+
# Configure the GlobalTracer
|
16
|
+
# See {LightStep::Tracer#initialize}
|
17
|
+
def configure(opts = nil)
|
18
|
+
raise ConfigurationError, 'Already configured' if configured
|
19
|
+
self.configured = true
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_accessor :configured
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
|
3
|
+
module LightStep
|
4
|
+
# Span represents an OpenTracer Span
|
5
|
+
#
|
6
|
+
# See http://www.opentracing.io for more information.
|
7
|
+
class Span
|
8
|
+
# Internal use only
|
9
|
+
# @private
|
10
|
+
attr_reader :guid, :trace_guid, :start_micros, :end_micros, :baggage, :tags
|
11
|
+
|
12
|
+
# Creates a new {Span}
|
13
|
+
#
|
14
|
+
# @param tracer [Tracer] the tracer that created this span
|
15
|
+
# @param operation_name [String] the operation name of this span
|
16
|
+
# @param child_of_guid [String] the guid of the span this span is a child of
|
17
|
+
# @param trace_guid [String] the guid of this span's trace
|
18
|
+
# @param start_micros [Numeric] start time of the span in microseconds
|
19
|
+
# @return [Span] a new Span
|
20
|
+
def initialize(
|
21
|
+
tracer:,
|
22
|
+
operation_name:,
|
23
|
+
child_of_guid: nil,
|
24
|
+
trace_guid:,
|
25
|
+
start_micros:,
|
26
|
+
tags: nil,
|
27
|
+
max_log_records:
|
28
|
+
)
|
29
|
+
@tags = Concurrent::Hash.new(tags)
|
30
|
+
@baggage = Concurrent::Hash.new
|
31
|
+
@log_records = Concurrent::Array.new
|
32
|
+
@dropped_logs = Concurrent::AtomicFixnum.new
|
33
|
+
@max_log_records = max_log_records
|
34
|
+
|
35
|
+
@tracer = tracer
|
36
|
+
@guid = LightStep.guid
|
37
|
+
self.operation_name = operation_name
|
38
|
+
self.start_micros = start_micros
|
39
|
+
self.trace_guid = trace_guid
|
40
|
+
set_tag(:parent_span_guid, child_of_guid) if !child_of_guid.nil?
|
41
|
+
end
|
42
|
+
|
43
|
+
# Set a tag value on this span
|
44
|
+
# @param key [String] the key of the tag
|
45
|
+
# @param value [String, Numeric, Boolean] the value of the tag. If it's not
|
46
|
+
# a String, Numeric, or Boolean it will be encoded with to_s
|
47
|
+
def set_tag(key, value)
|
48
|
+
case value
|
49
|
+
when String, Fixnum, TrueClass, FalseClass
|
50
|
+
tags[key] = value
|
51
|
+
else
|
52
|
+
tags[key] = value.to_s
|
53
|
+
end
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
# TODO(ngauthier@gmail.com) baggage keys have a restricted format according
|
58
|
+
# to the spec: http://opentracing.io/documentation/pages/spec#baggage-vs-span-tags
|
59
|
+
|
60
|
+
# Set a baggage item on the span
|
61
|
+
# @param key [String] the key of the baggage item
|
62
|
+
# @param value [String] the value of the baggage item
|
63
|
+
def set_baggage_item(key, value)
|
64
|
+
baggage[key] = value
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get a baggage item
|
69
|
+
# @param key [String] the key of the baggage item
|
70
|
+
# @return Value of the baggage item
|
71
|
+
def get_baggage_item(key)
|
72
|
+
baggage[key]
|
73
|
+
end
|
74
|
+
|
75
|
+
# Add a log entry to this span
|
76
|
+
# @param event [String] event name for the log
|
77
|
+
# @param timestamp [Time] time of the log
|
78
|
+
# @param fields [Hash] Additional information to log
|
79
|
+
def log(event: nil, timestamp: Time.now, **fields)
|
80
|
+
return unless tracer.enabled?
|
81
|
+
|
82
|
+
record = {
|
83
|
+
runtime_guid: tracer.guid,
|
84
|
+
timestamp_micros: LightStep.micros(timestamp)
|
85
|
+
}
|
86
|
+
record[:stable_name] = event.to_s if !event.nil?
|
87
|
+
|
88
|
+
begin
|
89
|
+
record[:payload_json] = JSON.generate(fields, max_nesting: 8)
|
90
|
+
rescue
|
91
|
+
# TODO: failure to encode a payload as JSON should be recorded in the
|
92
|
+
# internal library logs, with catioun not flooding the internal logs.
|
93
|
+
end
|
94
|
+
|
95
|
+
log_records.push(record)
|
96
|
+
if log_records.size > @max_log_records
|
97
|
+
log_records.shift
|
98
|
+
dropped_logs.increment
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Finish the {Span}
|
103
|
+
# @param end_time [Time] custom end time, if not now
|
104
|
+
def finish(end_time: Time.now)
|
105
|
+
if end_micros.nil?
|
106
|
+
self.end_micros = LightStep.micros(end_time)
|
107
|
+
end
|
108
|
+
tracer.finish_span(self)
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
# Hash representation of a span
|
113
|
+
def to_h
|
114
|
+
{
|
115
|
+
runtime_guid: tracer.guid,
|
116
|
+
span_guid: guid,
|
117
|
+
trace_guid: trace_guid,
|
118
|
+
span_name: operation_name,
|
119
|
+
attributes: tags.map {|key, value|
|
120
|
+
{Key: key.to_s, Value: value}
|
121
|
+
},
|
122
|
+
oldest_micros: start_micros,
|
123
|
+
youngest_micros: end_micros,
|
124
|
+
error_flag: false,
|
125
|
+
dropped_logs: dropped_logs_count,
|
126
|
+
log_records: log_records
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
130
|
+
# Internal use only
|
131
|
+
# @private
|
132
|
+
def dropped_logs_count
|
133
|
+
dropped_logs.value
|
134
|
+
end
|
135
|
+
|
136
|
+
# Internal use only
|
137
|
+
# @private
|
138
|
+
def logs_count
|
139
|
+
log_records.size
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
attr_reader :tracer, :dropped_logs, :log_records
|
145
|
+
attr_writer :guid, :trace_guid, :start_micros, :end_micros
|
146
|
+
attr_accessor :operation_name
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,309 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'concurrent'
|
3
|
+
|
4
|
+
require 'lightstep/span'
|
5
|
+
require 'lightstep/transport/http_json'
|
6
|
+
require 'lightstep/transport/nil'
|
7
|
+
require 'lightstep/transport/callback'
|
8
|
+
|
9
|
+
module LightStep
|
10
|
+
class Tracer
|
11
|
+
FORMAT_TEXT_MAP = 1
|
12
|
+
FORMAT_BINARY = 2
|
13
|
+
|
14
|
+
CARRIER_TRACER_STATE_PREFIX = 'ot-tracer-'.freeze
|
15
|
+
CARRIER_BAGGAGE_PREFIX = 'ot-baggage-'.freeze
|
16
|
+
|
17
|
+
DEFAULT_MAX_LOG_RECORDS = 1000
|
18
|
+
MIN_MAX_LOG_RECORDS = 1
|
19
|
+
DEFAULT_MAX_SPAN_RECORDS = 1000
|
20
|
+
MIN_MAX_SPAN_RECORDS = 1
|
21
|
+
DEFAULT_MIN_REPORTING_PERIOD_SECS = 1.5
|
22
|
+
DEFAULT_MAX_REPORTING_PERIOD_SECS = 30.0
|
23
|
+
|
24
|
+
class Error < LightStep::Error; end
|
25
|
+
class ConfigurationError < LightStep::Tracer::Error; end
|
26
|
+
|
27
|
+
attr_reader :access_token, :guid
|
28
|
+
|
29
|
+
# Initialize a new tracer. Either an access_token or a transport must be
|
30
|
+
# provided. A component_name is always required.
|
31
|
+
# @param component_name [String] Component name to use for the tracer
|
32
|
+
# @param access_token [String] The project access token when pushing to LightStep
|
33
|
+
# @param transport [LightStep::Transport] How the data should be transported
|
34
|
+
# @return LightStep::Tracer
|
35
|
+
# @raise LightStep::ConfigurationError if the group name or access token is not a valid string.
|
36
|
+
def initialize(component_name:, access_token: nil, transport: nil)
|
37
|
+
configure(component_name: component_name, access_token: access_token, transport: transport)
|
38
|
+
end
|
39
|
+
|
40
|
+
def max_log_records
|
41
|
+
@max_log_records ||= DEFAULT_MAX_LOG_RECORDS
|
42
|
+
end
|
43
|
+
|
44
|
+
def max_log_records=(max)
|
45
|
+
@max_log_records = [MIN_MAX_LOG_RECORDS, max].max
|
46
|
+
end
|
47
|
+
|
48
|
+
def max_span_records
|
49
|
+
@max_span_records ||= DEFAULT_MAX_SPAN_RECORDS
|
50
|
+
end
|
51
|
+
|
52
|
+
def max_span_records=(max)
|
53
|
+
@max_span_records = [MIN_MAX_SPAN_RECORDS, max].max
|
54
|
+
end
|
55
|
+
|
56
|
+
def min_flush_period_micros
|
57
|
+
@min_flush_period_micros ||= DEFAULT_MIN_REPORTING_PERIOD_SECS * 1E6
|
58
|
+
end
|
59
|
+
|
60
|
+
def min_reporting_period_secs=(secs)
|
61
|
+
@min_flush_period_micros = [DEFAULT_MIN_REPORTING_PERIOD_SECS, secs].max * 1E6
|
62
|
+
end
|
63
|
+
|
64
|
+
def max_flush_period_micros
|
65
|
+
@max_flush_period_micros ||= DEFAULT_MAX_REPORTING_PERIOD_SECS * 1E6
|
66
|
+
end
|
67
|
+
|
68
|
+
def max_reporting_period_secs=(secs)
|
69
|
+
@max_flush_period_micros = [DEFAULT_MAX_REPORTING_PERIOD_SECS, secs].min * 1E6
|
70
|
+
end
|
71
|
+
|
72
|
+
# TODO(ngauthier@gmail.com) inherit SpanContext from references
|
73
|
+
|
74
|
+
# Starts a new span.
|
75
|
+
# @param operation_name [String] the operation name for the Span
|
76
|
+
# @param child_of [Span] Span to inherit from
|
77
|
+
# @param start_time [Time] When the Span started, if not now
|
78
|
+
# @param tags [Hash] tags for the span
|
79
|
+
# @return [Span]
|
80
|
+
def start_span(operation_name, child_of: nil, start_time: nil, tags: nil)
|
81
|
+
child_of_guid = nil
|
82
|
+
trace_guid = nil
|
83
|
+
if Span === child_of
|
84
|
+
child_of_guid = child_of.guid
|
85
|
+
trace_guid = child_of.trace_guid
|
86
|
+
else
|
87
|
+
trace_guid = LightStep.guid
|
88
|
+
end
|
89
|
+
|
90
|
+
Span.new(
|
91
|
+
tracer: self,
|
92
|
+
operation_name: operation_name,
|
93
|
+
child_of_guid: child_of_guid,
|
94
|
+
trace_guid: trace_guid,
|
95
|
+
start_micros: start_time.nil? ? LightStep.micros(Time.now) : LightStep.micros(start_time),
|
96
|
+
tags: tags,
|
97
|
+
max_log_records: max_log_records
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Inject a span into the given carrier
|
102
|
+
# @param span [Span]
|
103
|
+
# @param format [LightStep::Tracer::FORMAT_TEXT_MAP, LightStep::Tracer::FORMAT_BINARY]
|
104
|
+
# @param carrier [Hash-like]
|
105
|
+
def inject(span, format, carrier)
|
106
|
+
case format
|
107
|
+
when LightStep::Tracer::FORMAT_TEXT_MAP
|
108
|
+
inject_to_text_map(span, carrier)
|
109
|
+
when LightStep::Tracer::FORMAT_BINARY
|
110
|
+
warn 'Binary inject format not yet implemented'
|
111
|
+
else
|
112
|
+
warn 'Unknown inject format'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Extract a span from a carrier
|
117
|
+
# @param operation_name [String]
|
118
|
+
# @param format [LightStep::Tracer::FORMAT_TEXT_MAP, LightStep::Tracer::FORMAT_BINARY]
|
119
|
+
# @param carrier [Hash-like]
|
120
|
+
# @return [Span]
|
121
|
+
def extract(operation_name, format, carrier)
|
122
|
+
case format
|
123
|
+
when LightStep::Tracer::FORMAT_TEXT_MAP
|
124
|
+
extract_from_text_map(operation_name, carrier)
|
125
|
+
when LightStep::Tracer::FORMAT_BINARY
|
126
|
+
warn 'Binary join format not yet implemented'
|
127
|
+
nil
|
128
|
+
else
|
129
|
+
warn 'Unknown join format'
|
130
|
+
nil
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# @return true if the tracer is enabled
|
135
|
+
def enabled?
|
136
|
+
@enabled ||= true
|
137
|
+
end
|
138
|
+
|
139
|
+
# Enables the tracer
|
140
|
+
def enable
|
141
|
+
@enabled = true
|
142
|
+
end
|
143
|
+
|
144
|
+
# Disables the tracer
|
145
|
+
# @param discard [Boolean] whether to discard queued data
|
146
|
+
def disable(discard: true)
|
147
|
+
@enabled = false
|
148
|
+
@transport.clear if discard
|
149
|
+
@transport.flush
|
150
|
+
end
|
151
|
+
|
152
|
+
# Flush to the Transport
|
153
|
+
def flush
|
154
|
+
_flush_worker
|
155
|
+
end
|
156
|
+
|
157
|
+
# Internal use only.
|
158
|
+
# @private
|
159
|
+
def finish_span(span)
|
160
|
+
return unless enabled?
|
161
|
+
@span_records.push(span.to_h)
|
162
|
+
if @span_records.size > max_span_records
|
163
|
+
@span_records.shift
|
164
|
+
@dropped_spans.increment
|
165
|
+
@dropped_span_logs.increment(span.logs_count + span.dropped_logs_count)
|
166
|
+
end
|
167
|
+
flush_if_needed
|
168
|
+
end
|
169
|
+
|
170
|
+
protected
|
171
|
+
|
172
|
+
def access_token=(token)
|
173
|
+
if !access_token.nil?
|
174
|
+
raise ConfigurationError, "access token cannot be changed"
|
175
|
+
end
|
176
|
+
@access_token = token
|
177
|
+
end
|
178
|
+
|
179
|
+
def configure(component_name:, access_token: nil, transport: nil)
|
180
|
+
raise ConfigurationError, "component_name must be a string" unless String === component_name
|
181
|
+
raise ConfigurationError, "component_name cannot be blank" if component_name.empty?
|
182
|
+
|
183
|
+
@span_records = Concurrent::Array.new
|
184
|
+
@dropped_spans = Concurrent::AtomicFixnum.new
|
185
|
+
@dropped_span_logs = Concurrent::AtomicFixnum.new
|
186
|
+
|
187
|
+
start_time = LightStep.micros(Time.now)
|
188
|
+
@guid = LightStep.guid
|
189
|
+
@report_start_time = start_time
|
190
|
+
@last_flush_micros = start_time
|
191
|
+
|
192
|
+
@runtime = {
|
193
|
+
guid: guid,
|
194
|
+
start_micros: start_time,
|
195
|
+
group_name: component_name,
|
196
|
+
attrs: [
|
197
|
+
{Key: "lightstep.tracer_platform", Value: "ruby"},
|
198
|
+
{Key: "lightstep.tracer_version", Value: LightStep::VERSION},
|
199
|
+
{Key: "lightstep.tracer_platform_version", Value: RUBY_VERSION}
|
200
|
+
]
|
201
|
+
}.freeze
|
202
|
+
|
203
|
+
if !transport.nil?
|
204
|
+
if !(LightStep::Transport::Base === transport)
|
205
|
+
raise ConfigurationError, "transport is not a LightStep transport class: #{transport}"
|
206
|
+
end
|
207
|
+
@transport = transport
|
208
|
+
else
|
209
|
+
if access_token.nil?
|
210
|
+
raise ConfigurationError, "you must provide an access token or a transport"
|
211
|
+
end
|
212
|
+
@transport = Transport::HTTPJSON.new(access_token: access_token)
|
213
|
+
end
|
214
|
+
|
215
|
+
# At exit, flush this objects data to the transport and close the transport
|
216
|
+
# (which in turn will send the flushed data over the network).
|
217
|
+
at_exit do
|
218
|
+
flush
|
219
|
+
@transport.close
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def flush_if_needed
|
224
|
+
return unless enabled?
|
225
|
+
|
226
|
+
delta = LightStep.micros(Time.now) - @last_flush_micros
|
227
|
+
return if delta < min_flush_period_micros
|
228
|
+
|
229
|
+
if delta > max_flush_period_micros || @span_records.size >= max_span_records / 2
|
230
|
+
flush
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
private
|
235
|
+
|
236
|
+
def inject_to_text_map(span, carrier)
|
237
|
+
carrier[CARRIER_TRACER_STATE_PREFIX + 'spanid'] = span.guid
|
238
|
+
carrier[CARRIER_TRACER_STATE_PREFIX + 'traceid'] = span.trace_guid unless span.trace_guid.nil?
|
239
|
+
carrier[CARRIER_TRACER_STATE_PREFIX + 'sampled'] = 'true'
|
240
|
+
|
241
|
+
span.baggage.each do |key, value|
|
242
|
+
carrier[CARRIER_BAGGAGE_PREFIX + key] = value
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def extract_from_text_map(operation_name, carrier)
|
247
|
+
span = Span.new(
|
248
|
+
tracer: self,
|
249
|
+
operation_name: operation_name,
|
250
|
+
start_micros: LightStep.micros(Time.now),
|
251
|
+
child_of_guid: carrier[CARRIER_TRACER_STATE_PREFIX + 'spanid'],
|
252
|
+
trace_guid: carrier[CARRIER_TRACER_STATE_PREFIX + 'traceid'],
|
253
|
+
max_log_records: max_log_records
|
254
|
+
)
|
255
|
+
|
256
|
+
carrier.each do |key, value|
|
257
|
+
next unless key.start_with?(CARRIER_BAGGAGE_PREFIX)
|
258
|
+
plain_key = key.to_s[CARRIER_BAGGAGE_PREFIX.length..key.to_s.length]
|
259
|
+
span.set_baggage_item(plain_key, value)
|
260
|
+
end
|
261
|
+
span
|
262
|
+
end
|
263
|
+
|
264
|
+
def _flush_worker
|
265
|
+
return unless enabled?
|
266
|
+
# The thrift configuration has not yet been set: allow logs and spans
|
267
|
+
# to be buffered in this case, but flushes won't yet be possible.
|
268
|
+
return if @runtime.nil?
|
269
|
+
return if @span_records.empty?
|
270
|
+
|
271
|
+
now = LightStep.micros(Time.now)
|
272
|
+
|
273
|
+
span_records = @span_records.slice!(0, @span_records.length)
|
274
|
+
dropped_spans = 0
|
275
|
+
@dropped_spans.update{|old| dropped_spans = old; 0 }
|
276
|
+
|
277
|
+
old_dropped_span_logs = 0
|
278
|
+
@dropped_span_logs.update{|old| old_dropped_span_logs = old; 0 }
|
279
|
+
dropped_logs = old_dropped_span_logs
|
280
|
+
dropped_logs = span_records.reduce(dropped_logs) do |memo, span|
|
281
|
+
memo += span.delete :dropped_logs
|
282
|
+
end
|
283
|
+
|
284
|
+
report_request = {
|
285
|
+
runtime: @runtime,
|
286
|
+
oldest_micros: @report_start_time,
|
287
|
+
youngest_micros: now,
|
288
|
+
span_records: span_records,
|
289
|
+
counters: [
|
290
|
+
{Name: "dropped_logs", Value: dropped_logs},
|
291
|
+
{Name: "dropped_spans", Value: dropped_spans},
|
292
|
+
]
|
293
|
+
}
|
294
|
+
|
295
|
+
@last_flush_micros = now
|
296
|
+
@report_start_time = now
|
297
|
+
|
298
|
+
begin
|
299
|
+
@transport.report(report_request)
|
300
|
+
rescue LightStep::Transport::HTTPJSON::QueueFullError
|
301
|
+
# If the queue is full, add the previous dropped logs to the logs
|
302
|
+
# that were going to get reported, as well as the previous dropped
|
303
|
+
# spans and spans that would have been recorded
|
304
|
+
@dropped_spans.increment(dropped_spans + span_records.length)
|
305
|
+
@dropped_span_logs.increment(old_dropped_span_logs)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'lightstep/transport/base'
|
2
|
+
|
3
|
+
module LightStep
|
4
|
+
module Transport
|
5
|
+
class Callback < Base
|
6
|
+
def initialize(callback:)
|
7
|
+
@callback = callback
|
8
|
+
end
|
9
|
+
|
10
|
+
def report(report)
|
11
|
+
@callback.call(report)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def close
|
16
|
+
end
|
17
|
+
|
18
|
+
def clear
|
19
|
+
end
|
20
|
+
|
21
|
+
def flush
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'lightstep/transport/base'
|
3
|
+
|
4
|
+
module LightStep
|
5
|
+
module Transport
|
6
|
+
# HTTPJSON is a transport that sends reports via HTTP in JSON format.
|
7
|
+
# It is thread-safe, however it is *not* fork-safe. When forking, all items
|
8
|
+
# in the queue will be copied and sent in duplicate.
|
9
|
+
#
|
10
|
+
# When forking, you should first `disable` the tracer, then `enable` it from
|
11
|
+
# within the fork (and in the parent post-fork). See
|
12
|
+
# `examples/fork_children/main.rb` for an example.
|
13
|
+
class HTTPJSON < Base
|
14
|
+
LIGHTSTEP_HOST = "collector.lightstep.com"
|
15
|
+
LIGHTSTEP_PORT = 443
|
16
|
+
QUEUE_SIZE = 16
|
17
|
+
|
18
|
+
ENCRYPTION_TLS = 'tls'
|
19
|
+
ENCRYPTION_NONE = 'none'
|
20
|
+
|
21
|
+
class QueueFullError < LightStep::Error; end
|
22
|
+
|
23
|
+
# Initialize the transport
|
24
|
+
# @param host [String] host of the domain to the endpoind to push data
|
25
|
+
# @param port [Numeric] port on which to connect
|
26
|
+
# @param verbose [Numeric] verbosity level. Right now 0-3 are supported
|
27
|
+
# @param secure [Boolean]
|
28
|
+
# @param access_token [String] access token for LightStep server
|
29
|
+
# @return [HTTPJSON]
|
30
|
+
def initialize(host: LIGHTSTEP_HOST, port: LIGHTSTEP_PORT, verbose: 0, encryption: ENCRYPTION_TLS, access_token:)
|
31
|
+
@host = host
|
32
|
+
@port = port
|
33
|
+
@verbose = verbose
|
34
|
+
@encryption = encryption
|
35
|
+
|
36
|
+
raise ConfigurationError, "access_token must be a string" unless String === access_token
|
37
|
+
raise ConfigurationError, "access_token cannot be blank" if access_token.empty?
|
38
|
+
@access_token = access_token
|
39
|
+
|
40
|
+
start_queue
|
41
|
+
end
|
42
|
+
|
43
|
+
# Queue a report for sending
|
44
|
+
def report(report)
|
45
|
+
p report if @verbose >= 3
|
46
|
+
# TODO(ngauthier@gmail.com): the queue could be full here if we're
|
47
|
+
# lagging, which would cause this to block!
|
48
|
+
@queue.push({
|
49
|
+
host: @host,
|
50
|
+
port: @port,
|
51
|
+
encryption: @encryption,
|
52
|
+
access_token: @access_token,
|
53
|
+
content: report,
|
54
|
+
verbose: @verbose
|
55
|
+
}, true)
|
56
|
+
nil
|
57
|
+
rescue ThreadError
|
58
|
+
raise QueueFullError
|
59
|
+
end
|
60
|
+
|
61
|
+
# Flush the current queue
|
62
|
+
def flush
|
63
|
+
close
|
64
|
+
start_queue
|
65
|
+
end
|
66
|
+
|
67
|
+
# Clear the current queue, deleting pending items
|
68
|
+
def clear
|
69
|
+
@queue.clear
|
70
|
+
end
|
71
|
+
|
72
|
+
# Close the transport. No further data can be sent!
|
73
|
+
def close
|
74
|
+
@queue.close
|
75
|
+
@thread.join
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def start_queue
|
81
|
+
@queue = SizedQueue.new(QUEUE_SIZE)
|
82
|
+
@thread = start_thread(@queue)
|
83
|
+
end
|
84
|
+
|
85
|
+
# TODO(ngauthier@gmail.com) abort on exception?
|
86
|
+
def start_thread(queue)
|
87
|
+
Thread.new do
|
88
|
+
while item = queue.pop
|
89
|
+
post_report(item)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def post_report(params)
|
95
|
+
https = Net::HTTP.new(params[:host], params[:port])
|
96
|
+
https.use_ssl = params[:encryption] == ENCRYPTION_TLS
|
97
|
+
req = Net::HTTP::Post.new('/api/v0/reports')
|
98
|
+
req['LightStep-Access-Token'] = params[:access_token]
|
99
|
+
req['Content-Type'] = 'application/json'
|
100
|
+
req['Connection'] = 'keep-alive'
|
101
|
+
req.body = params[:content].to_json
|
102
|
+
res = https.request(req)
|
103
|
+
|
104
|
+
puts res.to_s if params[:verbose] >= 3
|
105
|
+
|
106
|
+
# TODO(ngauthier@gmail.com): log unknown commands
|
107
|
+
# TODO(ngauthier@gmail.com): log errors from server
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'lightstep/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'lightstep'
|
8
|
+
spec.version = LightStep::VERSION
|
9
|
+
spec.authors = ['bcronin']
|
10
|
+
spec.email = ['support@lightstep.com']
|
11
|
+
|
12
|
+
spec.summary = 'LightStep OpenTracing Ruby bindings'
|
13
|
+
spec.homepage = 'https://github.com/lightstep/lightstep-tracer-ruby'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.require_paths = ['lib']
|
18
|
+
|
19
|
+
spec.add_dependency 'concurrent-ruby', '~> 1.0.0'
|
20
|
+
spec.add_development_dependency 'rake', '~> 11.3.0'
|
21
|
+
spec.add_development_dependency 'rack', '~> 2.0.0'
|
22
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
23
|
+
spec.add_development_dependency 'bump', '~> 0.5'
|
24
|
+
spec.add_development_dependency 'simplecov', '~> 0.12.0'
|
25
|
+
end
|
data/scripts/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lightstep
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- bcronin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: concurrent-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 11.3.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 11.3.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rack
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.0.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bump
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.5'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.5'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.12.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.12.0
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- support@lightstep.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
|
+
- Gemfile
|
107
|
+
- LICENSE.txt
|
108
|
+
- Makefile
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- benchmark/bench.rb
|
112
|
+
- benchmark/threading/thread_test.rb
|
113
|
+
- bin/console
|
114
|
+
- bin/setup
|
115
|
+
- circle.yml
|
116
|
+
- example.rb
|
117
|
+
- examples/fork_children/main.rb
|
118
|
+
- examples/rack/hello.rb
|
119
|
+
- lib/lightstep.rb
|
120
|
+
- lib/lightstep/global_tracer.rb
|
121
|
+
- lib/lightstep/span.rb
|
122
|
+
- lib/lightstep/tracer.rb
|
123
|
+
- lib/lightstep/transport/base.rb
|
124
|
+
- lib/lightstep/transport/callback.rb
|
125
|
+
- lib/lightstep/transport/http_json.rb
|
126
|
+
- lib/lightstep/transport/nil.rb
|
127
|
+
- lib/lightstep/version.rb
|
128
|
+
- lightstep-tracer.gemspec
|
129
|
+
- scripts/version.rb
|
130
|
+
homepage: https://github.com/lightstep/lightstep-tracer-ruby
|
131
|
+
licenses:
|
132
|
+
- MIT
|
133
|
+
metadata: {}
|
134
|
+
post_install_message:
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
requirements: []
|
149
|
+
rubyforge_project:
|
150
|
+
rubygems_version: 2.5.1
|
151
|
+
signing_key:
|
152
|
+
specification_version: 4
|
153
|
+
summary: LightStep OpenTracing Ruby bindings
|
154
|
+
test_files: []
|