bugsnag_performance 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +11 -0
- data/CHANGELOG.md +18 -0
- data/CODEOWNERS +1 -0
- data/CONTRIBUTING.md +69 -0
- data/README.md +33 -0
- data/SECURITY.md +11 -0
- data/TESTING.md +38 -0
- data/bugsnag-performance.gemspec +1 -0
- data/lib/bugsnag_performance/configuration.rb +61 -1
- data/lib/bugsnag_performance/internal/configuration_validator.rb +1 -0
- data/lib/bugsnag_performance/internal/delivery.rb +1 -0
- data/lib/bugsnag_performance/internal/nil_errors_configuration.rb +9 -0
- data/lib/bugsnag_performance/internal/parsed_tracestate.rb +24 -0
- data/lib/bugsnag_performance/internal/sampler.rb +36 -15
- data/lib/bugsnag_performance/internal/tracestate_parser.rb +37 -0
- data/lib/bugsnag_performance/version.rb +2 -1
- data/lib/bugsnag_performance.rb +18 -2
- metadata +26 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7209ef5a16d1a1f40cc5100f44f935f4deb13ada6eb5de82c785b823ef7c975a
|
4
|
+
data.tar.gz: 81d7fc68ae82ccca8d7aa1ca34fa15abd59fe72f9f17775a4100e11c4256ac6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2348391589b8bbce569efbeaff908dba3112364ef8f76c32197f00a9b095d876b52cba246e6e4c25ffd92e4b9856b2be234c9c17ecd04d54a9f252ac8aec68d5
|
7
|
+
data.tar.gz: 87594a7d40c5249cc60f28db2699df868d1f21adbd67d27647a070fa323957f0c19710fae24af4e6c59390726168a8ca84cdd62358bc3da5568a9498ee80cabb
|
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,2 +1,20 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
|
+
|
4
|
+
## 1.0.0 (2024-12-09)
|
5
|
+
|
6
|
+
### Enhancements
|
7
|
+
|
8
|
+
* Consolidate Ruby/Ruby-Perf environment variables.
|
9
|
+
[#45](https://github.com/bugsnag/bugsnag-ruby-performance/pull/45)
|
10
|
+
|
11
|
+
* Restore Bugsnag-Sent-At header.
|
12
|
+
[#46](https://github.com/bugsnag/bugsnag-ruby-performance/pull/46)
|
13
|
+
|
14
|
+
## 0.3.0 (2024-11-13)
|
15
|
+
|
16
|
+
### Enhancements
|
17
|
+
|
18
|
+
* Temporarily disable `Bugsnag-Sent-At` header. Add attributes with SDK name.
|
19
|
+
[#42](https://github.com/bugsnag/bugsnag-ruby-performance/pull/42)
|
20
|
+
[#43](https://github.com/bugsnag/bugsnag-ruby-performance/pull/43)
|
data/CODEOWNERS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
lib/ @imjoehaines @DariaKunoichi
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
## How to contribute
|
2
|
+
|
3
|
+
We are glad you're here! First-time and returning contributors are welcome to add bug fixes and new integrations. If you are unsure about the direction of an enhancement or if it would be generally useful, feel free to open an issue or a work-in-progress pull request and ask for input.
|
4
|
+
|
5
|
+
Thank you!
|
6
|
+
|
7
|
+
### Getting started
|
8
|
+
|
9
|
+
* [Fork](https://help.github.com/articles/fork-a-repo) the [library on github](https://github.com/bugsnag/bugsnag-ruby-performance)
|
10
|
+
* Commit and push until you are happy with your contribution
|
11
|
+
|
12
|
+
### Polish
|
13
|
+
|
14
|
+
* Install the test dependencies
|
15
|
+
|
16
|
+
```
|
17
|
+
bundle install
|
18
|
+
```
|
19
|
+
|
20
|
+
* Run the tests and make sure they all pass
|
21
|
+
|
22
|
+
```
|
23
|
+
bundle exec rspec
|
24
|
+
```
|
25
|
+
|
26
|
+
* Further information on installing and running the tests can be found in [the testing guide](./TESTING.md)
|
27
|
+
|
28
|
+
### Document
|
29
|
+
|
30
|
+
* Write API docs for your contributions using [YARD](https://yardoc.org/)
|
31
|
+
* Generate the API documentation locally
|
32
|
+
```
|
33
|
+
bin/rake yard
|
34
|
+
```
|
35
|
+
* Review your changes by opening `doc/index.html`
|
36
|
+
|
37
|
+
### Ship it!
|
38
|
+
|
39
|
+
* [Make a pull request](https://help.github.com/articles/using-pull-requests)
|
40
|
+
|
41
|
+
## How to release
|
42
|
+
|
43
|
+
If you're a member of the core team, follow these instructions for releasing bugsnag-ruby-performance.
|
44
|
+
|
45
|
+
### First time setup
|
46
|
+
|
47
|
+
* Create a Rubygems account
|
48
|
+
* Get someone to add you as contributor on bugsnag-ruby-performance in Rubygems
|
49
|
+
|
50
|
+
### Every time
|
51
|
+
|
52
|
+
* Create a new release branch named in the format `release/v1.x.x`
|
53
|
+
* Update the version number in [`lib/bugsnag_performance/version.rb`](./lib/bugsnag_performance/version.rb)
|
54
|
+
* Update [`CHANGELOG.md`](./CHANGELOG.md) with any changes
|
55
|
+
* Open a pull request into `main` and get it approved
|
56
|
+
* Merge the pull request using the message "Release v1.x.x"
|
57
|
+
* Make a GitHub release
|
58
|
+
* Release to rubygems:
|
59
|
+
|
60
|
+
```
|
61
|
+
gem build bugsnag-performance.gemspec
|
62
|
+
gem push bugsnag_performance-1.x.x.gem
|
63
|
+
```
|
64
|
+
|
65
|
+
* Update the version running in the bugsnag-website project
|
66
|
+
|
67
|
+
### Update docs.bugsnag.com
|
68
|
+
|
69
|
+
Update the setup guides for Ruby (and its frameworks) with any new content.
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
<div align="center">
|
2
|
+
<a href="https://www.bugsnag.com/distributed-tracing">
|
3
|
+
<picture>
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://assets.smartbear.com/m/3dab7e6cf880aa2b/original/BugSnag-Repository-Header-Dark.svg">
|
5
|
+
<img alt="SmartBear BugSnag logo" src="https://assets.smartbear.com/m/3945e02cdc983893/original/BugSnag-Repository-Header-Light.svg">
|
6
|
+
</picture>
|
7
|
+
</a>
|
8
|
+
<h1>Performance monitoring for Ruby</h1>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
[![Documentation](https://img.shields.io/badge/documentation-latest-blue.svg)](https://docs.bugsnag.com/performance/ruby/)
|
12
|
+
[![Build status](https://github.com/bugsnag/bugsnag-ruby-performance/actions/workflows/maze-runner.yml/badge.svg?branch=next)](https://github.com/bugsnag/bugsnag-ruby-performance/actions/workflows/maze-runner.yml)
|
13
|
+
|
14
|
+
Convenience SDK for using the [Ruby OpenTelemetry SDK](https://github.com/open-telemetry/opentelemetry-ruby) with BugSnag.
|
15
|
+
|
16
|
+
## Features
|
17
|
+
|
18
|
+
- Simple configuration using BugSnag API key
|
19
|
+
- Control sampling using BugSnag's probability-based sampler
|
20
|
+
|
21
|
+
## Getting started
|
22
|
+
|
23
|
+
For integration instructions, see our online docs: [docs.bugsnag.com/performance/ruby](https://docs.bugsnag.com/performance/ruby)
|
24
|
+
|
25
|
+
## Support
|
26
|
+
|
27
|
+
* [Read the integration guide](https://docs.bugsnag.com/performance/ruby)
|
28
|
+
* [Search open and closed issues](https://github.com/bugsnag/bugsnag-ruby-performance/issues?=is%3Aissue) for similar problems
|
29
|
+
* [Report a bug or request a feature](https://github.com/bugsnag/bugsnag-ruby-performance/issues/new)
|
30
|
+
|
31
|
+
## License
|
32
|
+
|
33
|
+
The BugSnag Ruby Performance SDK is free software released under the MIT License. See [LICENSE.txt](LICENSE.txt) for details.
|
data/SECURITY.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Security Policy
|
2
|
+
|
3
|
+
## Supported Versions
|
4
|
+
|
5
|
+
| Version | Supported |
|
6
|
+
| ------- | ------------------ |
|
7
|
+
| 1.x | Yes |
|
8
|
+
|
9
|
+
## Reporting a Vulnerability
|
10
|
+
|
11
|
+
If you find a vulnerability in this SDK, please report it to our [Support team](mailto:support@bugsnag.com) for review.
|
data/TESTING.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Testing the Ruby BugSnag performance SDK
|
2
|
+
|
3
|
+
## Unit tests
|
4
|
+
|
5
|
+
```
|
6
|
+
bundle install
|
7
|
+
bundle exec rspec
|
8
|
+
```
|
9
|
+
|
10
|
+
## End-to-end tests
|
11
|
+
|
12
|
+
These tests are implemented with our internal testing tool [Maze Runner](https://github.com/bugsnag/maze-runner).
|
13
|
+
|
14
|
+
End to end tests are written in cucumber-style `.feature` files, and need Ruby-backed "steps" in order to know what to run. The tests are located in the top level [`features`](./features/) directory.
|
15
|
+
|
16
|
+
The Maze Runner test fixtures are containerised so you'll need Docker and Docker Compose to run them.
|
17
|
+
|
18
|
+
### Running the end to end tests
|
19
|
+
|
20
|
+
Install Maze Runner:
|
21
|
+
|
22
|
+
```sh
|
23
|
+
$ BUNDLE_GEMFILE=Gemfile-maze-runner bundle install
|
24
|
+
```
|
25
|
+
|
26
|
+
Configure the tests to be run in the following way:
|
27
|
+
|
28
|
+
- Determine the Ruby version to be tested using the environment variable `RUBY_TEST_VERSION`, e.g. `RUBY_TEST_VERSION=3.3`
|
29
|
+
- Determine the Open Telemetry SDK version using the environment variable `OPEN_TELEMETRY_SDK_TEST_VERSION`, e.g. `OPEN_TELEMETRY_SDK_TEST_VERSION="~> 1.5"`
|
30
|
+
|
31
|
+
Use the Maze Runner CLI to run the tests:
|
32
|
+
|
33
|
+
```sh
|
34
|
+
$ RUBY_TEST_VERSION=3.3 \
|
35
|
+
OPEN_TELEMETRY_SDK_TEST_VERSION="~> 1.5" \
|
36
|
+
BUNDLE_GEMFILE=Gemfile-maze-runner \
|
37
|
+
bundle exec maze-runner
|
38
|
+
```
|
data/bugsnag-performance.gemspec
CHANGED
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_dependency "concurrent-ruby", "~> 1.3"
|
35
35
|
spec.add_dependency "opentelemetry-sdk", "~> 1.2"
|
36
36
|
|
37
|
+
spec.add_development_dependency "yard", "~> 0.9"
|
37
38
|
spec.add_development_dependency "rspec", "~> 3.0"
|
38
39
|
spec.add_development_dependency "webmock", "~> 3.23"
|
39
40
|
end
|
@@ -2,14 +2,61 @@
|
|
2
2
|
|
3
3
|
module BugsnagPerformance
|
4
4
|
class Configuration
|
5
|
+
# @api private
|
5
6
|
attr_reader :open_telemetry_configure_block
|
7
|
+
|
8
|
+
# The logger BugSnag Performance will write messages to
|
9
|
+
#
|
10
|
+
# If not set, this will default to the BugSnag Errors logger or the Open
|
11
|
+
# Telemetry SDK logger
|
12
|
+
#
|
13
|
+
# @return [Logger]
|
6
14
|
attr_reader :logger
|
7
15
|
|
16
|
+
# Your BugSnag API Key
|
17
|
+
#
|
18
|
+
# If not set, this will be read from the "BUGSNAG_PERFORMANCE_API_KEY" and
|
19
|
+
# "BUGSNAG_API_KEY" environment variables or BugSnag Errors configuration.
|
20
|
+
# If none of these returns an API key, a {MissingApiKeyError} will be raised
|
21
|
+
#
|
22
|
+
# @return [String, nil]
|
8
23
|
attr_accessor :api_key
|
24
|
+
|
25
|
+
# The current version of the application, for example "1.2.3"
|
26
|
+
#
|
27
|
+
# If not set, this will be read from the "BUGSNAG_PERFORMANCE_APP_VERSION"
|
28
|
+
# and "BUGSNAG_APP_VERSION" environment variables or BugSnag Errors
|
29
|
+
# configuration
|
30
|
+
#
|
31
|
+
# @return [String]
|
9
32
|
attr_accessor :app_version
|
33
|
+
|
34
|
+
# The current stage of the release process, for example "development" or "production"
|
35
|
+
#
|
36
|
+
# If not set, this will be read from the "BUGSNAG_PERFORMANCE_RELEASE_STAGE"
|
37
|
+
# and "BUGSNAG_RELEASE_STAGE" environment variables or BugSnag Errors
|
38
|
+
# configuration and defaults to "production"
|
39
|
+
#
|
40
|
+
# @return [String]
|
10
41
|
attr_accessor :release_stage
|
42
|
+
|
43
|
+
# Which release stages to send traces for, for example ["staging", production"]
|
44
|
+
#
|
45
|
+
# If not set, this will be read from the "BUGSNAG_PERFORMANCE_ENABLED_RELEASE_STAGES"
|
46
|
+
# and "BUGSNAG_ENABLED_RELEASE_STAGES" environment variables or BugSnag Errors
|
47
|
+
# configuration and defaults to allow any release stage
|
48
|
+
#
|
49
|
+
# @return [Array<String>, nil]
|
11
50
|
attr_accessor :enabled_release_stages
|
12
51
|
|
52
|
+
# The name of the service that is being traced
|
53
|
+
#
|
54
|
+
# If not set, this will default to the Open Telemetry SDK service name
|
55
|
+
# or the value set by the "OTEL_SERVICE_NAME" environment variable
|
56
|
+
#
|
57
|
+
# @return [String]
|
58
|
+
attr_accessor :service_name
|
59
|
+
|
13
60
|
attr_writer :endpoint
|
14
61
|
|
15
62
|
def initialize(errors_configuration)
|
@@ -17,9 +64,14 @@ module BugsnagPerformance
|
|
17
64
|
self.logger = errors_configuration.logger || OpenTelemetry.logger
|
18
65
|
|
19
66
|
@api_key = fetch(errors_configuration, :api_key, env: "BUGSNAG_PERFORMANCE_API_KEY")
|
20
|
-
@app_version = fetch(errors_configuration, :app_version)
|
67
|
+
@app_version = fetch(errors_configuration, :app_version, env: "BUGSNAG_PERFORMANCE_APP_VERSION")
|
21
68
|
@release_stage = fetch(errors_configuration, :release_stage, env: "BUGSNAG_PERFORMANCE_RELEASE_STAGE", default: "production")
|
22
69
|
|
70
|
+
service_env = ENV["BUGSNAG_PERFORMANCE_SERVICE_NAME"]
|
71
|
+
@service_name = service_env unless service_env.nil?
|
72
|
+
endpoint_env = ENV["BUGSNAG_PERFORMANCE_ENDPOINT"]
|
73
|
+
@endpoint = endpoint_env unless endpoint_env.nil?
|
74
|
+
|
23
75
|
@enabled_release_stages = fetch(errors_configuration, :enabled_release_stages, env: "BUGSNAG_PERFORMANCE_ENABLED_RELEASE_STAGES")
|
24
76
|
|
25
77
|
# transform enabled release stages into an array if we read its value from
|
@@ -38,6 +90,11 @@ module BugsnagPerformance
|
|
38
90
|
end
|
39
91
|
end
|
40
92
|
|
93
|
+
# The URL to send traces to
|
94
|
+
#
|
95
|
+
# If not set this defaults to "https://<api_key>.otlp.bugsnag.com/v1/traces"
|
96
|
+
#
|
97
|
+
# @return [String, nil]
|
41
98
|
def endpoint
|
42
99
|
case
|
43
100
|
when defined?(@endpoint)
|
@@ -51,6 +108,9 @@ module BugsnagPerformance
|
|
51
108
|
end
|
52
109
|
end
|
53
110
|
|
111
|
+
# Apply configuration for the Open Telemetry SDK
|
112
|
+
#
|
113
|
+
# This block should *replace* any calls to OpenTelemetry::SDK.configure
|
54
114
|
def configure_open_telemetry(&open_telemetry_configure_block)
|
55
115
|
@open_telemetry_configure_block = open_telemetry_configure_block
|
56
116
|
end
|
@@ -15,6 +15,7 @@ module BugsnagPerformance
|
|
15
15
|
validate_api_key
|
16
16
|
validate_string(:app_version, optional: true)
|
17
17
|
validate_string(:release_stage, optional: true)
|
18
|
+
validate_string(:service_name, optional: true)
|
18
19
|
validate_array(:enabled_release_stages, "non-empty strings", optional: true, &method(:valid_string?))
|
19
20
|
valid_endpoint = validate_endpoint
|
20
21
|
|
@@ -8,6 +8,7 @@ module BugsnagPerformance
|
|
8
8
|
def initialize(configuration)
|
9
9
|
@uri = URI(configuration.endpoint)
|
10
10
|
@common_headers = {
|
11
|
+
"User-Agent" => "#{BugsnagPerformance::SDK_NAME} v#{BugsnagPerformance::VERSION}",
|
11
12
|
"Bugsnag-Api-Key" => configuration.api_key,
|
12
13
|
"Content-Type" => "application/json",
|
13
14
|
}.freeze
|
@@ -10,6 +10,15 @@ module BugsnagPerformance
|
|
10
10
|
attr_accessor :release_stage
|
11
11
|
attr_accessor :enabled_release_stages
|
12
12
|
attr_accessor :logger
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
# if bugsnag errors is not installed we still want to read from the
|
16
|
+
# environment variables it supports
|
17
|
+
@api_key = ENV["BUGSNAG_API_KEY"]
|
18
|
+
@app_version = ENV["BUGSNAG_APP_VERSION"]
|
19
|
+
@release_stage = ENV["BUGSNAG_RELEASE_STAGE"]
|
20
|
+
@enabled_release_stages = ENV["BUGSNAG_ENABLED_RELEASE_STAGES"]
|
21
|
+
end
|
13
22
|
end
|
14
23
|
end
|
15
24
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BugsnagPerformance
|
4
|
+
module Internal
|
5
|
+
class ParsedTracestate
|
6
|
+
attr_reader :version
|
7
|
+
attr_reader :r_value
|
8
|
+
|
9
|
+
def initialize(version, r_value, r_value_32_bit:)
|
10
|
+
@version = version
|
11
|
+
@r_value = r_value
|
12
|
+
@r_value_32_bit = r_value_32_bit
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid?
|
16
|
+
!!(@version && @r_value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def r_value_32_bit?
|
20
|
+
@r_value_32_bit
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -3,12 +3,17 @@
|
|
3
3
|
module BugsnagPerformance
|
4
4
|
module Internal
|
5
5
|
class Sampler
|
6
|
-
|
6
|
+
# the scale factor to use with a 64 bit r value
|
7
|
+
PROBABILITY_SCALE_FACTOR_64 = 18_446_744_073_709_551_615 # (2 ** 64) - 1
|
7
8
|
|
8
|
-
|
9
|
+
# the scale factor to use with a 32 bit r value
|
10
|
+
PROBABILITY_SCALE_FACTOR_32 = 4_294_967_295 # (2 ** 32) - 1
|
9
11
|
|
10
|
-
|
12
|
+
private_constant :PROBABILITY_SCALE_FACTOR_64, :PROBABILITY_SCALE_FACTOR_32
|
13
|
+
|
14
|
+
def initialize(probability_manager, tracestate_parser)
|
11
15
|
@probability_manager = probability_manager
|
16
|
+
@tracestate_parser = tracestate_parser
|
12
17
|
end
|
13
18
|
|
14
19
|
def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
|
@@ -17,47 +22,63 @@ module BugsnagPerformance
|
|
17
22
|
# for the sampling decision & p value attribute which would result
|
18
23
|
# in inconsistent data
|
19
24
|
probability = @probability_manager.probability
|
25
|
+
parent_span_context = OpenTelemetry::Trace.current_span(parent_context).context
|
26
|
+
tracestate = parent_span_context.tracestate
|
20
27
|
|
21
28
|
decision =
|
22
|
-
if
|
29
|
+
if sample_using_probability_and_trace?(probability, tracestate, trace_id)
|
23
30
|
OpenTelemetry::SDK::Trace::Samplers::Decision::RECORD_AND_SAMPLE
|
24
31
|
else
|
25
32
|
OpenTelemetry::SDK::Trace::Samplers::Decision::DROP
|
26
33
|
end
|
27
34
|
|
28
|
-
parent_span_context = OpenTelemetry::Trace.current_span(parent_context).context
|
29
|
-
|
30
35
|
OpenTelemetry::SDK::Trace::Samplers::Result.new(
|
31
36
|
decision: decision,
|
32
|
-
tracestate:
|
37
|
+
tracestate: tracestate,
|
33
38
|
attributes: { "bugsnag.sampling.p" => probability },
|
34
39
|
)
|
35
40
|
end
|
36
41
|
|
37
42
|
# @api private
|
38
43
|
def resample_span?(span)
|
39
|
-
probability = @probability_manager.probability
|
40
|
-
|
41
44
|
# sample all spans that are missing the p value attribute
|
42
45
|
return true if span.attributes.nil? || span.attributes["bugsnag.sampling.p"].nil?
|
43
46
|
|
47
|
+
probability = @probability_manager.probability
|
48
|
+
|
44
49
|
# update the p value attribute if it was originally sampled with a larger
|
45
50
|
# probability than the current value
|
46
51
|
if span.attributes["bugsnag.sampling.p"] > probability
|
47
52
|
span.attributes["bugsnag.sampling.p"] = probability
|
48
53
|
end
|
49
54
|
|
50
|
-
|
55
|
+
sample_using_probability_and_trace?(
|
56
|
+
span.attributes["bugsnag.sampling.p"],
|
57
|
+
span.tracestate,
|
58
|
+
span.trace_id
|
59
|
+
)
|
51
60
|
end
|
52
61
|
|
53
62
|
private
|
54
63
|
|
55
|
-
def
|
56
|
-
#
|
57
|
-
|
64
|
+
def sample_using_probability_and_trace?(probability, tracestate, trace_id)
|
65
|
+
# parse the r value from tracestate or generate from the trace ID by
|
66
|
+
# unpacking it as a u64
|
67
|
+
parsed_tracestate = @tracestate_parser.parse(tracestate)
|
68
|
+
|
69
|
+
if parsed_tracestate.valid?
|
70
|
+
# the JS SDK will send a u32 as the r value so we need to scale the
|
71
|
+
# probability value to the same range for comparisons to work
|
72
|
+
r_value = parsed_tracestate.r_value
|
73
|
+
scale_factor = parsed_tracestate.r_value_32_bit? ? PROBABILITY_SCALE_FACTOR_32 : PROBABILITY_SCALE_FACTOR_64
|
74
|
+
else
|
75
|
+
r_value = trace_id.unpack1("@8Q>")
|
76
|
+
scale_factor = PROBABILITY_SCALE_FACTOR_64
|
77
|
+
end
|
58
78
|
|
59
|
-
#
|
60
|
-
|
79
|
+
# scale the probability (stored as a float from 0-1) to the appropriate
|
80
|
+
# size int (u32 or u64)
|
81
|
+
p_value = (probability * scale_factor).floor
|
61
82
|
|
62
83
|
p_value >= r_value
|
63
84
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BugsnagPerformance
|
4
|
+
module Internal
|
5
|
+
class TracestateParser
|
6
|
+
def parse(tracestate)
|
7
|
+
smartbear_values = tracestate.value("sb")
|
8
|
+
return ParsedTracestate.new(nil, nil, r_value_32_bit: false) if smartbear_values.nil?
|
9
|
+
|
10
|
+
version = nil
|
11
|
+
r_value_32 = nil
|
12
|
+
r_value_64 = nil
|
13
|
+
|
14
|
+
smartbear_values.split(";").each do |field|
|
15
|
+
key, value = field.split(":", 2)
|
16
|
+
|
17
|
+
case key
|
18
|
+
when "v"
|
19
|
+
version = value
|
20
|
+
when "r32"
|
21
|
+
r_value_32 = Integer(value, exception: false)
|
22
|
+
when "r64"
|
23
|
+
r_value_64 = Integer(value, exception: false)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
ParsedTracestate.new(
|
28
|
+
version,
|
29
|
+
# a 64 bit value should take precedence over a 32 bit one if both are
|
30
|
+
# present in the tracestate
|
31
|
+
r_value_64 || r_value_32,
|
32
|
+
r_value_32_bit: r_value_64.nil? && !r_value_32.nil?
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/bugsnag_performance.rb
CHANGED
@@ -18,6 +18,8 @@ require_relative "bugsnag_performance/internal/span_exporter"
|
|
18
18
|
require_relative "bugsnag_performance/internal/logger_wrapper"
|
19
19
|
require_relative "bugsnag_performance/internal/task_scheduler"
|
20
20
|
require_relative "bugsnag_performance/internal/payload_encoder"
|
21
|
+
require_relative "bugsnag_performance/internal/parsed_tracestate"
|
22
|
+
require_relative "bugsnag_performance/internal/tracestate_parser"
|
21
23
|
require_relative "bugsnag_performance/internal/probability_fetcher"
|
22
24
|
require_relative "bugsnag_performance/internal/probability_manager"
|
23
25
|
require_relative "bugsnag_performance/internal/configuration_validator"
|
@@ -26,6 +28,11 @@ require_relative "bugsnag_performance/internal/nil_errors_configuration"
|
|
26
28
|
require_relative "bugsnag_performance/internal/probability_attribute_span_processor"
|
27
29
|
|
28
30
|
module BugsnagPerformance
|
31
|
+
# Configure BugSnag Performance
|
32
|
+
#
|
33
|
+
# Yields a {Configuration} object to use to set application settings.
|
34
|
+
#
|
35
|
+
# @yieldparam configuration [Configuration]
|
29
36
|
def self.configure(&block)
|
30
37
|
unvalidated_configuration = Configuration.new(load_bugsnag_errors_configuration)
|
31
38
|
|
@@ -40,7 +47,7 @@ module BugsnagPerformance
|
|
40
47
|
task_scheduler = Internal::TaskScheduler.new
|
41
48
|
probability_fetcher = Internal::ProbabilityFetcher.new(configuration.logger, delivery, task_scheduler)
|
42
49
|
probability_manager = Internal::ProbabilityManager.new(probability_fetcher)
|
43
|
-
sampler = Internal::Sampler.new(probability_manager)
|
50
|
+
sampler = Internal::Sampler.new(probability_manager, Internal::TracestateParser.new)
|
44
51
|
|
45
52
|
exporter = Internal::SpanExporter.new(
|
46
53
|
configuration.logger,
|
@@ -76,8 +83,17 @@ module BugsnagPerformance
|
|
76
83
|
otel_configurator.service_version = app_version
|
77
84
|
end
|
78
85
|
|
86
|
+
# set the service name if explicitly set by the user
|
87
|
+
if configuration.service_name != nil && configuration.service_name != ""
|
88
|
+
otel_configurator.service_name = configuration.service_name
|
89
|
+
end
|
90
|
+
|
79
91
|
otel_configurator.resource = OpenTelemetry::SDK::Resources::Resource.create(
|
80
|
-
|
92
|
+
{
|
93
|
+
OpenTelemetry::SemanticConventions::Resource::DEPLOYMENT_ENVIRONMENT => configuration.release_stage,
|
94
|
+
"bugsnag.telemetry.sdk.name" => SDK_NAME,
|
95
|
+
"bugsnag.telemetry.sdk.version" => VERSION,
|
96
|
+
}
|
81
97
|
)
|
82
98
|
|
83
99
|
# add batch processor with bugsnag exporter to send payloads
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bugsnag_performance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- BugSnag
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yard
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.9'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.9'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rspec
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -73,8 +87,14 @@ executables: []
|
|
73
87
|
extensions: []
|
74
88
|
extra_rdoc_files: []
|
75
89
|
files:
|
90
|
+
- ".yardopts"
|
76
91
|
- CHANGELOG.md
|
92
|
+
- CODEOWNERS
|
93
|
+
- CONTRIBUTING.md
|
77
94
|
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- SECURITY.md
|
97
|
+
- TESTING.md
|
78
98
|
- bugsnag-performance.gemspec
|
79
99
|
- lib/bugsnag_performance.rb
|
80
100
|
- lib/bugsnag_performance/configuration.rb
|
@@ -83,6 +103,7 @@ files:
|
|
83
103
|
- lib/bugsnag_performance/internal/delivery.rb
|
84
104
|
- lib/bugsnag_performance/internal/logger_wrapper.rb
|
85
105
|
- lib/bugsnag_performance/internal/nil_errors_configuration.rb
|
106
|
+
- lib/bugsnag_performance/internal/parsed_tracestate.rb
|
86
107
|
- lib/bugsnag_performance/internal/payload_encoder.rb
|
87
108
|
- lib/bugsnag_performance/internal/probability_attribute_span_processor.rb
|
88
109
|
- lib/bugsnag_performance/internal/probability_fetcher.rb
|
@@ -92,6 +113,7 @@ files:
|
|
92
113
|
- lib/bugsnag_performance/internal/span_exporter.rb
|
93
114
|
- lib/bugsnag_performance/internal/task.rb
|
94
115
|
- lib/bugsnag_performance/internal/task_scheduler.rb
|
116
|
+
- lib/bugsnag_performance/internal/tracestate_parser.rb
|
95
117
|
- lib/bugsnag_performance/version.rb
|
96
118
|
homepage: https://www.bugsnag.com
|
97
119
|
licenses:
|
@@ -100,7 +122,7 @@ metadata:
|
|
100
122
|
homepage_uri: https://www.bugsnag.com
|
101
123
|
source_code_uri: https://github.com/bugsnag/bugsnag-ruby-performance
|
102
124
|
bug_tracker_uri: https://github.com/bugsnag/bugsnag-ruby-performance/issues
|
103
|
-
changelog_uri: https://github.com/bugsnag/bugsnag-ruby-performance/blob/
|
125
|
+
changelog_uri: https://github.com/bugsnag/bugsnag-ruby-performance/blob/v1.0.0/CHANGELOG.md
|
104
126
|
documentation_uri: https://docs.bugsnag.com/performance/integration-guides/ruby/
|
105
127
|
rubygems_mfa_required: 'true'
|
106
128
|
post_install_message:
|
@@ -118,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
140
|
- !ruby/object:Gem::Version
|
119
141
|
version: '0'
|
120
142
|
requirements: []
|
121
|
-
rubygems_version: 3.4.
|
143
|
+
rubygems_version: 3.4.19
|
122
144
|
signing_key:
|
123
145
|
specification_version: 4
|
124
146
|
summary: BugSnag integration for the Ruby Open Telemetry SDK
|