zipkin 1.5.0 → 1.6.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 +5 -5
- data/.travis.yml +2 -2
- data/README.md +10 -0
- data/lib/zipkin/async_reporter.rb +39 -0
- data/lib/zipkin/async_reporter/buffer.rb +27 -0
- data/lib/zipkin/encoders.rb +3 -0
- data/lib/zipkin/encoders/json_encoder.rb +104 -0
- data/lib/zipkin/encoders/json_encoder/log_annotations.rb +34 -0
- data/lib/zipkin/encoders/json_encoder/timestamp.rb +13 -0
- data/lib/zipkin/endpoint.rb +19 -15
- data/lib/zipkin/{json_client.rb → http_client.rb} +6 -26
- data/lib/zipkin/samplers.rb +4 -0
- data/lib/zipkin/samplers/const.rb +20 -0
- data/lib/zipkin/samplers/probabilistic.rb +21 -0
- data/lib/zipkin/span.rb +12 -11
- data/lib/zipkin/span_context.rb +3 -2
- data/lib/zipkin/trace_id.rb +21 -1
- data/lib/zipkin/tracer.rb +21 -22
- data/script/create_follows_from_trace +3 -5
- data/script/create_http_trace +56 -0
- data/script/create_trace +34 -20
- data/zipkin.gemspec +3 -3
- metadata +17 -11
- data/lib/zipkin/collector.rb +0 -71
- data/lib/zipkin/collector/log_annotations.rb +0 -27
- data/lib/zipkin/collector/timestamp.rb +0 -11
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: d406755c3fae0a6ad07050d0bfa19a903ce5e5ca414ad0530d172061ef0e2a69
         | 
| 4 | 
            +
              data.tar.gz: 8f377efd4748398e92dc6cf565f40819e25cf26ca0a0b2f9c119e21ed7ce36c6
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c94f44c0d12367b67bddef7c928fa27528a13eedddf4a1b99c4c3eec34553ee8a6c949dc43797e00ce13ba8a47f59b615f4779fd7375ea1d28e2dda1a1fc6058
         | 
| 7 | 
            +
              data.tar.gz: 904580f268829d5699001cc260ed53c26def532e84e50bf6eb9b9e44c89daa5861482d77a24722b729d775c1b5dbb514812d4ff68ac0b242fbfbf873409baffc
         | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -31,6 +31,16 @@ end | |
| 31 31 |  | 
| 32 32 | 
             
            See [opentracing-ruby](https://github.com/opentracing/opentracing-ruby) for more examples.
         | 
| 33 33 |  | 
| 34 | 
            +
            ### Samplers
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            #### Const sampler
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            `Const` sampler always makes the same decision for new traces depending on the initialization value. Set `sampler` to: `Zipkin::Samplers::Const.new(true)` to mark all new traces as sampled.
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            #### Probabilistic sampler
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            `Probabilistic` sampler samples traces with probability equal to `rate` (must be between 0.0 and 1.0). Set `sampler` to `Zipkin::Samplers::Probabilistic.new(rate: 0.1)` to mark 10% of new traces as sampled.
         | 
| 43 | 
            +
             | 
| 34 44 | 
             
            ## Development
         | 
| 35 45 |  | 
| 36 46 | 
             
            After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
         | 
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'thread'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require_relative './async_reporter/buffer'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Zipkin
         | 
| 8 | 
            +
              class AsyncReporter
         | 
| 9 | 
            +
                def self.create(sender:, flush_interval:)
         | 
| 10 | 
            +
                  reporter = new(sender)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  # start flush thread
         | 
| 13 | 
            +
                  Thread.new do
         | 
| 14 | 
            +
                    loop do
         | 
| 15 | 
            +
                      reporter.flush
         | 
| 16 | 
            +
                      sleep(flush_interval)
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  reporter
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def initialize(sender)
         | 
| 24 | 
            +
                  @sender = sender
         | 
| 25 | 
            +
                  @buffer = Buffer.new
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def flush
         | 
| 29 | 
            +
                  spans = @buffer.retrieve
         | 
| 30 | 
            +
                  @sender.send_spans(spans) if spans.any?
         | 
| 31 | 
            +
                  spans
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def report(span)
         | 
| 35 | 
            +
                  return unless span.context.sampled?
         | 
| 36 | 
            +
                  @buffer << span
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Zipkin
         | 
| 4 | 
            +
              class AsyncReporter
         | 
| 5 | 
            +
                class Buffer
         | 
| 6 | 
            +
                  def initialize
         | 
| 7 | 
            +
                    @buffer = []
         | 
| 8 | 
            +
                    @mutex = Mutex.new
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def <<(element)
         | 
| 12 | 
            +
                    @mutex.synchronize do
         | 
| 13 | 
            +
                      @buffer << element
         | 
| 14 | 
            +
                      true
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def retrieve
         | 
| 19 | 
            +
                    @mutex.synchronize do
         | 
| 20 | 
            +
                      elements = @buffer.dup
         | 
| 21 | 
            +
                      @buffer.clear
         | 
| 22 | 
            +
                      elements
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,104 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'json'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require_relative 'json_encoder/timestamp'
         | 
| 6 | 
            +
            require_relative 'json_encoder/log_annotations'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            module Zipkin
         | 
| 9 | 
            +
              module Encoders
         | 
| 10 | 
            +
                class JsonEncoder
         | 
| 11 | 
            +
                  OT_KIND_TO_ZIPKIN_KIND = {
         | 
| 12 | 
            +
                    'server' => 'SERVER',
         | 
| 13 | 
            +
                    'client' => 'CLIENT',
         | 
| 14 | 
            +
                    'producer' => 'PRODUCER',
         | 
| 15 | 
            +
                    'consumer' => 'CONSUMER'
         | 
| 16 | 
            +
                  }.freeze
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  CONTENT_TYPE = 'application/json'.freeze
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  module Fields
         | 
| 21 | 
            +
                    TRACE_ID = 'traceId'.freeze
         | 
| 22 | 
            +
                    SPAN_ID = 'id'.freeze
         | 
| 23 | 
            +
                    PARENT_ID = 'parentId'.freeze
         | 
| 24 | 
            +
                    OPERATION_NAME = 'name'.freeze
         | 
| 25 | 
            +
                    KIND = 'kind'.freeze
         | 
| 26 | 
            +
                    TIMESTAMP = 'timestamp'.freeze
         | 
| 27 | 
            +
                    DURATION = 'duration'.freeze
         | 
| 28 | 
            +
                    DEBUG = 'debug'.freeze
         | 
| 29 | 
            +
                    SHARED = 'shared'.freeze
         | 
| 30 | 
            +
                    LOCAL_ENDPOINT = 'localEndpoint'.freeze
         | 
| 31 | 
            +
                    REMOTE_ENDPOINT = 'remoteEndpoint'.freeze
         | 
| 32 | 
            +
                    ANNOTATIONS = 'annotations'.freeze
         | 
| 33 | 
            +
                    TAGS = 'tags'.freeze
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    module Endpoint
         | 
| 36 | 
            +
                      SERVICE_NAME = 'serviceName'.freeze
         | 
| 37 | 
            +
                      IPV4 = 'ipv4'.freeze
         | 
| 38 | 
            +
                      IPV6 = 'ipv6'.freeze
         | 
| 39 | 
            +
                      PORT = 'port'.freeze
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def initialize(local_endpoint)
         | 
| 44 | 
            +
                    @adapter = defined?(Oj) ? OjAdapter : JsonAdapter
         | 
| 45 | 
            +
                    @local_endpoint = serialize_endpoint(local_endpoint)
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def content_type
         | 
| 49 | 
            +
                    CONTENT_TYPE
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  def encode(spans)
         | 
| 53 | 
            +
                    @adapter.dump(spans.map(&method(:serialize)))
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  private
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  def serialize(span)
         | 
| 59 | 
            +
                    finish_ts = Timestamp.create(span.end_time)
         | 
| 60 | 
            +
                    start_ts = Timestamp.create(span.start_time)
         | 
| 61 | 
            +
                    duration = finish_ts - start_ts
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    {
         | 
| 64 | 
            +
                      Fields::TRACE_ID => span.context.trace_id,
         | 
| 65 | 
            +
                      Fields::SPAN_ID => span.context.span_id,
         | 
| 66 | 
            +
                      Fields::PARENT_ID => span.context.parent_id,
         | 
| 67 | 
            +
                      Fields::OPERATION_NAME => span.operation_name,
         | 
| 68 | 
            +
                      Fields::KIND => OT_KIND_TO_ZIPKIN_KIND[span.tags[:'span.kind'] || 'server'],
         | 
| 69 | 
            +
                      Fields::TIMESTAMP => start_ts,
         | 
| 70 | 
            +
                      Fields::DURATION => duration,
         | 
| 71 | 
            +
                      Fields::DEBUG => false,
         | 
| 72 | 
            +
                      Fields::SHARED => false,
         | 
| 73 | 
            +
                      Fields::LOCAL_ENDPOINT => @local_endpoint,
         | 
| 74 | 
            +
                      Fields::REMOTE_ENDPOINT => serialize_endpoint(Endpoint.remote_endpoint(span)),
         | 
| 75 | 
            +
                      Fields::ANNOTATIONS => LogAnnotations.build(span),
         | 
| 76 | 
            +
                      Fields::TAGS => span.tags
         | 
| 77 | 
            +
                    }
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  def serialize_endpoint(endpoint)
         | 
| 81 | 
            +
                    return nil unless endpoint
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    {
         | 
| 84 | 
            +
                      Fields::Endpoint::SERVICE_NAME => endpoint.service_name,
         | 
| 85 | 
            +
                      Fields::Endpoint::IPV4 => endpoint.ipv4,
         | 
| 86 | 
            +
                      Fields::Endpoint::IPV6 => endpoint.ipv6,
         | 
| 87 | 
            +
                      Fields::Endpoint::PORT => endpoint.port
         | 
| 88 | 
            +
                    }
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  module OjAdapter
         | 
| 92 | 
            +
                    def self.dump(payload)
         | 
| 93 | 
            +
                      Oj.dump(payload, mode: :object)
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  module JsonAdapter
         | 
| 98 | 
            +
                    def self.dump(payload)
         | 
| 99 | 
            +
                      JSON.dump(payload)
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
              end
         | 
| 104 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Zipkin
         | 
| 4 | 
            +
              module Encoders
         | 
| 5 | 
            +
                class JsonEncoder
         | 
| 6 | 
            +
                  module LogAnnotations
         | 
| 7 | 
            +
                    module Fields
         | 
| 8 | 
            +
                      TIMESTAMP = 'timestamp'.freeze
         | 
| 9 | 
            +
                      VALUE = 'value'.freeze
         | 
| 10 | 
            +
                    end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    def self.build(span)
         | 
| 13 | 
            +
                      span.logs.map do |log|
         | 
| 14 | 
            +
                        {
         | 
| 15 | 
            +
                          Fields::TIMESTAMP => Timestamp.create(log.fetch(:timestamp)),
         | 
| 16 | 
            +
                          Fields::VALUE => format_log_value(log)
         | 
| 17 | 
            +
                        }
         | 
| 18 | 
            +
                      end
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    def self.format_log_value(log)
         | 
| 22 | 
            +
                      if log.keys == %i[event timestamp]
         | 
| 23 | 
            +
                        log.fetch(:event)
         | 
| 24 | 
            +
                      else
         | 
| 25 | 
            +
                        log
         | 
| 26 | 
            +
                          .reject { |key, _value| key == :timestamp }
         | 
| 27 | 
            +
                          .map { |key, value| "#{key}=#{value}" }
         | 
| 28 | 
            +
                          .join(' ')
         | 
| 29 | 
            +
                      end
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
    
        data/lib/zipkin/endpoint.rb
    CHANGED
    
    | @@ -17,10 +17,10 @@ module Zipkin | |
| 17 17 | 
             
                end
         | 
| 18 18 |  | 
| 19 19 | 
             
                module PeerInfo
         | 
| 20 | 
            -
                  SERVICE =  | 
| 21 | 
            -
                  IPV4 =  | 
| 22 | 
            -
                  IPV6 =  | 
| 23 | 
            -
                  PORT =  | 
| 20 | 
            +
                  SERVICE = 'peer.service'.freeze
         | 
| 21 | 
            +
                  IPV4 = 'peer.ipv4'.freeze
         | 
| 22 | 
            +
                  IPV6 = 'peer.ipv6'.freeze
         | 
| 23 | 
            +
                  PORT = 'peer.port'.freeze
         | 
| 24 24 |  | 
| 25 25 | 
             
                  def self.keys
         | 
| 26 26 | 
             
                    [SERVICE, IPV4, IPV6, PORT]
         | 
| @@ -28,34 +28,38 @@ module Zipkin | |
| 28 28 | 
             
                end
         | 
| 29 29 |  | 
| 30 30 | 
             
                def self.local_endpoint(service_name)
         | 
| 31 | 
            -
                   | 
| 32 | 
            -
                    serviceName: service_name,
         | 
| 33 | 
            -
                    ipv4: LOCAL_IP
         | 
| 34 | 
            -
                  }
         | 
| 31 | 
            +
                  new(service_name: service_name, ipv4: LOCAL_IP)
         | 
| 35 32 | 
             
                end
         | 
| 36 33 |  | 
| 37 34 | 
             
                def self.remote_endpoint(span)
         | 
| 38 35 | 
             
                  tags = span.tags
         | 
| 39 | 
            -
                  kind = tags[ | 
| 36 | 
            +
                  kind = tags['span.kind'] || SpanKind::SERVER
         | 
| 40 37 |  | 
| 41 38 | 
             
                  case kind
         | 
| 42 39 | 
             
                  when SpanKind::SERVER, SpanKind::CLIENT
         | 
| 43 40 | 
             
                    return nil if (tags.keys & PeerInfo.keys).empty?
         | 
| 44 41 |  | 
| 45 | 
            -
                     | 
| 46 | 
            -
                       | 
| 42 | 
            +
                    new(
         | 
| 43 | 
            +
                      service_name: tags[PeerInfo::SERVICE],
         | 
| 47 44 | 
             
                      ipv4: tags[PeerInfo::IPV4],
         | 
| 48 45 | 
             
                      ipv6: tags[PeerInfo::IPV6],
         | 
| 49 46 | 
             
                      port: tags[PeerInfo::PORT]
         | 
| 50 | 
            -
                     | 
| 47 | 
            +
                    )
         | 
| 51 48 | 
             
                  when SpanKind::PRODUCER, SpanKind::CONSUMER
         | 
| 52 | 
            -
                     | 
| 53 | 
            -
                      serviceName: 'broker'
         | 
| 54 | 
            -
                    }
         | 
| 49 | 
            +
                    new(service_name: 'broker')
         | 
| 55 50 | 
             
                  else
         | 
| 56 51 | 
             
                    warn "Unkown span kind: #{kind}"
         | 
| 57 52 | 
             
                    nil
         | 
| 58 53 | 
             
                  end
         | 
| 59 54 | 
             
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                def initialize(service_name: nil, ipv4: nil, ipv6: nil, port: nil)
         | 
| 57 | 
            +
                  @service_name = service_name
         | 
| 58 | 
            +
                  @ipv4 = ipv4
         | 
| 59 | 
            +
                  @ipv6 = ipv6
         | 
| 60 | 
            +
                  @port = port
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                attr_reader :service_name, :ipv4, :ipv6, :port
         | 
| 60 64 | 
             
              end
         | 
| 61 65 | 
             
            end
         | 
| @@ -2,43 +2,23 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require 'net/http'
         | 
| 4 4 | 
             
            require 'uri'
         | 
| 5 | 
            -
            require 'json'
         | 
| 6 5 |  | 
| 7 6 | 
             
            module Zipkin
         | 
| 8 | 
            -
              class  | 
| 9 | 
            -
                def initialize(url:,  | 
| 10 | 
            -
                  @ | 
| 11 | 
            -
                  @flush_interval = flush_interval
         | 
| 7 | 
            +
              class HTTPClient
         | 
| 8 | 
            +
                def initialize(url:, encoder:, logger:)
         | 
| 9 | 
            +
                  @encoder = encoder
         | 
| 12 10 | 
             
                  @spans_uri = URI.parse("#{url}/api/v2/spans")
         | 
| 13 11 | 
             
                  @logger = logger
         | 
| 14 12 | 
             
                end
         | 
| 15 13 |  | 
| 16 | 
            -
                def  | 
| 17 | 
            -
                  @thread = Thread.new do
         | 
| 18 | 
            -
                    loop do
         | 
| 19 | 
            -
                      emit_batch(@collector.retrieve)
         | 
| 20 | 
            -
                      sleep @flush_interval
         | 
| 21 | 
            -
                    end
         | 
| 22 | 
            -
                  end
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                def stop
         | 
| 26 | 
            -
                  @thread.terminate if @thread
         | 
| 27 | 
            -
                  emit_batch(@collector.retrieve)
         | 
| 28 | 
            -
                end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                private
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                def emit_batch(spans)
         | 
| 33 | 
            -
                  return if spans.empty?
         | 
| 34 | 
            -
             | 
| 14 | 
            +
                def send_spans(spans)
         | 
| 35 15 | 
             
                  http = Net::HTTP.new(@spans_uri.host, @spans_uri.port)
         | 
| 36 16 | 
             
                  http.use_ssl = @spans_uri.scheme == 'https'
         | 
| 37 17 | 
             
                  request = Net::HTTP::Post.new(
         | 
| 38 18 | 
             
                    @spans_uri.request_uri,
         | 
| 39 | 
            -
                    'Content-Type' =>  | 
| 19 | 
            +
                    'Content-Type' => @encoder.content_type
         | 
| 40 20 | 
             
                  )
         | 
| 41 | 
            -
                  request.body =  | 
| 21 | 
            +
                  request.body = @encoder.encode(spans)
         | 
| 42 22 | 
             
                  response = http.request(request)
         | 
| 43 23 |  | 
| 44 24 | 
             
                  if response.code != '202'
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Zipkin
         | 
| 4 | 
            +
              module Samplers
         | 
| 5 | 
            +
                # Const sampler
         | 
| 6 | 
            +
                #
         | 
| 7 | 
            +
                # A sampler that always makes the same decision for new traces depending
         | 
| 8 | 
            +
                # on the initialization value. Use `Zipkin::Samplers::Const.new(true)`
         | 
| 9 | 
            +
                # to mark all new traces as sampled.
         | 
| 10 | 
            +
                class Const
         | 
| 11 | 
            +
                  def initialize(decision)
         | 
| 12 | 
            +
                    @decision = decision
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def sample?(*)
         | 
| 16 | 
            +
                    @decision
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Zipkin
         | 
| 4 | 
            +
              module Samplers
         | 
| 5 | 
            +
                # Probabilistic sampler
         | 
| 6 | 
            +
                #
         | 
| 7 | 
            +
                # Sample a portion of traces using trace_id as the random decision
         | 
| 8 | 
            +
                class Probabilistic
         | 
| 9 | 
            +
                  def initialize(rate: 0.001)
         | 
| 10 | 
            +
                    if rate < 0.0 || rate > 1.0
         | 
| 11 | 
            +
                      raise "Sampling rate must be between 0.0 and 1.0, got #{rate.inspect}"
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
                    @boundary = TraceId::TRACE_ID_UPPER_BOUND * rate
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def sample?(trace_id:, **)
         | 
| 17 | 
            +
                    @boundary >= trace_id.to_i(16)
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
    
        data/lib/zipkin/span.rb
    CHANGED
    
    | @@ -4,30 +4,32 @@ module Zipkin | |
| 4 4 | 
             
              class Span
         | 
| 5 5 | 
             
                attr_accessor :operation_name
         | 
| 6 6 |  | 
| 7 | 
            -
                attr_reader :context, :start_time, :tags, :logs, :references
         | 
| 7 | 
            +
                attr_reader :context, :start_time, :end_time, :tags, :logs, :references
         | 
| 8 8 |  | 
| 9 9 | 
             
                # Creates a new {Span}
         | 
| 10 10 | 
             
                #
         | 
| 11 11 | 
             
                # @param context [SpanContext] the context of the span
         | 
| 12 12 | 
             
                # @param operation_name [String] the operation name
         | 
| 13 | 
            -
                # @param  | 
| 13 | 
            +
                # @param reporter [#report] the span reporter
         | 
| 14 14 | 
             
                #
         | 
| 15 15 | 
             
                # @return [Span] a new Span
         | 
| 16 16 | 
             
                def initialize(
         | 
| 17 17 | 
             
                  context,
         | 
| 18 18 | 
             
                  operation_name,
         | 
| 19 | 
            -
                   | 
| 19 | 
            +
                  reporter,
         | 
| 20 20 | 
             
                  start_time: Time.now,
         | 
| 21 21 | 
             
                  tags: {},
         | 
| 22 22 | 
             
                  references: nil
         | 
| 23 23 | 
             
                )
         | 
| 24 24 | 
             
                  @context = context
         | 
| 25 25 | 
             
                  @operation_name = operation_name
         | 
| 26 | 
            -
                  @ | 
| 26 | 
            +
                  @reporter = reporter
         | 
| 27 27 | 
             
                  @start_time = start_time
         | 
| 28 | 
            -
                  @tags =  | 
| 28 | 
            +
                  @tags = {}
         | 
| 29 29 | 
             
                  @logs = []
         | 
| 30 30 | 
             
                  @references = references
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  tags.each(&method(:set_tag))
         | 
| 31 33 | 
             
                end
         | 
| 32 34 |  | 
| 33 35 | 
             
                # Set a tag value on this span
         | 
| @@ -37,7 +39,7 @@ module Zipkin | |
| 37 39 | 
             
                # a String, Numeric, or Boolean it will be encoded with to_s
         | 
| 38 40 | 
             
                def set_tag(key, value)
         | 
| 39 41 | 
             
                  sanitized_value = valid_tag_value?(value) ? value : value.to_s
         | 
| 40 | 
            -
                  @tags = @tags.merge(key. | 
| 42 | 
            +
                  @tags = @tags.merge(key.to_s => sanitized_value)
         | 
| 41 43 | 
             
                end
         | 
| 42 44 |  | 
| 43 45 | 
             
                # Set a baggage item on the span
         | 
| @@ -78,16 +80,15 @@ module Zipkin | |
| 78 80 | 
             
                #
         | 
| 79 81 | 
             
                # @param end_time [Time] custom end time, if not now
         | 
| 80 82 | 
             
                def finish(end_time: Time.now)
         | 
| 81 | 
            -
                  @ | 
| 83 | 
            +
                  @end_time = end_time
         | 
| 84 | 
            +
                  @reporter.report(self)
         | 
| 82 85 | 
             
                end
         | 
| 83 86 |  | 
| 84 87 | 
             
                private
         | 
| 85 88 |  | 
| 89 | 
            +
                # Zipkin supports only strings and numbers
         | 
| 86 90 | 
             
                def valid_tag_value?(value)
         | 
| 87 | 
            -
                  value.is_a?(String) ||
         | 
| 88 | 
            -
                    value.is_a?(Numeric) ||
         | 
| 89 | 
            -
                    value.is_a?(TrueClass) ||
         | 
| 90 | 
            -
                    value.is_a?(FalseClass)
         | 
| 91 | 
            +
                  value.is_a?(String) || value.is_a?(Numeric)
         | 
| 91 92 | 
             
                end
         | 
| 92 93 | 
             
              end
         | 
| 93 94 | 
             
            end
         | 
    
        data/lib/zipkin/span_context.rb
    CHANGED
    
    | @@ -3,9 +3,10 @@ | |
| 3 3 | 
             
            module Zipkin
         | 
| 4 4 | 
             
              # SpanContext holds the data for a span that gets inherited to child spans
         | 
| 5 5 | 
             
              class SpanContext
         | 
| 6 | 
            -
                def self.create_parent_context
         | 
| 6 | 
            +
                def self.create_parent_context(sampler = Samplers::Const.new(true))
         | 
| 7 7 | 
             
                  trace_id = TraceId.generate
         | 
| 8 | 
            -
                   | 
| 8 | 
            +
                  sampled = sampler.sample?(trace_id: trace_id)
         | 
| 9 | 
            +
                  new(trace_id: trace_id, span_id: trace_id, sampled: sampled)
         | 
| 9 10 | 
             
                end
         | 
| 10 11 |  | 
| 11 12 | 
             
                def self.create_from_parent_context(span_context)
         | 
    
        data/lib/zipkin/trace_id.rb
    CHANGED
    
    | @@ -4,8 +4,28 @@ module Zipkin | |
| 4 4 | 
             
              module TraceId
         | 
| 5 5 | 
             
                TRACE_ID_UPPER_BOUND = 2**64
         | 
| 6 6 |  | 
| 7 | 
            +
                # Random number generator for generating IDs. This is an object that can
         | 
| 8 | 
            +
                # respond to `#bytes` and uses the system PRNG. The current logic is
         | 
| 9 | 
            +
                # compatible with Ruby 2.5 (which does not implement the `Random.bytes`
         | 
| 10 | 
            +
                # class method) and with Ruby 3.0+ (which deprecates `Random::DEFAULT`).
         | 
| 11 | 
            +
                # When we drop support for Ruby 2.5, this can simply be replaced with
         | 
| 12 | 
            +
                # the class `Random`.
         | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                # @return [#bytes]
         | 
| 15 | 
            +
                RANDOM = Random.respond_to?(:bytes) ? Random : Random::DEFAULT
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                # An invalid trace identifier, an 8-byte string with all zero bytes.
         | 
| 18 | 
            +
                INVALID_TRACE_ID = ("\0" * 8).b
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                # Generates a valid trace identifier, an 8-byte string with at least one
         | 
| 21 | 
            +
                # non-zero byte.
         | 
| 22 | 
            +
                #
         | 
| 23 | 
            +
                # @return [String] a valid trace ID.
         | 
| 7 24 | 
             
                def self.generate
         | 
| 8 | 
            -
                   | 
| 25 | 
            +
                  loop do
         | 
| 26 | 
            +
                    id = RANDOM.bytes(8)
         | 
| 27 | 
            +
                    return id.unpack1('H*') if id != INVALID_TRACE_ID
         | 
| 28 | 
            +
                  end
         | 
| 9 29 | 
             
                end
         | 
| 10 30 | 
             
              end
         | 
| 11 31 | 
             
            end
         | 
    
        data/lib/zipkin/tracer.rb
    CHANGED
    
    | @@ -7,37 +7,36 @@ require_relative 'span' | |
| 7 7 | 
             
            require_relative 'span_context'
         | 
| 8 8 | 
             
            require_relative 'carrier'
         | 
| 9 9 | 
             
            require_relative 'trace_id'
         | 
| 10 | 
            -
            require_relative ' | 
| 10 | 
            +
            require_relative 'http_client'
         | 
| 11 11 | 
             
            require_relative 'endpoint'
         | 
| 12 | 
            -
            require_relative ' | 
| 12 | 
            +
            require_relative 'async_reporter'
         | 
| 13 13 | 
             
            require_relative 'scope_manager'
         | 
| 14 14 | 
             
            require_relative 'scope'
         | 
| 15 | 
            +
            require_relative 'samplers'
         | 
| 16 | 
            +
            require_relative 'encoders'
         | 
| 15 17 |  | 
| 16 18 | 
             
            module Zipkin
         | 
| 17 19 | 
             
              class Tracer
         | 
| 18 20 | 
             
                DEFAULT_FLUSH_INTERVAL = 10
         | 
| 19 21 |  | 
| 20 | 
            -
                def self.build(url:, | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
                  )
         | 
| 28 | 
            -
                  sender | 
| 29 | 
            -
                  new( | 
| 22 | 
            +
                def self.build(url:,
         | 
| 23 | 
            +
                               service_name:,
         | 
| 24 | 
            +
                               flush_interval: DEFAULT_FLUSH_INTERVAL,
         | 
| 25 | 
            +
                               logger: Logger.new(STDOUT),
         | 
| 26 | 
            +
                               sampler: Samplers::Const.new(true),
         | 
| 27 | 
            +
                               encoder: Encoders::JsonEncoder)
         | 
| 28 | 
            +
                  encoder = encoder.new(Endpoint.local_endpoint(service_name))
         | 
| 29 | 
            +
                  sender = HTTPClient.new(url: url, encoder: encoder, logger: logger)
         | 
| 30 | 
            +
                  reporter = AsyncReporter.create(sender: sender, flush_interval: flush_interval)
         | 
| 31 | 
            +
                  new(reporter, sender, logger: logger, sampler: sampler)
         | 
| 30 32 | 
             
                end
         | 
| 31 33 |  | 
| 32 | 
            -
                def initialize( | 
| 33 | 
            -
                  @ | 
| 34 | 
            +
                def initialize(reporter, sender, logger: Logger.new(STDOUT), sampler:)
         | 
| 35 | 
            +
                  @reporter = reporter
         | 
| 34 36 | 
             
                  @sender = sender
         | 
| 35 37 | 
             
                  @logger = logger
         | 
| 36 38 | 
             
                  @scope_manager = ScopeManager.new
         | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
                def stop
         | 
| 40 | 
            -
                  @sender.stop
         | 
| 39 | 
            +
                  @sampler = sampler
         | 
| 41 40 | 
             
                end
         | 
| 42 41 |  | 
| 43 42 | 
             
                # @return [ScopeManager] the current ScopeManager, which may be a no-op but
         | 
| @@ -75,7 +74,7 @@ module Zipkin | |
| 75 74 | 
             
                def start_span(operation_name,
         | 
| 76 75 | 
             
                               child_of: nil,
         | 
| 77 76 | 
             
                               start_time: Time.now,
         | 
| 78 | 
            -
                               tags:  | 
| 77 | 
            +
                               tags: nil,
         | 
| 79 78 | 
             
                               references: nil,
         | 
| 80 79 | 
             
                               ignore_active_scope: false,
         | 
| 81 80 | 
             
                               **)
         | 
| @@ -87,10 +86,10 @@ module Zipkin | |
| 87 86 | 
             
                  Span.new(
         | 
| 88 87 | 
             
                    context,
         | 
| 89 88 | 
             
                    operation_name,
         | 
| 90 | 
            -
                    @ | 
| 89 | 
            +
                    @reporter,
         | 
| 91 90 | 
             
                    start_time: start_time,
         | 
| 92 91 | 
             
                    references: references,
         | 
| 93 | 
            -
                    tags: tags
         | 
| 92 | 
            +
                    tags: tags || {}
         | 
| 94 93 | 
             
                  )
         | 
| 95 94 | 
             
                end
         | 
| 96 95 |  | 
| @@ -220,7 +219,7 @@ module Zipkin | |
| 220 219 | 
             
                  if context
         | 
| 221 220 | 
             
                    SpanContext.create_from_parent_context(context)
         | 
| 222 221 | 
             
                  else
         | 
| 223 | 
            -
                    SpanContext.create_parent_context
         | 
| 222 | 
            +
                    SpanContext.create_parent_context(@sampler)
         | 
| 224 223 | 
             
                  end
         | 
| 225 224 | 
             
                end
         | 
| 226 225 |  | 
| @@ -1,4 +1,5 @@ | |
| 1 1 | 
             
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require 'bundler'
         | 
| 4 5 | 
             
            Bundler.setup
         | 
| @@ -7,8 +8,8 @@ require 'zipkin/tracer' | |
| 7 8 |  | 
| 8 9 | 
             
            url = ENV['ZIPKIN_URL'] || 'http://localhost:9411'
         | 
| 9 10 |  | 
| 10 | 
            -
            tracer1 = Zipkin::Tracer.build(url: url, service_name: 'test-service')
         | 
| 11 | 
            -
            tracer2 = Zipkin::Tracer.build(url: url, service_name: 'downstream-service')
         | 
| 11 | 
            +
            tracer1 = Zipkin::Tracer.build(url: url, service_name: 'test-service', flush_interval: 1)
         | 
| 12 | 
            +
            tracer2 = Zipkin::Tracer.build(url: url, service_name: 'downstream-service', flush_interval: 1)
         | 
| 12 13 |  | 
| 13 14 | 
             
            rpc_span = tracer1.start_span(
         | 
| 14 15 | 
             
              'receive request',
         | 
| @@ -45,7 +46,4 @@ async_span = tracer2.start_span( | |
| 45 46 | 
             
            sleep 0.3 # emulate network delay
         | 
| 46 47 | 
             
            async_span.finish
         | 
| 47 48 |  | 
| 48 | 
            -
            tracer1.stop
         | 
| 49 | 
            -
            tracer2.stop
         | 
| 50 | 
            -
             | 
| 51 49 | 
             
            puts 'Finished'
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'bundler'
         | 
| 5 | 
            +
            Bundler.setup
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            require 'zipkin/tracer'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            url = ENV['ZIPKIN_URL'] || 'http://localhost:9411'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            tracer1 = Zipkin::Tracer.build(url: url, service_name: 'user-service', flush_interval: 1)
         | 
| 12 | 
            +
            tracer2 = Zipkin::Tracer.build(url: url, service_name: 'name-service', flush_interval: 1)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            root_span = tracer1.start_span(
         | 
| 15 | 
            +
              'GET /users/:id',
         | 
| 16 | 
            +
              tags: {
         | 
| 17 | 
            +
                'span.kind' => 'server',
         | 
| 18 | 
            +
                'http.method' => 'get',
         | 
| 19 | 
            +
                'http.url' => 'http://example.com/users/5'
         | 
| 20 | 
            +
              }
         | 
| 21 | 
            +
            )
         | 
| 22 | 
            +
            sleep 1
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            fetch_name_span = tracer1.start_span(
         | 
| 25 | 
            +
              'get',
         | 
| 26 | 
            +
              child_of: root_span,
         | 
| 27 | 
            +
              tags: {
         | 
| 28 | 
            +
                'span.kind' => 'client',
         | 
| 29 | 
            +
                'http.method' => 'get',
         | 
| 30 | 
            +
                'http.url' => 'GET /users/5/name'
         | 
| 31 | 
            +
              }
         | 
| 32 | 
            +
            )
         | 
| 33 | 
            +
            sleep 0.3 # emulate network delay
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            name_service_span = tracer2.start_span(
         | 
| 36 | 
            +
              'GET /users/:id/name',
         | 
| 37 | 
            +
              child_of: fetch_name_span,
         | 
| 38 | 
            +
              tags: {
         | 
| 39 | 
            +
                'span.kind' => 'server',
         | 
| 40 | 
            +
                'http.method' => 'get',
         | 
| 41 | 
            +
                'http.url' => 'http://example.com/users/5/name'
         | 
| 42 | 
            +
              }
         | 
| 43 | 
            +
            )
         | 
| 44 | 
            +
            sleep 0.5
         | 
| 45 | 
            +
            name_service_span.finish
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            sleep 0.2 # emulate network delay
         | 
| 48 | 
            +
            fetch_name_span.finish
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            sleep 0.1 # doing something with fetched info
         | 
| 51 | 
            +
            root_span.finish
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            puts 'Finishing...'
         | 
| 54 | 
            +
            sleep 3
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            puts 'Finished'
         | 
    
        data/script/create_trace
    CHANGED
    
    | @@ -1,4 +1,5 @@ | |
| 1 1 | 
             
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require 'bundler'
         | 
| 4 5 | 
             
            Bundler.setup
         | 
| @@ -7,10 +8,10 @@ require 'zipkin/tracer' | |
| 7 8 |  | 
| 8 9 | 
             
            url = ENV['ZIPKIN_URL'] || 'http://localhost:9411'
         | 
| 9 10 |  | 
| 10 | 
            -
            tracer1 = Zipkin::Tracer.build(url: url, service_name: 'test-service')
         | 
| 11 | 
            -
            tracer2 = Zipkin::Tracer.build(url: url, service_name: 'downstream-service')
         | 
| 11 | 
            +
            tracer1 = Zipkin::Tracer.build(url: url, service_name: 'test-service', flush_interval: 1)
         | 
| 12 | 
            +
            tracer2 = Zipkin::Tracer.build(url: url, service_name: 'downstream-service-1', flush_interval: 1)
         | 
| 12 13 |  | 
| 13 | 
            -
             | 
| 14 | 
            +
            root_span = tracer1.start_span(
         | 
| 14 15 | 
             
              'receive request',
         | 
| 15 16 | 
             
              tags: {
         | 
| 16 17 | 
             
                'span.kind' => 'server'
         | 
| @@ -18,39 +19,52 @@ outer_span = tracer1.start_span( | |
| 18 19 | 
             
            )
         | 
| 19 20 | 
             
            sleep 1
         | 
| 20 21 |  | 
| 21 | 
            -
             | 
| 22 | 
            -
              'fetch info from  | 
| 23 | 
            -
              child_of:  | 
| 22 | 
            +
            fetch_info_from_service1_span = tracer1.start_span(
         | 
| 23 | 
            +
              'fetch info from service 1',
         | 
| 24 | 
            +
              child_of: root_span,
         | 
| 24 25 | 
             
              tags: {
         | 
| 25 26 | 
             
                'span.kind' => 'client',
         | 
| 26 | 
            -
                'peer. | 
| 27 | 
            -
                'peer.ipv4' => '6.6.6.6',
         | 
| 27 | 
            +
                'peer.ipv4' => '2.2.2.2',
         | 
| 28 28 | 
             
                'peer.port' => 443
         | 
| 29 29 | 
             
              }
         | 
| 30 30 | 
             
            )
         | 
| 31 31 | 
             
            sleep 0.3 # emulate network delay
         | 
| 32 32 |  | 
| 33 | 
            -
             | 
| 34 | 
            -
              ' | 
| 35 | 
            -
              child_of:  | 
| 36 | 
            -
              tags: { | 
| 33 | 
            +
            service1_span = tracer2.start_span(
         | 
| 34 | 
            +
              'service 1 operation',
         | 
| 35 | 
            +
              child_of: fetch_info_from_service1_span,
         | 
| 36 | 
            +
              tags: {
         | 
| 37 | 
            +
                'span.kind' => 'server',
         | 
| 38 | 
            +
                'peer.ipv4' => '1.1.1.1',
         | 
| 39 | 
            +
                'peer.port' => 443
         | 
| 40 | 
            +
              }
         | 
| 37 41 | 
             
            )
         | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 42 | 
            +
            service1_span.log_kv(event: 'custom-event')
         | 
| 43 | 
            +
            service1_span.log_kv(foo: 'bar', baz: 'buz')
         | 
| 40 44 | 
             
            sleep 0.5
         | 
| 41 | 
            -
             | 
| 45 | 
            +
            service1_span.finish
         | 
| 42 46 |  | 
| 43 47 | 
             
            sleep 0.2 # emulate network delay
         | 
| 44 48 |  | 
| 45 | 
            -
             | 
| 49 | 
            +
            fetch_info_from_service1_span.finish
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            fetch_info_from_service2_span = tracer1.start_span(
         | 
| 52 | 
            +
              'fetch info from service 2 which does not have tracing',
         | 
| 53 | 
            +
              child_of: root_span,
         | 
| 54 | 
            +
              tags: {
         | 
| 55 | 
            +
                'span.kind' => 'client',
         | 
| 56 | 
            +
                'peer.service' => 'downstream-service-2',
         | 
| 57 | 
            +
                'peer.ipv4' => '3.3.3.3',
         | 
| 58 | 
            +
                'peer.port' => 443
         | 
| 59 | 
            +
              }
         | 
| 60 | 
            +
            )
         | 
| 61 | 
            +
            sleep 0.3 # emulate network delay
         | 
| 62 | 
            +
            fetch_info_from_service2_span.finish
         | 
| 46 63 |  | 
| 47 64 | 
             
            sleep 0.1 # doing something with fetched info
         | 
| 48 | 
            -
             | 
| 65 | 
            +
            root_span.finish
         | 
| 49 66 |  | 
| 50 67 | 
             
            puts 'Finishing...'
         | 
| 51 68 | 
             
            sleep 3
         | 
| 52 69 |  | 
| 53 | 
            -
            tracer1.stop
         | 
| 54 | 
            -
            tracer2.stop
         | 
| 55 | 
            -
             | 
| 56 70 | 
             
            puts 'Finished'
         | 
    
        data/zipkin.gemspec
    CHANGED
    
    | @@ -3,13 +3,13 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) | |
| 3 3 |  | 
| 4 4 | 
             
            Gem::Specification.new do |spec|
         | 
| 5 5 | 
             
              spec.name          = 'zipkin'
         | 
| 6 | 
            -
              spec.version       = '1. | 
| 6 | 
            +
              spec.version       = '1.6.2'
         | 
| 7 7 | 
             
              spec.authors       = ['SaleMove TechMovers']
         | 
| 8 8 | 
             
              spec.email         = ['techmovers@salemove.com']
         | 
| 9 9 |  | 
| 10 10 | 
             
              spec.summary       = 'OpenTracing Tracer implementation for Zipkin in Ruby'
         | 
| 11 11 | 
             
              spec.description   = ''
         | 
| 12 | 
            -
              spec.homepage      = ''
         | 
| 12 | 
            +
              spec.homepage      = 'https://github.com/salemove/zipkin-ruby-opentracing'
         | 
| 13 13 | 
             
              spec.license       = 'MIT'
         | 
| 14 14 |  | 
| 15 15 | 
             
              spec.files         = `git ls-files -z`.split("\x0").reject do |f|
         | 
| @@ -18,7 +18,7 @@ Gem::Specification.new do |spec| | |
| 18 18 | 
             
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         | 
| 19 19 | 
             
              spec.require_paths = ['lib']
         | 
| 20 20 |  | 
| 21 | 
            -
              spec.add_development_dependency 'bundler', '~>  | 
| 21 | 
            +
              spec.add_development_dependency 'bundler', '~> 2.0'
         | 
| 22 22 | 
             
              spec.add_development_dependency 'rake', '~> 10.0'
         | 
| 23 23 | 
             
              spec.add_development_dependency 'rspec', '~> 3.0'
         | 
| 24 24 | 
             
              spec.add_development_dependency 'rubocop', '~> 0.54.0'
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: zipkin
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.6.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - SaleMove TechMovers
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2021-01-21 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -16,14 +16,14 @@ dependencies: | |
| 16 16 | 
             
                requirements:
         | 
| 17 17 | 
             
                - - "~>"
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: ' | 
| 19 | 
            +
                    version: '2.0'
         | 
| 20 20 | 
             
              type: :development
         | 
| 21 21 | 
             
              prerelease: false
         | 
| 22 22 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 23 | 
             
                requirements:
         | 
| 24 24 | 
             
                - - "~>"
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            -
                    version: ' | 
| 26 | 
            +
                    version: '2.0'
         | 
| 27 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 28 | 
             
              name: rake
         | 
| 29 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -126,12 +126,18 @@ files: | |
| 126 126 | 
             
            - bin/console
         | 
| 127 127 | 
             
            - bin/setup
         | 
| 128 128 | 
             
            - lib/zipkin.rb
         | 
| 129 | 
            +
            - lib/zipkin/async_reporter.rb
         | 
| 130 | 
            +
            - lib/zipkin/async_reporter/buffer.rb
         | 
| 129 131 | 
             
            - lib/zipkin/carrier.rb
         | 
| 130 | 
            -
            - lib/zipkin/ | 
| 131 | 
            -
            - lib/zipkin/ | 
| 132 | 
            -
            - lib/zipkin/ | 
| 132 | 
            +
            - lib/zipkin/encoders.rb
         | 
| 133 | 
            +
            - lib/zipkin/encoders/json_encoder.rb
         | 
| 134 | 
            +
            - lib/zipkin/encoders/json_encoder/log_annotations.rb
         | 
| 135 | 
            +
            - lib/zipkin/encoders/json_encoder/timestamp.rb
         | 
| 133 136 | 
             
            - lib/zipkin/endpoint.rb
         | 
| 134 | 
            -
            - lib/zipkin/ | 
| 137 | 
            +
            - lib/zipkin/http_client.rb
         | 
| 138 | 
            +
            - lib/zipkin/samplers.rb
         | 
| 139 | 
            +
            - lib/zipkin/samplers/const.rb
         | 
| 140 | 
            +
            - lib/zipkin/samplers/probabilistic.rb
         | 
| 135 141 | 
             
            - lib/zipkin/scope.rb
         | 
| 136 142 | 
             
            - lib/zipkin/scope_manager.rb
         | 
| 137 143 | 
             
            - lib/zipkin/scope_manager/scope_identifier.rb
         | 
| @@ -141,9 +147,10 @@ files: | |
| 141 147 | 
             
            - lib/zipkin/trace_id.rb
         | 
| 142 148 | 
             
            - lib/zipkin/tracer.rb
         | 
| 143 149 | 
             
            - script/create_follows_from_trace
         | 
| 150 | 
            +
            - script/create_http_trace
         | 
| 144 151 | 
             
            - script/create_trace
         | 
| 145 152 | 
             
            - zipkin.gemspec
         | 
| 146 | 
            -
            homepage:  | 
| 153 | 
            +
            homepage: https://github.com/salemove/zipkin-ruby-opentracing
         | 
| 147 154 | 
             
            licenses:
         | 
| 148 155 | 
             
            - MIT
         | 
| 149 156 | 
             
            metadata: {}
         | 
| @@ -162,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 162 169 | 
             
                - !ruby/object:Gem::Version
         | 
| 163 170 | 
             
                  version: '0'
         | 
| 164 171 | 
             
            requirements: []
         | 
| 165 | 
            -
             | 
| 166 | 
            -
            rubygems_version: 2.6.11
         | 
| 172 | 
            +
            rubygems_version: 3.0.3
         | 
| 167 173 | 
             
            signing_key: 
         | 
| 168 174 | 
             
            specification_version: 4
         | 
| 169 175 | 
             
            summary: OpenTracing Tracer implementation for Zipkin in Ruby
         | 
    
        data/lib/zipkin/collector.rb
    DELETED
    
    | @@ -1,71 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require 'thread'
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            require_relative './collector/timestamp'
         | 
| 6 | 
            -
            require_relative './collector/log_annotations'
         | 
| 7 | 
            -
             | 
| 8 | 
            -
            module Zipkin
         | 
| 9 | 
            -
              class Collector
         | 
| 10 | 
            -
                OT_KIND_TO_ZIPKIN_KIND = {
         | 
| 11 | 
            -
                  'server' => 'SERVER',
         | 
| 12 | 
            -
                  'client' => 'CLIENT',
         | 
| 13 | 
            -
                  'producer' => 'PRODUCER',
         | 
| 14 | 
            -
                  'consumer' => 'CONSUMER'
         | 
| 15 | 
            -
                }.freeze
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                def initialize(local_endpoint)
         | 
| 18 | 
            -
                  @buffer = Buffer.new
         | 
| 19 | 
            -
                  @local_endpoint = local_endpoint
         | 
| 20 | 
            -
                end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                def retrieve
         | 
| 23 | 
            -
                  @buffer.retrieve
         | 
| 24 | 
            -
                end
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                def send_span(span, end_time)
         | 
| 27 | 
            -
                  finish_ts = Timestamp.create(end_time)
         | 
| 28 | 
            -
                  start_ts = Timestamp.create(span.start_time)
         | 
| 29 | 
            -
                  duration = finish_ts - start_ts
         | 
| 30 | 
            -
                  return unless span.context.sampled?
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                  @buffer << {
         | 
| 33 | 
            -
                    traceId: span.context.trace_id,
         | 
| 34 | 
            -
                    id: span.context.span_id,
         | 
| 35 | 
            -
                    parentId: span.context.parent_id,
         | 
| 36 | 
            -
                    name: span.operation_name,
         | 
| 37 | 
            -
                    kind: OT_KIND_TO_ZIPKIN_KIND[span.tags[:'span.kind'] || 'server'],
         | 
| 38 | 
            -
                    timestamp: start_ts,
         | 
| 39 | 
            -
                    duration: duration,
         | 
| 40 | 
            -
                    debug: false,
         | 
| 41 | 
            -
                    shared: false,
         | 
| 42 | 
            -
                    localEndpoint: @local_endpoint,
         | 
| 43 | 
            -
                    remoteEndpoint: Endpoint.remote_endpoint(span),
         | 
| 44 | 
            -
                    annotations: LogAnnotations.build(span),
         | 
| 45 | 
            -
                    tags: span.tags
         | 
| 46 | 
            -
                  }
         | 
| 47 | 
            -
                end
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                class Buffer
         | 
| 50 | 
            -
                  def initialize
         | 
| 51 | 
            -
                    @buffer = []
         | 
| 52 | 
            -
                    @mutex = Mutex.new
         | 
| 53 | 
            -
                  end
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                  def <<(element)
         | 
| 56 | 
            -
                    @mutex.synchronize do
         | 
| 57 | 
            -
                      @buffer << element
         | 
| 58 | 
            -
                      true
         | 
| 59 | 
            -
                    end
         | 
| 60 | 
            -
                  end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                  def retrieve
         | 
| 63 | 
            -
                    @mutex.synchronize do
         | 
| 64 | 
            -
                      elements = @buffer.dup
         | 
| 65 | 
            -
                      @buffer.clear
         | 
| 66 | 
            -
                      elements
         | 
| 67 | 
            -
                    end
         | 
| 68 | 
            -
                  end
         | 
| 69 | 
            -
                end
         | 
| 70 | 
            -
              end
         | 
| 71 | 
            -
            end
         | 
| @@ -1,27 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Zipkin
         | 
| 4 | 
            -
              class Collector
         | 
| 5 | 
            -
                module LogAnnotations
         | 
| 6 | 
            -
                  def self.build(span)
         | 
| 7 | 
            -
                    span.logs.map do |log|
         | 
| 8 | 
            -
                      {
         | 
| 9 | 
            -
                        timestamp: Timestamp.create(log.fetch(:timestamp)),
         | 
| 10 | 
            -
                        value: format_log_value(log)
         | 
| 11 | 
            -
                      }
         | 
| 12 | 
            -
                    end
         | 
| 13 | 
            -
                  end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                  def self.format_log_value(log)
         | 
| 16 | 
            -
                    if log.keys == %i[event timestamp]
         | 
| 17 | 
            -
                      log.fetch(:event)
         | 
| 18 | 
            -
                    else
         | 
| 19 | 
            -
                      log
         | 
| 20 | 
            -
                        .reject { |key, _value| key == :timestamp }
         | 
| 21 | 
            -
                        .map { |key, value| "#{key}=#{value}" }
         | 
| 22 | 
            -
                        .join(' ')
         | 
| 23 | 
            -
                    end
         | 
| 24 | 
            -
                  end
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
              end
         | 
| 27 | 
            -
            end
         |