honeycomb-beeline 2.3.0 → 2.5.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: 0606efad889f46b53eaa00c4a4c2f0e134641ce9a2427f65cc79eaf138a840be
4
- data.tar.gz: 95449860c9a30558bdb512b498f93fe0d00beca14b89582555e0cf2479316f74
3
+ metadata.gz: 8dfad7bddebd49b8645b61389e74035626a0cc817d5fc7ea9e51ab17cb571584
4
+ data.tar.gz: eadf7a28b41ddb6437e0e5a2c0824c2a2cf67fbf36a95bc18f77ad03b4f74306
5
5
  SHA512:
6
- metadata.gz: 0cf79345b6b669d4e07d02035840f7ba05bb508c9185259c7d308afd7cf18cb9d44c5c1592b04e445cf025037756a9c8512bfd436ea2e4c1f52884db9a08dbe7
7
- data.tar.gz: 7e73b0970480db0173ef147102da4ea9511e920457feea7178b1b4fd03905b4929c3581d01ec050586241028b7ec7921df5b90d466c882ea57d97ca69c58d5dd
6
+ metadata.gz: 7c6204f46a27e4a3af3bf5d2d173fdb4d06f820ecf76dd2ed84d0de52aca83fb155190075b244ee6ab7e811c93927874ae51d36cc117b018de995ad5aeb76f40
7
+ data.tar.gz: 175c355b5a5833bfd68b17a281fc2d71f0321f7c708e339b03090b367d64d7a6c9294ed8afcc84d5f538b6c80644f9c26488475962903a2364bb6ab0e7ee93f8
@@ -3,6 +3,10 @@
3
3
  set -ux
4
4
 
5
5
  if [[ "$BUNDLE_GEMFILE" =~ (rails_41.gemfile|rails_42.gemfile)$ ]]; then
6
+ echo "Rails 4.1 and 4.2 require an old Bundler"
6
7
  gem uninstall -v '>= 2' -ax bundler
7
8
  gem install bundler -v '< 2'
9
+ else
10
+ echo "Get the latest Bundler"
11
+ gem update bundler
8
12
  fi
data/.circleci/config.yml CHANGED
@@ -6,7 +6,6 @@ commands:
6
6
  type: string
7
7
  gemfile:
8
8
  type: string
9
- default: Gemfile
10
9
  command:
11
10
  type: string
12
11
  default: bundle exec rake test
@@ -14,28 +13,68 @@ commands:
14
13
  - checkout
15
14
  - restore_cache:
16
15
  keys:
17
- - gems-v1-<< parameters.ruby-version >>-{{ checksum "Gemfile.lock" }}
16
+ - gems-v1-<< parameters.ruby-version >>-<< parameters.gemfile >>-{{ checksum "Gemfile.lock" }}
17
+ - gems-v1-<< parameters.ruby-version >>-<< parameters.gemfile >>
18
18
  - gems-v1-<< parameters.ruby-version >>
19
- - run: gem update bundler
20
- - run: BUNDLE_GEMFILE=<< parameters.gemfile >> ./.circleci/bundler_version.sh
21
- - run: BUNDLE_GEMFILE=<< parameters.gemfile >> bundle install --jobs=4 --retry=3 --path vendor/bundle
19
+ - run: .circleci/bundler_version.sh
20
+ - run: bundle config set --local path $HOME/project/vendor/bundle
21
+ - run: bundle install --jobs=4 --retry=3
22
+ - run: bundle clean --force
23
+ - run: bundle env
22
24
  - save_cache:
23
25
  paths:
24
26
  - ./vendor/bundle
25
- key: gems-v1-<< parameters.ruby-version >>-{{ checksum "Gemfile.lock" }}
26
- - run: BUNDLE_GEMFILE=<< parameters.gemfile >> << parameters.command >>
27
+ key: gems-v1-<< parameters.ruby-version >>-<< parameters.gemfile >>-{{ checksum "Gemfile.lock" }}
28
+ - run: << parameters.command >>
27
29
 
28
30
  jobs:
29
- publish:
31
+ build_artifacts:
30
32
  docker:
31
- - image: circleci/ruby:2.6
33
+ - image: circleci/ruby:2.6
32
34
  steps:
33
35
  - checkout
36
+ - run: mkdir -p ~/artifacts
37
+ - run: gem build honeycomb-beeline.gemspec
38
+ - run: cp honeycomb-beeline-*.gem ~/artifacts/
39
+ - persist_to_workspace:
40
+ root: ~/
41
+ paths:
42
+ - artifacts
43
+ - store_artifacts:
44
+ path: ~/artifacts
45
+
46
+ publish_rubygems:
47
+ docker:
48
+ - image: circleci/ruby:2.6
49
+ steps:
50
+ - attach_workspace:
51
+ at: ~/
52
+ - run:
53
+ name: "Artifacts being published"
54
+ command: |
55
+ echo "about to publish to tag ${CIRCLE_TAG}"
56
+ ls -l ~/artifacts/*
57
+ - checkout
34
58
  - run:
35
59
  name: Setup Rubygems
36
60
  command: bash .circleci/setup-rubygems.sh
37
- - run: gem build honeycomb-beeline.gemspec
38
- - run: gem push honeycomb-beeline-*.gem
61
+ - run: gem push ~/artifacts/honeycomb-beeline-*.gem
62
+
63
+ publish_github:
64
+ docker:
65
+ - image: cibuilds/github:0.13.0
66
+ steps:
67
+ - attach_workspace:
68
+ at: ~/
69
+ - run:
70
+ name: "Artifacts being published"
71
+ command: |
72
+ echo "about to publish to tag ${CIRCLE_TAG}"
73
+ ls -l ~/artifacts/*
74
+ - run:
75
+ name: "GHR Draft"
76
+ command: ghr -draft -n ${CIRCLE_TAG} -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${CIRCLE_TAG} ~/artifacts
77
+
39
78
  lint:
40
79
  parameters:
41
80
  ruby-version:
@@ -43,9 +82,12 @@ jobs:
43
82
  default: "2.6"
44
83
  docker:
45
84
  - image: circleci/ruby:<< parameters.ruby-version >>
85
+ environment:
86
+ BUNDLE_GEMFILE: ./Gemfile
46
87
  steps:
47
88
  - ruby:
48
89
  ruby-version: << parameters.ruby-version >>
90
+ gemfile: root
49
91
  command: bundle exec rake rubocop
50
92
  test:
51
93
  parameters:
@@ -55,11 +97,15 @@ jobs:
55
97
  type: string
56
98
  docker:
57
99
  - image: circleci/ruby:<< parameters.ruby-version >>
100
+ environment:
101
+ BUNDLE_GEMFILE: gemfiles/<< parameters.gemfile >>.gemfile
58
102
  steps:
59
103
  - ruby:
60
104
  ruby-version: << parameters.ruby-version >>
61
105
  gemfile: << parameters.gemfile >>
62
106
  command: bundle exec rake test
107
+ - store_test_results:
108
+ path: test/reports
63
109
 
64
110
  workflows:
65
111
  nightly:
@@ -73,62 +119,68 @@ workflows:
73
119
  jobs:
74
120
  - lint
75
121
  - test: &test
122
+ name: test-<< matrix.gemfile >>-ruby_<< matrix.ruby-version >>
76
123
  requires:
77
124
  - lint
78
125
  matrix:
79
126
  parameters:
80
127
  ruby-version: ["2.2", "2.3", "2.4", "2.5", "2.6", "2.7"]
81
128
  gemfile:
82
- - gemfiles/aws_2.gemfile
83
- - gemfiles/aws_3.gemfile
84
- - gemfiles/faraday_0.gemfile
85
- - gemfiles/faraday_1.gemfile
86
- - gemfiles/sequel4.gemfile
87
- - gemfiles/sequel5.gemfile
88
- - gemfiles/sinatra.gemfile
89
- - gemfiles/rack.gemfile
90
- - gemfiles/rails_41.gemfile
91
- - gemfiles/rails_42.gemfile
92
- - gemfiles/rails_5.gemfile
93
- - gemfiles/rails_51.gemfile
94
- - gemfiles/rails_52.gemfile
95
- - gemfiles/rails_6.gemfile
96
- - gemfiles/redis_3.gemfile
97
- - gemfiles/redis_4.gemfile
129
+ - aws_2
130
+ - aws_3
131
+ - faraday_0
132
+ - faraday_1
133
+ - sequel4
134
+ - sequel5
135
+ - sinatra
136
+ - rack
137
+ - rails_41
138
+ - rails_42
139
+ - rails_5
140
+ - rails_51
141
+ - rails_52
142
+ - rails_6
143
+ - rails_61
144
+ - redis_3
145
+ - redis_4
98
146
  exclude:
99
147
  - ruby-version: "2.2"
100
- gemfile: gemfiles/faraday_1.gemfile
148
+ gemfile: faraday_1
149
+ - ruby-version: "2.2"
150
+ gemfile: rails_52
101
151
  - ruby-version: "2.2"
102
- gemfile: gemfiles/rails_52.gemfile
152
+ gemfile: rails_6
153
+ - ruby-version: "2.3"
154
+ gemfile: rails_6
155
+ - ruby-version: "2.4"
156
+ gemfile: rails_6
103
157
  - ruby-version: "2.2"
104
- gemfile: gemfiles/rails_6.gemfile
158
+ gemfile: rails_61
105
159
  - ruby-version: "2.3"
106
- gemfile: gemfiles/rails_6.gemfile
160
+ gemfile: rails_61
107
161
  - ruby-version: "2.4"
108
- gemfile: gemfiles/rails_6.gemfile
162
+ gemfile: rails_61
109
163
  - ruby-version: "2.4"
110
- gemfile: gemfiles/rails_41.gemfile
164
+ gemfile: rails_41
111
165
  - ruby-version: "2.5"
112
- gemfile: gemfiles/rails_41.gemfile
166
+ gemfile: rails_41
113
167
  - ruby-version: "2.6"
114
- gemfile: gemfiles/rails_41.gemfile
168
+ gemfile: rails_41
115
169
  - ruby-version: "2.7"
116
- gemfile: gemfiles/rails_41.gemfile
170
+ gemfile: rails_41
117
171
  - ruby-version: "2.7"
118
- gemfile: gemfiles/rails_42.gemfile
172
+ gemfile: rails_42
119
173
  beeline:
120
174
  jobs:
121
175
  - lint:
122
- filters:
176
+ filters: &regular_filters
123
177
  tags:
124
178
  only: /.*/
125
179
  - test:
126
180
  <<: *test
127
- filters:
128
- tags:
129
- only: /.*/
130
- - publish:
131
- filters:
181
+ filters: *regular_filters
182
+ - build_artifacts:
183
+ filters: &tag_filters
132
184
  tags:
133
185
  only: /^v.*/
134
186
  branches:
@@ -136,3 +188,10 @@ workflows:
136
188
  requires:
137
189
  - lint
138
190
  - test
191
+ - publish_rubygems: &publish
192
+ filters: *tag_filters
193
+ requires:
194
+ - build_artifacts
195
+ - publish_github:
196
+ <<: *publish
197
+ context: Honeycomb Secrets for Public Repos
data/.github/CODEOWNERS CHANGED
@@ -2,4 +2,4 @@
2
2
  # This file controls who is tagged for review for any given pull request.
3
3
 
4
4
  # For anything not explicitly taken by someone else:
5
- * @honeycombio/integrations-team @martin308
5
+ * @honeycombio/telemetry-team @martin308
@@ -0,0 +1,15 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "bundler" # See documentation for possible values
9
+ directory: "/gemfiles/" # Location of package manifests
10
+ schedule:
11
+ interval: "weekly"
12
+ labels:
13
+ - "type: dependencies"
14
+ reviewers:
15
+ - "honeycombio/telemetry-team"
@@ -0,0 +1,14 @@
1
+ name: Apply project management flow
2
+ on:
3
+ issues:
4
+ types: [opened]
5
+ pull_request_target:
6
+ types: [opened]
7
+ jobs:
8
+ project-management:
9
+ runs-on: ubuntu-latest
10
+ name: Apply project management flow
11
+ steps:
12
+ - uses: honeycombio/oss-management-actions/projects@v1
13
+ with:
14
+ ghprojects-token: ${{ secrets.GHPROJECTS_TOKEN }}
@@ -0,0 +1,10 @@
1
+ name: Apply project labels
2
+ on: [issues, pull_request, label]
3
+ jobs:
4
+ apply-labels:
5
+ runs-on: ubuntu-latest
6
+ name: Apply common project labels
7
+ steps:
8
+ - uses: honeycombio/oss-management-actions/labels@v1
9
+ with:
10
+ github-token: ${{ secrets.GITHUB_TOKEN }}
data/.gitignore CHANGED
@@ -5,6 +5,7 @@
5
5
  /doc/
6
6
  /pkg/
7
7
  /spec/reports/
8
+ /test/reports/
8
9
  /tmp/
9
10
  .idea/
10
11
 
data/.rspec CHANGED
@@ -1,3 +1,7 @@
1
+ <% if ENV['CI'] %>
2
+ --format RspecJunitFormatter
3
+ --out test/reports/result.xml
4
+ <% end %>
1
5
  --format documentation
2
6
  --color
3
7
  --require spec_helper
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 2.7.2
data/CHANGELOG.md ADDED
@@ -0,0 +1,116 @@
1
+ # beeline-ruby changelog
2
+
3
+ ## 2.5.0 2021-07-16
4
+
5
+ ### Added
6
+
7
+ - Allow backtrace to be sent with errors (#160) | [@lirossarvet](https://github.com/lirossarvet)
8
+
9
+ ### Maintenance
10
+
11
+ - Updates Github Action Workflows (#159) | [@bdarfler](https://github.com/bdarfler)
12
+ - Adds dependabot label (#158) | [@bdarfler](https://github.com/bdarfler)
13
+ - Switches CODEOWNERS to telemetry-team (#157) | [@bdarfler](https://github.com/bdarfler)
14
+
15
+ ## 2.4.2 2021-06-25
16
+
17
+ ### Fixes
18
+
19
+ - Update Rails middleware to get status code even on raised error. (#153) [@lirossarvet](https://github.com/lirossarvet)
20
+ - Make Rails spec consistent with Honeycomb Railtie Initialization. (#154) [@robbkidd](https://github.com/robbkidd)
21
+ - CI Improvements (#155) [@robbkidd](https://github.com/robbkidd)
22
+ - Improve performance of Redis command serialization. (#146) [@ajvondrak](https://github.com/ajvondrak)
23
+
24
+ ## 2.4.1 2021-06-01
25
+
26
+ ### Fixes
27
+
28
+ - Updates Redis event-field filter to handle string keys in options in
29
+ addition to symbol keys. (#147) [@cupakromer](https://github.com/cupakromer)
30
+
31
+ ### Maintenance
32
+
33
+ - Expanded on the Rails 5.2 example. (#141) [@robbkidd](https://github.com/robbkidd)
34
+ - Added a test case for current behavior of event emitted for an
35
+ exception raised in Rails. (@132) [@vreynolds](https://github.com/vreynolds)
36
+
37
+ ## 2.4.0 2021-01-07
38
+ ### Added
39
+ - Add support for HTTP Accept-Encoding header (#125) [@irvingreid](https://github.com/irvingreid)
40
+ - Add with_field, with_trace_field wrapper methods (#51) [@ajvondrak](https://github.com/ajvondrak)
41
+
42
+ ## 2.3.0 2020-11-06
43
+ ### Improvements
44
+ - Custom trace header hooks (#117)
45
+ - Add rspec filter :focus for assisting with debugging tests (#120)
46
+ - Be more lenient in expected output from AWS gem (#119)
47
+
48
+ ## 2.2.0 2020-09-02
49
+ ### New things
50
+ - refactor parsers/propagators, add w3c and aws parsers and propagators (#104) [@katiebayes](https://github.com/katiebayes)
51
+
52
+ ### Tiny fix
53
+ - Adjusted a threshold that should resolve the occasional build failures (#107) [@katiebayes](https://github.com/katiebayes)
54
+
55
+ ## 2.1.2 2020-08-26
56
+ ### Improvements
57
+ - reference current span in start_span (#105) [@rintaun](https://github.com/rintaun)
58
+ - switch trace and span ids over to w3c-supported formats (#100) [@katiebayes](https://github.com/katiebayes)
59
+
60
+ ## 2.1.1 2020-07-28
61
+ ### Fixes
62
+ - Remove children after sending | #98 | [@martin308](https://github.com/martin308)
63
+
64
+ ## 2.1.0 2020-06-10
65
+ ### Features
66
+ - Adding X-Forwarded-For to instrumented fields | #91 | [@paulosman](https://github.com/paulosman)
67
+ - Add request.header.accept_language field | #94 | [@timcraft](https://github.com/timcraft)
68
+ - Support custom notifications based on a regular expression | #92 | [@mrchucho](https://github.com/mrchucho)
69
+
70
+ ### Fixes
71
+ - Properly pass options for Ruby 2.7 | #85 | [@terracatta](https://github.com/terracatta)
72
+ - Fix regex substitution for warden and empty? errors for Rack | #88 | [@irvingreid](https://github.com/irvingreid)
73
+
74
+ ## 2.0.0 2020-03-10
75
+ See [release notes](https://github.com/honeycombio/beeline-ruby/releases/tag/v2.0.0)
76
+
77
+ ## 1.3.0 2019-11-20
78
+ ### Features
79
+ - redis integration | #42 | [@ajvondrak](https://github.com/ajvondrak)
80
+
81
+ ## 1.2.0 2019-11-04
82
+ ### Features
83
+ - aws-sdk v2 & v3 integration | #40 | [@ajvondrak](https://github.com/ajvondrak)
84
+
85
+ ## 1.1.1 2019-10-10
86
+ ### Fixes
87
+ - Skip params when unavailable | #39 | [@martin308](https://github.com/martin308)
88
+
89
+ ## 1.1.0 2019-10-07
90
+ ### Features
91
+ - Split rails and railtie integrations | #35 | [@martin308](https://github.com/martin308)
92
+
93
+ ## 1.0.1 2019-09-03
94
+ ### Fixes
95
+ - Set sample_hook and presend_hook on child spans | #26 | [@orangejulius](https://github.com/orangejulius)
96
+ - No-op if no client found in Faraday integration | #27 | [@Sergio-Mira](https://github.com/Sergio-Mira)
97
+
98
+ ## 1.0.0 2019-07-23
99
+ Version 1 is a milestone release. A complete re-write and modernization of Honeycomb's Ruby support.
100
+ See UPGRADING.md for migrating from v0.8.0 and see https://docs.honeycomb.io for full documentation.
101
+
102
+ ## 0.8.0 2019-05-06
103
+ ### Enhancements
104
+ - Expose event to #span block | #17 | [@eternal44](https://github.com/eternal44)
105
+
106
+ ## 0.7.0 2019-03-13
107
+ ### Enhancements
108
+ - Remove default inclusion of Sequel instrumentation | #12 | [@martin308](https://github.com/martin308)
109
+
110
+ ## 0.6.0 2018-11-29
111
+ ### Enhancements
112
+ - Tracing API and cross-process tracing | #4 | [@samstokes](https://github.com/samstokes)
113
+
114
+ ## 0.5.0 2018-11-29
115
+ ### Enhancements
116
+ - Improved rails support | #3 | [@samstokes](https://github.com/samstokes)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- honeycomb-beeline (2.3.0)
4
+ honeycomb-beeline (2.5.0)
5
5
  libhoney (~> 1.14, >= 1.14.2)
6
6
 
7
7
  GEM
@@ -29,6 +29,7 @@ GEM
29
29
  docile (1.3.2)
30
30
  domain_name (0.5.20190701)
31
31
  unf (>= 0.0.5, < 1.0.0)
32
+ excon (0.82.0)
32
33
  ffi (1.12.2)
33
34
  ffi-compiler (1.0.1)
34
35
  ffi (>= 1.0.0)
@@ -39,16 +40,17 @@ GEM
39
40
  http-cookie (~> 1.0)
40
41
  http-form_data (~> 2.2)
41
42
  http-parser (~> 1.2.0)
42
- http-cookie (1.0.3)
43
+ http-cookie (1.0.4)
43
44
  domain_name (~> 0.5)
44
45
  http-form_data (2.3.0)
45
- http-parser (1.2.1)
46
+ http-parser (1.2.3)
46
47
  ffi-compiler (>= 1.0, < 2.0)
47
48
  iniparse (1.5.0)
48
49
  jaro_winkler (1.5.4)
49
50
  json (2.3.1)
50
- libhoney (1.14.5)
51
+ libhoney (1.18.0)
51
52
  addressable (~> 2.0)
53
+ excon
52
54
  http (>= 2.0, < 5.0)
53
55
  method_source (0.9.2)
54
56
  overcommit (0.46.0)
@@ -79,6 +81,8 @@ GEM
79
81
  diff-lcs (>= 1.2.0, < 2.0)
80
82
  rspec-support (~> 3.9.0)
81
83
  rspec-support (3.9.3)
84
+ rspec_junit_formatter (0.4.1)
85
+ rspec-core (>= 2, < 4, != 2.12.0)
82
86
  rubocop (0.68.1)
83
87
  jaro_winkler (~> 1.5.1)
84
88
  parallel (~> 1.10)
@@ -124,6 +128,7 @@ DEPENDENCIES
124
128
  pry-byebug (~> 3.6.0)
125
129
  rake
126
130
  rspec (~> 3.0)
131
+ rspec_junit_formatter
127
132
  rubocop (< 0.69)
128
133
  rubocop-performance (< 1.3.0)
129
134
  simplecov
@@ -131,4 +136,4 @@ DEPENDENCIES
131
136
  webmock
132
137
 
133
138
  BUNDLED WITH
134
- 2.1.4
139
+ 2.2.21
data/UPGRADING.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Upgrade Guide
2
2
 
3
+ ## 1.0.0 - 2.0.0
4
+
5
+ 1. See release notes: https://github.com/honeycombio/beeline-ruby/releases/tag/v2.0.0
6
+ 1. This update requires no code changes, but you must be aware of certain instrumentation changes. New fields will be added to your dataset and other fields will be removed.
7
+ 1. ActionController::Parameters will now result in extra fields, or nested json, depending on your unfurl settings.
8
+ 1. aws.params are now exploded into separate fields.
9
+ 1. request.error becomes error.
10
+ 1. request.error_detail becomes error_detail
11
+ 1. request.protocol becomes request.scheme
12
+
3
13
  ## 0.8.0 - 1.0.0
4
14
 
5
15
  1. If you have a web application, remove beeline configuration from the `config.ru` file
@@ -48,6 +48,7 @@ Gem::Specification.new do |spec|
48
48
  spec.add_development_dependency "pry-byebug", "~> 3.6.0"
49
49
  spec.add_development_dependency "rake"
50
50
  spec.add_development_dependency "rspec", "~> 3.0"
51
+ spec.add_development_dependency "rspec_junit_formatter"
51
52
  spec.add_development_dependency "rubocop", "< 0.69"
52
53
  spec.add_development_dependency "rubocop-performance", "< 1.3.0"
53
54
  spec.add_development_dependency "simplecov"
@@ -26,7 +26,8 @@ module Honeycomb
26
26
  attr_reader :client
27
27
 
28
28
  def_delegators :@client, :libhoney, :start_span, :add_field,
29
- :add_field_to_trace, :current_span, :current_trace
29
+ :add_field_to_trace, :current_span, :current_trace,
30
+ :with_field, :with_trace_field
30
31
 
31
32
  def configure
32
33
  Configuration.new.tap do |config|
@@ -3,7 +3,7 @@
3
3
  module Honeycomb
4
4
  module Beeline
5
5
  NAME = "honeycomb-beeline".freeze
6
- VERSION = "2.3.0".freeze
6
+ VERSION = "2.5.0".freeze
7
7
  USER_AGENT_SUFFIX = "#{NAME}/#{VERSION}".freeze
8
8
  end
9
9
  end
@@ -38,6 +38,7 @@ module Honeycomb
38
38
  parser_hook: configuration.http_trace_parser_hook,
39
39
  propagation_hook: configuration.http_trace_propagation_hook,
40
40
  }
41
+ @error_backtrace_limit = configuration.error_backtrace_limit.to_i
41
42
 
42
43
  configuration.after_initialize(self)
43
44
 
@@ -47,16 +48,7 @@ module Honeycomb
47
48
  end
48
49
 
49
50
  def start_span(name:, serialized_trace: nil, **fields)
50
- if context.current_trace.nil?
51
- Trace.new(serialized_trace: serialized_trace,
52
- builder: libhoney.builder,
53
- context: context,
54
- **@additional_trace_options)
55
- else
56
- context.current_span.create_child
57
- end
58
-
59
- current_span = context.current_span
51
+ current_span = new_span_for_context(serialized_trace: serialized_trace)
60
52
 
61
53
  fields.each do |key, value|
62
54
  current_span.add_field(key, value)
@@ -69,8 +61,8 @@ module Honeycomb
69
61
  begin
70
62
  yield current_span
71
63
  rescue StandardError => e
72
- current_span.add_field("error", e.class.name)
73
- current_span.add_field("error_detail", e.message)
64
+ add_exception_data(current_span, e)
65
+
74
66
  raise e
75
67
  ensure
76
68
  current_span.send
@@ -89,8 +81,49 @@ module Honeycomb
89
81
  context.current_span.trace.add_field("app.#{key}", value)
90
82
  end
91
83
 
84
+ def with_field(key)
85
+ yield.tap { |value| add_field(key, value) }
86
+ end
87
+
88
+ def with_trace_field(key)
89
+ yield.tap { |value| add_field_to_trace(key, value) }
90
+ end
91
+
92
92
  private
93
93
 
94
- attr_reader :context
94
+ attr_reader :context, :error_backtrace_limit
95
+
96
+ def new_span_for_context(serialized_trace:)
97
+ if context.current_trace.nil?
98
+ Trace.new(
99
+ serialized_trace: serialized_trace,
100
+ builder: libhoney.builder,
101
+ context: context,
102
+ **@additional_trace_options,
103
+ )
104
+ else
105
+ context.current_span.create_child
106
+ end
107
+
108
+ context.current_span
109
+ end
110
+
111
+ def add_exception_data(span, exception)
112
+ span.add_field("error", exception.class.name)
113
+ span.add_field("error_detail", exception.message)
114
+
115
+ return if error_backtrace_limit <= 0
116
+
117
+ span.add_field(
118
+ "error_backtrace",
119
+ exception
120
+ .backtrace
121
+ .take(error_backtrace_limit)
122
+ .join("\n")
123
+ .encode("UTF-8", invalid: :replace, undef: :replace, replace: "�"),
124
+ )
125
+ span.add_field("error_backtrace_limit", error_backtrace_limit)
126
+ span.add_field("error_backtrace_total_length", exception.backtrace.length)
127
+ end
95
128
  end
96
129
  end
@@ -12,12 +12,14 @@ module Honeycomb
12
12
  :debug
13
13
 
14
14
  attr_writer :service_name, :client, :host_name
15
+ attr_reader :error_backtrace_limit
15
16
 
16
17
  def initialize
17
18
  @write_key = ENV["HONEYCOMB_WRITEKEY"]
18
19
  @dataset = ENV["HONEYCOMB_DATASET"]
19
20
  @service_name = ENV["HONEYCOMB_SERVICE"]
20
21
  @debug = ENV.key?("HONEYCOMB_DEBUG")
22
+ @error_backtrace_limit = 0
21
23
  @client = nil
22
24
  end
23
25
 
@@ -25,6 +27,10 @@ module Honeycomb
25
27
  @service_name || dataset
26
28
  end
27
29
 
30
+ def error_backtrace_limit=(val)
31
+ @error_backtrace_limit = Integer(val)
32
+ end
33
+
28
34
  def client
29
35
  options = {}.tap do |o|
30
36
  o[:writekey] = write_key
@@ -17,6 +17,7 @@ module Honeycomb
17
17
  ["HTTP_X_FORWARDED_PROTO", "request.header.x_forwarded_proto"],
18
18
  ["HTTP_X_FORWARDED_PORT", "request.header.x_forwarded_port"],
19
19
  ["HTTP_ACCEPT", "request.header.accept"],
20
+ ["HTTP_ACCEPT_ENCODING", "request.header.accept_encoding"],
20
21
  ["HTTP_ACCEPT_LANGUAGE", "request.header.accept_language"],
21
22
  ["CONTENT_TYPE", "request.header.content_type"],
22
23
  ["HTTP_USER_AGENT", "request.header.user_agent"],
@@ -47,11 +48,12 @@ module Honeycomb
47
48
  span.add_field("request.secure", req.ssl?)
48
49
  span.add_field("request.xhr", req.xhr?)
49
50
 
50
- status, headers, body = app.call(env)
51
-
52
- add_package_information(env, &add_field)
53
-
54
- extract_user_information(env, &add_field)
51
+ begin
52
+ status, headers, body = call_with_hook(env, span, &add_field)
53
+ ensure
54
+ add_package_information(env, &add_field)
55
+ extract_user_information(env, &add_field)
56
+ end
55
57
 
56
58
  span.add_field("response.status_code", status)
57
59
  span.add_field("response.content_type", headers["Content-Type"])
@@ -71,6 +73,12 @@ module Honeycomb
71
73
  end
72
74
  end
73
75
 
76
+ private
77
+
78
+ def call_with_hook(env, _span, &_add_field)
79
+ app.call(env)
80
+ end
81
+
74
82
  # Rack middleware
75
83
  class Middleware
76
84
  include Rack
@@ -89,6 +89,16 @@ module Honeycomb
89
89
  include Rack
90
90
  include Warden
91
91
  include Rails
92
+
93
+ def call_with_hook(env, span, &_add_field)
94
+ super
95
+ rescue StandardError => e
96
+ wrapped = ActionDispatch::ExceptionWrapper.new(nil, e)
97
+
98
+ span.add_field "response.status_code", wrapped.status_code
99
+
100
+ raise e
101
+ end
92
102
  end
93
103
  end
94
104
  end
@@ -159,7 +159,17 @@ module Honeycomb
159
159
  # * :logger - just some Ruby object, not useful
160
160
  # * :_parsed - implementation detail
161
161
  def ignore?(option)
162
- %i[url password logger _parsed].include?(option)
162
+ # Redis options may be symbol or string keys.
163
+ #
164
+ # This normalizes `option` using `to_sym` as benchmarking on Ruby MRI
165
+ # v2.6.6 and v2.7.3 has shown that was faster compared to `to_s`.
166
+ # However, `nil` does not support `to_sym`. This uses a guard clause to
167
+ # handle the `nil` case because this is still faster than safe
168
+ # navigation. Also this lib still supports Ruby 2.2.0; which does not
169
+ # include safe navigation.
170
+ return true unless option
171
+
172
+ %i[url password logger _parsed].include?(option.to_sym)
163
173
  end
164
174
 
165
175
  def format(cmd)
@@ -177,16 +187,6 @@ module Honeycomb
177
187
  args.map! { "[sanitized]" }
178
188
  end
179
189
 
180
- def prettify(arg)
181
- quotes = false
182
- pretty = "".dup
183
- arg.to_s.each_char do |c|
184
- quotes ||= needs_quotes?(c)
185
- pretty << escape(c)
186
- end
187
- quotes ? "\"#{pretty}\"" : pretty
188
- end
189
-
190
190
  # This aims to replicate the algorithms used by redis-cli.
191
191
  #
192
192
  # @see https://github.com/antirez/redis/blob/0f026af185e918a9773148f6ceaa1b084662be88/src/sds.c#L940-L1067
@@ -194,54 +194,15 @@ module Honeycomb
194
194
  #
195
195
  # @see https://github.com/antirez/redis/blob/0f026af185e918a9773148f6ceaa1b084662be88/src/sds.c#L878-L907
196
196
  # The redis-cli printing algorithm
197
- def escape(char)
198
- return escape_with_backslash(char) if escape_with_backslash?(char)
199
- return escape_with_hex_codes(char) if escape_with_hex_codes?(char)
200
-
201
- char
202
- end
203
-
204
- # A lookup table for backslash-escaped characters.
205
- #
206
- # This is used by {#escape_with_backslash?} and {#escape_with_backslash}
207
- # to replicate the hard-coded `case` statements in redis-cli. As of this
208
- # writing, Redis recognizes a handful of standard C escape sequences,
209
- # like "\n" for newlines.
210
- #
211
- # Because {#prettify} will output double quoted strings if any escaping
212
- # is needed, this table must additionally consider the double-quote to be
213
- # a backslash-escaped character. For example, instead of generating
214
- #
215
- # '"hello"'
216
- #
217
- # we'll generate
218
- #
219
- # "\"hello\""
220
- #
221
- # even though redis-cli would technically recognize the single-quoted
222
- # version.
223
- #
224
- # @see https://github.com/antirez/redis/blob/0f026af185e918a9773148f6ceaa1b084662be88/src/sds.c#L888-L896
225
- # The redis-cli algorithm for outputting standard escape sequences
226
- BACKSLASHES = {
227
- "\\" => "\\\\",
228
- '"' => '\\"',
229
- "\n" => "\\n",
230
- "\r" => "\\r",
231
- "\t" => "\\t",
232
- "\a" => "\\a",
233
- "\b" => "\\b",
234
- }.freeze
235
-
236
- def escape_with_backslash?(char)
237
- BACKSLASHES.key?(char)
238
- end
239
-
240
- def escape_with_backslash(char)
241
- BACKSLASHES.fetch(char, char)
197
+ def prettify(arg)
198
+ pretty = arg.to_s.dup
199
+ pretty.encode!("UTF-8", "binary", fallback: ->(c) { hex(c) })
200
+ pretty.gsub!(NEEDS_BACKSLASH, BACKSLASH)
201
+ pretty.gsub!(NEEDS_HEX) { |c| hex(c) }
202
+ pretty =~ NEEDS_QUOTES ? "\"#{pretty}\"" : pretty
242
203
  end
243
204
 
244
- # Do we need to hex-encode this character?
205
+ # A regular expression matching characters that need to be hex-encoded.
245
206
  #
246
207
  # This replicates the C isprint() function that redis-cli uses to decide
247
208
  # whether to escape a character in hexadecimal notation, "\xhh". Any
@@ -277,18 +238,95 @@ module Honeycomb
277
238
  # escape it.
278
239
  #
279
240
  # What's more, Ruby's Regexp#=~ method will blow up if the string does
280
- # not have a valid encoding (e.g., in UTF-8). In this case, though,
281
- # {#escape_with_hex_codes} can still convert the bytes that make up the
282
- # invalid character into a hex code. So we preemptively check for
283
- # invalidly-encoded characters before testing the above match.
241
+ # not have a valid encoding (e.g., in UTF-8). We handle this case
242
+ # separately, though, using String#encode! with a :fallback option to
243
+ # hex-encode invalid UTF-8 byte sequences with {#hex}.
284
244
  #
285
245
  # @see https://ruby-doc.org/core-2.6.5/Regexp.html
286
246
  # @see https://github.com/antirez/redis/blob/0f026af185e918a9773148f6ceaa1b084662be88/src/sds.c#L878-L880
287
247
  # @see https://github.com/antirez/redis/blob/0f026af185e918a9773148f6ceaa1b084662be88/src/sds.c#L898-L901
288
248
  # @see https://www.justinweiss.com/articles/3-steps-to-fix-encoding-problems-in-ruby/
289
- def escape_with_hex_codes?(char)
290
- !char.valid_encoding? || char =~ /[^[:print:]&&[:ascii:]]/
291
- end
249
+ NEEDS_HEX = /[^[:print:]&&[:ascii:]]/.freeze
250
+
251
+ # A regular expression for characters that need to be backslash-escaped.
252
+ #
253
+ # Any match of this regexp will be substituted according to the
254
+ # {BACKSLASH} table. This includes standard C escape sequences (newlines,
255
+ # tabs, etc) as well as a couple special considerations:
256
+ #
257
+ # 1. Because {#prettify} will output double quoted strings if any
258
+ # escaping is needed, we must match double quotes (") so they'll be
259
+ # replaced by escaped quotes (\").
260
+ #
261
+ # 2. Backslashes themselves get backslash-escaped, so \ becomes \\.
262
+ # However, strings with invalid UTF-8 encoding will blow up when we
263
+ # try to use String#gsub!, so {#prettify} must first use
264
+ # String#encode! to scrub out invalid characters. It does this by
265
+ # replacing invalid bytes with hex-encoded escape sequences using
266
+ # {#hex}. This will insert sequences like \xhh, which contains a
267
+ # backslash that we *don't* want to escape.
268
+ #
269
+ # Unfortunately, this regexp can't really distinguish between
270
+ # backslashes in the original input vs backslashes resulting from the
271
+ # UTF-8 fallback. We make an effort by using a negative lookahead.
272
+ # That way, only backslashes that *aren't* followed by x + hex digit +
273
+ # hex digit will be escaped.
274
+ NEEDS_BACKSLASH = /["\n\r\t\a\b]|\\(?!x\h\h)/.freeze
275
+
276
+ # A lookup table for backslash-escaped characters.
277
+ #
278
+ # This is used by {#prettify} to replicate the hard-coded `case`
279
+ # statements in redis-cli. As of this writing, Redis recognizes a handful
280
+ # of standard C escape sequences, like "\n" for newlines.
281
+ #
282
+ # Because {#prettify} will output double quoted strings if any escaping
283
+ # is needed, this table must additionally consider the double-quote to be
284
+ # a backslash-escaped character. For example, instead of generating
285
+ #
286
+ # '"hello"'
287
+ #
288
+ # we'll generate
289
+ #
290
+ # "\"hello\""
291
+ #
292
+ # even though redis-cli would technically recognize the single-quoted
293
+ # version.
294
+ #
295
+ # @see https://github.com/antirez/redis/blob/0f026af185e918a9773148f6ceaa1b084662be88/src/sds.c#L888-L896
296
+ # The redis-cli algorithm for outputting standard escape sequences
297
+ BACKSLASH = {
298
+ "\\" => "\\\\",
299
+ '"' => '\\"',
300
+ "\n" => "\\n",
301
+ "\r" => "\\r",
302
+ "\t" => "\\t",
303
+ "\a" => "\\a",
304
+ "\b" => "\\b",
305
+ }.freeze
306
+
307
+ # If the final escaped string needs quotes, it will match this regexp.
308
+ #
309
+ # The overall string returned by {#prettify} should only be quoted if at
310
+ # least one of the following holds:
311
+ #
312
+ # 1. The string contains an escape sequence, broadly demarcated by a
313
+ # backslash. This includes standard escape sequences like "\n" and
314
+ # "\t" as well as hex-encoded bytes using the "\x" escape sequence.
315
+ # Since {#prettify} uses double quotes on its output string, we must
316
+ # also force quotes if the string itself contains a literal
317
+ # double quote. This double quote behavior is handled tacitly by the
318
+ # {NEEDS_BACKSLASH} + {BACKSLASH} replacement.
319
+ #
320
+ # 2. The string contains a single quote. Since redis-cli recognizes
321
+ # single-quoted strings, we want to wrap the {#prettify} output in
322
+ # double quotes so that the literal single quote character isn't
323
+ # mistaken as the delimiter of a new string.
324
+ #
325
+ # 3. The string contains any whitespace characters. If the {#prettify}
326
+ # output weren't wrapped in quotes, whitespace would act as a
327
+ # separator between arguments to the Redis command. To group things
328
+ # together, we need to quote the string.
329
+ NEEDS_QUOTES = /[\\'\s]/.freeze
292
330
 
293
331
  # Hex-encodes a (presumably non-printable or non-ASCII) character.
294
332
  #
@@ -316,38 +354,9 @@ module Honeycomb
316
354
  # @see https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap07.html
317
355
  # @see https://github.com/antirez/redis/blob/0f026af185e918a9773148f6ceaa1b084662be88/src/sds.c#L878-L880
318
356
  # @see https://github.com/antirez/redis/blob/0f026af185e918a9773148f6ceaa1b084662be88/src/sds.c#L898-L901
319
- def escape_with_hex_codes(char)
357
+ def hex(char)
320
358
  char.bytes.map { |b| Kernel.format("\\x%02x", b) }.join
321
359
  end
322
-
323
- def escape?(char)
324
- escape_with_backslash?(char) || escape_with_hex_codes?(char)
325
- end
326
-
327
- # Should this character cause {#prettify} to wrap its output in quotes?
328
- #
329
- # The overall string returned by {#prettify} should only be quoted if at
330
- # least one of the following holds:
331
- #
332
- # 1. The string contains a character that needs to be escaped. This
333
- # includes standard backslash escape sequences (like "\n" and "\t") as
334
- # well as hex-encoded bytes using the "\x" escape sequence. Since
335
- # {#prettify} uses double quotes on its output string, we must also
336
- # force quotes if the string itself contains a literal double quote.
337
- # This double quote behavior is handled tacitly by {BACKSLASHES}.
338
- #
339
- # 2. The string contains a single quote. Since redis-cli recognizes
340
- # single-quoted strings, we want to wrap the {#prettify} output in
341
- # double quotes so that the literal single quote character isn't
342
- # mistaken as the delimiter of a new string.
343
- #
344
- # 3. The string contains any whitespace characters. If the {#prettify}
345
- # output weren't wrapped in quotes, whitespace would act as a
346
- # separator between arguments to the Redis command. To group things
347
- # together, we need to quote the string.
348
- def needs_quotes?(char)
349
- escape?(char) || char == "'" || char =~ /\s/
350
- end
351
360
  end
352
361
  end
353
362
  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.3.0
4
+ version: 2.5.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-11-06 00:00:00.000000000 Z
11
+ date: 2021-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: libhoney
@@ -156,6 +156,20 @@ dependencies:
156
156
  - - "~>"
157
157
  - !ruby/object:Gem::Version
158
158
  version: '3.0'
159
+ - !ruby/object:Gem::Dependency
160
+ name: rspec_junit_formatter
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
159
173
  - !ruby/object:Gem::Dependency
160
174
  name: rubocop
161
175
  requirement: !ruby/object:Gem::Requirement
@@ -238,12 +252,17 @@ files:
238
252
  - ".circleci/setup-rubygems.sh"
239
253
  - ".editorconfig"
240
254
  - ".github/CODEOWNERS"
255
+ - ".github/dependabot.yml"
256
+ - ".github/workflows/add-to-project.yml"
257
+ - ".github/workflows/apply-labels.yml"
241
258
  - ".gitignore"
242
259
  - ".overcommit.yml"
243
260
  - ".rspec"
244
261
  - ".rubocop.yml"
245
262
  - ".ruby-version"
263
+ - ".tool-versions"
246
264
  - Appraisals
265
+ - CHANGELOG.md
247
266
  - CODE_OF_CONDUCT.md
248
267
  - CONTRIBUTORS.md
249
268
  - Gemfile
@@ -303,7 +322,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
303
322
  - !ruby/object:Gem::Version
304
323
  version: '0'
305
324
  requirements: []
306
- rubygems_version: 3.0.3
325
+ rubygems_version: 3.0.3.1
307
326
  signing_key:
308
327
  specification_version: 4
309
328
  summary: Instrument your Ruby apps with Honeycomb