honeycomb-beeline 2.8.1 → 2.10.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: ce57f1fcfd4e116392e16f4296760b7a707f780bab641149d148ddc31dda7ff2
4
- data.tar.gz: 4d1013f4036fd56923f725a745a0e9387835775b7fd53d671fa270840b737047
3
+ metadata.gz: 590816d848fd6df0a39dce83e6261c2d3ba66934ccb12f59011b789251d42fb9
4
+ data.tar.gz: 8b45a8e7738e3364d47907c2a2e5bbd05cd5c83b7a41c70e7c33524e6bc28188
5
5
  SHA512:
6
- metadata.gz: 4d236e51b6cc86afbfa22f85c24f9633186b99b0e33cdbf6c842936ec060a24735e11bb8a778c55fe6bae82c461ffbf75e72e99ce190b2c2f2a6cb0f419b4074
7
- data.tar.gz: c33e5df57ebb42e47915006c2cf62259c13743c9419a76f04b89ca8bbf58d2cc500106217e32b1863432d937686aea32637f8bde0f7824ea2bd6453a60b65268
6
+ metadata.gz: 36cdd5a79a28f83ad6f2ba81528c4d4610f71f40a0bcaf3436179c8f0e1ce07710bec89bb9a409fe4fc124d78682d59c89067d1ec793c17f14b6b1bd77854e55
7
+ data.tar.gz: 71804df5927682587c09f078e7af2edebab99b49369735cf32312f4bea3ed9ec0a2f28cfa8b9ddf968da9ac142132e788eed85f712c4904686ab80fdbfb9aa4b
data/.rubocop.yml CHANGED
@@ -26,6 +26,7 @@ Metrics/MethodLength:
26
26
  - lib/generators/honeycomb/honeycomb_generator.rb
27
27
 
28
28
  Metrics/LineLength:
29
+ Max: 100
29
30
  Exclude:
30
31
  - spec/honeycomb/integrations/active_support_spec.rb
31
32
  - spec/support/event_data_shared_examples.rb
@@ -71,3 +72,6 @@ Style/AsciiComments:
71
72
 
72
73
  Style/Alias:
73
74
  EnforcedStyle: prefer_alias_method
75
+
76
+ Style/IfUnlessModifier:
77
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # beeline-ruby changelog
2
2
 
3
+ ## 2.10.0 2022-04-08
4
+
5
+ ### Improvments
6
+
7
+ - Add HTTP referer to rack integration (#197) | [@bgitt](https://github.com/bgitt)
8
+
9
+ ### Fixed
10
+
11
+ - Fix regression with mid vs leaf meta.span_type detection (#194) | [@ajvondrak](https://github.com/ajvondrak)
12
+
13
+ ## 2.9.0 2022-03-23
14
+
15
+ ### Enhancements
16
+
17
+ - Add Environment and Services support (#196) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
18
+
19
+ ## 2.8.2 2022-02-02
20
+
21
+ ### Maintenance
22
+
23
+ - Remove the upperbound on libhoney version (#191) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
24
+
3
25
  ## 2.8.1 2022-01-12
4
26
 
5
27
  ### Fixed
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
37
37
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
38
  spec.require_paths = ["lib"]
39
39
 
40
- spec.add_dependency "libhoney", ">= 1.14.2", "~> 1.14"
40
+ spec.add_dependency "libhoney", ">= 1.14.2"
41
41
 
42
42
  spec.add_development_dependency "appraisal"
43
43
  spec.add_development_dependency "bump"
@@ -11,7 +11,7 @@ class HoneycombGenerator < Rails::Generators::Base
11
11
 
12
12
  argument :write_key, required: true, desc: "required"
13
13
 
14
- class_option :dataset, type: :string, default: "rails"
14
+ class_option :service_name, type: :string, default: "rails"
15
15
 
16
16
  gem "honeycomb-beeline"
17
17
 
@@ -22,7 +22,7 @@ class HoneycombGenerator < Rails::Generators::Base
22
22
  <<-RUBY.strip_heredoc
23
23
  Honeycomb.configure do |config|
24
24
  config.write_key = #{write_key.inspect}
25
- config.dataset = #{options['dataset'].inspect}
25
+ config.service_name = #{options['service_name'].inspect}
26
26
  config.presend_hook do |fields|
27
27
  if fields["name"] == "redis" && fields.has_key?("redis.command")
28
28
  # remove potential PII from the redis command
@@ -3,7 +3,7 @@
3
3
  module Honeycomb
4
4
  module Beeline
5
5
  NAME = "honeycomb-beeline".freeze
6
- VERSION = "2.8.1".freeze
6
+ VERSION = "2.10.0".freeze
7
7
  USER_AGENT_SUFFIX = "#{NAME}/#{VERSION}".freeze
8
8
  end
9
9
  end
@@ -30,8 +30,11 @@ module Honeycomb
30
30
 
31
31
  # maybe make `service_name` a required parameter
32
32
  @libhoney.add_field "service_name", configuration.service_name
33
+ @libhoney.add_field "service.name", configuration.service_name
33
34
  @context = Context.new
34
35
 
36
+ @context.classic = classic_write_key?(configuration.write_key)
37
+
35
38
  @additional_trace_options = {
36
39
  presend_hook: configuration.presend_hook,
37
40
  sample_hook: configuration.sample_hook,
@@ -125,5 +128,9 @@ module Honeycomb
125
128
  span.add_field("error_backtrace_limit", error_backtrace_limit)
126
129
  span.add_field("error_backtrace_total_length", exception.backtrace.length)
127
130
  end
131
+
132
+ def classic_write_key?(write_key)
133
+ write_key.nil? || write_key.length == 32
134
+ end
128
135
  end
129
136
  end
@@ -2,16 +2,16 @@
2
2
 
3
3
  require "socket"
4
4
  require "honeycomb/propagation/default"
5
+ require "honeycomb/propagation/default_modern"
5
6
 
6
7
  module Honeycomb
7
8
  # Used to configure the Honeycomb client
8
9
  class Configuration
9
10
  attr_accessor :write_key,
10
- :dataset,
11
11
  :api_host,
12
12
  :debug
13
13
 
14
- attr_writer :service_name, :client, :host_name
14
+ attr_writer :service_name, :client, :host_name, :dataset
15
15
  attr_reader :error_backtrace_limit
16
16
 
17
17
  def initialize
@@ -23,8 +23,31 @@ module Honeycomb
23
23
  @client = nil
24
24
  end
25
25
 
26
+ def classic?
27
+ @write_key.nil? || @write_key.length == 32
28
+ end
29
+
26
30
  def service_name
27
- @service_name || dataset
31
+ return @service_name if service_name_given?
32
+ return @dataset if classic?
33
+
34
+ "unknown_service:" + $PROGRAM_NAME.split("/").last
35
+ end
36
+
37
+ def dataset
38
+ return @dataset if classic?
39
+ return "unknown_service" if service_name.nil?
40
+
41
+ stripped_service_name = service_name.strip
42
+
43
+ warn("found extra whitespace in service name") if stripped_service_name != service_name
44
+
45
+ if stripped_service_name.empty? || stripped_service_name.start_with?("unknown_service")
46
+ # don't use process name in dataset
47
+ "unknown_service"
48
+ else
49
+ stripped_service_name
50
+ end
28
51
  end
29
52
 
30
53
  def error_backtrace_limit=(val)
@@ -39,6 +62,7 @@ module Honeycomb
39
62
  if debug
40
63
  Libhoney::LogClient.new
41
64
  else
65
+ validate_options
42
66
  Libhoney::Client.new(**libhoney_client_options)
43
67
  end
44
68
  end
@@ -73,9 +97,11 @@ module Honeycomb
73
97
  @http_trace_parser_hook = hook
74
98
  elsif @http_trace_parser_hook
75
99
  @http_trace_parser_hook
100
+ elsif classic?
101
+ DefaultPropagation::UnmarshalTraceContext.method(:parse_rack_env)
76
102
  else
77
103
  # by default we try to parse incoming honeycomb traces
78
- DefaultPropagation::UnmarshalTraceContext.method(:parse_rack_env)
104
+ DefaultModernPropagation::UnmarshalTraceContext.method(:parse_rack_env)
79
105
  end
80
106
  end
81
107
 
@@ -84,9 +110,11 @@ module Honeycomb
84
110
  @http_trace_propagation_hook = hook
85
111
  elsif @http_trace_propagation_hook
86
112
  @http_trace_propagation_hook
113
+ elsif classic?
114
+ HoneycombPropagation::MarshalTraceContext.method(:parse_faraday_env)
87
115
  else
88
116
  # by default we send outgoing honeycomb trace headers
89
- HoneycombPropagation::MarshalTraceContext.method(:parse_faraday_env)
117
+ HoneycombModernPropagation::MarshalTraceContext.method(:parse_faraday_env)
90
118
  end
91
119
  end
92
120
 
@@ -102,5 +130,31 @@ module Honeycomb
102
130
  options[:api_host] = api_host if api_host
103
131
  end
104
132
  end
133
+
134
+ def validate_options
135
+ warn("missing write_key") if write_key.nil? || write_key.empty?
136
+ if classic?
137
+ validate_options_classic
138
+ else
139
+ warn("service_name is unknown, will set to " + service_name) \
140
+ if service_name.start_with?("unknown_service")
141
+ warn("dataset will be ignored, sending data to " + service_name) \
142
+ if dataset_given?
143
+ end
144
+ end
145
+
146
+ def validate_options_classic
147
+ warn("empty service_name option") unless service_name_given?
148
+ warn("empty dataset option") unless dataset_given?
149
+ end
150
+
151
+ def service_name_given?
152
+ # check the instance variables, not the accessor method
153
+ @service_name && !@service_name.empty?
154
+ end
155
+
156
+ def dataset_given?
157
+ @dataset && !@dataset.empty?
158
+ end
105
159
  end
106
160
  end
@@ -3,6 +3,7 @@
3
3
  module Honeycomb
4
4
  # Stores the current span and trace context
5
5
  class Context
6
+ attr_writer :classic
6
7
  def current_trace
7
8
  return if current_span.nil?
8
9
 
@@ -23,6 +24,10 @@ module Honeycomb
23
24
  spans.pop
24
25
  end
25
26
 
27
+ def classic?
28
+ @classic
29
+ end
30
+
26
31
  private
27
32
 
28
33
  def spans
@@ -22,6 +22,7 @@ module Honeycomb
22
22
  ["CONTENT_TYPE", "request.header.content_type"],
23
23
  ["HTTP_USER_AGENT", "request.header.user_agent"],
24
24
  ["rack.url_scheme", "request.scheme"],
25
+ ["HTTP_REFERER", "request.header.referer"],
25
26
  ].freeze
26
27
 
27
28
  attr_reader :app, :client
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "honeycomb/propagation/honeycomb_modern"
4
+ require "honeycomb/propagation/w3c"
5
+
6
+ module Honeycomb
7
+ # Default behavior for handling trace propagation
8
+ module DefaultModernPropagation
9
+ # Parse incoming trace headers.
10
+ #
11
+ # Checks for and parses Honeycomb's trace header or, if not found,
12
+ # then checks for and parses W3C trace parent header.
13
+ module UnmarshalTraceContext
14
+ def parse_rack_env(env)
15
+ if env["HTTP_X_HONEYCOMB_TRACE"]
16
+ HoneycombModernPropagation::UnmarshalTraceContext.parse_rack_env env
17
+ elsif env["HTTP_TRACEPARENT"]
18
+ W3CPropagation::UnmarshalTraceContext.parse_rack_env env
19
+ else
20
+ [nil, nil, nil, nil]
21
+ end
22
+ end
23
+ # rubocop:disable Style/AccessModifierDeclarations
24
+ module_function :parse_rack_env
25
+ public :parse_rack_env
26
+ # rubocop:enable Style/AccessModifierDeclarations
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+ require "json"
5
+ require "uri"
6
+
7
+ module Honeycomb
8
+ # Parsing and propagation for honeycomb trace headers
9
+ module HoneycombModernPropagation
10
+ # Parse trace headers
11
+ module UnmarshalTraceContext
12
+ def parse_rack_env(env)
13
+ parse env["HTTP_X_HONEYCOMB_TRACE"]
14
+ end
15
+
16
+ def parse(serialized_trace)
17
+ unless serialized_trace.nil?
18
+ version, payload = serialized_trace.split(";", 2)
19
+
20
+ if version == "1"
21
+ trace_id, parent_span_id, trace_fields = parse_v1(payload)
22
+
23
+ if !trace_id.nil? && !parent_span_id.nil?
24
+ return [trace_id, parent_span_id, trace_fields, nil]
25
+ end
26
+ end
27
+ end
28
+
29
+ [nil, nil, nil, nil]
30
+ end
31
+
32
+ def parse_v1(payload)
33
+ trace_id, parent_span_id, trace_fields = nil
34
+ payload.split(",").each do |entry|
35
+ key, value = entry.split("=", 2)
36
+ case key.downcase
37
+ when "trace_id"
38
+ trace_id = value
39
+ when "parent_id"
40
+ parent_span_id = value
41
+ when "context"
42
+ Base64.decode64(value).tap do |json|
43
+ begin
44
+ trace_fields = JSON.parse json
45
+ rescue JSON::ParserError
46
+ trace_fields = {}
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ [trace_id, parent_span_id, trace_fields, nil]
53
+ end
54
+
55
+ module_function :parse_rack_env, :parse, :parse_v1
56
+ public :parse_rack_env, :parse
57
+ end
58
+
59
+ # Serialize trace headers
60
+ module MarshalTraceContext
61
+ def to_trace_header
62
+ context = Base64.urlsafe_encode64(JSON.generate(trace.fields)).strip
63
+ data_to_propogate = [
64
+ "trace_id=#{trace.id}",
65
+ "parent_id=#{id}",
66
+ "context=#{context}",
67
+ ]
68
+ "1;#{data_to_propogate.join(',')}"
69
+ end
70
+
71
+ def self.parse_faraday_env(_env, propagation_context)
72
+ {
73
+ "X-Honeycomb-Trace" => to_trace_header(propagation_context),
74
+ }
75
+ end
76
+
77
+ def self.to_trace_header(propagation_context)
78
+ fields = propagation_context.trace_fields
79
+ context = Base64.urlsafe_encode64(JSON.generate(fields)).strip
80
+ data_to_propogate = [
81
+ "trace_id=#{propagation_context.trace_id}",
82
+ "parent_id=#{propagation_context.parent_id}",
83
+ "context=#{context}",
84
+ ]
85
+ "1;#{data_to_propogate.join(',')}"
86
+ end
87
+ end
88
+ end
89
+ end
@@ -31,12 +31,8 @@ module Honeycomb
31
31
  def parse_v1(payload)
32
32
  trace_id, parent_span_id, trace_flags = payload.split("-", 3)
33
33
 
34
- if trace_flags.nil?
35
- # if trace_flags is nil, it means a field is missing
36
- return [nil, nil]
37
- end
38
-
39
- if trace_id == INVALID_TRACE_ID || parent_span_id == INVALID_SPAN_ID
34
+ # if trace_flags is nil, it means a field is missing
35
+ if trace_flags.nil? || trace_id == INVALID_TRACE_ID || parent_span_id == INVALID_SPAN_ID
40
36
  return [nil, nil]
41
37
  end
42
38
 
@@ -50,6 +50,7 @@ module Honeycomb
50
50
  # compatability
51
51
  @parent_id = parent_id
52
52
  @is_root = is_root
53
+ @is_leaf = true
53
54
  end
54
55
 
55
56
  def parse_hooks(sample_hook: nil,
@@ -71,6 +72,7 @@ module Honeycomb
71
72
  presend_hook: presend_hook,
72
73
  propagation_hook: propagation_hook).tap do |c|
73
74
  children << c
75
+ @is_leaf = false
74
76
  end
75
77
  end
76
78
 
@@ -132,6 +134,10 @@ module Honeycomb
132
134
  @is_root
133
135
  end
134
136
 
137
+ def leaf?
138
+ @is_leaf
139
+ end
140
+
135
141
  def send_internal
136
142
  add_additional_fields
137
143
  send_children
@@ -180,7 +186,7 @@ module Honeycomb
180
186
  def span_type
181
187
  if root?
182
188
  parent_id.nil? ? "root" : "subroot"
183
- elsif children.empty?
189
+ elsif leaf?
184
190
  "leaf"
185
191
  else
186
192
  "mid"
@@ -9,7 +9,6 @@ require "honeycomb/rollup_fields"
9
9
  module Honeycomb
10
10
  # Represents a Honeycomb trace, which groups spans together
11
11
  class Trace
12
- include PropagationParser
13
12
  include RollupFields
14
13
  extend Forwardable
15
14
 
@@ -19,9 +18,14 @@ module Honeycomb
19
18
 
20
19
  def initialize(builder:, context:, serialized_trace: nil, **options)
21
20
  trace_id, parent_span_id, trace_fields, dataset =
22
- internal_parse(serialized_trace: serialized_trace, **options)
21
+ internal_parse(context: context, serialized_trace: serialized_trace, **options)
22
+
23
+ # if dataset is not nil,
24
+ # set trace's builder.dataset = dataset from trace header
25
+ if context.classic?
26
+ dataset && builder.dataset = dataset
27
+ end
23
28
 
24
- dataset && builder.dataset = dataset
25
29
  @id = trace_id || generate_trace_id
26
30
  @fields = trace_fields || {}
27
31
  @root_span = Span.new(trace: self,
@@ -47,15 +51,17 @@ module Honeycomb
47
51
  end
48
52
  end
49
53
 
50
- def internal_parse(serialized_trace: nil, parser_hook: nil, **_options)
54
+ def internal_parse(context:, serialized_trace: nil, parser_hook: nil, **_options)
51
55
  # previously we passed in the header directly as a string for us to parse
52
56
  # now we get passed the rack env to use as an argument to the provided
53
57
  # parser_hook. This preserves the current behaviour and allows us to
54
58
  # move forward with the new behaviour without breaking changes
55
59
  if serialized_trace.is_a?(Hash) && parser_hook
56
60
  parser_hook.call(serialized_trace)
61
+ elsif context.classic?
62
+ HoneycombPropagation::UnmarshalTraceContext.parse serialized_trace
57
63
  else
58
- parse serialized_trace
64
+ HoneycombModernPropagation::UnmarshalTraceContext.parse serialized_trace
59
65
  end
60
66
  end
61
67
  end
metadata CHANGED
@@ -1,22 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: honeycomb-beeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.1
4
+ version: 2.10.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: 2022-01-12 00:00:00.000000000 Z
11
+ date: 2022-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: libhoney
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.14'
20
17
  - - ">="
21
18
  - !ruby/object:Gem::Version
22
19
  version: 1.14.2
@@ -24,9 +21,6 @@ dependencies:
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '1.14'
30
24
  - - ">="
31
25
  - !ruby/object:Gem::Version
32
26
  version: 1.14.2
@@ -294,7 +288,9 @@ files:
294
288
  - lib/honeycomb/propagation/aws.rb
295
289
  - lib/honeycomb/propagation/context.rb
296
290
  - lib/honeycomb/propagation/default.rb
291
+ - lib/honeycomb/propagation/default_modern.rb
297
292
  - lib/honeycomb/propagation/honeycomb.rb
293
+ - lib/honeycomb/propagation/honeycomb_modern.rb
298
294
  - lib/honeycomb/propagation/w3c.rb
299
295
  - lib/honeycomb/rollup_fields.rb
300
296
  - lib/honeycomb/span.rb