jaeger-client 0.10.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7de16fd42664a20ad343e3fdc701f057b93df9e9c8ac6e76d4ea6b36895a7733
4
- data.tar.gz: 32421b715a39b2710cae5bf9f7c6ca075872717ac53964de98429f063ebc93ba
3
+ metadata.gz: 16e6a368a65ce75432681a4487909971193d06e6bca4aff72cf39b0a4af2eb8f
4
+ data.tar.gz: f6a665ce70c4804484fefb1fb5d1c0ddbd41b117b78d688559fa9adceaa55e1c
5
5
  SHA512:
6
- metadata.gz: dacf1771b57e8f12074a0426b75b09b6a19610c13d4cb86b687e9930fc24a7e4a20f5c5e2819760e02a88baf01a8438f2175688be57dff2dffd80e5d45303522
7
- data.tar.gz: b8bdaa192c6c2109b7711431ec9eebe3e4352e5e71426c65355abd5aad358cf0f4ceaaecb25dec2cf3a622d0982294ea578858234c71682a841f7bb3bb4090c0
6
+ metadata.gz: 06165b0c04dd22c36064cd4f4e829c06e8883dc56b5b9b48aa8e4c82c673a150dd0d426bb56ffc73148d466965c11d1518c322dedf4134e986e54c7bfaad24c7
7
+ data.tar.gz: 2e91ace1219ad1f9456098ef897c234c92f79b2190794c95775a56a8b79086869bed55e4f4076d69d7aea7b0630fa78be5d6811ed4bd04a865ffba2d8105f3c8
@@ -0,0 +1,33 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+ branches: [ master ]
7
+ schedule:
8
+ # Runs at 00:00 UTC on the 1st of every month.
9
+ - cron: '0 0 1 * *'
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ ruby-version: ['2.7.2', '3.0', '3.1']
17
+
18
+ services:
19
+ postgres:
20
+ image: docker
21
+ steps:
22
+ - uses: actions/checkout@v2
23
+ with:
24
+ submodules: true
25
+ - name: Set up Ruby
26
+ uses: ruby/setup-ruby@v1
27
+ with:
28
+ ruby-version: ${{ matrix.ruby-version }}
29
+ bundler-cache: true
30
+ - name: Run tests
31
+ run: bundle exec rake
32
+ - name: Run crossdock
33
+ run: make crossdock
data/.rubocop.yml CHANGED
@@ -1,8 +1,13 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
1
3
  require: rubocop-rspec
2
4
 
3
5
  AllCops:
4
6
  Exclude:
5
7
  - 'thrift/**/*'
8
+ - 'vendor/bundle/**/*'
9
+ NewCops: enable
10
+ TargetRubyVersion: '2.7'
6
11
 
7
12
  Style/Documentation:
8
13
  Enabled: no
@@ -19,6 +24,9 @@ RSpec/ExampleLength:
19
24
  RSpec/MultipleExpectations:
20
25
  Enabled: no
21
26
 
27
+ RSpec/MultipleMemoizedHelpers:
28
+ Enabled: no
29
+
22
30
  RSpec/MessageSpies:
23
31
  Enabled: no
24
32
 
@@ -46,5 +54,8 @@ Style/FrozenStringLiteralComment:
46
54
  Include:
47
55
  - 'lib/**/*'
48
56
 
49
- Metrics/LineLength:
57
+ Layout/LineLength:
50
58
  Max: 120
59
+
60
+ Style/SingleLineMethods:
61
+ Enabled: false
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,13 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2022-01-25 17:49:13 UTC using RuboCop version 1.25.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Cop supports --auto-correct.
11
+ Style/CollectionCompact:
12
+ Exclude:
13
+ - 'lib/jaeger/tracer.rb'
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  Jaeger::Client
2
2
  ================
3
3
  [![Gem Version](https://badge.fury.io/rb/jaeger-client.svg)](https://rubygems.org/gems/jaeger-client)
4
- [![Build Status](https://travis-ci.org/salemove/jaeger-client-ruby.svg)](https://travis-ci.org/salemove/jaeger-client-ruby)
4
+ [![Build Status](https://github.com/salemove/jaeger-client-ruby/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/salemove/jaeger-client-ruby/actions/workflows/ci.yml?query=branch%3Amaster)
5
+
6
+ **This project is not actively maintained. Please consider using [OpenTelemetry](https://opentelemetry.io/)**
5
7
 
6
8
  OpenTracing Tracer implementation for Jaeger in Ruby
7
9
 
@@ -26,6 +28,9 @@ OpenTracing.start_active_span('span name') do
26
28
  # do something else
27
29
  end
28
30
  end
31
+
32
+ # don't kill the program too soon, allow time for the background reporter to send the traces
33
+ sleep 2
29
34
  ```
30
35
 
31
36
  See [opentracing-ruby](https://github.com/opentracing/opentracing-ruby) for more examples.
@@ -109,8 +114,8 @@ Set `sampler` to
109
114
  Jaeger::Samplers::PerOperation.new(
110
115
  strategies: {
111
116
  per_operation_strategies: [
112
- { operation: 'GET /articles', probabilistic_sampling: 0.5 },
113
- { operation: 'POST /articles', probabilistic_sampling: 1.0 }
117
+ { operation: 'GET /articles', probabilistic_sampling: { sampling_rate: 0.5 } },
118
+ { operation: 'POST /articles', probabilistic_sampling: { sampling_rate: 1.0 } }
114
119
  ],
115
120
  default_sampling_probability: 0.001,
116
121
  default_lower_bound_traces_per_second: 1.0 / (10.0 * 60.0)
@@ -119,6 +124,39 @@ Set `sampler` to
119
124
  )
120
125
  ```
121
126
 
127
+ #### RemoteControlled sampler
128
+
129
+ `RemoteControlled` sampler is a sampler that is controller by jaeger agent. It starts out with `Probabilistic` sampler. It polls the jaeger-agent and changes sampling strategy accordingly. Set `sampler` to `Jaeger::Client::Samplers::RemoteControlled.new(service_name: 'service_name')`.
130
+
131
+ RemoteControlled sampler options:
132
+
133
+ | Param | Required | Description |
134
+ |-------------------|----------|-------------|
135
+ | service_name | x | name of the current service / application, same as given to Tracer |
136
+ | sampler | | initial sampler to use prior to retrieving strategies from Agent |
137
+ | refresh_interval | | interval in seconds before sampling strategy refreshes (0 to not refresh, defaults to 60) |
138
+ | host | | host for jaeger-agent (defaults to 'localhost') |
139
+ | port | | port for jaeger-agent for SamplingManager endpoint (defaults to 5778) |
140
+ | logger | | logger for communication between jaeger-agent (default to $stdout logger) |
141
+
142
+ ### TraceContext compatible header propagation
143
+
144
+ It is possible to use [W3C Trace Context](https://www.w3.org/TR/trace-context/#overview) headers to propagate the tracing information.
145
+
146
+ To set it up you need to change FORMAT_RACK injector and extractor.
147
+
148
+ ```ruby
149
+ OpenTracing.global_tracer = Jaeger::Client.build(
150
+ service_name: 'service_name',
151
+ injectors: {
152
+ OpenTracing::FORMAT_RACK => [Jaeger::Injectors::TraceContextRackCodec]
153
+ },
154
+ extractors: {
155
+ OpenTracing::FORMAT_RACK => [Jaeger::Extractors::TraceContextRackCodec]
156
+ }
157
+ )
158
+ ```
159
+
122
160
  ### Zipkin HTTP B3 compatible header propagation
123
161
 
124
162
  Jaeger Tracer supports Zipkin B3 Propagation HTTP headers, which are used by a lot of Zipkin tracers. This means that you can use Jaeger in conjunction with OpenZipkin tracers.
@@ -141,6 +179,20 @@ It's also possible to set up multiple injectors and extractors. Each injector wi
141
179
 
142
180
  If multiple extractors is used then the span context from the first match will be returned.
143
181
 
182
+ ### Process Tags
183
+
184
+ Jaeger Tracer allows you to define process level tags. By default the tracer provides `jaeger.version`, `ip` and `hostname`. You may want to overwrite `ip` or `hostname` if the tracer cannot auto-detect them.
185
+
186
+ ```ruby
187
+ OpenTracing.global_tracer = Jaeger::Client.build(
188
+ service_name: 'service_name',
189
+ tags: {
190
+ 'hostname' => 'custom-hostname',
191
+ 'custom_tag' => 'custom-tag-value'
192
+ }
193
+ )
194
+ ```
195
+
144
196
  ## Development
145
197
 
146
198
  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.
data/crossdock/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM ruby:2.5-alpine
1
+ FROM ruby:2.7-alpine
2
2
 
3
3
  ENV APP_HOME /app
4
4
 
@@ -12,6 +12,8 @@ ADD Gemfile Gemfile.lock jaeger-client.gemspec $APP_HOME/
12
12
  ADD lib/jaeger/client/version.rb $APP_HOME/lib/jaeger/client/
13
13
  ADD crossdock/Gemfile crossdock/Gemfile.lock $APP_HOME/crossdock/
14
14
 
15
+ RUN gem install bundler -v $(tail -n 1 $APP_HOME/Gemfile.lock | awk '{$1=$1};1')
16
+
15
17
  RUN apk add --no-cache --virtual .app-builddeps build-base \
16
18
  && cd $APP_HOME && bundle install \
17
19
  && cd $APP_HOME/crossdock && bundle install \
data/crossdock/Gemfile CHANGED
@@ -3,4 +3,4 @@ source 'https://rubygems.org'
3
3
  gem 'jaeger-client', path: '../'
4
4
  gem 'rack'
5
5
  gem 'sinatra'
6
- gem 'webrick', '~> 1.4.2'
6
+ gem 'webrick', '~> 1.7'
@@ -1,26 +1,28 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- jaeger-client (0.7.1)
4
+ jaeger-client (1.2.0)
5
5
  opentracing (~> 0.3)
6
6
  thrift
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- mustermann (1.0.3)
12
- opentracing (0.4.3)
13
- rack (2.0.6)
14
- rack-protection (2.0.4)
11
+ mustermann (1.1.1)
12
+ ruby2_keywords (~> 0.0.1)
13
+ opentracing (0.5.0)
14
+ rack (2.2.3)
15
+ rack-protection (2.1.0)
15
16
  rack
16
- sinatra (2.0.4)
17
+ ruby2_keywords (0.0.5)
18
+ sinatra (2.1.0)
17
19
  mustermann (~> 1.0)
18
- rack (~> 2.0)
19
- rack-protection (= 2.0.4)
20
+ rack (~> 2.2)
21
+ rack-protection (= 2.1.0)
20
22
  tilt (~> 2.0)
21
- thrift (0.11.0.0)
22
- tilt (2.0.9)
23
- webrick (1.4.2)
23
+ thrift (0.15.0)
24
+ tilt (2.0.10)
25
+ webrick (1.7.0)
24
26
 
25
27
  PLATFORMS
26
28
  ruby
@@ -29,7 +31,7 @@ DEPENDENCIES
29
31
  jaeger-client!
30
32
  rack
31
33
  sinatra
32
- webrick (~> 1.4.2)
34
+ webrick (~> 1.7)
33
35
 
34
36
  BUNDLED WITH
35
- 1.16.2
37
+ 2.3.5
@@ -3,46 +3,51 @@ version: '2'
3
3
  services:
4
4
  jaeger-collector:
5
5
  image: jaegertracing/jaeger-collector
6
- command: ["--cassandra.keyspace=jaeger_v1_dc1", "--cassandra.servers=cassandra", "--collector.zipkin.http-port=9411"]
6
+ command: ["--es.num-shards=1", "--es.num-replicas=0", "--es.server-urls=http://elasticsearch:9200", "--collector.zipkin.host-port=:9411"]
7
7
  ports:
8
8
  - "14269"
9
9
  - "14268:14268"
10
- - "14267"
11
10
  - "14250"
12
11
  - "9411:9411"
12
+ environment:
13
+ - SPAN_STORAGE_TYPE=elasticsearch
14
+ - LOG_LEVEL=debug
13
15
  restart: on-failure
14
16
  depends_on:
15
- - cassandra-schema
17
+ - elasticsearch
16
18
 
17
19
  jaeger-query:
18
20
  image: jaegertracing/jaeger-query
19
- command: ["--cassandra.keyspace=jaeger_v1_dc1", "--cassandra.servers=cassandra"]
21
+ command: ["--es.num-shards=1", "--es.num-replicas=0", "--es.server-urls=http://elasticsearch:9200"]
20
22
  ports:
21
23
  - "16686:16686"
22
24
  - "16687"
25
+ environment:
26
+ - SPAN_STORAGE_TYPE=elasticsearch
27
+ - LOG_LEVEL=debug
23
28
  restart: on-failure
24
29
  depends_on:
25
- - cassandra-schema
30
+ - elasticsearch
26
31
 
27
32
  jaeger-agent:
28
33
  image: jaegertracing/jaeger-agent
29
- # FIXME temporarily switching back to tchannel
30
- # https://github.com/jaegertracing/jaeger/issues/1229
31
- command: ["--reporter.tchannel.host-port=jaeger-collector:14267"]
34
+ command: ["--reporter.grpc.host-port=jaeger-collector:14250", "--reporter.grpc.retry.max=1000"]
32
35
  ports:
33
36
  - "5775:5775/udp"
34
37
  - "6831:6831/udp"
35
38
  - "6832:6832/udp"
36
39
  - "5778:5778"
40
+ environment:
41
+ - LOG_LEVEL=debug
37
42
  restart: on-failure
38
43
  depends_on:
39
44
  - jaeger-collector
40
45
 
41
- cassandra:
42
- image: cassandra:3.9
46
+ elasticsearch:
47
+ image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.8.3
48
+ environment:
49
+ - discovery.type=single-node
50
+ ports:
51
+ - "9200:9200/tcp"
43
52
 
44
- cassandra-schema:
45
- image: jaegertracing/jaeger-cassandra-schema
46
- depends_on:
47
- - cassandra
48
53
 
data/crossdock/server CHANGED
@@ -36,9 +36,10 @@ class HttpServer < Sinatra::Application
36
36
  transport = downstream['transport']
37
37
 
38
38
  response[:downstream] =
39
- if transport == 'HTTP'
39
+ case transport
40
+ when 'HTTP'
40
41
  call_downstream_http(downstream, server_span)
41
- elsif transport == 'DUMMY'
42
+ when 'DUMMY'
42
43
  { notImplementedError: 'Dummy has not been implemented' }
43
44
  else
44
45
  { notImplementedError: "Unrecognized transport received: #{transport}" }
@@ -69,9 +70,10 @@ class HttpServer < Sinatra::Application
69
70
  transport = downstream['transport']
70
71
 
71
72
  response[:downstream] =
72
- if transport == 'HTTP'
73
+ case transport
74
+ when 'HTTP'
73
75
  call_downstream_http(downstream, server_span)
74
- elsif transport == 'DUMMY'
76
+ when 'DUMMY'
75
77
  { notImplementedError: 'Dummy has not been implemented' }
76
78
  else
77
79
  { notImplementedError: "Unrecognized transport received: #{transport}" }
@@ -8,6 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Jaeger::Client::VERSION
9
9
  spec.authors = ['SaleMove TechMovers']
10
10
  spec.email = ['techmovers@salemove.com']
11
+ spec.metadata['rubygems_mfa_required'] = 'true'
11
12
 
12
13
  spec.summary = 'OpenTracing Tracer implementation for Jaeger in Ruby'
13
14
  spec.description = ''
@@ -20,12 +21,16 @@ Gem::Specification.new do |spec|
20
21
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
22
  spec.require_paths = ['lib']
22
23
 
23
- spec.add_development_dependency 'bundler', '~> 1.14'
24
- spec.add_development_dependency 'rake', '~> 10.0'
25
- spec.add_development_dependency 'rspec', '~> 3.0'
26
- spec.add_development_dependency 'rubocop', '~> 0.54.0'
27
- spec.add_development_dependency 'rubocop-rspec', '~> 1.24.0'
24
+ spec.required_ruby_version = ['>= 2.7', '< 3.2']
25
+
26
+ spec.add_development_dependency 'bundler'
27
+ spec.add_development_dependency 'rake', '~> 13.0'
28
+ spec.add_development_dependency 'rspec', '~> 3.10'
29
+ spec.add_development_dependency 'rubocop', '~> 1.25'
30
+ spec.add_development_dependency 'rubocop-rake', '~> 0.6'
31
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.8'
28
32
  spec.add_development_dependency 'timecop', '~> 0.9'
33
+ spec.add_development_dependency 'webmock', '~> 3.14'
29
34
 
30
35
  spec.add_dependency 'opentracing', '~> 0.3'
31
36
  spec.add_dependency 'thrift'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jaeger
4
4
  module Client
5
- VERSION = '0.10.0'.freeze
5
+ VERSION = '1.3.0'
6
6
  end
7
7
  end
data/lib/jaeger/client.rb CHANGED
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- $LOAD_PATH.push(File.dirname(__FILE__) + '/../../thrift/gen-rb')
3
+ $LOAD_PATH.push("#{File.dirname(__FILE__)}/../../thrift/gen-rb")
4
4
 
5
5
  require 'opentracing'
6
6
  require 'jaeger/thrift/agent'
7
7
  require 'logger'
8
+ require 'time'
9
+ require 'net/http'
10
+ require 'cgi'
11
+ require 'json'
8
12
 
9
13
  require_relative 'tracer'
10
14
  require_relative 'span'
@@ -21,6 +25,8 @@ require_relative 'encoders/thrift_encoder'
21
25
  require_relative 'injectors'
22
26
  require_relative 'extractors'
23
27
  require_relative 'rate_limiter'
28
+ require_relative 'thrift_tag_builder'
29
+ require_relative 'recurring_executor'
24
30
 
25
31
  module Jaeger
26
32
  module Client
@@ -37,21 +43,22 @@ module Jaeger
37
43
 
38
44
  DEFAULT_FLUSH_INTERVAL = 10
39
45
 
40
- def self.build(host: '127.0.0.1',
46
+ def self.build(service_name:,
47
+ host: '127.0.0.1',
41
48
  port: 6831,
42
- service_name:,
43
49
  flush_interval: DEFAULT_FLUSH_INTERVAL,
44
50
  sampler: Samplers::Const.new(true),
45
- logger: Logger.new(STDOUT),
51
+ logger: Logger.new($stdout),
46
52
  sender: nil,
47
53
  reporter: nil,
48
54
  injectors: {},
49
- extractors: {})
50
- encoder = Encoders::ThriftEncoder.new(service_name: service_name)
55
+ extractors: {},
56
+ tags: {})
57
+ encoder = Encoders::ThriftEncoder.new(service_name: service_name, tags: tags, logger: logger)
51
58
 
52
59
  if sender
53
60
  warn '[DEPRECATION] Passing `sender` directly to Jaeger::Client.build is deprecated.' \
54
- 'Please use `reporter` instead.'
61
+ 'Please use `reporter` instead.'
55
62
  end
56
63
 
57
64
  reporter ||= Reporters::RemoteReporter.new(
@@ -3,49 +3,59 @@
3
3
  module Jaeger
4
4
  module Encoders
5
5
  class ThriftEncoder
6
- def initialize(service_name:)
6
+ def initialize(service_name:, logger:, tags: {})
7
7
  @service_name = service_name
8
- @tags = [
9
- Jaeger::Thrift::Tag.new(
10
- 'key' => 'jaeger.version',
11
- 'vType' => Jaeger::Thrift::TagType::STRING,
12
- 'vStr' => 'Ruby-' + Jaeger::Client::VERSION
13
- ),
14
- Jaeger::Thrift::Tag.new(
15
- 'key' => 'hostname',
16
- 'vType' => Jaeger::Thrift::TagType::STRING,
17
- 'vStr' => Socket.gethostname
18
- )
19
- ]
20
- ipv4 = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }
21
- unless ipv4.nil? # rubocop:disable Style/GuardClause
22
- @tags << Jaeger::Thrift::Tag.new(
23
- 'key' => 'ip',
24
- 'vType' => Jaeger::Thrift::TagType::STRING,
25
- 'vStr' => ipv4.ip_address
26
- )
27
- end
8
+ @logger = logger
9
+ @tags = prepare_tags(tags)
10
+ @process = Jaeger::Thrift::Process.new('serviceName' => @service_name, 'tags' => @tags)
28
11
  end
29
12
 
30
13
  def encode(spans)
31
- Jaeger::Thrift::Batch.new(
32
- 'process' => Jaeger::Thrift::Process.new(
33
- 'serviceName' => @service_name,
34
- 'tags' => @tags
35
- ),
36
- 'spans' => spans.map(&method(:encode_span))
37
- )
14
+ encode_batch(spans.map(&method(:encode_span)))
15
+ end
16
+
17
+ def encode_limited_size(spans, protocol_class, max_message_length)
18
+ batches = []
19
+ current_batch = []
20
+ current_batch_size = 0
21
+
22
+ max_spans_length = calculate_max_spans_length(protocol_class, max_message_length)
23
+
24
+ spans.each do |span|
25
+ encoded_span = encode_span(span)
26
+ span_size = message_size(encoded_span, protocol_class)
27
+
28
+ if span_size > max_spans_length
29
+ @logger.warn("Skip span #{span.operation_name} with size #{span_size}")
30
+ next
31
+ end
32
+
33
+ if (current_batch_size + span_size) > max_spans_length
34
+ batches << encode_batch(current_batch)
35
+ current_batch = []
36
+ current_batch_size = 0
37
+ end
38
+
39
+ current_batch << encoded_span
40
+ current_batch_size += span_size
41
+ end
42
+ batches << encode_batch(current_batch) unless current_batch.empty?
43
+ batches
38
44
  end
39
45
 
40
46
  private
41
47
 
48
+ def encode_batch(encoded_spans)
49
+ Jaeger::Thrift::Batch.new('process' => @process, 'spans' => encoded_spans)
50
+ end
51
+
42
52
  def encode_span(span)
43
53
  context = span.context
44
54
  start_ts, duration = build_timestamps(span)
45
55
 
46
56
  Jaeger::Thrift::Span.new(
47
- 'traceIdLow' => TraceId.uint64_id_to_int64(context.trace_id),
48
- 'traceIdHigh' => 0,
57
+ 'traceIdLow' => TraceId.uint64_id_to_int64(trace_id_to_low(context.trace_id)),
58
+ 'traceIdHigh' => TraceId.uint64_id_to_int64(trace_id_to_high(context.trace_id)),
49
59
  'spanId' => TraceId.uint64_id_to_int64(context.span_id),
50
60
  'parentSpanId' => TraceId.uint64_id_to_int64(context.parent_id),
51
61
  'operationName' => span.operation_name,
@@ -62,8 +72,8 @@ module Jaeger
62
72
  references.map do |ref|
63
73
  Jaeger::Thrift::SpanRef.new(
64
74
  'refType' => span_ref_type(ref.type),
65
- 'traceIdLow' => TraceId.uint64_id_to_int64(ref.context.trace_id),
66
- 'traceIdHigh' => 0,
75
+ 'traceIdLow' => TraceId.uint64_id_to_int64(trace_id_to_low(ref.context.trace_id)),
76
+ 'traceIdHigh' => TraceId.uint64_id_to_int64(trace_id_to_high(ref.context.trace_id)),
67
77
  'spanId' => TraceId.uint64_id_to_int64(ref.context.span_id)
68
78
  )
69
79
  end
@@ -87,6 +97,77 @@ module Jaeger
87
97
  nil
88
98
  end
89
99
  end
100
+
101
+ def prepare_tags(tags)
102
+ with_default_tags = tags.dup
103
+ with_default_tags['jaeger.version'] = "Ruby-#{Jaeger::Client::VERSION}"
104
+ with_default_tags['hostname'] ||= Socket.gethostname
105
+
106
+ unless with_default_tags['ip']
107
+ ipv4 = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }
108
+ with_default_tags['ip'] = ipv4.ip_address unless ipv4.nil?
109
+ end
110
+
111
+ with_default_tags.map do |key, value|
112
+ ThriftTagBuilder.build(key, value)
113
+ end
114
+ end
115
+
116
+ # Returns the right most 64 bits of trace id
117
+ def trace_id_to_low(trace_id)
118
+ trace_id & TraceId::MAX_64BIT_UNSIGNED_INT
119
+ end
120
+
121
+ # Returns the left most 64 bits of trace id
122
+ def trace_id_to_high(trace_id)
123
+ (trace_id >> 64) & TraceId::MAX_64BIT_UNSIGNED_INT
124
+ end
125
+
126
+ class DummyTransport
127
+ attr_accessor :size
128
+
129
+ def initialize
130
+ @size = 0
131
+ end
132
+
133
+ def write(buf)
134
+ @size += buf.size
135
+ end
136
+
137
+ def flush
138
+ @size = 0
139
+ end
140
+
141
+ def close; end
142
+ end
143
+
144
+ def message_size(message, protocol_class)
145
+ transport = DummyTransport.new
146
+ protocol = protocol_class.new(transport)
147
+ message.write(protocol)
148
+ transport.size
149
+ end
150
+
151
+ # Compact protocol have dynamic size of list header
152
+ # https://erikvanoosten.github.io/thrift-missing-specification/#_list_and_set_2
153
+ BATCH_SPANS_SIZE_WINDOW = 4
154
+
155
+ def empty_batch_size_cache
156
+ @empty_batch_size_cache ||= {}
157
+ end
158
+
159
+ def caclulate_empty_batch_size(protocol_class)
160
+ empty_batch_size_cache[protocol_class] ||=
161
+ message_size(encode_batch([]), protocol_class) + BATCH_SPANS_SIZE_WINDOW
162
+ end
163
+
164
+ def calculate_max_spans_length(protocol_class, max_message_length)
165
+ empty_batch_size = caclulate_empty_batch_size(protocol_class)
166
+ max_spans_length = max_message_length - empty_batch_size
167
+ return max_spans_length if max_spans_length.positive?
168
+
169
+ raise "Batch header have size #{empty_batch_size}, but limit #{max_message_length}"
170
+ end
90
171
  end
91
172
  end
92
173
  end