honeycomb-beeline 2.0.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.
@@ -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
@@ -0,0 +1,5 @@
1
+ # Code owners file.
2
+ # This file controls who is tagged for review for any given pull request.
3
+
4
+ # For anything not explicitly taken by someone else:
5
+ * @honeycombio/integrations-team @martin308
@@ -29,6 +29,15 @@ Metrics/LineLength:
29
29
  Exclude:
30
30
  - spec/support/event_data_shared_examples.rb
31
31
 
32
+ Metrics/ParameterLists:
33
+ Max: 6
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
+
32
41
  Style/FrozenStringLiteralComment:
33
42
  EnforcedStyle: always
34
43
  Exclude:
@@ -1,24 +1,27 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- honeycomb-beeline (2.0.0)
4
+ honeycomb-beeline (2.3.0)
5
5
  libhoney (~> 1.14, >= 1.14.2)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- addressable (2.6.0)
11
- public_suffix (>= 2.0.2, < 4.0)
10
+ addressable (2.7.0)
11
+ public_suffix (>= 2.0.2, < 5.0)
12
12
  ansi (1.5.0)
13
13
  appraisal (2.2.0)
14
14
  bundler
15
15
  rake
16
16
  thor (>= 0.14.0)
17
17
  ast (2.4.0)
18
- bump (0.8.0)
19
- byebug (11.0.1)
18
+ bump (0.9.0)
19
+ byebug (10.0.2)
20
20
  childprocess (0.9.0)
21
21
  ffi (~> 1.0, >= 1.0.11)
22
+ codecov (0.2.8)
23
+ json
24
+ simplecov
22
25
  coderay (1.1.2)
23
26
  crack (0.4.3)
24
27
  safe_yaml (~> 1.0.0)
@@ -26,12 +29,12 @@ GEM
26
29
  docile (1.3.2)
27
30
  domain_name (0.5.20190701)
28
31
  unf (>= 0.0.5, < 1.0.0)
29
- ffi (1.11.1)
32
+ ffi (1.12.2)
30
33
  ffi-compiler (1.0.1)
31
34
  ffi (>= 1.0.0)
32
35
  rake
33
- hashdiff (0.4.0)
34
- http (4.3.0)
36
+ hashdiff (1.0.1)
37
+ http (4.4.1)
35
38
  addressable (~> 2.3)
36
39
  http-cookie (~> 1.0)
37
40
  http-form_data (~> 2.2)
@@ -41,41 +44,41 @@ GEM
41
44
  http-form_data (2.3.0)
42
45
  http-parser (1.2.1)
43
46
  ffi-compiler (>= 1.0, < 2.0)
44
- iniparse (1.4.4)
45
- jaro_winkler (1.5.3)
46
- json (2.2.0)
47
- libhoney (1.14.4)
47
+ iniparse (1.5.0)
48
+ jaro_winkler (1.5.4)
49
+ json (2.3.1)
50
+ libhoney (1.14.5)
48
51
  addressable (~> 2.0)
49
52
  http (>= 2.0, < 5.0)
50
53
  method_source (0.9.2)
51
54
  overcommit (0.46.0)
52
55
  childprocess (~> 0.6, >= 0.6.3)
53
56
  iniparse (~> 1.4)
54
- parallel (1.17.0)
55
- parser (2.6.3.0)
57
+ parallel (1.19.1)
58
+ parser (2.7.1.2)
56
59
  ast (~> 2.4.0)
57
60
  pry (0.12.2)
58
61
  coderay (~> 1.1.0)
59
62
  method_source (~> 0.9.0)
60
- pry-byebug (3.7.0)
61
- byebug (~> 11.0)
63
+ pry-byebug (3.6.0)
64
+ byebug (~> 10.0)
62
65
  pry (~> 0.10)
63
- public_suffix (3.1.1)
66
+ public_suffix (4.0.4)
64
67
  rainbow (3.0.0)
65
68
  rake (13.0.1)
66
- rspec (3.8.0)
67
- rspec-core (~> 3.8.0)
68
- rspec-expectations (~> 3.8.0)
69
- rspec-mocks (~> 3.8.0)
70
- rspec-core (3.8.1)
71
- rspec-support (~> 3.8.0)
72
- rspec-expectations (3.8.4)
69
+ rspec (3.9.0)
70
+ rspec-core (~> 3.9.0)
71
+ rspec-expectations (~> 3.9.0)
72
+ rspec-mocks (~> 3.9.0)
73
+ rspec-core (3.9.2)
74
+ rspec-support (~> 3.9.3)
75
+ rspec-expectations (3.9.2)
73
76
  diff-lcs (>= 1.2.0, < 2.0)
74
- rspec-support (~> 3.8.0)
75
- rspec-mocks (3.8.1)
77
+ rspec-support (~> 3.9.0)
78
+ rspec-mocks (3.9.1)
76
79
  diff-lcs (>= 1.2.0, < 2.0)
77
- rspec-support (~> 3.8.0)
78
- rspec-support (3.8.2)
80
+ rspec-support (~> 3.9.0)
81
+ rspec-support (3.9.3)
79
82
  rubocop (0.68.1)
80
83
  jaro_winkler (~> 1.5.1)
81
84
  parallel (~> 1.10)
@@ -87,23 +90,22 @@ GEM
87
90
  rubocop (>= 0.68.0)
88
91
  ruby-progressbar (1.10.1)
89
92
  safe_yaml (1.0.5)
90
- simplecov (0.16.1)
93
+ simplecov (0.18.5)
91
94
  docile (~> 1.1)
92
- json (>= 1.8, < 3)
93
- simplecov-html (~> 0.10.0)
94
- simplecov-console (0.5.0)
95
+ simplecov-html (~> 0.11)
96
+ simplecov-console (0.7.2)
95
97
  ansi
96
98
  simplecov
97
99
  terminal-table
98
- simplecov-html (0.10.2)
100
+ simplecov-html (0.12.2)
99
101
  terminal-table (1.8.0)
100
102
  unicode-display_width (~> 1.1, >= 1.1.1)
101
- thor (0.20.3)
103
+ thor (1.0.1)
102
104
  unf (0.1.4)
103
105
  unf_ext
104
- unf_ext (0.0.7.6)
106
+ unf_ext (0.0.7.7)
105
107
  unicode-display_width (1.5.0)
106
- webmock (3.6.0)
108
+ webmock (3.8.3)
107
109
  addressable (>= 2.3.6)
108
110
  crack (>= 0.3.2)
109
111
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -115,9 +117,11 @@ DEPENDENCIES
115
117
  appraisal
116
118
  bump
117
119
  bundler
120
+ codecov
118
121
  honeycomb-beeline!
119
122
  overcommit (~> 0.46.0)
120
- pry-byebug
123
+ pry (< 0.13.0)
124
+ pry-byebug (~> 3.6.0)
121
125
  rake
122
126
  rspec (~> 3.0)
123
127
  rubocop (< 0.69)
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![Build Status](https://circleci.com/gh/honeycombio/beeline-ruby.svg?style=svg)](https://circleci.com/gh/honeycombio/beeline-ruby)
4
4
  [![Gem Version](https://badge.fury.io/rb/honeycomb-beeline.svg)](https://badge.fury.io/rb/honeycomb-beeline)
5
+ [![codecov](https://codecov.io/gh/honeycombio/beeline-ruby/branch/main/graph/badge.svg)](https://codecov.io/gh/honeycombio/beeline-ruby)
5
6
 
6
7
  This package makes it easy to instrument your Ruby web app to send useful events to [Honeycomb](https://www.honeycomb.io), a service for debugging your software in production.
7
8
  - [Usage and Examples](https://docs.honeycomb.io/getting-data-in/beelines/ruby-beeline/)
@@ -24,6 +25,13 @@ Built in instrumentation for:
24
25
  - Sequel
25
26
  - Sinatra
26
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
+
27
35
  ## Get in touch
28
36
 
29
37
  Please reach out to [support@honeycomb.io](mailto:support@honeycomb.io) or ping
@@ -42,8 +42,10 @@ Gem::Specification.new do |spec|
42
42
  spec.add_development_dependency "appraisal"
43
43
  spec.add_development_dependency "bump"
44
44
  spec.add_development_dependency "bundler"
45
+ spec.add_development_dependency "codecov"
45
46
  spec.add_development_dependency "overcommit", "~> 0.46.0"
46
- spec.add_development_dependency "pry-byebug"
47
+ spec.add_development_dependency "pry", "< 0.13.0"
48
+ spec.add_development_dependency "pry-byebug", "~> 3.6.0"
47
49
  spec.add_development_dependency "rake"
48
50
  spec.add_development_dependency "rspec", "~> 3.0"
49
51
  spec.add_development_dependency "rubocop", "< 0.69"
@@ -3,7 +3,7 @@
3
3
  module Honeycomb
4
4
  module Beeline
5
5
  NAME = "honeycomb-beeline".freeze
6
- VERSION = "2.0.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)
@@ -54,24 +56,24 @@ module Honeycomb
54
56
  context.current_span.create_child
55
57
  end
56
58
 
59
+ current_span = context.current_span
60
+
57
61
  fields.each do |key, value|
58
- context.current_span.add_field(key, value)
62
+ current_span.add_field(key, value)
59
63
  end
60
64
 
61
- context.current_span.add_field("name", name)
62
-
63
- if block_given?
64
- begin
65
- yield context.current_span
66
- rescue StandardError => e
67
- context.current_span.add_field("error", e.class.name)
68
- context.current_span.add_field("error_detail", e.message)
69
- raise e
70
- ensure
71
- context.current_span.send
72
- end
73
- else
74
- context.current_span
65
+ current_span.add_field("name", name)
66
+
67
+ return current_span unless block_given?
68
+
69
+ begin
70
+ yield current_span
71
+ rescue StandardError => e
72
+ current_span.add_field("error", e.class.name)
73
+ current_span.add_field("error_detail", e.message)
74
+ raise e
75
+ ensure
76
+ current_span.send
75
77
  end
76
78
  end
77
79
 
@@ -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
@@ -33,7 +34,7 @@ module Honeycomb
33
34
 
34
35
  @client ||
35
36
  (debug && Libhoney::LogClient.new) ||
36
- Libhoney::Client.new(options)
37
+ Libhoney::Client.new(**options)
37
38
  end
38
39
 
39
40
  def after_initialize(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
@@ -65,7 +65,7 @@ module Honeycomb
65
65
  def finish(name, id, payload)
66
66
  return unless (span = spans[id].pop)
67
67
 
68
- handlers[name].call(name, span, payload)
68
+ handler_for(name).call(name, span, payload)
69
69
 
70
70
  span.send
71
71
  end
@@ -77,6 +77,16 @@ module Honeycomb
77
77
  def spans
78
78
  Thread.current[key] ||= Hash.new { |h, id| h[id] = [] }
79
79
  end
80
+
81
+ def handler_for(name)
82
+ handlers.fetch(name) do
83
+ handlers[
84
+ handlers.keys.detect do |key|
85
+ key.is_a?(Regexp) && key =~ name
86
+ end
87
+ ]
88
+ end
89
+ end
80
90
  end
81
91
  end
82
92
  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
@@ -13,7 +13,11 @@ module Honeycomb
13
13
  ["HTTP_VERSION", "request.http_version"],
14
14
  ["HTTP_HOST", "request.host"],
15
15
  ["REMOTE_ADDR", "request.remote_addr"],
16
+ ["HTTP_X_FORWARDED_FOR", "request.header.x_forwarded_for"],
17
+ ["HTTP_X_FORWARDED_PROTO", "request.header.x_forwarded_proto"],
18
+ ["HTTP_X_FORWARDED_PORT", "request.header.x_forwarded_port"],
16
19
  ["HTTP_ACCEPT", "request.header.accept"],
20
+ ["HTTP_ACCEPT_LANGUAGE", "request.header.accept_language"],
17
21
  ["CONTENT_TYPE", "request.header.content_type"],
18
22
  ["HTTP_USER_AGENT", "request.header.user_agent"],
19
23
  ["rack.url_scheme", "request.scheme"],
@@ -28,12 +32,14 @@ module Honeycomb
28
32
 
29
33
  def call(env)
30
34
  req = ::Rack::Request.new(env)
31
- hny = env["HTTP_X_HONEYCOMB_TRACE"]
32
- 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|
33
39
  add_field = lambda do |key, value|
34
- next unless value && !value.empty?
35
-
36
- span.add_field(key, value)
40
+ unless value.nil? || (value.respond_to?(:empty?) && value.empty?)
41
+ span.add_field(key, value)
42
+ end
37
43
  end
38
44
 
39
45
  extract_fields(env, RACK_FIELDS, &add_field)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Honeycomb
4
- # Methods for extracing common warden/devise fields from a rack env hash
4
+ # Methods for extracting common warden/devise fields from a rack env hash
5
5
  module Warden
6
6
  COMMON_USER_FIELDS = %i[
7
7
  email
@@ -24,7 +24,7 @@ module Honeycomb
24
24
  key.match(SCOPE_PATTERN)
25
25
  end
26
26
  warden_scopes = keys.map do |key|
27
- key.gsub(SCOPE_PATTERN, "\1")
27
+ key.gsub(SCOPE_PATTERN, "\\1")
28
28
  end
29
29
  best_scope = warden_scopes.include?("user") ? "user" : warden_scopes.first
30
30
 
@@ -4,63 +4,16 @@ require "base64"
4
4
  require "json"
5
5
  require "uri"
6
6
 
7
+ require "honeycomb/propagation/honeycomb"
8
+
7
9
  module Honeycomb
8
10
  # Parse trace headers
9
11
  module PropagationParser
10
- def parse(serialized_trace)
11
- unless serialized_trace.nil?
12
- version, payload = serialized_trace.split(";", 2)
13
-
14
- if version == "1"
15
- trace_id, parent_span_id, trace_fields, dataset = parse_v1(payload)
16
-
17
- if !trace_id.nil? && !parent_span_id.nil?
18
- return [trace_id, parent_span_id, trace_fields, dataset]
19
- end
20
- end
21
- end
22
-
23
- [nil, nil, nil, nil]
24
- end
25
-
26
- def parse_v1(payload)
27
- trace_id, parent_span_id, trace_fields, dataset = nil
28
- payload.split(",").each do |entry|
29
- key, value = entry.split("=", 2)
30
- case key
31
- when "dataset"
32
- dataset = URI.decode_www_form_component(value)
33
- when "trace_id"
34
- trace_id = value
35
- when "parent_id"
36
- parent_span_id = value
37
- when "context"
38
- Base64.decode64(value).tap do |json|
39
- begin
40
- trace_fields = JSON.parse json
41
- rescue JSON::ParserError
42
- trace_fields = {}
43
- end
44
- end
45
- end
46
- end
47
-
48
- [trace_id, parent_span_id, trace_fields, dataset]
49
- end
12
+ include HoneycombPropagation::UnmarshalTraceContext
50
13
  end
51
14
 
52
15
  # Serialize trace headers
53
16
  module PropagationSerializer
54
- def to_trace_header
55
- context = Base64.urlsafe_encode64(JSON.generate(trace.fields)).strip
56
- encoded_dataset = URI.encode_www_form_component(builder.dataset)
57
- data_to_propogate = [
58
- "dataset=#{encoded_dataset}",
59
- "trace_id=#{trace.id}",
60
- "parent_id=#{id}",
61
- "context=#{context}",
62
- ]
63
- "1;#{data_to_propogate.join(',')}"
64
- end
17
+ include HoneycombPropagation::MarshalTraceContext
65
18
  end
66
19
  end