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 +4 -4
- data/.github/workflows/ci.yml +33 -0
- data/.rubocop.yml +12 -1
- data/.rubocop_todo.yml +13 -0
- data/README.md +55 -3
- data/crossdock/Dockerfile +3 -1
- data/crossdock/Gemfile +1 -1
- data/crossdock/Gemfile.lock +15 -13
- data/crossdock/jaeger-docker-compose.yml +19 -14
- data/crossdock/server +6 -4
- data/jaeger-client.gemspec +10 -5
- data/lib/jaeger/client/version.rb +1 -1
- data/lib/jaeger/client.rb +14 -7
- data/lib/jaeger/encoders/thrift_encoder.rb +113 -32
- data/lib/jaeger/extractors.rb +71 -7
- data/lib/jaeger/http_sender.rb +3 -3
- data/lib/jaeger/injectors.rb +19 -5
- data/lib/jaeger/recurring_executor.rb +35 -0
- data/lib/jaeger/samplers/const.rb +1 -1
- data/lib/jaeger/samplers/guaranteed_throughput_probabilistic.rb +13 -6
- data/lib/jaeger/samplers/per_operation.rb +44 -14
- data/lib/jaeger/samplers/probabilistic.rb +15 -1
- data/lib/jaeger/samplers/rate_limiting.rb +24 -6
- data/lib/jaeger/samplers/remote_controlled/instructions_fetcher.rb +34 -0
- data/lib/jaeger/samplers/remote_controlled.rb +119 -0
- data/lib/jaeger/samplers.rb +1 -0
- data/lib/jaeger/scope.rb +3 -2
- data/lib/jaeger/scope_manager.rb +1 -0
- data/lib/jaeger/span.rb +3 -4
- data/lib/jaeger/span_context.rb +3 -3
- data/lib/jaeger/thrift_tag_builder.rb +42 -0
- data/lib/jaeger/trace_id.rb +10 -1
- data/lib/jaeger/tracer.rb +29 -10
- data/lib/jaeger/udp_sender/transport.rb +4 -3
- data/lib/jaeger/udp_sender.rb +9 -7
- metadata +55 -20
- data/.travis.yml +0 -14
- data/lib/jaeger/span/thrift_tag_builder.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16e6a368a65ce75432681a4487909971193d06e6bca4aff72cf39b0a4af2eb8f
|
4
|
+
data.tar.gz: f6a665ce70c4804484fefb1fb5d1c0ddbd41b117b78d688559fa9adceaa55e1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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://
|
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.
|
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
data/crossdock/Gemfile.lock
CHANGED
@@ -1,26 +1,28 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
jaeger-client (
|
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.
|
12
|
-
|
13
|
-
|
14
|
-
rack
|
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
|
-
|
17
|
+
ruby2_keywords (0.0.5)
|
18
|
+
sinatra (2.1.0)
|
17
19
|
mustermann (~> 1.0)
|
18
|
-
rack (~> 2.
|
19
|
-
rack-protection (= 2.0
|
20
|
+
rack (~> 2.2)
|
21
|
+
rack-protection (= 2.1.0)
|
20
22
|
tilt (~> 2.0)
|
21
|
-
thrift (0.
|
22
|
-
tilt (2.0.
|
23
|
-
webrick (1.
|
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.
|
34
|
+
webrick (~> 1.7)
|
33
35
|
|
34
36
|
BUNDLED WITH
|
35
|
-
|
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: ["--
|
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
|
-
-
|
17
|
+
- elasticsearch
|
16
18
|
|
17
19
|
jaeger-query:
|
18
20
|
image: jaegertracing/jaeger-query
|
19
|
-
command: ["--
|
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
|
-
-
|
30
|
+
- elasticsearch
|
26
31
|
|
27
32
|
jaeger-agent:
|
28
33
|
image: jaegertracing/jaeger-agent
|
29
|
-
|
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
|
-
|
42
|
-
image:
|
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
|
-
|
39
|
+
case transport
|
40
|
+
when 'HTTP'
|
40
41
|
call_downstream_http(downstream, server_span)
|
41
|
-
|
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
|
-
|
73
|
+
case transport
|
74
|
+
when 'HTTP'
|
73
75
|
call_downstream_http(downstream, server_span)
|
74
|
-
|
76
|
+
when 'DUMMY'
|
75
77
|
{ notImplementedError: 'Dummy has not been implemented' }
|
76
78
|
else
|
77
79
|
{ notImplementedError: "Unrecognized transport received: #{transport}" }
|
data/jaeger-client.gemspec
CHANGED
@@ -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.
|
24
|
-
|
25
|
-
spec.add_development_dependency '
|
26
|
-
spec.add_development_dependency '
|
27
|
-
spec.add_development_dependency '
|
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'
|
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__)
|
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(
|
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(
|
51
|
+
logger: Logger.new($stdout),
|
46
52
|
sender: nil,
|
47
53
|
reporter: nil,
|
48
54
|
injectors: {},
|
49
|
-
extractors: {}
|
50
|
-
|
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
|
-
|
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
|
-
@
|
9
|
-
|
10
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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' =>
|
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' =>
|
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
|