honeycomb-beeline 2.8.2 → 2.9.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: 124e1b05ae5609ab32eae6a0340171848bb3bdd8e4291ea082e1da5c706a9eec
4
- data.tar.gz: f77c6cc246e8801386f09dee46fae845997aa4b1a9e978ac03d9c5e254ca9d49
3
+ metadata.gz: 2dd1c8587f1aaa8ca239aa4a526f1be4aea49814f3c92134a9dd59ecdb79f4dc
4
+ data.tar.gz: cc1e21f4d0e2d5e65d58502196fd74eb862d5890b577f789875b4427c66c2d0f
5
5
  SHA512:
6
- metadata.gz: dee1ffab32296f88e2f2fff6a53045e390f9dc7cd12a37dc016ed3d3555e022f90de689ce980293ef0b8080dab2ece6fab61056addbe0802a80bc3d0e53918d9
7
- data.tar.gz: 7ccccb62ef9ef6b9f93fa9e9aa2178dd028239614955e12409a66e06be9c01579ded06ae6c8a995bb1aaec37a947d24f66ac0a19ea92073eef77eb02b73c63a5
6
+ metadata.gz: 53765870c5c3d5b2eda2992e472f270412548a0f5f71e5ed36fa005129d9ae831bbb1ad19903797c558909fc9d2e93e42002d0d15fba05756fa4a785064f1eb9
7
+ data.tar.gz: c3be19aed350b937ff3ec4d9789861f609afc490f16670c370d9a60f263eea4759198ce4a93ec3802cd42948abc87745f1a8b06cd0c56c4f1fcfe8b6a25a31a4
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,11 @@
1
1
  # beeline-ruby changelog
2
2
 
3
+ ## 2.9.0 2022-03-23
4
+
5
+ ### Enhancements
6
+
7
+ - Add Environment and Services support (#196) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
8
+
3
9
  ## 2.8.2 2022-02-02
4
10
 
5
11
  ### Maintenance
@@ -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.2".freeze
6
+ VERSION = "2.9.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
@@ -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
 
@@ -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,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: honeycomb-beeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.2
4
+ version: 2.9.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-02-02 00:00:00.000000000 Z
11
+ date: 2022-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: libhoney
@@ -288,7 +288,9 @@ files:
288
288
  - lib/honeycomb/propagation/aws.rb
289
289
  - lib/honeycomb/propagation/context.rb
290
290
  - lib/honeycomb/propagation/default.rb
291
+ - lib/honeycomb/propagation/default_modern.rb
291
292
  - lib/honeycomb/propagation/honeycomb.rb
293
+ - lib/honeycomb/propagation/honeycomb_modern.rb
292
294
  - lib/honeycomb/propagation/w3c.rb
293
295
  - lib/honeycomb/rollup_fields.rb
294
296
  - lib/honeycomb/span.rb