honeycomb-beeline 2.2.0 → 2.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: 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