aspecto-opentelemetry 0.1.0 → 0.1.4

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: a2bcc099a425ea9d9d4ea5279fcdde5fd1c72ee7a747cac0db749ec4946e6400
4
- data.tar.gz: 4045a1f967fc690eb67d057311f8543924abb14a223fd6484135e3831bc1fa11
3
+ metadata.gz: 1b300da76183578ab46935f20f8910aba9c73e19734f8ca19e83a5d0886dd09f
4
+ data.tar.gz: cd326d3a7855570df0fa90fa3a7ea7be7431f7554efa7292166d83fdcbbb7b99
5
5
  SHA512:
6
- metadata.gz: 5abe512f0a006febca0d20dab3dc2600539ef5af63429e3f05e715278e2760f611cc85908176a08e84a5570a045d02fd6baba260a8b769b691e9ad13f8d29abd
7
- data.tar.gz: f37300481a7a2994eb99600ed22fd122abaae7afe2569f36beb342f79204320b8726125fdb226adf1114169b178f6b7f43ff93c482c3d8b682681c9503d4579a
6
+ metadata.gz: da49265bb04f5d7f67a82f26d4ce14e2812602238e1fe9b5d4c83a68b010831215ddde521d62ad85175672730bf922e53bfcfe9d90728a136464c01873fa937d
7
+ data.tar.gz: 6ba067f0aeca189748bfe2e129a3bed4d01f0e59604ced9890948f7fd097c2869db1eae91192bc44ae7e31731e7691c4f48264c5992fd60f0b3cb646abaeb2a6
data/README.md CHANGED
@@ -1,81 +1,110 @@
1
1
  # Aspecto::OpenTelemetry
2
2
 
3
- Aspecto's SDK for ruby. This gem is a distribution of OpenTelemetry configured to use all available instrumentations and export trace data to Aspecto.
3
+ Aspecto's SDK for ruby.
4
+ This gem is a distribution of OpenTelemetry pre-configured to use all available instrumentations and export trace data to Aspecto.
4
5
 
5
6
  ## Installation
6
7
 
7
- Add this line to your application's Gemfile:
8
+ Install the gem using:
8
9
 
9
- ```ruby
10
- gem 'aspecto-opentelemetry'
10
+ ```zsh
11
+ $ gem install aspecto-opentelemetry
11
12
  ```
12
13
 
13
- And then execute:
14
+ Or, if you use [bundler](https://bundler.io), include aspecto-opentelemetry in your Gemfile.
14
15
 
15
- $ bundle install
16
+ ## Usage
16
17
 
17
- Or install it yourself as:
18
+ ### Rails Applications
18
19
 
19
- $ gem install aspecto-opentelemetry
20
+ #### Configuration in Code
20
21
 
21
- ## Usage
22
+ Add this code to a new file `aspecto.rb` under `config/initializers/`:
23
+
24
+ ```rb
25
+ # config/initializers/aspecto.rb
26
+ require 'aspecto/opentelemetry'
27
+
28
+ Aspecto::OpenTelemetry::configure do |c|
29
+ c.service_name = '<YOUR_SERVICE_NAME>'
30
+ c.aspecto_auth = '<YOUR_ASPECTO_TOKEN>'
31
+ # c.sampling_ratio = 1.0 # [optional]: defaults to 1.0, use aspecto app to configure remotely
32
+ end
33
+ ```
22
34
 
23
- ### Auto Instrumentation
35
+ #### Configuration via Environment Variables
24
36
 
25
- Does not require code changes. Just modify you `Gemfile` to add `require` like this:
37
+ In your Gemfile:
26
38
 
27
39
  ```
28
40
  gem 'aspecto-opentelemetry', require: 'aspecto/auto_instrument'
29
41
  ```
30
42
 
31
- When using auto-instrumentation, you need to pass relevant configuration options via environment variables.
43
+ And set environment variables:
44
+
45
+ ```
46
+ OTEL_SERVICE_NAME=<YOUR_SERVICE_NAME>
47
+ ASPECTO_AUTH=<YOUR_ASPECTO_TOKEN>
48
+ # ASPECTO_SAMPLING_RATIO=1.0 # [optional]: defaults to 1.0, use aspecto app to configure remotely
49
+ ```
50
+
51
+ ### Ruby Applications
32
52
 
33
- ### Manual Instrumentation
53
+ #### Configuration in Code
34
54
 
35
- Allow you to configure the SDK via code:
55
+ Add this code after your require other gems:
36
56
 
37
57
  ```rb
38
58
  require 'aspecto/opentelemetry'
39
59
 
40
- Aspecto::OpenTelemetry::configure
60
+ Aspecto::OpenTelemetry::configure do |c|
61
+ c.service_name = '<YOUR_SERVICE_NAME>'
62
+ c.aspecto_auth = '<YOUR_ASPECTO_TOKEN>'
63
+ # c.env = '<CURRENT_ENVIRONMENT>' # [optional]: automatically detected for rails and sinatra
64
+ # c.sampling_ratio = 1.0 # [optional]: defaults to 1.0, use aspecto app to configure remotely
65
+ end
41
66
  ```
42
67
 
43
- Add this code at the beginning of your application.
44
- For rails - add this code to a file `aspecto.rb` under `config/initializers/`.
68
+ #### Configuration via Environment Variables
45
69
 
46
- ## Configuration
47
-
48
- You can set configuration it 2 ways: via environment variables or via code.
49
- The only required config options are `aspecto_auth` and `service_name`.
50
-
51
- ### Configuration in Code
70
+ Add this require statement after your require other gems:
52
71
 
53
72
  ```rb
54
- require 'aspecto/opentelemetry'
73
+ require 'aspecto/auto_instrument'
74
+ ```
55
75
 
56
- Aspecto::OpenTelemetry::configure do |c|
57
- c.service_name = 'MY_SERIVCE'
58
- c.aspecto_auth = 'YOUR_TOKEN_HERE'
59
- c.env = 'MY_COOL_ENV'
60
- c.sampling_ratio = 0.1
61
- end
76
+ And set environment variables:
77
+
78
+ ```
79
+ OTEL_SERVICE_NAME=<YOUR_SERVICE_NAME>
80
+ ASPECTO_AUTH=<YOUR_ASPECTO_TOKEN>
81
+ # ASPECTO_ENV=<CURRENT_ENVIRONMENT> # [optional]: automatically detected for rails and sinatra
82
+ # ASPECTO_SAMPLING_RATIO=1.0 # [optional]: defaults to 1.0, use aspecto app to configure remotely
62
83
  ```
63
84
 
64
- ### Configuration Options
85
+ ### Shutdown
65
86
 
66
- | Option Name | Environment Variable | Type | Default | Description |
67
- | -------------- | ---------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
68
- | aspecto_auth | ASPECTO_AUTH | UUID string | - | Aspecto's [API key for authentication](https://app.aspecto.io/app/integration/api-key) |
69
- | service_name | OTEL_SERVICE_NAME | string | - | name of the service which is sending telemetry |
70
- | env | ASPECTO_ENV | string | extracted from rails or sinatra if used | deployment environment: `"production"` / `"staging"` / `"development"`, etc. |
71
- | log_level | OTEL_LOG_LEVEL | string | 'ERROR' | `"ERROR"` / `"WARN"` / `"INFO"`, etc. |
72
- | sampling_ratio | ASPECTO_SAMPLING_RATIO | float | 1.0 | How many of the traces starting in this service should be sampled. set to number in range [0.0, 1.0] where 0.0 is no sampling, and 1.0 is sample all |
87
+ Call this function when your application shuts down
73
88
 
74
- ## Development
89
+ ```rb
90
+ Aspecto::OpenTelemetry::shutdown
91
+ ```
75
92
 
76
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
93
+ ## Configuration
94
+
95
+ You can set configuration via environment variables or via code. Values set in code takes precedence.
96
+ The only required config options are [`aspecto_auth`](https://app.aspecto.io/app/integration/api-key) and `service_name`.
97
+
98
+ ### Configuration Options
77
99
 
78
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
100
+ | Option Name | Environment Variable | Type | Default | Description |
101
+ | ------------------------------------ | ------------------------------------ | ----------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
102
+ | `aspecto_auth` | `ASPECTO_AUTH` | UUID string | - | Aspecto's [API key for authentication](https://app.aspecto.io/app/integration/api-key) |
103
+ | `service_name` | `OTEL_SERVICE_NAME` | string | - | name of the service which is sending telemetry |
104
+ | `env` | `ASPECTO_ENV` | string | extracted from rails or sinatra if used | deployment environment: `production` / `staging` / `development`, etc. |
105
+ | `log_level` | `OTEL_LOG_LEVEL` | string | `ERROR` | `ERROR` / `WARN` / `INFO`, etc. |
106
+ | `sampling_ratio` | `ASPECTO_SAMPLING_RATIO` | float | 1.0 | How many of the traces starting in this service should be sampled. set to number in range [0.0, 1.0] where 0.0 is no sampling, and 1.0 is sample all |
107
+ | `otel_exporter_otlp_traces_endpoint` | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | URL | "https://otelcol.aspecto.io/v1/trace" | Url |
79
108
 
80
109
  ## Contributing
81
110
 
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "faraday_middleware"
5
+ require "rufus/scheduler"
6
+
7
+ require_relative "../sampler/rules_sampler"
8
+ require_relative "../sampler/message_process_sampler"
9
+
10
+ module Aspecto
11
+ # Aspecto's OpenTelemetry distribution
12
+ module OpenTelemetry
13
+ module Config
14
+ # Handle fetching of remote configuration from aspecto
15
+ class RemoteConfig
16
+ def initialize(aspecto_auth, service_name, env, fallback_sampler)
17
+ @service_name = service_name
18
+ @env = env
19
+ @fallback_sampler = fallback_sampler
20
+
21
+ aspecto_config_url = ENV.fetch("ASPECTO_CONFIG_HOST", "https://config.aspecto.io")
22
+ @http_client = Faraday.new "#{aspecto_config_url}/config/#{aspecto_auth}" do |f|
23
+ f.response :json # decode response bodies as JSON
24
+ end
25
+ @http_client.options.timeout = 10
26
+
27
+ @scheduler = Rufus::Scheduler.new
28
+ @remote_config_poll_frequency = ENV.fetch("ASPECTO_REMOTE_CONFIG_POLL_FREQUENCY", "30s")
29
+ @scheduler.interval @remote_config_poll_frequency, first: :now do
30
+ update_config
31
+ end
32
+
33
+ ::OpenTelemetry.logger.info "[Aspecto] SDK client initialized"
34
+ end
35
+
36
+ def shutdown
37
+ @scheduler.shutdown
38
+ end
39
+
40
+ private
41
+
42
+ def update_config # rubocop:disable Metrics/AbcSize
43
+ ::OpenTelemetry::Common::Utilities.untraced do
44
+ response = @http_client.get do |req|
45
+ req.headers["If-None-Match"] = @latest_config_etag unless @latest_config_etag.nil?
46
+ end
47
+ @latest_config_etag = response.headers["etag"]
48
+ return if response.status == 304
49
+
50
+ if response.status >= 400
51
+ ::OpenTelemetry.logger.error("[Aspecto] error when trying to get remote config. will try again in #{@remote_config_poll_frequency}")
52
+ return
53
+ end
54
+ handle_new_config response.body if response.status < 300
55
+ end
56
+ rescue StandardError => e
57
+ ::OpenTelemetry.logger.error "[Aspecto] updating remote config failed. using previous remote config"
58
+ ::OpenTelemetry.logger.debug e
59
+ end
60
+
61
+ def handle_new_config(config)
62
+ ::OpenTelemetry.logger.info("[Aspecto] successfully received remote configuration")
63
+ update_sampler config["samplingRules"]
64
+ end
65
+
66
+ def update_sampler(sampler_config)
67
+ rules_sampler = Sampler::RulesSampler.new sampler_config, @fallback_sampler, @service_name, @env
68
+ service_sampler = ::OpenTelemetry::SDK::Trace::Samplers.parent_based(root: rules_sampler)
69
+ message_process_sampler = Sampler::MessageProcessSampler.new rules_sampler, service_sampler
70
+ # updating the sampler should be thread safe as it's an atomic setter on a global value
71
+ ::OpenTelemetry.tracer_provider.sampler = message_process_sampler
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -13,6 +13,7 @@ module Aspecto
13
13
  self.log_level = ENV.fetch("OTEL_LOG_LEVEL", Logger::ERROR)
14
14
  self.env = ENV["ASPECTO_ENV"] if ENV["ASPECTO_ENV"]
15
15
  self.sampling_ratio = Float(ENV.fetch("ASPECTO_SAMPLING_RATIO", 1.0))
16
+ self.otel_exporter_otlp_traces_endpoint = ENV.fetch("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "https://otelcol.aspecto.io/v1/trace")
16
17
  end
17
18
 
18
19
  def service_name=(service_name)
@@ -23,7 +24,7 @@ module Aspecto
23
24
  @override_resource_attributes[::OpenTelemetry::SemanticConventions::Resource::DEPLOYMENT_ENVIRONMENT] = env
24
25
  end
25
26
 
26
- attr_accessor :sampling_ratio, :log_level
27
+ attr_accessor :sampling_ratio, :log_level, :otel_exporter_otlp_traces_endpoint
27
28
  attr_reader :aspecto_auth
28
29
 
29
30
  def aspecto_auth=(aspecto_auth)
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./operator"
4
+
5
+ module Aspecto
6
+ # Aspecto OpenTelemetry Distro
7
+ module OpenTelemetry
8
+ module Sampler
9
+ # Aspecto's sampling rule condition
10
+ class Condition
11
+ def initialize(condition_config)
12
+ @operator = Operator.new condition_config["comparison"], condition_config["value"]
13
+ @from = condition_config["from"]&.to_sym
14
+ @key = condition_config["key"]
15
+ end
16
+
17
+ def satisfies?(attributes, span_name)
18
+ case @from
19
+ when :attribute
20
+ @operator.satisfies? attributes&.[](@key)&.to_s
21
+ when :operation
22
+ @operator.satisfies? span_name
23
+ else
24
+ # Other "from" are not implemented for now
25
+ false
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "opentelemetry/semantic_conventions"
4
+ require "opentelemetry-api"
5
+
6
+ module Aspecto
7
+ # Aspecto OpenTelemetry Distro
8
+ module OpenTelemetry
9
+ module Sampler
10
+ # OpenTelemetry sampler which implements the remote rules logic with fallback to service sampler
11
+ class MessageProcessSampler
12
+ def initialize(rules_sampler, service_sampler)
13
+ @rules_sampler = rules_sampler
14
+ @service_sampler = service_sampler
15
+ end
16
+
17
+ def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
18
+ if attributes && attributes[::OpenTelemetry::SemanticConventions::Trace::MESSAGING_OPERATION] == "process"
19
+ sampling_decision = should_sample_processing(parent_context, links, name, attributes)
20
+ return sampling_decision if sampling_decision
21
+ end
22
+ @service_sampler.should_sample?(trace_id: trace_id, parent_context: parent_context, links: links, name: name, kind: kind, attributes: attributes)
23
+ end
24
+
25
+ def description
26
+ "MessageProcessSampler"
27
+ end
28
+
29
+ private
30
+
31
+ def should_sample_processing(parent_context, links, name, attributes)
32
+ return if links.length.zero?
33
+
34
+ decision = link_decision(links[0])
35
+
36
+ # sidekiq receive side is a single "process" span which is the entry for the trace
37
+ is_root = ::OpenTelemetry::Trace.current_span(parent_context) == ::OpenTelemetry::Trace::Span::INVALID
38
+ if is_root # rubocop:disable Style/GuardClause
39
+ matched_rule = @rules_sampler.matching_rule(name: name, attributes: attributes)
40
+ rule_context = matched_rule&.context
41
+ return ::OpenTelemetry::SDK::Trace::Samplers::Result.new(decision: decision, tracestate: ::OpenTelemetry::Trace.current_span(parent_context).context.tracestate) if rule_context && rule_context["messaging.sampling.inherit_from_publisher"]
42
+ end
43
+
44
+ # if not root, then we need to check if the entry span set "messaging.sampling.inherit_from_publisher" on the context.
45
+ # since we currently only support sidekiq, it is not needed.
46
+ # but in the future, it can be implemented with context.attach when the rule is applied, and context.get here
47
+ end
48
+
49
+ def link_decision(link)
50
+ publisher_sampled = link.span_context.trace_flags.sampled?
51
+ publisher_sampled ? ::OpenTelemetry::SDK::Trace::Samplers::Decision::RECORD_AND_SAMPLE : ::OpenTelemetry::SDK::Trace::Samplers::Decision::DROP
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aspecto
4
+ # Aspecto OpenTelemetry Distro
5
+ module OpenTelemetry
6
+ # Sampling logic for aspecto otel distribution
7
+ module Sampler
8
+ # A single operator used to evaluate sampling rules
9
+ class Operator
10
+ def initialize(operator, expected) # rubocop:disable Metrics/AbcSize
11
+ @expected = expected&.downcase
12
+ @expected = Regexp.new(@expected) if operator == "matches"
13
+
14
+ operator_to_proc = {
15
+ "eq" => proc { |actual| @expected == actual },
16
+ "ne" => proc { |actual| @expected != actual },
17
+ "starts_with" => proc { |actual| actual&.start_with?(expected) },
18
+ "ends_with" => proc { |actual| actual&.end_with?(expected) },
19
+ "contains" => proc { |actual| actual&.include?(expected) },
20
+ "not_contains" => proc { |actual| !actual&.include?(expected) },
21
+ "matches" => proc { |actual| @expected.match(actual) },
22
+ "defined" => proc { |actual| !actual.nil? },
23
+ "undefined" => proc { |actual| actual.nil? },
24
+ "any" => proc { true }
25
+ }
26
+
27
+ @evaluate = operator_to_proc.fetch(operator, proc { false })
28
+ end
29
+
30
+ def satisfies?(actual)
31
+ @evaluate.call actual&.downcase
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./sampling_rule"
4
+ require_relative "./operator"
5
+
6
+ module Aspecto
7
+ # Aspecto OpenTelemetry Distro
8
+ module OpenTelemetry
9
+ module Sampler
10
+ # OpenTelemetry sampler which implements the remote rules logic with fallback to service sampler
11
+ class RulesSampler
12
+ def initialize(config, fallback_sampler, service_name, env)
13
+ @rules = config
14
+ .select { |rule| Operator.new(rule["packageName"]["comparison"], rule["packageName"]["value"]).satisfies?(service_name) }
15
+ .select { |rule| Operator.new(rule["env"]["comparison"], rule["env"]["value"]).satisfies?(env) }
16
+ .map { |rule_config| SamplingRule.new rule_config }
17
+ @fallback_sampler = fallback_sampler
18
+ end
19
+
20
+ def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
21
+ rule = matching_rule(name: name, attributes: attributes)
22
+ delegate_sampler = rule ? rule.sampler : @fallback_sampler
23
+ delegate_sampler.should_sample?(trace_id: trace_id, parent_context: parent_context, links: links, name: name, kind: kind, attributes: attributes)
24
+ end
25
+
26
+ def description
27
+ "RulesSampler {#{rules.length} rules}"
28
+ end
29
+
30
+ def matching_rule(name:, attributes:)
31
+ @rules.find { |rule| rule.satisfies?(attributes, name) }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "opentelemetry/sdk"
4
+ require_relative "./condition"
5
+
6
+ module Aspecto
7
+ # Aspecto OpenTelemetry Distro
8
+ module OpenTelemetry
9
+ module Sampler
10
+ # Single rule for sampling
11
+ class SamplingRule
12
+ def initialize(rule_config)
13
+ @id = rule_config["_id"]
14
+ @sampler = ::OpenTelemetry::SDK::Trace::Samplers.trace_id_ratio_based(rule_config["samplingRate"])
15
+ @conditions = rule_config["conditions"].map { |condition_config| Condition.new condition_config }
16
+ @context = rule_config["context"]
17
+ end
18
+
19
+ attr_reader :sampler, :context
20
+
21
+ def satisfies?(attributes, span_name)
22
+ @conditions.all? { |condition| condition.satisfies?(attributes, span_name) }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Aspecto
4
4
  module OpenTelemetry
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.4"
6
6
  end
7
7
  end
@@ -4,6 +4,8 @@ require_relative "opentelemetry/version"
4
4
  require_relative "opentelemetry/configurator"
5
5
  require_relative "opentelemetry/resource/detectors/aspecto"
6
6
  require_relative "opentelemetry/resource/detectors/deployment"
7
+ require_relative "opentelemetry/config/remote_config"
8
+
7
9
  require "opentelemetry/sdk"
8
10
  require "opentelemetry/exporter/otlp"
9
11
  require "opentelemetry/instrumentation/all"
@@ -28,26 +30,41 @@ module Aspecto
28
30
  c.resource = Aspecto::OpenTelemetry::Resource::Detectors::Deployment.detect
29
31
  c.resource = configurator.config_override_resource # must be last
30
32
  c.use_all "OpenTelemetry::Instrumentation::ActionPack" => { enable_recognize_route: true },
31
- "OpenTelemetry::Instrumentation::AwsSdk" => { suppress_internal_instrumentation: true }
33
+ "OpenTelemetry::Instrumentation::AwsSdk" => { suppress_internal_instrumentation: true, inject_messaging_context: true }
34
+
35
+ otlp_exporter = ::OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: configurator.otel_exporter_otlp_traces_endpoint, headers: {
36
+ "Authorization" => configurator.aspecto_auth
37
+ })
38
+ span_processor = ::OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new otlp_exporter
39
+ c.add_span_processor span_processor
32
40
 
33
- c.add_span_processor(
34
- ::OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
35
- ::OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: "https://otelcol.aspecto.io/v1/trace", headers: {
36
- "Authorization" => configurator.aspecto_auth
37
- })
38
- )
39
- )
41
+ at_exit do
42
+ # at_exit might be call when service terminates
43
+ # but can also be the initiator or the application like with sinatra:
44
+ # https://github.com/sinatra/sinatra/blob/cd503e6c590cd48c2c9bb7869522494bfc62cb14/lib/sinatra/main.rb#L25
45
+ span_processor.force_flush timeout: 2
46
+ end
40
47
  end
41
48
 
42
- ::OpenTelemetry.tracer_provider.sampler = ::OpenTelemetry::SDK::Trace::Samplers.parent_based(root: ::OpenTelemetry::SDK::Trace::Samplers.trace_id_ratio_based(configurator.sampling_ratio))
49
+ fallback_sampler = ::OpenTelemetry::SDK::Trace::Samplers.trace_id_ratio_based(configurator.sampling_ratio)
50
+ # TODO: how to properly extract the data from resource?
51
+ _, service_name = ::OpenTelemetry.tracer_provider.resource.attribute_enumerator.detect { |elem| elem[0] == ::OpenTelemetry::SemanticConventions::Resource::SERVICE_NAME }
52
+ _, env = ::OpenTelemetry.tracer_provider.resource.attribute_enumerator.detect { |elem| elem[0] == ::OpenTelemetry::SemanticConventions::Resource::DEPLOYMENT_ENVIRONMENT }
53
+ @remote_config_service = Config::RemoteConfig.new configurator.aspecto_auth, service_name, env, fallback_sampler
43
54
  rescue StandardError => e
44
55
  warn "Failed to initialize Aspecto tracing."
45
56
  warn e
46
57
  end
47
58
 
59
+ def shutdown
60
+ ::OpenTelemetry.logger.info("Aspecto is shuting down. tracing is now stopped")
61
+ ::OpenTelemetry.tracer_provider.shutdown
62
+ @remote_config_service&.shutdown
63
+ end
64
+
48
65
  def validate_configurator_options(configurator)
49
66
  # aspecto_auth
50
- unless configurator.aspecto_auth.instance_of?(String)
67
+ unless configurator.aspecto_auth.instance_of?(String) && !configurator.aspecto_auth.empty?
51
68
  raise "
52
69
  Unable to retrieve Aspecto token.
53
70
  In order for the Aspecto service to work, it requires an auth token.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aspecto-opentelemetry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aspecto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-23 00:00:00.000000000 Z
11
+ date: 2021-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aspecto-opentelemetry-instrumentation-aws_sdk
@@ -16,56 +16,98 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.3
19
+ version: 0.1.7
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.3
26
+ version: 0.1.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.8'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday_middleware
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.2'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: opentelemetry-exporter-otlp
29
57
  requirement: !ruby/object:Gem::Requirement
30
58
  requirements:
31
59
  - - '='
32
60
  - !ruby/object:Gem::Version
33
- version: 0.20.6
61
+ version: 0.21.0
34
62
  type: :runtime
35
63
  prerelease: false
36
64
  version_requirements: !ruby/object:Gem::Requirement
37
65
  requirements:
38
66
  - - '='
39
67
  - !ruby/object:Gem::Version
40
- version: 0.20.6
68
+ version: 0.21.0
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: opentelemetry-instrumentation-all
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
73
  - - '='
46
74
  - !ruby/object:Gem::Version
47
- version: 0.21.3
75
+ version: 0.22.0
48
76
  type: :runtime
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
80
  - - '='
53
81
  - !ruby/object:Gem::Version
54
- version: 0.21.3
82
+ version: 0.22.0
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: opentelemetry-sdk
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
87
  - - '='
60
88
  - !ruby/object:Gem::Version
61
- version: '1.0'
89
+ version: 1.0.2
62
90
  type: :runtime
63
91
  prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
94
  - - '='
67
95
  - !ruby/object:Gem::Version
68
- version: '1.0'
96
+ version: 1.0.2
97
+ - !ruby/object:Gem::Dependency
98
+ name: rufus-scheduler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.8'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.8'
69
111
  - !ruby/object:Gem::Dependency
70
112
  name: minitest
71
113
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +122,20 @@ dependencies:
80
122
  - - "~>"
81
123
  - !ruby/object:Gem::Version
82
124
  version: '5.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: opentelemetry-common
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '='
130
+ - !ruby/object:Gem::Version
131
+ version: 0.19.3
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '='
137
+ - !ruby/object:Gem::Version
138
+ version: 0.19.3
83
139
  - !ruby/object:Gem::Dependency
84
140
  name: rake
85
141
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +150,20 @@ dependencies:
94
150
  - - "~>"
95
151
  - !ruby/object:Gem::Version
96
152
  version: '13.0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rspec-mocks
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
97
167
  - !ruby/object:Gem::Dependency
98
168
  name: rubocop
99
169
  requirement: !ruby/object:Gem::Requirement
@@ -123,9 +193,15 @@ files:
123
193
  - Rakefile
124
194
  - lib/aspecto/auto_instrument.rb
125
195
  - lib/aspecto/opentelemetry.rb
196
+ - lib/aspecto/opentelemetry/config/remote_config.rb
126
197
  - lib/aspecto/opentelemetry/configurator.rb
127
198
  - lib/aspecto/opentelemetry/resource/detectors/aspecto.rb
128
199
  - lib/aspecto/opentelemetry/resource/detectors/deployment.rb
200
+ - lib/aspecto/opentelemetry/sampler/condition.rb
201
+ - lib/aspecto/opentelemetry/sampler/message_process_sampler.rb
202
+ - lib/aspecto/opentelemetry/sampler/operator.rb
203
+ - lib/aspecto/opentelemetry/sampler/rules_sampler.rb
204
+ - lib/aspecto/opentelemetry/sampler/sampling_rule.rb
129
205
  - lib/aspecto/opentelemetry/version.rb
130
206
  homepage: https://docs.aspecto.io/
131
207
  licenses: