honeycomb-beeline 2.8.0 → 2.9.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: fa203ac2df453da5a0e29891b24e4a29e354fb903f7cd5dcc9ad628412675955
4
- data.tar.gz: 36d850c39cd38114abc078ac433afd8e1ec7f3e7bc6f6b2d58500e6c75cb09a9
3
+ metadata.gz: 2dd1c8587f1aaa8ca239aa4a526f1be4aea49814f3c92134a9dd59ecdb79f4dc
4
+ data.tar.gz: cc1e21f4d0e2d5e65d58502196fd74eb862d5890b577f789875b4427c66c2d0f
5
5
  SHA512:
6
- metadata.gz: '0820b6a9fc82ab51d583184eb34a4abdfff98f61d8d1c2807c3dffe884c3cc815499c718f90920c79e92e20d6166b990a39c47bb4e0eb17ff4da161e4f802f38'
7
- data.tar.gz: 8a17134f59e43879990446dc9ec53a07fdf49567c77b04c2339586eb35c472924e6d36743ee2515adfaffd88db05835f28a5f1cdf7b2776bbdd2fc169ba660cb
6
+ metadata.gz: 53765870c5c3d5b2eda2992e472f270412548a0f5f71e5ed36fa005129d9ae831bbb1ad19903797c558909fc9d2e93e42002d0d15fba05756fa4a785064f1eb9
7
+ data.tar.gz: c3be19aed350b937ff3ec4d9789861f609afc490f16670c370d9a60f263eea4759198ce4a93ec3802cd42948abc87745f1a8b06cd0c56c4f1fcfe8b6a25a31a4
@@ -0,0 +1,12 @@
1
+ name: Re-triage issues with new comments
2
+ on:
3
+ issue_comment:
4
+ types: [created]
5
+ jobs:
6
+ re-triage:
7
+ runs-on: ubuntu-latest
8
+ name: Re-triage issues with new comments
9
+ steps:
10
+ - uses: honeycombio/oss-management-actions/re-triage@v1
11
+ with:
12
+ ghprojects-token: ${{ secrets.GHPROJECTS_TOKEN }}
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,28 @@
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
+
9
+ ## 2.8.2 2022-02-02
10
+
11
+ ### Maintenance
12
+
13
+ - Remove the upperbound on libhoney version (#191) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
14
+
15
+ ## 2.8.1 2022-01-12
16
+
17
+ ### Fixed
18
+
19
+ - fix Beeline user-agent addition when creating a Libhoney client (#189) | [@robbkidd](https://github.com/robbkidd)
20
+
21
+ ### Maintenance
22
+
23
+ - gh: add re-triage workflow (#185) | [@vreynolds](https://github.com/vreynolds)
24
+ - set minimum version of rspec_junit_formatter (#188) | [@robbkidd](https://github.com/robbkidd)
25
+
3
26
  ## 2.8.0 2021-12-22
4
27
 
5
28
  ### Improvements
@@ -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"
@@ -47,7 +47,7 @@ Gem::Specification.new do |spec|
47
47
  spec.add_development_dependency "pry-byebug", "~> 3.6.0"
48
48
  spec.add_development_dependency "rake"
49
49
  spec.add_development_dependency "rspec", "~> 3.0"
50
- spec.add_development_dependency "rspec_junit_formatter"
50
+ spec.add_development_dependency "rspec_junit_formatter", ">= 0.5.1"
51
51
  spec.add_development_dependency "rubocop", "< 0.69"
52
52
  spec.add_development_dependency "rubocop-performance", "< 1.3.0"
53
53
  spec.add_development_dependency "simplecov"
@@ -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.0".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)
@@ -32,15 +55,16 @@ module Honeycomb
32
55
  end
33
56
 
34
57
  def client
35
- options = {}.tap do |o|
36
- o[:writekey] = write_key
37
- o[:dataset] = dataset
38
- api_host && o[:api_host] = api_host
39
- end
40
-
41
- @client ||
42
- (debug && Libhoney::LogClient.new) ||
43
- Libhoney::Client.new(**options)
58
+ # memoized:
59
+ # either the user has supplied a pre-configured Libhoney client
60
+ @client ||=
61
+ # or we'll create one and return it from here on
62
+ if debug
63
+ Libhoney::LogClient.new
64
+ else
65
+ validate_options
66
+ Libhoney::Client.new(**libhoney_client_options)
67
+ end
44
68
  end
45
69
 
46
70
  def after_initialize(client)
@@ -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,10 +110,51 @@ 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)
118
+ end
119
+ end
120
+
121
+ private
122
+
123
+ def libhoney_client_options
124
+ {
125
+ writekey: write_key,
126
+ dataset: dataset,
127
+ user_agent_addition: Honeycomb::Beeline::USER_AGENT_SUFFIX,
128
+ }.tap do |options|
129
+ # only set the API host for the client if one has been given
130
+ options[:api_host] = api_host if api_host
90
131
  end
91
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
92
159
  end
93
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,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.0
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: 2021-12-22 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
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
@@ -148,14 +142,14 @@ dependencies:
148
142
  requirements:
149
143
  - - ">="
150
144
  - !ruby/object:Gem::Version
151
- version: '0'
145
+ version: 0.5.1
152
146
  type: :development
153
147
  prerelease: false
154
148
  version_requirements: !ruby/object:Gem::Requirement
155
149
  requirements:
156
150
  - - ">="
157
151
  - !ruby/object:Gem::Version
158
- version: '0'
152
+ version: 0.5.1
159
153
  - !ruby/object:Gem::Dependency
160
154
  name: rubocop
161
155
  requirement: !ruby/object:Gem::Requirement
@@ -246,6 +240,7 @@ files:
246
240
  - ".github/dependabot.yml"
247
241
  - ".github/workflows/add-to-project.yml"
248
242
  - ".github/workflows/apply-labels.yml"
243
+ - ".github/workflows/re-triage.yml"
249
244
  - ".github/workflows/stale.yml"
250
245
  - ".gitignore"
251
246
  - ".overcommit.yml"
@@ -293,7 +288,9 @@ files:
293
288
  - lib/honeycomb/propagation/aws.rb
294
289
  - lib/honeycomb/propagation/context.rb
295
290
  - lib/honeycomb/propagation/default.rb
291
+ - lib/honeycomb/propagation/default_modern.rb
296
292
  - lib/honeycomb/propagation/honeycomb.rb
293
+ - lib/honeycomb/propagation/honeycomb_modern.rb
297
294
  - lib/honeycomb/propagation/w3c.rb
298
295
  - lib/honeycomb/rollup_fields.rb
299
296
  - lib/honeycomb/span.rb