honeycomb-beeline 2.2.0 → 2.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 861b65eb2d7ef9f82cad990b966247465eebb0eac7ec4fa6d668491d979e9eee
4
- data.tar.gz: 2e1b7ef3a15d2b2be27a4593eafabe399331909df925724abc3978cc47aed01c
3
+ metadata.gz: 0606efad889f46b53eaa00c4a4c2f0e134641ce9a2427f65cc79eaf138a840be
4
+ data.tar.gz: 95449860c9a30558bdb512b498f93fe0d00beca14b89582555e0cf2479316f74
5
5
  SHA512:
6
- metadata.gz: b50cd4118393ff03349894bb4942bb166baafb51fdf587b76a5e8f1b34411d2a49c8698cc9bb8f28746211143f93bf88e5fc23de13479acbd526383f7065410d
7
- data.tar.gz: f123f2ad239e1f72874199999d08a8b3137b318f1d92d9a295b3bfdb4d17d8097c3577ebca666e7b26d0d9d5940fe6b6db2ec92f9028dfbffa1740898e43281c
6
+ metadata.gz: 0cf79345b6b669d4e07d02035840f7ba05bb508c9185259c7d308afd7cf18cb9d44c5c1592b04e445cf025037756a9c8512bfd436ea2e4c1f52884db9a08dbe7
7
+ data.tar.gz: 7e73b0970480db0173ef147102da4ea9511e920457feea7178b1b4fd03905b4929c3581d01ec050586241028b7ec7921df5b90d466c882ea57d97ca69c58d5dd
@@ -0,0 +1,12 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 2
6
+ charset = utf-8
7
+ trim_trailing_whitespace = true
8
+ insert_final_newline = true
9
+
10
+ [*.md]
11
+ indent_size = 4
12
+ trim_trailing_whitespace = true
@@ -32,6 +32,12 @@ Metrics/LineLength:
32
32
  Metrics/ParameterLists:
33
33
  Max: 6
34
34
 
35
+ Style/AccessModifierDeclarations:
36
+ Exclude:
37
+ - lib/honeycomb/propagation/aws.rb
38
+ - lib/honeycomb/propagation/w3c.rb
39
+ - lib/honeycomb/propagation/honeycomb.rb
40
+
35
41
  Style/FrozenStringLiteralComment:
36
42
  EnforcedStyle: always
37
43
  Exclude:
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- honeycomb-beeline (2.2.0)
4
+ honeycomb-beeline (2.3.0)
5
5
  libhoney (~> 1.14, >= 1.14.2)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -25,6 +25,13 @@ Built in instrumentation for:
25
25
  - Sequel
26
26
  - Sinatra
27
27
 
28
+ ## Testing
29
+ Find `rspec` test files in the `spec` directory.
30
+
31
+ To run tests on gem-specific instrumentations or across various dependency versions, use [appraisal](https://github.com/thoughtbot/appraisal) (further instructions in the readme for that gem). Find gem sets in the `Appraisals` config.
32
+
33
+ To run a specific file: `bundle exec appraisal <gem set> rspec <path/to/file>`
34
+
28
35
  ## Get in touch
29
36
 
30
37
  Please reach out to [support@honeycomb.io](mailto:support@honeycomb.io) or ping
@@ -3,7 +3,7 @@
3
3
  module Honeycomb
4
4
  module Beeline
5
5
  NAME = "honeycomb-beeline".freeze
6
- VERSION = "2.2.0".freeze
6
+ VERSION = "2.3.0".freeze
7
7
  USER_AGENT_SUFFIX = "#{NAME}/#{VERSION}".freeze
8
8
  end
9
9
  end
@@ -35,6 +35,8 @@ module Honeycomb
35
35
  @additional_trace_options = {
36
36
  presend_hook: configuration.presend_hook,
37
37
  sample_hook: configuration.sample_hook,
38
+ parser_hook: configuration.http_trace_parser_hook,
39
+ propagation_hook: configuration.http_trace_propagation_hook,
38
40
  }
39
41
 
40
42
  configuration.after_initialize(self)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "socket"
4
+ require "honeycomb/propagation/honeycomb"
4
5
 
5
6
  module Honeycomb
6
7
  # Used to configure the Honeycomb client
@@ -60,5 +61,27 @@ module Honeycomb
60
61
  @sample_hook
61
62
  end
62
63
  end
64
+
65
+ def http_trace_parser_hook(&hook)
66
+ if block_given?
67
+ @http_trace_parser_hook = hook
68
+ elsif @http_trace_parser_hook
69
+ @http_trace_parser_hook
70
+ else
71
+ # by default we try to parse incoming honeycomb traces
72
+ HoneycombPropagation::UnmarshalTraceContext.method(:parse_rack_env)
73
+ end
74
+ end
75
+
76
+ def http_trace_propagation_hook(&hook)
77
+ if block_given?
78
+ @http_trace_propagation_hook = hook
79
+ elsif @http_trace_propagation_hook
80
+ @http_trace_propagation_hook
81
+ else
82
+ # by default we send outgoing honeycomb trace headers
83
+ HoneycombPropagation::MarshalTraceContext.method(:parse_faraday_env)
84
+ end
85
+ end
63
86
  end
64
87
  end
@@ -22,7 +22,9 @@ module Honeycomb
22
22
  span.add_field "meta.package", "faraday"
23
23
  span.add_field "meta.package_version", ::Faraday::VERSION
24
24
 
25
- env.request_headers["X-Honeycomb-Trace"] = span.to_trace_header
25
+ if (headers = span.trace_headers(env)).is_a?(Hash)
26
+ env.request_headers.merge!(headers)
27
+ end
26
28
 
27
29
  @app.call(env).tap do |response|
28
30
  span.add_field "response.status_code", response.status
@@ -32,8 +32,10 @@ module Honeycomb
32
32
 
33
33
  def call(env)
34
34
  req = ::Rack::Request.new(env)
35
- hny = env["HTTP_X_HONEYCOMB_TRACE"]
36
- client.start_span(name: "http_request", serialized_trace: hny) do |span|
35
+ client.start_span(
36
+ name: "http_request",
37
+ serialized_trace: env,
38
+ ) do |span|
37
39
  add_field = lambda do |key, value|
38
40
  unless value.nil? || (value.respond_to?(:empty?) && value.empty?)
39
41
  span.add_field(key, value)
@@ -43,6 +43,9 @@ module Honeycomb
43
43
 
44
44
  [trace_id, parent_span_id, trace_fields]
45
45
  end
46
+
47
+ module_function :parse, :get_fields
48
+ public :parse
46
49
  end
47
50
 
48
51
  # Serialize trace headers
@@ -61,6 +64,22 @@ module Honeycomb
61
64
  ]
62
65
  "#{data_to_propagate.join(';')}#{context.join(';')}"
63
66
  end
67
+
68
+ def self.to_trace_header(propagation_context)
69
+ context = [""]
70
+ fields = propagation_context.trace_fields
71
+ unless fields.keys.nil?
72
+ fields.keys.each do |key|
73
+ context.push("#{key}=#{fields[key]}")
74
+ end
75
+ end
76
+
77
+ data_to_propagate = [
78
+ "Root=#{propagation_context.trace_id}",
79
+ "Parent=#{propagation_context.parent_id}",
80
+ ]
81
+ "#{data_to_propagate.join(';')}#{context.join(';')}"
82
+ end
64
83
  end
65
84
  end
66
85
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Honeycomb
4
+ module Propagation
5
+ Context = Struct.new(:trace_id, :parent_id, :trace_fields, :dataset) do
6
+ def to_array
7
+ [trace_id, parent_id, trace_fields, dataset]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -9,6 +9,10 @@ module Honeycomb
9
9
  module HoneycombPropagation
10
10
  # Parse trace headers
11
11
  module UnmarshalTraceContext
12
+ def parse_rack_env(env)
13
+ parse env["HTTP_X_HONEYCOMB_TRACE"]
14
+ end
15
+
12
16
  def parse(serialized_trace)
13
17
  unless serialized_trace.nil?
14
18
  version, payload = serialized_trace.split(";", 2)
@@ -49,6 +53,9 @@ module Honeycomb
49
53
 
50
54
  [trace_id, parent_span_id, trace_fields, dataset]
51
55
  end
56
+
57
+ module_function :parse_rack_env, :parse, :parse_v1
58
+ public :parse_rack_env, :parse
52
59
  end
53
60
 
54
61
  # Serialize trace headers
@@ -64,6 +71,26 @@ module Honeycomb
64
71
  ]
65
72
  "1;#{data_to_propogate.join(',')}"
66
73
  end
74
+
75
+ def self.parse_faraday_env(_env, propagation_context)
76
+ {
77
+ "X-Honeycomb-Trace" => to_trace_header(propagation_context),
78
+ }
79
+ end
80
+
81
+ def self.to_trace_header(propagation_context)
82
+ fields = propagation_context.trace_fields
83
+ context = Base64.urlsafe_encode64(JSON.generate(fields)).strip
84
+ dataset = propagation_context.dataset
85
+ encoded_dataset = URI.encode_www_form_component(dataset)
86
+ data_to_propogate = [
87
+ "dataset=#{encoded_dataset}",
88
+ "trace_id=#{propagation_context.trace_id}",
89
+ "parent_id=#{propagation_context.parent_id}",
90
+ "context=#{context}",
91
+ ]
92
+ "1;#{data_to_propogate.join(',')}"
93
+ end
67
94
  end
68
95
  end
69
96
  end
@@ -8,6 +8,10 @@ module Honeycomb
8
8
  INVALID_TRACE_ID = "00000000000000000000000000000000".freeze
9
9
  INVALID_SPAN_ID = "0000000000000000".freeze
10
10
 
11
+ def parse_rack_env(env)
12
+ parse env["HTTP_TRACEPARENT"]
13
+ end
14
+
11
15
  def parse(serialized_trace)
12
16
  unless serialized_trace.nil?
13
17
  version, payload = serialized_trace.split("-", 2)
@@ -38,6 +42,9 @@ module Honeycomb
38
42
 
39
43
  [trace_id, parent_span_id]
40
44
  end
45
+
46
+ module_function :parse_rack_env, :parse, :parse_v1
47
+ public :parse
41
48
  end
42
49
 
43
50
  # Serialize trace headers
@@ -50,6 +57,23 @@ module Honeycomb
50
57
 
51
58
  nil
52
59
  end
60
+
61
+ def self.parse_faraday_env(_env, propagation_context)
62
+ {
63
+ "traceparent" => to_trace_header(propagation_context),
64
+ }
65
+ end
66
+
67
+ def self.to_trace_header(propagation_context)
68
+ trace_id = propagation_context.trace_id
69
+ parent_id = propagation_context.parent_id
70
+ # do not propagate malformed ids
71
+ if trace_id =~ /^[A-Fa-f0-9]{32}$/ && parent_id =~ /^[A-Fa-f0-9]{16}$/
72
+ return "00-#{trace_id}-#{parent_id}-01"
73
+ end
74
+
75
+ nil
76
+ end
53
77
  end
54
78
  end
55
79
  end
@@ -3,6 +3,7 @@
3
3
  require "forwardable"
4
4
  require "securerandom"
5
5
  require "honeycomb/propagation"
6
+ require "honeycomb/propagation/context"
6
7
  require "honeycomb/deterministic_sampler"
7
8
  require "honeycomb/rollup_fields"
8
9
 
@@ -34,13 +35,14 @@ module Honeycomb
34
35
  @sent = false
35
36
  @started = clock_time
36
37
  parse_options(**options)
38
+ parse_hooks(**options)
37
39
  end
38
40
 
39
41
  def parse_options(parent: nil,
40
42
  parent_id: nil,
41
43
  is_root: parent_id.nil?,
42
- sample_hook: nil,
43
- presend_hook: nil,
44
+ _sample_hook: nil,
45
+ _presend_hook: nil,
44
46
  **_options)
45
47
  @parent = parent
46
48
  # parent_id should be removed in the next major version bump. It has been
@@ -48,8 +50,15 @@ module Honeycomb
48
50
  # compatability
49
51
  @parent_id = parent_id
50
52
  @is_root = is_root
53
+ end
54
+
55
+ def parse_hooks(sample_hook: nil,
56
+ presend_hook: nil,
57
+ propagation_hook: nil,
58
+ **_options)
51
59
  @presend_hook = presend_hook
52
60
  @sample_hook = sample_hook
61
+ @propagation_hook = propagation_hook
53
62
  end
54
63
 
55
64
  def create_child
@@ -59,7 +68,8 @@ module Honeycomb
59
68
  parent: self,
60
69
  parent_id: id,
61
70
  sample_hook: sample_hook,
62
- presend_hook: presend_hook).tap do |c|
71
+ presend_hook: presend_hook,
72
+ propagation_hook: propagation_hook).tap do |c|
63
73
  children << c
64
74
  end
65
75
  end
@@ -70,6 +80,14 @@ module Honeycomb
70
80
  send_internal
71
81
  end
72
82
 
83
+ def trace_headers(env)
84
+ if propagation_hook
85
+ propagation_hook.call(env, propagation_context)
86
+ else
87
+ {}
88
+ end
89
+ end
90
+
73
91
  protected
74
92
 
75
93
  def send_by_parent
@@ -94,7 +112,17 @@ module Honeycomb
94
112
  :builder,
95
113
  :context,
96
114
  :presend_hook,
97
- :sample_hook
115
+ :sample_hook,
116
+ :propagation_hook
117
+
118
+ def propagation_context
119
+ Honeycomb::Propagation::Context.new(
120
+ trace.id,
121
+ id,
122
+ trace.fields,
123
+ builder.dataset,
124
+ )
125
+ end
98
126
 
99
127
  def sent?
100
128
  @sent
@@ -19,7 +19,8 @@ module Honeycomb
19
19
 
20
20
  def initialize(builder:, context:, serialized_trace: nil, **options)
21
21
  trace_id, parent_span_id, trace_fields, dataset =
22
- parse serialized_trace
22
+ internal_parse(serialized_trace: serialized_trace, **options)
23
+
23
24
  dataset && builder.dataset = dataset
24
25
  @id = trace_id || generate_trace_id
25
26
  @fields = trace_fields || {}
@@ -45,5 +46,17 @@ module Honeycomb
45
46
  return id unless id == INVALID_TRACE_ID
46
47
  end
47
48
  end
49
+
50
+ def internal_parse(serialized_trace: nil, parser_hook: nil, **_options)
51
+ # previously we passed in the header directly as a string for us to parse
52
+ # now we get passed the rack env to use as an argument to the provided
53
+ # parser_hook. This preserves the current behaviour and allows us to
54
+ # move forward with the new behaviour without breaking changes
55
+ if serialized_trace.is_a?(Hash) && parser_hook
56
+ parser_hook.call(serialized_trace)
57
+ else
58
+ parse serialized_trace
59
+ end
60
+ end
48
61
  end
49
62
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: honeycomb-beeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Holman
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-02 00:00:00.000000000 Z
11
+ date: 2020-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: libhoney
@@ -236,6 +236,7 @@ files:
236
236
  - ".circleci/bundler_version.sh"
237
237
  - ".circleci/config.yml"
238
238
  - ".circleci/setup-rubygems.sh"
239
+ - ".editorconfig"
239
240
  - ".github/CODEOWNERS"
240
241
  - ".gitignore"
241
242
  - ".overcommit.yml"
@@ -274,6 +275,7 @@ files:
274
275
  - lib/honeycomb/integrations/warden.rb
275
276
  - lib/honeycomb/propagation.rb
276
277
  - lib/honeycomb/propagation/aws.rb
278
+ - lib/honeycomb/propagation/context.rb
277
279
  - lib/honeycomb/propagation/honeycomb.rb
278
280
  - lib/honeycomb/propagation/w3c.rb
279
281
  - lib/honeycomb/rollup_fields.rb