libhoney 2.1.0 → 2.2.0.pre.dev

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: 87accb91b956f38c24050ebc8931d49041ab02551c394a7447434730eb827f18
4
- data.tar.gz: 899a27302a4e04e2ac50af6f792a8515b252a838bb6b09d9471bf6aab9058cbc
3
+ metadata.gz: e2acde76ef3fc685e6ea13a5178b08f8f097df45b9731d157d3ef0ed653d1bbf
4
+ data.tar.gz: 4fe2094102da89e268aa9acc67e10c722b255d846aed078f10212209da45ff52
5
5
  SHA512:
6
- metadata.gz: 42b5a14b536bdda18f2900e2767c4702dd16e5a441300830c9a6cd7ae15d3e4c7d6b0edb3346bb278f239731b16ca8bc807851d57d3d3ad6da185782a48bf64c
7
- data.tar.gz: 1e764f94ded5a848f6a90197f340d31efbc13b2fa6eae9f7be2444a19b8a8e65165356d68cd76dd51f5ce8910e742db9fd8a49546170b4dafa4d99471445979d
6
+ metadata.gz: e5e52c97beae8e79a44a605260cf6d393461b434ee7fdab2fdb4652819899d8923a3460497b136dfa1c691032544e1276c5c6e8b28f5b38804c6f7d5528e050b
7
+ data.tar.gz: 64984f592c88602e9033ccc7ed4f5e3fd271edf6c1356791cffab21224e4bdf9c64df2d86e1dd95b203ae62ea7af0e385b9092d12276a4bf0fe770718e01329c
data/.circleci/config.yml CHANGED
@@ -19,7 +19,7 @@ filters_publish: &filters_publish
19
19
  matrix_rubyversions: &matrix_rubyversions
20
20
  matrix:
21
21
  parameters:
22
- rubyversion: ["2.4", "2.5", "2.6", "2.7", "3.0"]
22
+ rubyversion: ["2.4", "2.5", "2.6", "2.7", "3.0", "3.1"]
23
23
 
24
24
  # Default version of ruby to use for lint and publishing
25
25
  default_rubyversion: &default_rubyversion "3.0"
@@ -13,3 +13,6 @@ updates:
13
13
  - "type: dependencies"
14
14
  reviewers:
15
15
  - "honeycombio/telemetry-team"
16
+ commit-message:
17
+ prefix: "maint"
18
+ include: "scope"
@@ -0,0 +1,23 @@
1
+ # .github/release.yml
2
+
3
+ changelog:
4
+ exclude:
5
+ labels:
6
+ - no-changelog
7
+ categories:
8
+ - title: 💥 Breaking Changes 💥
9
+ labels:
10
+ - "version: bump major"
11
+ - breaking-change
12
+ - title: 💡 Enhancements
13
+ labels:
14
+ - "type: enhancement"
15
+ - title: 🐛 Fixes
16
+ labels:
17
+ - "type: bug"
18
+ - title: 🛠 Maintenance
19
+ labels:
20
+ - "type: maintenance"
21
+ - title: 🤷 Other Changes
22
+ labels:
23
+ - "*"
@@ -0,0 +1,15 @@
1
+ name: Add to project
2
+ on:
3
+ issues:
4
+ types: [opened]
5
+ pull_request_target:
6
+ types: [opened]
7
+ jobs:
8
+ add-to-project:
9
+ runs-on: ubuntu-latest
10
+ name: Add issues and PRs to project
11
+ steps:
12
+ - uses: actions/add-to-project@main
13
+ with:
14
+ project-url: https://github.com/orgs/honeycombio/projects/11
15
+ github-token: ${{ secrets.GHPROJECTS_TOKEN }}
@@ -0,0 +1,64 @@
1
+ name: "Validate PR Title"
2
+
3
+ on:
4
+ pull_request:
5
+ types:
6
+ - opened
7
+ - edited
8
+ - synchronize
9
+
10
+ jobs:
11
+ main:
12
+ name: Validate PR title
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: amannn/action-semantic-pull-request@v5
16
+ id: lint_pr_title
17
+ name: "🤖 Check PR title follows conventional commit spec"
18
+ env:
19
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
20
+ with:
21
+ # Have to specify all types because `maint` and `rel` aren't defaults
22
+ types: |
23
+ maint
24
+ rel
25
+ fix
26
+ feat
27
+ chore
28
+ ci
29
+ docs
30
+ style
31
+ refactor
32
+ perf
33
+ test
34
+ ignoreLabels: |
35
+ "type: dependencies"
36
+ # When the previous steps fails, the workflow would stop. By adding this
37
+ # condition you can continue the execution with the populated error message.
38
+ - if: always() && (steps.lint_pr_title.outputs.error_message != null)
39
+ name: "📝 Add PR comment about using conventional commit spec"
40
+ uses: marocchino/sticky-pull-request-comment@v2
41
+ with:
42
+ header: pr-title-lint-error
43
+ message: |
44
+ Thank you for contributing to the project! 🎉
45
+
46
+ We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted.
47
+
48
+ Make sure to prepend with `feat:`, `fix:`, or another option in the list below.
49
+
50
+ Once you update the title, this workflow will re-run automatically and validate the updated title.
51
+
52
+ Details:
53
+
54
+ ```
55
+ ${{ steps.lint_pr_title.outputs.error_message }}
56
+ ```
57
+
58
+ # Delete a previous comment when the issue has been resolved
59
+ - if: ${{ steps.lint_pr_title.outputs.error_message == null }}
60
+ name: "❌ Delete PR comment after title has been updated"
61
+ uses: marocchino/sticky-pull-request-comment@v2
62
+ with:
63
+ header: pr-title-lint-error
64
+ delete: true
data/.gitignore CHANGED
@@ -11,6 +11,7 @@
11
11
  /test/tmp/
12
12
  /test/version_tmp/
13
13
  /tmp/
14
+ /examples/wiki-manual-tracing/*.txt
14
15
 
15
16
  # Used by dotenv library to load environment variables.
16
17
  # .env
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [2.2.0] - 2022-04-14
2
+
3
+ ### Added
4
+
5
+ - Add Environment and Services support (#123) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
6
+
1
7
  ## [2.1.0] - 2022-02-02
2
8
 
3
9
  ### Improvements
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ gem 'libhoney', path: '../..'
@@ -1,6 +1,3 @@
1
- lib = File.expand_path('../lib', __dir__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
-
4
1
  require 'libhoney'
5
2
 
6
3
  # replace this with yours from https://ui.honeycomb.com/account
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ gem 'libhoney', path: '../..'
8
+ gem 'sinatra-base'
@@ -0,0 +1,52 @@
1
+ # ruby-wiki-tracing
2
+
3
+ This example illustrates a simple wiki application instrumented with the bare minimum necessary to utilize Honeycomb's tracing functionality.
4
+
5
+ ## What We'll Do in This Example
6
+
7
+ We'll instrument a simple application for tracing by following a few general steps:
8
+
9
+ 1. Set a top-level `trace.trace_id` at the origin of the request and set it on the request context. Generate a root span indicated by omitting a `trace.parent_id` field.
10
+ 2. To represent a unit of work within a trace as a span, add code to generate a span ID and capture the start time. At the **call site** of the unit of work, pass down a new request context with the newly-generated span ID as the `trace.parent_id`. Upon work completion, send the span with a calculated `duration_ms`.
11
+ 3. Rinse and repeat.
12
+
13
+ **Note**: The [OpenTelemetry for Ruby](https://docs.honeycomb.io/getting-data-in/opentelemetry/ruby/) handles all of this propagation magic for you :)
14
+
15
+ ## Usage
16
+
17
+ You can [find your API key](https://docs.honeycomb.io/getting-data-in/api-keys/#find-api-keys) in your Environment Settings.
18
+ If you do not have an API key yet, sign up for a [free Honeycomb account](https://ui.honeycomb.io/signup).
19
+
20
+
21
+ Once you have your API key, run:
22
+
23
+ ```shell
24
+ bundle install
25
+ ```
26
+
27
+ ```shell
28
+ HONEYCOMB_API_KEY=foobarbaz bundle exec ruby wiki.rb
29
+ ```
30
+
31
+ And load [`http://localhost:4567/view/MyFirstWikiPage`](http://localhost:4567/view/MyFirstWikiPage) to create (then view) your first wiki page.
32
+
33
+ Methods within the simple wiki application have been instrumented with tracing-like calls, with tracing identifiers propagated via thread locals.
34
+
35
+ ## Tips for Instrumenting Your Own Service
36
+
37
+ - For a given span (e.g. `"loadPage"`), remember that the span definition lives in its parent, and the instrumentation is around the **call site** of `loadPage`:
38
+ ```ruby
39
+ with_span("load_page") do
40
+ # sets the appropriate "parent id" within the scope of the block
41
+ load_page(title)
42
+ # span is sent to Honeycomb upon completion of the block
43
+ end
44
+ ```
45
+ - If emitting Honeycomb events or structured logs, make sure that the **start** time gets used as the canonical timestamp, not the time at event emission.
46
+ - Remember, the root span should **not** have a `trace.parent_id`.
47
+ - Don't forget to add some metadata of your own! It's helpful to identify metadata in the surrounding code that might be interesting when debugging your application.
48
+ - Check out [OpenTelemetry for Ruby](https://docs.honeycomb.io/getting-data-in/opentelemetry/ruby/) to get this context propagation for free!
49
+
50
+ ## A Note on Code Style
51
+
52
+ The purpose of this example is to illustrate the **bare minimum necessary** to propagate and set identifiers to enable tracing on an application for consumption by Honeycomb, illustrating the steps described in the top section of this README. We prioritized legibility over style and intentionally resisted refactoring that would sacrifice clarity. :)
@@ -0,0 +1,11 @@
1
+ <h1><%= @page.title %></h1>
2
+
3
+ <form action='/save/<%= @page.title %>' method='POST'>
4
+ <div>
5
+ <textarea name='body' rows='20' cols='80'><%= @page.body %></textarea>
6
+ </div>
7
+
8
+ <div>
9
+ <input type='submit' value='Save'>
10
+ </div>
11
+ </form>
@@ -0,0 +1,5 @@
1
+ <h1><%= @page.title %></h1>
2
+
3
+ <p>[<a href='/edit/<%= @page.title %>'>edit</a>]</p>
4
+
5
+ <div><%= @page.body %></div>
@@ -0,0 +1,180 @@
1
+ require 'sinatra/base'
2
+ require 'libhoney'
3
+
4
+ # Page represents the data (and some basic operations) on a wiki page.
5
+ #
6
+ # While the tracing instrumentation in this example is constrained to the
7
+ # handlers, we could just as easily propagate context down directly into this
8
+ # class if needed.
9
+ class Page
10
+ attr_reader :filename, :title
11
+ attr_accessor :body
12
+
13
+ def initialize(title)
14
+ @title = title
15
+ @filename = "#{title}.txt"
16
+ end
17
+
18
+ def exist?
19
+ File.exist? @filename
20
+ end
21
+
22
+ def save(body)
23
+ File.write @filename, body
24
+ true
25
+ rescue StandardError
26
+ false
27
+ end
28
+ end
29
+
30
+ # Generate a new unique identifier for our spans and traces. This can be any
31
+ # unique string -- Zipkin uses hex-encoded base64 ints, as we do here; other
32
+ # folks may prefer to use their UUID library of choice.
33
+ def new_id
34
+ rand(2**63).to_s(16)
35
+ end
36
+
37
+ # This middleware treats each HTTP request as a distinct "trace." Each trace
38
+ # begins with a top-level ("root") span indicating that the HTTP request has
39
+ # begun.
40
+ VALID_PATH = Regexp.new('^/(edit|save|view)/')
41
+
42
+ class RequestTracer
43
+ def initialize(app)
44
+ @app = app
45
+ end
46
+
47
+ def call(env)
48
+ Thread.current[:request_id] = new_id
49
+ match = env['REQUEST_PATH'].match(VALID_PATH)
50
+
51
+ @app.with_span(match ? match[1] : env['REQUEST_PATH']) do
52
+ @app.call env
53
+ end
54
+ end
55
+ end
56
+
57
+ # This is our basic wiki webapp. It uses our RequestTracer middleware to track
58
+ # all HTTP requests with a root span, then defines a handful of handlers to
59
+ # handle the display / edit / saving of wiki pages on disk.
60
+ class App < Sinatra::Base
61
+ use RequestTracer
62
+
63
+ # Initialize our Honeycomb client once, and pull Honeycomb credentials from
64
+ # an environment variable.
65
+ configure do
66
+ set :libhoney, Libhoney::Client.new(
67
+ writekey: ENV['HONEYCOMB_API_KEY'],
68
+ dataset: 'ruby-wiki-tracing-example'
69
+ )
70
+ end
71
+
72
+ # Redirect to a default wiki page.
73
+ get '/' do
74
+ redirect '/view/Index'
75
+ end
76
+
77
+ # Our "View" handler. Tries to load a page from disk and render it. Falls back
78
+ # to the Edit handler if the page does not yet exist.
79
+ get '/view/:title' do |title|
80
+ @page = with_span('load_page', title: title) do
81
+ load_page title
82
+ end
83
+
84
+ return redirect "/edit/#{title}" if @page.nil?
85
+
86
+ with_span('render_template', template: 'view') do
87
+ erb :view
88
+ end
89
+ end
90
+
91
+ # Our "Edit" handler. Tries to load a page from disk to seed the edit screen,
92
+ # then renders a form to allow the user to define the content of the requested
93
+ # wiki page.
94
+ get '/edit/:title' do |title|
95
+ @page = with_span('load_page', title: title) do
96
+ load_page title
97
+ end
98
+
99
+ @page = Page.new(title) if @page.nil?
100
+
101
+ with_span('render_template', template: 'edit') do
102
+ erb :edit
103
+ end
104
+ end
105
+
106
+ # Our "Save" handler simply persists a page to disk.
107
+ post '/save/:page' do |title|
108
+ saved = with_span('File.write', title: title, body_len: params['body'].size) do
109
+ page = Page.new(title)
110
+ page.save(params['body'])
111
+ end
112
+
113
+ return redirect "/view/#{title}" if saved
114
+
115
+ 'error'
116
+ end
117
+
118
+ # This wrapper takes a span name, some optional metadata, and a block; then
119
+ # emits a "span" to Honeycomb as part of the trace begun in the RequestTracer
120
+ # middleware.
121
+ #
122
+ # The special sauce in this method is the definition / resetting of thread
123
+ # local variables in order to correctly propagate "parent" identifiers down
124
+ # into the block.
125
+ def with_span(name, metadata = nil)
126
+ id = new_id
127
+ start = Time.new
128
+ # Field keys to trigger Honeycomb's tracing functionality on this dataset
129
+ # defined at:
130
+ # https://docs.honeycomb.io/getting-data-in/tracing/send-trace-data/#opentelemetry
131
+ data = {
132
+ name: name,
133
+ id: id,
134
+ "trace.trace_id": Thread.current[:request_id],
135
+ "service.name": 'wiki'
136
+ }
137
+
138
+ # Capture the calling scope's span ID, then restore it at the end of the
139
+ # method.
140
+ parent_id = Thread.current[:span_id]
141
+ data[:"trace.parent_id"] = parent_id if parent_id
142
+
143
+ # Set the current span ID before invoking the provided block, then capture
144
+ # the return value to return after emitting the Honeycomb event.
145
+ Thread.current[:span_id] = id
146
+ output = yield
147
+
148
+ data[:duration_ms] = (Time.new - start) * 1000
149
+ data.merge!(metadata) if metadata
150
+
151
+ event = settings.libhoney.event
152
+ # NOTE: Don't forget to set the timestamp to `start` -- because spans are
153
+ # emitted at the *end* of their execution, we want to be doubly sure that
154
+ # our manually-emitted events are timestamped with the time that the work
155
+ # (the span's actual execution) really begun.
156
+ event.timestamp = start
157
+ event.add data
158
+ event.send
159
+
160
+ output
161
+ ensure
162
+ Thread.current[:span_id] = parent_id
163
+ end
164
+
165
+ private
166
+
167
+ # Helper method for returning a Page object for easy rendering
168
+ def load_page(title)
169
+ page = Page.new(title)
170
+ return nil unless page.exist?
171
+
172
+ with_span('File.read') do
173
+ page.body = File.read(page.filename)
174
+ page
175
+ end
176
+ end
177
+ end
178
+
179
+ # Let's go!
180
+ App.run!
@@ -34,6 +34,7 @@ module Libhoney
34
34
  extend Forwardable
35
35
 
36
36
  API_HOST = 'https://api.honeycomb.io/'.freeze
37
+ DEFAULT_DATASET = 'unknown_dataset'.freeze
37
38
 
38
39
  # Instantiates libhoney and prepares it to send events to Honeycomb.
39
40
  #
@@ -81,7 +82,7 @@ module Libhoney
81
82
  @builder = Builder.new(self, nil)
82
83
 
83
84
  @builder.writekey = writekey
84
- @builder.dataset = dataset
85
+ @builder.dataset = get_dataset(dataset, writekey)
85
86
  @builder.sample_rate = sample_rate
86
87
  @builder.api_host = api_host
87
88
 
@@ -275,5 +276,24 @@ module Libhoney
275
276
  rescue URI::Error => e
276
277
  warn "#{self.class.name}: unable to parse proxy_config. Detail: #{e.class}: #{e.message}"
277
278
  end
279
+
280
+ def get_dataset(dataset, write_key)
281
+ return dataset if classic_write_key?(write_key)
282
+
283
+ if dataset.nil? || dataset.empty?
284
+ warn "nil or empty dataset - sending data to '#{DEFAULT_DATASET}'"
285
+ dataset = DEFAULT_DATASET
286
+ end
287
+ trimmed = dataset.strip
288
+ if dataset != trimmed
289
+ warn "dataset contained leading or trailing whitespace - sending data to '#{trimmed}'"
290
+ dataset = trimmed
291
+ end
292
+ dataset
293
+ end
294
+
295
+ def classic_write_key?(write_key)
296
+ write_key.nil? || write_key.length == 32
297
+ end
278
298
  end
279
299
  end
@@ -1,3 +1,3 @@
1
1
  module Libhoney
2
- VERSION = '2.1.0'.freeze
2
+ VERSION = '2.2.0-dev'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libhoney
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0.pre.dev
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Honeycomb.io Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-02 00:00:00.000000000 Z
11
+ date: 2023-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bump
@@ -256,10 +256,11 @@ files:
256
256
  - ".github/ISSUE_TEMPLATE/security-vulnerability-report.md"
257
257
  - ".github/PULL_REQUEST_TEMPLATE.md"
258
258
  - ".github/dependabot.yml"
259
- - ".github/workflows/add-to-project.yml"
259
+ - ".github/release.yml"
260
+ - ".github/workflows/add-to-project-v2.yml"
260
261
  - ".github/workflows/apply-labels.yml"
261
- - ".github/workflows/re-triage.yml"
262
262
  - ".github/workflows/stale.yml"
263
+ - ".github/workflows/validate-pr-title.yml"
263
264
  - ".gitignore"
264
265
  - ".rubocop.yml"
265
266
  - ".rubocop_todo.yml"
@@ -276,7 +277,13 @@ files:
276
277
  - Rakefile
277
278
  - SECURITY.md
278
279
  - SUPPORT.md
279
- - example/factorial.rb
280
+ - examples/factorial/Gemfile
281
+ - examples/factorial/factorial.rb
282
+ - examples/wiki-manual-tracing/Gemfile
283
+ - examples/wiki-manual-tracing/README.md
284
+ - examples/wiki-manual-tracing/views/edit.erb
285
+ - examples/wiki-manual-tracing/views/view.erb
286
+ - examples/wiki-manual-tracing/wiki.rb
280
287
  - lib/libhoney.rb
281
288
  - lib/libhoney/builder.rb
282
289
  - lib/libhoney/cleaner.rb
@@ -311,11 +318,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
311
318
  version: 2.4.0
312
319
  required_rubygems_version: !ruby/object:Gem::Requirement
313
320
  requirements:
314
- - - ">="
321
+ - - ">"
315
322
  - !ruby/object:Gem::Version
316
- version: '0'
323
+ version: 1.3.1
317
324
  requirements: []
318
- rubygems_version: 3.2.32
325
+ rubygems_version: 3.3.26
319
326
  signing_key:
320
327
  specification_version: 4
321
328
  summary: send data to Honeycomb
@@ -1,14 +0,0 @@
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 }}
@@ -1,12 +0,0 @@
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 }}