elastic-apm 1.1.0 → 2.0.0
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.
Potentially problematic release.
This version of elastic-apm might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.rubocop.yml +7 -1
- data/CHANGELOG.md +45 -0
- data/Gemfile +17 -12
- data/bench/app.rb +1 -2
- data/bench/benchmark.rb +1 -1
- data/bench/stackprof.rb +1 -1
- data/docs/api.asciidoc +115 -76
- data/docs/configuration.asciidoc +232 -167
- data/docs/context.asciidoc +7 -3
- data/docs/custom-instrumentation.asciidoc +17 -28
- data/docs/index.asciidoc +13 -7
- data/docs/supported-technologies.asciidoc +65 -0
- data/elastic-apm.gemspec +3 -2
- data/lib/elastic_apm.rb +272 -121
- data/lib/elastic_apm/agent.rb +56 -107
- data/lib/elastic_apm/config.rb +130 -106
- data/lib/elastic_apm/config/duration.rb +25 -0
- data/lib/elastic_apm/config/size.rb +28 -0
- data/lib/elastic_apm/context_builder.rb +1 -0
- data/lib/elastic_apm/deprecations.rb +19 -0
- data/lib/elastic_apm/error.rb +5 -2
- data/lib/elastic_apm/error/exception.rb +1 -1
- data/lib/elastic_apm/error_builder.rb +5 -0
- data/lib/elastic_apm/instrumenter.rb +121 -53
- data/lib/elastic_apm/internal_error.rb +1 -0
- data/lib/elastic_apm/{log.rb → logging.rb} +16 -11
- data/lib/elastic_apm/metadata.rb +20 -0
- data/lib/elastic_apm/metadata/process_info.rb +26 -0
- data/lib/elastic_apm/metadata/service_info.rb +56 -0
- data/lib/elastic_apm/metadata/system_info.rb +30 -0
- data/lib/elastic_apm/middleware.rb +31 -15
- data/lib/elastic_apm/normalizers/action_controller.rb +1 -1
- data/lib/elastic_apm/normalizers/action_mailer.rb +1 -1
- data/lib/elastic_apm/normalizers/action_view.rb +3 -3
- data/lib/elastic_apm/normalizers/active_record.rb +2 -1
- data/lib/elastic_apm/railtie.rb +1 -1
- data/lib/elastic_apm/span.rb +59 -29
- data/lib/elastic_apm/span/context.rb +30 -4
- data/lib/elastic_apm/span_helpers.rb +1 -1
- data/lib/elastic_apm/spies/delayed_job.rb +7 -7
- data/lib/elastic_apm/spies/elasticsearch.rb +4 -4
- data/lib/elastic_apm/spies/http.rb +38 -0
- data/lib/elastic_apm/spies/mongo.rb +22 -11
- data/lib/elastic_apm/spies/net_http.rb +7 -4
- data/lib/elastic_apm/spies/rake.rb +5 -6
- data/lib/elastic_apm/spies/redis.rb +1 -1
- data/lib/elastic_apm/spies/sequel.rb +9 -7
- data/lib/elastic_apm/spies/sidekiq.rb +5 -5
- data/lib/elastic_apm/spies/tilt.rb +2 -2
- data/lib/elastic_apm/sql_summarizer.rb +3 -3
- data/lib/elastic_apm/stacktrace_builder.rb +6 -6
- data/lib/elastic_apm/subscriber.rb +3 -3
- data/lib/elastic_apm/traceparent.rb +62 -0
- data/lib/elastic_apm/transaction.rb +62 -93
- data/lib/elastic_apm/transport/base.rb +98 -0
- data/lib/elastic_apm/transport/connection.rb +175 -0
- data/lib/elastic_apm/transport/filters.rb +45 -0
- data/lib/elastic_apm/transport/filters/request_body_filter.rb +31 -0
- data/lib/elastic_apm/transport/filters/secrets_filter.rb +59 -0
- data/lib/elastic_apm/transport/serializers.rb +58 -0
- data/lib/elastic_apm/transport/serializers/error_serializer.rb +59 -0
- data/lib/elastic_apm/transport/serializers/span_serializer.rb +30 -0
- data/lib/elastic_apm/transport/serializers/transaction_serializer.rb +33 -0
- data/lib/elastic_apm/transport/worker.rb +73 -0
- data/lib/elastic_apm/util.rb +11 -8
- data/lib/elastic_apm/version.rb +1 -1
- metadata +40 -21
- data/.travis.yml +0 -5
- data/docs/troubleshooting.asciidoc +0 -28
- data/lib/elastic_apm/filters.rb +0 -46
- data/lib/elastic_apm/filters/request_body_filter.rb +0 -33
- data/lib/elastic_apm/filters/secrets_filter.rb +0 -59
- data/lib/elastic_apm/http.rb +0 -139
- data/lib/elastic_apm/process_info.rb +0 -24
- data/lib/elastic_apm/serializers.rb +0 -28
- data/lib/elastic_apm/serializers/errors.rb +0 -61
- data/lib/elastic_apm/serializers/transactions.rb +0 -51
- data/lib/elastic_apm/service_info.rb +0 -54
- data/lib/elastic_apm/system_info.rb +0 -28
- data/lib/elastic_apm/util/dig.rb +0 -31
- data/lib/elastic_apm/util/inspector.rb +0 -61
- data/lib/elastic_apm/worker.rb +0 -106
@@ -5,9 +5,9 @@ module ElasticAPM
|
|
5
5
|
module Spies
|
6
6
|
# @api private
|
7
7
|
class DelayedJobSpy
|
8
|
-
CLASS_SEPARATOR = '.'
|
9
|
-
METHOD_SEPARATOR = '#'
|
10
|
-
TYPE = 'Delayed::Job'
|
8
|
+
CLASS_SEPARATOR = '.'
|
9
|
+
METHOD_SEPARATOR = '#'
|
10
|
+
TYPE = 'Delayed::Job'
|
11
11
|
|
12
12
|
def install
|
13
13
|
::Delayed::Backend::Base.class_eval do
|
@@ -22,15 +22,15 @@ module ElasticAPM
|
|
22
22
|
|
23
23
|
def self.invoke_job(job, *args, &block)
|
24
24
|
job_name = name_from_payload(job.payload_object)
|
25
|
-
transaction = ElasticAPM.
|
25
|
+
transaction = ElasticAPM.start_transaction(job_name, TYPE)
|
26
26
|
job.invoke_job_without_apm(*args, &block)
|
27
|
-
transaction.
|
27
|
+
transaction.done 'success'
|
28
28
|
rescue ::Exception => e
|
29
29
|
ElasticAPM.report(e, handled: false)
|
30
|
-
transaction.
|
30
|
+
transaction.done 'error'
|
31
31
|
raise
|
32
32
|
ensure
|
33
|
-
|
33
|
+
ElasticAPM.end_transaction
|
34
34
|
end
|
35
35
|
|
36
36
|
def self.name_from_payload(payload_object)
|
@@ -5,8 +5,8 @@ module ElasticAPM
|
|
5
5
|
module Spies
|
6
6
|
# @api private
|
7
7
|
class ElasticsearchSpy
|
8
|
-
NAME_FORMAT = '%s %s'
|
9
|
-
TYPE = 'db.elasticsearch'
|
8
|
+
NAME_FORMAT = '%s %s'
|
9
|
+
TYPE = 'db.elasticsearch'
|
10
10
|
|
11
11
|
# rubocop:disable Metrics/MethodLength
|
12
12
|
def install
|
@@ -16,9 +16,9 @@ module ElasticAPM
|
|
16
16
|
def perform_request(method, path, *args, &block)
|
17
17
|
name = format(NAME_FORMAT, method, path)
|
18
18
|
statement = args[0].is_a?(String) ? args[0] : args[0].to_json
|
19
|
-
context = Span::Context.new(statement: statement)
|
19
|
+
context = Span::Context.new(db: { statement: statement })
|
20
20
|
|
21
|
-
ElasticAPM.
|
21
|
+
ElasticAPM.with_span name, TYPE, context: context do
|
22
22
|
perform_request_without_apm(method, path, *args, &block)
|
23
23
|
end
|
24
24
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ElasticAPM
|
4
|
+
# @api private
|
5
|
+
module Spies
|
6
|
+
# @api private
|
7
|
+
class HTTPSpy
|
8
|
+
# rubocop:disable Metrics/MethodLength
|
9
|
+
def install
|
10
|
+
::HTTP::Client.class_eval do
|
11
|
+
alias perform_without_apm perform
|
12
|
+
|
13
|
+
def perform(req, options)
|
14
|
+
unless (transaction = ElasticAPM.current_transaction)
|
15
|
+
return perform_without_apm(req, options)
|
16
|
+
end
|
17
|
+
|
18
|
+
method = req.verb.to_s.upcase
|
19
|
+
host = req.uri.host
|
20
|
+
|
21
|
+
name = "#{method} #{host}"
|
22
|
+
type = "ext.http_rb.#{method}"
|
23
|
+
|
24
|
+
ElasticAPM.with_span name, type do |span|
|
25
|
+
req['Elastic-Apm-Traceparent'] =
|
26
|
+
transaction.traceparent.to_header(span_id: span.id)
|
27
|
+
|
28
|
+
perform_without_apm(req, options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
# rubocop:enable Metrics/MethodLength
|
34
|
+
end
|
35
|
+
|
36
|
+
register 'HTTP', 'http', HTTPSpy.new
|
37
|
+
end
|
38
|
+
end
|
@@ -14,7 +14,7 @@ module ElasticAPM
|
|
14
14
|
|
15
15
|
# @api private
|
16
16
|
class Subscriber
|
17
|
-
TYPE = 'db.mongodb.query'
|
17
|
+
TYPE = 'db.mongodb.query'
|
18
18
|
|
19
19
|
def initialize
|
20
20
|
@events = {}
|
@@ -37,21 +37,32 @@ module ElasticAPM
|
|
37
37
|
def push_event(event)
|
38
38
|
return unless ElasticAPM.current_transaction
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
40
|
+
span =
|
41
|
+
ElasticAPM.start_span(
|
42
|
+
event.command_name.to_s,
|
43
|
+
TYPE,
|
44
|
+
context: build_context(event)
|
45
|
+
)
|
46
|
+
|
47
47
|
@events[event.operation_id] = span
|
48
48
|
end
|
49
49
|
|
50
50
|
def pop_event(event)
|
51
|
-
return unless ElasticAPM.
|
52
|
-
|
51
|
+
return unless (curr = ElasticAPM.current_span)
|
53
52
|
span = @events.delete(event.operation_id)
|
54
|
-
|
53
|
+
|
54
|
+
curr == span && ElasticAPM.end_span
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_context(event)
|
58
|
+
Span::Context.new(
|
59
|
+
db: {
|
60
|
+
instance: event.database_name,
|
61
|
+
statement: nil,
|
62
|
+
type: 'mongodb',
|
63
|
+
user: nil
|
64
|
+
}
|
65
|
+
)
|
55
66
|
end
|
56
67
|
end
|
57
68
|
end
|
@@ -5,13 +5,13 @@ module ElasticAPM
|
|
5
5
|
module Spies
|
6
6
|
# @api private
|
7
7
|
class NetHTTPSpy
|
8
|
-
# rubocop:disable Metrics/MethodLength
|
8
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
9
9
|
def install
|
10
10
|
Net::HTTP.class_eval do
|
11
11
|
alias request_without_apm request
|
12
12
|
|
13
13
|
def request(req, body = nil, &block)
|
14
|
-
unless ElasticAPM.current_transaction
|
14
|
+
unless (transaction = ElasticAPM.current_transaction)
|
15
15
|
return request_without_apm(req, body, &block)
|
16
16
|
end
|
17
17
|
|
@@ -23,13 +23,16 @@ module ElasticAPM
|
|
23
23
|
name = "#{method} #{host}"
|
24
24
|
type = "ext.net_http.#{method}"
|
25
25
|
|
26
|
-
ElasticAPM.
|
26
|
+
ElasticAPM.with_span name, type do |span|
|
27
|
+
req['Elastic-Apm-Traceparent'] =
|
28
|
+
transaction.traceparent.to_header(span_id: span.id)
|
29
|
+
|
27
30
|
request_without_apm(req, body, &block)
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
31
34
|
end
|
32
|
-
# rubocop:enable Metrics/MethodLength
|
35
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
33
36
|
end
|
34
37
|
|
35
38
|
register 'Net::HTTP', 'net/http', NetHTTPSpy.new
|
@@ -6,7 +6,6 @@ module ElasticAPM
|
|
6
6
|
# @api private
|
7
7
|
class RakeSpy
|
8
8
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
9
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
10
9
|
def install
|
11
10
|
::Rake::Task.class_eval do
|
12
11
|
alias execute_without_apm execute
|
@@ -18,19 +17,20 @@ module ElasticAPM
|
|
18
17
|
return execute_without_apm(*args)
|
19
18
|
end
|
20
19
|
|
21
|
-
transaction =
|
20
|
+
transaction =
|
21
|
+
ElasticAPM.start_transaction("Rake::Task[#{name}]", 'Rake')
|
22
22
|
|
23
23
|
begin
|
24
24
|
result = execute_without_apm(*args)
|
25
25
|
|
26
|
-
transaction.
|
26
|
+
transaction.result = 'success' if transaction
|
27
27
|
rescue StandardError => e
|
28
|
-
transaction.
|
28
|
+
transaction.result = 'error' if transaction
|
29
29
|
ElasticAPM.report(e)
|
30
30
|
|
31
31
|
raise
|
32
32
|
ensure
|
33
|
-
|
33
|
+
ElasticAPM.end_transaction
|
34
34
|
ElasticAPM.stop
|
35
35
|
end
|
36
36
|
|
@@ -38,7 +38,6 @@ module ElasticAPM
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
42
41
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
43
42
|
end
|
44
43
|
register 'Rake::Task', 'rake', RakeSpy.new
|
@@ -7,12 +7,18 @@ module ElasticAPM
|
|
7
7
|
module Spies
|
8
8
|
# @api private
|
9
9
|
class SequelSpy
|
10
|
-
TYPE = 'db.sequel.sql'
|
10
|
+
TYPE = 'db.sequel.sql'
|
11
11
|
|
12
12
|
def self.summarizer
|
13
13
|
@summarizer ||= SqlSummarizer.new
|
14
14
|
end
|
15
15
|
|
16
|
+
def self.build_context(sql, opts)
|
17
|
+
Span::Context.new(
|
18
|
+
db: { statement: sql, type: 'sql', user: opts[:user] }
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
16
22
|
# rubocop:disable Metrics/MethodLength
|
17
23
|
def install
|
18
24
|
require 'sequel/database/logging'
|
@@ -27,13 +33,9 @@ module ElasticAPM
|
|
27
33
|
|
28
34
|
summarizer = ElasticAPM::Spies::SequelSpy.summarizer
|
29
35
|
name = summarizer.summarize sql
|
30
|
-
context =
|
31
|
-
statement: sql,
|
32
|
-
type: 'sql',
|
33
|
-
user: opts[:user]
|
34
|
-
)
|
36
|
+
context = ElasticAPM::Spies::SequelSpy.build_context(sql, opts)
|
35
37
|
|
36
|
-
ElasticAPM.
|
38
|
+
ElasticAPM.with_span(name, TYPE, context: context, &block)
|
37
39
|
end
|
38
40
|
end
|
39
41
|
end
|
@@ -6,25 +6,25 @@ module ElasticAPM
|
|
6
6
|
# @api private
|
7
7
|
class SidekiqSpy
|
8
8
|
ACTIVE_JOB_WRAPPER =
|
9
|
-
'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper'
|
9
|
+
'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper'
|
10
10
|
|
11
11
|
# @api private
|
12
12
|
class Middleware
|
13
13
|
# rubocop:disable Metrics/MethodLength
|
14
14
|
def call(_worker, job, queue)
|
15
15
|
name = SidekiqSpy.name_for(job)
|
16
|
-
transaction = ElasticAPM.
|
16
|
+
transaction = ElasticAPM.start_transaction(name, 'Sidekiq')
|
17
17
|
ElasticAPM.set_tag(:queue, queue)
|
18
18
|
|
19
19
|
yield
|
20
20
|
|
21
|
-
transaction.
|
21
|
+
transaction.done :success if transaction
|
22
22
|
rescue ::Exception => e
|
23
23
|
ElasticAPM.report(e, handled: false)
|
24
|
-
transaction.
|
24
|
+
transaction.done :error if transaction
|
25
25
|
raise
|
26
26
|
ensure
|
27
|
-
|
27
|
+
ElasticAPM.end_transaction
|
28
28
|
end
|
29
29
|
# rubocop:enable Metrics/MethodLength
|
30
30
|
end
|
@@ -5,7 +5,7 @@ module ElasticAPM
|
|
5
5
|
module Spies
|
6
6
|
# @api private
|
7
7
|
class TiltSpy
|
8
|
-
TYPE = 'template.tilt'
|
8
|
+
TYPE = 'template.tilt'
|
9
9
|
|
10
10
|
def install
|
11
11
|
::Tilt::Template.class_eval do
|
@@ -14,7 +14,7 @@ module ElasticAPM
|
|
14
14
|
def render(*args, &block)
|
15
15
|
name = options[:__elastic_apm_template_name] || 'Unknown template'
|
16
16
|
|
17
|
-
ElasticAPM.
|
17
|
+
ElasticAPM.with_span name, TYPE do
|
18
18
|
render_without_apm(*args, &block)
|
19
19
|
end
|
20
20
|
end
|
@@ -5,8 +5,8 @@ require 'elastic_apm/util/lru_cache'
|
|
5
5
|
module ElasticAPM
|
6
6
|
# @api private
|
7
7
|
class SqlSummarizer
|
8
|
-
DEFAULT = 'SQL'
|
9
|
-
TABLE_REGEX = %{["'`]?([A-Za-z0-9]+)}
|
8
|
+
DEFAULT = 'SQL'
|
9
|
+
TABLE_REGEX = %{["'`]?([A-Za-z0-9]+)}
|
10
10
|
|
11
11
|
REGEXES = {
|
12
12
|
/^BEGIN/i => 'BEGIN',
|
@@ -17,7 +17,7 @@ module ElasticAPM
|
|
17
17
|
/^DELETE FROM #{TABLE_REGEX}/i => 'DELETE FROM '
|
18
18
|
}.freeze
|
19
19
|
|
20
|
-
FORMAT = '%s%s'
|
20
|
+
FORMAT = '%s%s'
|
21
21
|
|
22
22
|
def self.cache
|
23
23
|
@cache ||= Util::LruCache.new
|
@@ -6,14 +6,14 @@ require 'elastic_apm/util/lru_cache'
|
|
6
6
|
module ElasticAPM
|
7
7
|
# @api private
|
8
8
|
class StacktraceBuilder
|
9
|
-
JAVA_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)
|
10
|
-
RUBY_FORMAT = /^(.+?):(\d+)(?::in `(.+?)')
|
9
|
+
JAVA_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/.freeze
|
10
|
+
RUBY_FORMAT = /^(.+?):(\d+)(?::in `(.+?)')?$/.freeze
|
11
11
|
|
12
|
-
RUBY_VERS_REGEX = %r{ruby(/gems)?[-/](\d+\.)+\d}
|
13
|
-
JRUBY_ORG_REGEX = %r{org/jruby}
|
12
|
+
RUBY_VERS_REGEX = %r{ruby(/gems)?[-/](\d+\.)+\d}.freeze
|
13
|
+
JRUBY_ORG_REGEX = %r{org/jruby}.freeze
|
14
14
|
|
15
|
-
def initialize(
|
16
|
-
@config =
|
15
|
+
def initialize(config)
|
16
|
+
@config = config
|
17
17
|
@cache = Util::LruCache.new(2048, &method(:build_frame))
|
18
18
|
end
|
19
19
|
|
@@ -6,7 +6,7 @@ require 'elastic_apm/normalizers'
|
|
6
6
|
module ElasticAPM
|
7
7
|
# @api private
|
8
8
|
class Subscriber
|
9
|
-
include
|
9
|
+
include Logging
|
10
10
|
|
11
11
|
def initialize(agent)
|
12
12
|
@agent = agent
|
@@ -40,7 +40,7 @@ module ElasticAPM
|
|
40
40
|
nil
|
41
41
|
else
|
42
42
|
name, type, context = normalized
|
43
|
-
@agent.
|
43
|
+
@agent.start_span(name, type, context: context)
|
44
44
|
end
|
45
45
|
|
46
46
|
transaction.notifications << Notification.new(id, span)
|
@@ -54,7 +54,7 @@ module ElasticAPM
|
|
54
54
|
next unless notification.id == id
|
55
55
|
|
56
56
|
if (span = notification.span)
|
57
|
-
span.
|
57
|
+
@agent.end_span if span == @agent.current_span
|
58
58
|
end
|
59
59
|
return
|
60
60
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ElasticAPM
|
4
|
+
# @api private
|
5
|
+
class Traceparent
|
6
|
+
class InvalidTraceparentHeader < StandardError; end
|
7
|
+
|
8
|
+
VERSION = '00'
|
9
|
+
HEX_REGEX = /[^[:xdigit:]]/.freeze
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@version = VERSION
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.from_transaction(transaction)
|
16
|
+
new.tap do |t|
|
17
|
+
t.trace_id = SecureRandom.hex(16)
|
18
|
+
t.recorded = transaction.sampled?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# rubocop:disable Metrics/AbcSize
|
23
|
+
def self.parse(header)
|
24
|
+
raise InvalidTraceparentHeader unless header.length == 55
|
25
|
+
raise InvalidTraceparentHeader unless header[0..1] == VERSION
|
26
|
+
|
27
|
+
new.tap do |t|
|
28
|
+
t.version, t.trace_id, t.span_id, t.flags =
|
29
|
+
header.split('-').tap do |values|
|
30
|
+
values[-1] = Util.hex_to_bits(values[-1])
|
31
|
+
end
|
32
|
+
|
33
|
+
raise InvalidTraceparentHeader if HEX_REGEX =~ t.trace_id
|
34
|
+
raise InvalidTraceparentHeader if HEX_REGEX =~ t.span_id
|
35
|
+
end
|
36
|
+
end
|
37
|
+
# rubocop:enable Metrics/AbcSize
|
38
|
+
|
39
|
+
attr_accessor :header, :version, :trace_id, :span_id, :recorded
|
40
|
+
|
41
|
+
alias :recorded? :recorded
|
42
|
+
|
43
|
+
def flags=(flags)
|
44
|
+
@flags = flags
|
45
|
+
|
46
|
+
self.recorded = flags[7] == '1'
|
47
|
+
end
|
48
|
+
|
49
|
+
def flags
|
50
|
+
format('0000000%d', recorded? ? 1 : 0)
|
51
|
+
end
|
52
|
+
|
53
|
+
def hex_flags
|
54
|
+
format('%02x', flags.to_i(2))
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_header(span_id: nil)
|
58
|
+
span_id ||= self.span_id
|
59
|
+
format('%s-%s-%s-%s', version, trace_id, span_id, hex_flags)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|