lightstep 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](https://badge.fury.io/rb/lightstep-tracer) [](https://circleci.com/gh/lightstep/lightstep-tracer-ruby) [](http://opensource.org/licenses/MIT) [](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: []
|