diff --git a/.circleci/config.yml b/.circleci/config.yml index 05d5c79f..e2afb0cc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -36,43 +36,6 @@ library_gemfile: &library_gemfile - "./gemfiles/mongo_216.gemfile" - "./gemfiles/mongo_219.gemfile" executors: - ruby_30: - docker: - - image: cimg/ruby:3.0-node - environment: - MEMCACHED_HOST: '127.0.0.1:11211' - REDIS_URL: 'redis://127.0.0.1:6379' - DATABASE_URL: 'sqlite3::memory:' - - image: memcached - - image: redis - - image: amazon/dynamodb-local - - image: minio/minio:latest - command: ["server", "/data"] - - image: s12v/sns - - image: softwaremill/elasticmq-native - - image: mongo:5-focal - ruby_30_mysql2: - docker: - - image: cimg/ruby:3.0-node - environment: - DATABASE_URL: "mysql2://root@127.0.0.1:3306/ci_test" - - image: mariadb - environment: - MYSQL_DATABASE: 'ci_test' - MYSQL_USER: 'root' - MYSQL_PASSWORD: '' - MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' - MYSQL_ROOT_PASSWORD: '' - MYSQL_ROOT_HOST: '%' - ruby_30_postgres: - docker: - - image: cimg/ruby:3.0-node - environment: - DATABASE_URL: "postgres://postgres:test@127.0.0.1:5432/ci_test" - - image: postgres - environment: - POSTGRES_PASSWORD: 'test' - POSTGRES_DB: 'ci_test' ruby_31: docker: - image: cimg/ruby:3.1-node @@ -323,7 +286,7 @@ jobs: parameters: stack: type: executor - default: ruby_30 + default: ruby_31 executor: << parameters.stack >> steps: - checkout @@ -333,7 +296,7 @@ jobs: parameters: stack: type: executor - default: ruby_30 + default: ruby_31 gemfile: type: string default: "./gemfiles/aws_30.gemfile" @@ -384,18 +347,16 @@ workflows: matrix: parameters: stack: - - ruby_30 - ruby_31 - ruby_32 - ruby_33 - ruby_34 - libraries_ruby_30_32: + libraries_ruby_31_32: jobs: - test_apprisal: matrix: parameters: stack: - - ruby_30 - ruby_31 - ruby_32 <<: *library_gemfile @@ -418,15 +379,12 @@ workflows: exclude: - stack: ruby_34 gemfile: "./gemfiles/grpc_10.gemfile" - rails_ruby_3: + rails_ruby_31_34: jobs: - test_apprisal: matrix: parameters: stack: - - ruby_30 - - ruby_30_postgres - - ruby_30_mysql2 - ruby_31 - ruby_31_postgres - ruby_31_mysql2 @@ -466,8 +424,6 @@ workflows: matrix: parameters: stack: - - ruby_30 - - ruby_30_mysql2 - ruby_31 - ruby_31_mysql2 - ruby_32 diff --git a/.tekton/.currency/scripts/generate_report.py b/.tekton/.currency/scripts/generate_report.py index 7582f045..42c56ebc 100644 --- a/.tekton/.currency/scripts/generate_report.py +++ b/.tekton/.currency/scripts/generate_report.py @@ -2,6 +2,7 @@ import glob import re from json import load +from datetime import datetime # Third Party from requests import get @@ -11,9 +12,10 @@ JSON_FILE = "resources/table.json" REPORT_FILE = "docs/report.md" API_V1_ENDPOINT = "https://rubygems.org/api/v1/versions/" +GEM_INFO_ENDPOINT = "https://rubygems.org/api/v1/gems/" -def get_bundle_install_output(): +def get_bundle_install_output(): libraries_from_logs = { "cuba": "cuba_40_ruby_3.3.", "excon": "excon_100_ruby_3.3.", @@ -28,22 +30,23 @@ def get_bundle_install_output(): "dalli": "dalli_32_ruby_3.3.", "resque": "resque_20_ruby_3.3.", "sidekiq": "sidekiq_70_ruby_3.3.", - "sequel": "sequel_58_ruby_3.3." + "sequel": "sequel_58_ruby_3.3.", } bundle_install_output = "" for library, pattern in libraries_from_logs.items(): glob_result = glob.glob(f"../../dep_{pattern}*") + if not glob_result: print(f"Could not find bundle install log for gem '{library}'.") continue - with open(glob_result[0], 'r') as file: - logs = file.read().replace('\n', ' ') + with open(glob_result[0], "r") as file: + logs = file.read().replace("\n", " ") if "Installing" not in logs: - print( f"Unable to retrieve logs from for gem '{library}'.") + print(f"Unable to retrieve logs from for gem '{library}'.") continue print(f"Retrieving currency for gem '{library}'.") @@ -53,27 +56,176 @@ def get_bundle_install_output(): return bundle_install_output +def estimate_days_behind(release_date, last_supported_release_date): + """Calculate days between release dates""" + latest_date = datetime.strptime(release_date, "%Y-%m-%d") + supported_date = datetime.strptime(last_supported_release_date, "%Y-%m-%d") + days_diff = (latest_date - supported_date).days + return max(0, days_diff) + + def get_upstream_version(dependency): - """get the latest version available upstream""" + """get the latest version available upstream and release date""" if dependency != "rails lts": - response = get(f"{API_V1_ENDPOINT}/{dependency}/latest.json") - response_json = response.json() - latest_version = response_json["version"] + try: + response = get(f"{API_V1_ENDPOINT}{dependency}/latest.json") + if not response: + return "Unknown", "Unknown" + + response_json = response.json() + latest_version = response_json["version"] + + gem_info_response = get(f"{GEM_INFO_ENDPOINT}{dependency}.json") + if not gem_info_response: + return latest_version, "Unknown" + gem_info = gem_info_response.json() + + version_info_response = get(f"{API_V1_ENDPOINT}{dependency}.json") + if not version_info_response: + return latest_version, "Unknown" + version_info = version_info_response.json() + + latest_version_release_date = None + for version_data in version_info: + if version_data["number"] == latest_version: + if "created_at" in version_data: + created_at = version_data["created_at"] + latest_version_release_date = datetime.strptime( + created_at, "%Y-%m-%dT%H:%M:%S.%fZ" + ).strftime("%Y-%m-%d") + break + + if not latest_version_release_date and "created_at" in gem_info: + created_at = gem_info["created_at"] + latest_version_release_date = datetime.strptime( + created_at, "%Y-%m-%dT%H:%M:%S.%fZ" + ).strftime("%Y-%m-%d") + + if not latest_version_release_date: + latest_version_release_date = "Unknown" + print(f"Could not find release date for {dependency}") + + return latest_version, latest_version_release_date + except Exception as e: + return "Unknown", "Unknown" else: - url = "https://makandracards.com/railslts/16137-installing-rails-lts/read" - page = get(url) - soup = BeautifulSoup(page.text, "html.parser") - text = soup.findAll("li")[-1].text - pattern = "(\d+\.\d+\.?\d*)" - latest_version = re.search(pattern, text)[1] - return latest_version + try: + initial_response = get( + "https://makandracards.com/railslts/16137-installing-rails-lts/read" + ) + if not initial_response: + return "Unknown", "Unknown" + + initial_soup = BeautifulSoup(initial_response.text, "html.parser") + + text = initial_soup.find_all("li")[-1].text + pattern = "(\d+\.\d+\.?\d*)" + latest_version_match = re.search(pattern, text) + + latest_version = "Unknown" + if latest_version_match: + latest_version = latest_version_match[1] + rails_lts_links = initial_soup.find_all("a", href=re.compile(r"railslts")) + latest_rails_lts_link = None + latest_version_num = 0.0 + + for link in rails_lts_links: + href = link.get("href", "") + link_text = link.text.strip() + + if "Installing Rails" in link_text: + version_match = re.search(r"Installing Rails (\d+\.\d+)", link_text) + if version_match: + version_str = version_match.group(1) + try: + version_num = float(version_str) + if version_num > latest_version_num: + latest_version_num = version_num + latest_rails_lts_link = href + latest_version = version_str + except ValueError: + pass + + latest_version_release_date = None + + if latest_rails_lts_link: + if latest_rails_lts_link.startswith("/"): + full_url = f"https://makandracards.com{latest_rails_lts_link}" + else: + full_url = latest_rails_lts_link + + detail_response = get(full_url) + if detail_response: + detail_soup = BeautifulSoup(detail_response.text, "html.parser") + + time_tags = detail_soup.find_all( + "time", attrs={"data-relative": "true"} + ) + for time_tag in time_tags: + if "Updated" in time_tag.parent.text: + if "datetime" in time_tag.attrs: + datetime_str = time_tag["datetime"] + try: + date_obj = datetime.strptime( + datetime_str, "%Y-%m-%dT%H:%M:%SZ" + ) + latest_version_release_date = date_obj.strftime( + "%Y-%m-%d" + ) + break + except ValueError: + try: + date_obj = datetime.strptime( + datetime_str, "%Y-%m-%dT%H:%M:%S.%fZ" + ) + latest_version_release_date = date_obj.strftime( + "%Y-%m-%d" + ) + break + except ValueError as e: + print(f"Error parsing datetime: {e}") + + if not latest_version_release_date: + latest_version_release_date = datetime.now().strftime("%Y-%m-%d") + return latest_version, latest_version_release_date + + except Exception as e: + print(f"Error getting Rails LTS information: {str(e)}") + return "Unknown", datetime.now().strftime("%Y-%m-%d") + + +def get_version_release_date(dependency, version): + if dependency == "rails lts": + _, release_date = get_upstream_version(dependency) + return release_date + + try: + response = get(f"{API_V1_ENDPOINT}/{dependency}.json") + if not response: + print(f"Failed to get version info for {dependency}") + return "Unknown" + + version_info = response.json() + for version_data in version_info: + if version_data["number"] == version and "created_at" in version_data: + created_at = version_data["created_at"] + release_date = datetime.strptime( + created_at, "%Y-%m-%dT%H:%M:%S.%fZ" + ).strftime("%Y-%m-%d") + return release_date + except Exception as e: + print(f"Error getting release date for {dependency} {version}: {str(e)}") + + return "Unknown" def get_last_supported_version(bundle_install_output, dependency): """get up-to-date supported version""" pattern = r" ([^\s]+)" - last_supported_version = re.search(dependency + pattern, bundle_install_output, flags=re.I | re.M) + last_supported_version = re.search( + dependency + pattern, bundle_install_output, flags=re.I | re.M + ) return last_supported_version[1] @@ -86,6 +238,7 @@ def isUptodate(last_supported_version, latest_version): return up_to_date + def main(): # Read the JSON file with open(JSON_FILE) as file: @@ -99,23 +252,41 @@ def main(): package = item["Package name"] package = package.lower().replace("::", "-") - latest_version = get_upstream_version(package) - - if not package in ["rails lts", "rails-api"]: - last_supported_version = get_last_supported_version(bundle_install_output, package) + latest_version, release_date = get_upstream_version(package) + if package not in ["rails lts", "rails-api"]: + last_supported_version = get_last_supported_version( + bundle_install_output, package + ) else: last_supported_version = latest_version + last_supported_version_release_date = get_version_release_date( + package, last_supported_version + ) + up_to_date = isUptodate(last_supported_version, latest_version) + days_behind = "0 day/s" + if ( + up_to_date == "No" + and release_date != "Unknown" + and last_supported_version_release_date != "Unknown" + ): + days = estimate_days_behind( + release_date, last_supported_version_release_date + ) + days_behind = f"{days} day/s" + item.update( { "Last Supported Version": last_supported_version, "Latest version": latest_version, "Up-to-date": up_to_date, + "Release date": release_date, + "Latest Version Published At": last_supported_version_release_date, + "Days behind": days_behind, }, ) - # Create a DataFrame from the list of dictionaries df = DataFrame(items) df.insert(len(df.columns) - 1, "Cloud Native", df.pop("Cloud Native")) @@ -132,5 +303,6 @@ def main(): with open(REPORT_FILE, "w") as file: file.write(final_markdown) + if __name__ == "__main__": main() diff --git a/Gemfile b/Gemfile index 981af702..51ac033b 100644 --- a/Gemfile +++ b/Gemfile @@ -19,3 +19,4 @@ gemspec gem "opentelemetry-api", "~> 1.4" gem "rubocop", "~> 1.71" +gem "opentelemetry-common", "~> 0.22.0" diff --git a/instana.gemspec b/instana.gemspec index 3bddc2ea..f8196cad 100644 --- a/instana.gemspec +++ b/instana.gemspec @@ -45,5 +45,6 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency('csv', '>= 0.1') spec.add_runtime_dependency('sys-proctable', '>= 1.2.2') spec.add_runtime_dependency('opentelemetry-api', '~> 1.4') + spec.add_runtime_dependency('opentelemetry-common') spec.add_runtime_dependency('oj', '>=3.0.11') unless RUBY_PLATFORM =~ /java/i end diff --git a/lib/instana/instrumentation/active_job.rb b/lib/instana/instrumentation/active_job.rb index 059805e9..63797a63 100644 --- a/lib/instana/instrumentation/active_job.rb +++ b/lib/instana/instrumentation/active_job.rb @@ -37,7 +37,7 @@ def self.prepended(target) incoming_context = if job.arguments.is_a?(Array) && job.arguments.last.is_a?(Hash) && job.arguments.last.key?(:instana_context) instana_context = job.arguments.last[:instana_context] job.arguments.pop - instana_context ? ::Instana::SpanContext.new(instana_context[:trace_id], instana_context[:span_id]) : nil + instana_context ? ::Instana::SpanContext.new(trace_id: instana_context[:trace_id], span_id: instana_context[:span_id]) : nil end ::Instana::Tracer.start_or_continue_trace(:activejob, tags, incoming_context) do diff --git a/lib/instana/instrumentation/resque.rb b/lib/instana/instrumentation/resque.rb index 0015dc86..73fe9f61 100644 --- a/lib/instana/instrumentation/resque.rb +++ b/lib/instana/instrumentation/resque.rb @@ -78,8 +78,8 @@ def perform(job) trace_context = if ::Instana.config[:'resque-client'][:propagate] && job.payload['args'][-1].is_a?(Hash) && job.payload['args'][-1].keys.include?('trace_id') context_from_wire = job.payload['args'].pop ::Instana::SpanContext.new( - context_from_wire['trace_id'], - context_from_wire['span_id'] + trace_id: context_from_wire['trace_id'], + span_id: context_from_wire['span_id'] ) end diff --git a/lib/instana/trace/span.rb b/lib/instana/trace/span.rb index c91e5ef7..8ccf1e0d 100644 --- a/lib/instana/trace/span.rb +++ b/lib/instana/trace/span.rb @@ -9,8 +9,9 @@ class Span < OpenTelemetry::Trace::Span attr_accessor :parent, :baggage, :is_root, :context - def initialize(name, parent_ctx: nil, start_time: ::Instana::Util.now_in_ms) # rubocop:disable Lint/MissingSuper - @data = {} + def initialize(name, parent_ctx = nil, _context = nil, _parent_span = nil, _kind = nil, _parent_span_id = nil, _span_limits = nil, _span_processors = nil, _attributes = nil, _links = nil, start_timestamp = ::Instana::Util.now_in_ms, _resource = nil, _instrumentation_scope = nil) # rubocop:disable Lint/MissingSuper + @attributes = {} + start_timestamp = ::Instana::Util.now_in_ms # Todo figure out a way to restructure arguments to pass proper timestamp and re-arrange the arguments @ended = false if parent_ctx.is_a?(::Instana::Span) @parent = parent_ctx @@ -22,13 +23,13 @@ def initialize(name, parent_ctx: nil, start_time: ::Instana::Util.now_in_ms) # r # If we have a parent trace, link to it if parent_ctx.trace_id - @data[:t] = parent_ctx.trace_id # Trace ID - @data[:p] = parent_ctx.span_id # Parent ID + @attributes[:t] = parent_ctx.trace_id # Trace ID + @attributes[:p] = parent_ctx.span_id # Parent ID else - @data[:t] = ::Instana::Trace.generate_trace_id + @attributes[:t] = ::Instana::Trace.generate_trace_id end - @data[:s] = ::Instana::Trace.generate_span_id # Span ID + @attributes[:s] = ::Instana::Trace.generate_span_id # Span ID @baggage = parent_ctx.baggage.dup @level = parent_ctx.level @@ -38,34 +39,34 @@ def initialize(name, parent_ctx: nil, start_time: ::Instana::Util.now_in_ms) # r @level = 1 id = ::Instana::Trace.generate_span_id - @data[:t] = id # Trace ID - @data[:s] = id # Span ID + @attributes[:t] = id # Trace ID + @attributes[:s] = id # Span ID end - @data[:data] = {} + @attributes[:data] = {} if ENV.key?('INSTANA_SERVICE_NAME') - @data[:data][:service] = ENV['INSTANA_SERVICE_NAME'] + @attributes[:data][:service] = ENV['INSTANA_SERVICE_NAME'] end # Entity Source - @data[:f] = ::Instana.agent.source + @attributes[:f] = ::Instana.agent.source # Start time - @data[:ts] = if start_time.is_a?(Time) - ::Instana::Util.time_to_ms(start_time) - else - start_time - end + @attributes[:ts] = if start_timestamp.is_a?(Time) + ::Instana::Util.time_to_ms(start_timestamp) + else + start_timestamp + end # Check for custom tracing - if REGISTERED_SPANS.include?(name.to_sym) - @data[:n] = name.to_sym + if REGISTERED_SPANS.include?(name&.to_sym) # Todo remove the safe & operator once all the tests are adapted to new init structure + @attributes[:n] = name.to_sym else configure_custom(name) end ::Instana.processor.on_start(self) - + # super(span_context: context) #Todo check if there is need of parent class methods else this line can be removed # Attach a backtrace to all exit spans add_stack if ::Instana.config[:collect_backtraces] && exit_span? end @@ -78,8 +79,8 @@ def add_stack(limit: 30, stack: Kernel.caller) cleaner = ::Instana.config[:backtrace_cleaner] stack = cleaner.call(stack) if cleaner - @data[:stack] = stack - .map do |call| + @attributes[:stack] = stack + .map do |call| file, line, *method = call.split(':') { @@ -95,13 +96,13 @@ def add_stack(limit: 30, stack: Kernel.caller) # @param e [Exception] The exception to be logged # def record_exception(error) - @data[:error] = true + @attributes[:error] = true - @data[:ec] = if @data.key?(:ec) - @data[:ec] + 1 - else - 1 - end + @attributes[:ec] = if @attributes.key?(:ec) + @attributes[:ec] + 1 + else + 1 + end # If a valid exception has been passed in, log the information about it # In case of just logging an error for things such as HTTP client 5xx @@ -111,10 +112,10 @@ def record_exception(error) add_stack(stack: error.backtrace) end - if HTTP_SPANS.include?(@data[:n]) + if HTTP_SPANS.include?(@attributes[:n]) set_tags(:http => { :error => "#{error.class}: #{error.message}" }) - elsif @data[:n] == :activerecord - @data[:data][:activerecord][:error] = error.message + elsif @attributes[:n] == :activerecord + @attributes[:data][:activerecord][:error] = error.message else log(:error, Time.now, message: error.message, parameters: error.class.to_s) end @@ -133,17 +134,17 @@ def record_exception(error) # @param kvs [Hash] list of key values to be reported in the span # def configure_custom(name) - @data[:n] = :sdk - @data[:data] = { :sdk => { :name => name.to_sym } } - @data[:data][:sdk][:custom] = { :tags => {}, :logs => {} } + @attributes[:n] = :sdk + @attributes[:data] = { :sdk => { :name => name&.to_sym } } # Todo remove safe operator once other tests adapt to new init structure + @attributes[:data][:sdk][:custom] = { :tags => {}, :logs => {} } if @is_root # For custom root spans (via SDK or opentracing), default to entry type - @data[:k] = 1 - @data[:data][:sdk][:type] = :entry + @attributes[:k] = 1 + @attributes[:data][:sdk][:type] = :entry else - @data[:k] = 3 - @data[:data][:sdk][:type] = :intermediate + @attributes[:k] = 3 + @attributes[:data][:sdk][:type] = :intermediate end self end @@ -160,7 +161,7 @@ def close(end_time = ::Instana::Util.now_in_ms) end_time = ::Instana::Util.time_to_ms(end_time) end - @data[:d] = end_time - @data[:ts] + @attributes[:d] = end_time - @attributes[:ts] @ended = true # Add this span to the queue for reporting ::Instana.processor.on_finish(self) @@ -177,35 +178,35 @@ def close(end_time = ::Instana::Util.now_in_ms) # @return [Instana::SpanContext] # def context # rubocop:disable Lint/DuplicateMethods - @context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], @level, @baggage) + @context ||= ::Instana::SpanContext.new(trace_id: @attributes[:t], span_id: @attributes[:s], level: @level, baggage: @baggage) end # Retrieve the ID for this span # # @return [Integer] the span ID def id - @data[:s] + @attributes[:s] end # Retrieve the Trace ID for this span # # @return [Integer] the Trace ID def trace_id - @data[:t] + @attributes[:t] end # Retrieve the parent ID of this span # # @return [Integer] parent span ID def parent_id - @data[:p] + @attributes[:p] end # Set the parent ID of this span # # @return [Integer] parent span ID def parent_id=(id) - @data[:p] = id + @attributes[:p] = id end # Get the name (operation) of this Span @@ -213,9 +214,9 @@ def parent_id=(id) # @return [String] or [Symbol] representing the span name def name if custom? - @data[:data][:sdk][:name] + @attributes[:data][:sdk][:name] else - @data[:n] + @attributes[:n] end end @@ -225,9 +226,9 @@ def name # def name=(name) if custom? - @data[:data][:sdk][:name] = name + @attributes[:data][:sdk][:name] = name else - @data[:n] = name + @attributes[:n] = name end end @@ -235,46 +236,46 @@ def name=(name) # # @return [Integer] the duration in milliseconds def duration - @data[:d] + @attributes[:d] end - # Hash accessor to the internal @data hash + # Hash accessor to the internal @attributes hash # def [](key) - @data[key.to_sym] + @attributes[key.to_sym] end - # Hash setter to the internal @data hash + # Hash setter to the internal @attributes hash # def []=(key, value) - @data[key.to_sym] = value + @attributes[key.to_sym] = value end - # Hash key query to the internal @data hash + # Hash key query to the internal @attributes hash # def key?(key) - @data.key?(key.to_sym) + @attributes.key?(key.to_sym) end - # Get the raw @data hash that summarizes this span + # Get the raw @attributes hash that summarizes this span # def raw - @data + @attributes end # Indicates whether this span is a custom or registered Span def custom? - @data[:n] == :sdk + @attributes[:n] == :sdk end def inspect - @data.inspect + @attributes.inspect end # Check to see if the current span indicates an exit from application # code and into an external service def exit_span? - EXIT_SPANS.include?(@data[:n]) + EXIT_SPANS.include?(@attributes[:n]) end ############################################################# @@ -287,7 +288,7 @@ def exit_span? # @params name [String] or [Symbol] # def operation_name=(name) - @data[:n] = name + @attributes[:n] = name end # Set a tag value on this span @@ -308,27 +309,27 @@ def set_tag(key, value) end if custom? - @data[:data][:sdk][:custom] ||= {} - @data[:data][:sdk][:custom][:tags] ||= {} - @data[:data][:sdk][:custom][:tags][key] = value + @attributes[:data][:sdk][:custom] ||= {} + @attributes[:data][:sdk][:custom][:tags] ||= {} + @attributes[:data][:sdk][:custom][:tags][key] = value if key.to_sym == :'span.kind' case value.to_sym when ENTRY, SERVER, CONSUMER - @data[:data][:sdk][:type] = ENTRY - @data[:k] = 1 + @attributes[:data][:sdk][:type] = ENTRY + @attributes[:k] = 1 when EXIT, CLIENT, PRODUCER - @data[:data][:sdk][:type] = EXIT - @data[:k] = 2 + @attributes[:data][:sdk][:type] = EXIT + @attributes[:k] = 2 else - @data[:data][:sdk][:type] = INTERMEDIATE - @data[:k] = 3 + @attributes[:data][:sdk][:type] = INTERMEDIATE + @attributes[:k] = 3 end end - elsif value.is_a?(Hash) && @data[:data][key].is_a?(Hash) - @data[:data][key].merge!(value) + elsif value.is_a?(Hash) && @attributes[:data][key].is_a?(Hash) + @attributes[:data][key].merge!(value) else - @data[:data][key] = value + @attributes[:data][key] = value end self end @@ -360,7 +361,7 @@ def set_baggage_item(key, value) if @context @context.baggage = @baggage else - @context ||= ::Instana::SpanContext.new(@data[:t], @data[:s], @level, @baggage) + @context ||= ::Instana::SpanContext.new(trace_id: @attributes[:t], span_id: @attributes[:s], level: @level, baggage: @baggage) end self end @@ -379,9 +380,9 @@ def get_baggage_item(key) # def tags(key = nil) tags = if custom? - @data[:data][:sdk][:custom][:tags] + @attributes[:data][:sdk][:custom][:tags] else - @data[:data] + @attributes[:data] end key ? tags[key] : tags end @@ -396,8 +397,8 @@ def tags(key = nil) def log(event = nil, timestamp = Time.now, **fields) ts = ::Instana::Util.time_to_ms(timestamp).to_s if custom? - @data[:data][:sdk][:custom][:logs][ts] = fields - @data[:data][:sdk][:custom][:logs][ts][:event] = event + @attributes[:data][:sdk][:custom][:logs][ts] = fields + @attributes[:data][:sdk][:custom][:logs][ts][:event] = event else set_tags(:log => fields) end @@ -434,8 +435,8 @@ def recording? # # @return [self] returns itself def set_attribute(key, value) - @data ||= {} - @data[key] = value + @attributes ||= {} + @attributes[key] = value self end # alias []= set_attribute @@ -454,8 +455,8 @@ def set_attribute(key, value) # # @return [self] returns itself def add_attributes(attributes) - @data ||= {} - @data.merge!(attributes) + @attributes ||= {} + @attributes.merge!(attributes) self end diff --git a/lib/instana/trace/span_context.rb b/lib/instana/trace/span_context.rb index 451197f2..23500a00 100644 --- a/lib/instana/trace/span_context.rb +++ b/lib/instana/trace/span_context.rb @@ -2,7 +2,7 @@ # (c) Copyright Instana Inc. 2017 module Instana - class SpanContext + class SpanContext < OpenTelemetry::Trace::SpanContext attr_accessor :trace_id, :span_id, :baggage attr_reader :level @@ -13,9 +13,20 @@ class SpanContext # @param level [Integer] default 1 # @param baggage [Hash] baggage applied to this trace # - def initialize(tid, sid, level = 1, baggage = {}) - @trace_id = tid - @span_id = sid + def initialize( + trace_id: Trace.generate_trace_id, + span_id: Trace.generate_span_id, + trace_flags: nil, # Todo - implement traceflags + tracestate: nil, # Todo - implement tracestates + remote: false, + level: 1, + baggage: {} + ) + @trace_id = trace_id + @span_id = span_id + @trace_flags = trace_flags + @tracestate = tracestate + @remote = remote @level = Integer(level || 1) @baggage = baggage || {} end diff --git a/lib/instana/trace/span_limits.rb b/lib/instana/trace/span_limits.rb index 97f1fa4f..5a4fe15f 100644 --- a/lib/instana/trace/span_limits.rb +++ b/lib/instana/trace/span_limits.rb @@ -1,63 +1,63 @@ # (c) Copyright IBM Corp. 2025 -module OpenTelemetry - module SDK - module Trace - # Class that holds global trace parameters. - class SpanLimits - # The global default max number of attributes per {Span}. - attr_reader :attribute_count_limit - - # The global default max length of attribute value per {Span}. - attr_reader :attribute_length_limit - - # The global default max number of {OpenTelemetry::SDK::Trace::Event}s per {Span}. - attr_reader :event_count_limit - - # The global default max number of {OpenTelemetry::Trace::Link} entries per {Span}. - attr_reader :link_count_limit - - # The global default max number of attributes per {OpenTelemetry::SDK::Trace::Event}. - attr_reader :event_attribute_count_limit - - # The global default max length of attribute value per {OpenTelemetry::SDK::Trace::Event}. - attr_reader :event_attribute_length_limit - - # The global default max number of attributes per {OpenTelemetry::Trace::Link}. - attr_reader :link_attribute_count_limit - - # Returns a {SpanLimits} with the desired values. - # - # @return [SpanLimits] with the desired values. - # @raise [ArgumentError] if any of the max numbers are not positive. - def initialize(attribute_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT', 'OTEL_ATTRIBUTE_COUNT_LIMIT', default: 128)), # rubocop:disable Metrics/ParameterLists - attribute_length_limit: OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT', 'OTEL_RUBY_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT', - 'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT'), - event_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_EVENT_COUNT_LIMIT', default: 128)), - link_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_LINK_COUNT_LIMIT', default: 128)), - event_attribute_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT', default: 128)), - event_attribute_length_limit: OpenTelemetry::Common::Utilities.config_opt('OTEL_EVENT_ATTRIBUTE_VALUE_LENGTH_LIMIT', 'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT'), - link_attribute_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_LINK_ATTRIBUTE_COUNT_LIMIT', default: 128))) - raise ArgumentError, 'attribute_count_limit must be positive' unless attribute_count_limit.positive? - raise ArgumentError, 'attribute_length_limit must not be less than 32' unless attribute_length_limit.nil? || Integer(attribute_length_limit) >= 32 - raise ArgumentError, 'event_count_limit must be positive' unless event_count_limit.positive? - raise ArgumentError, 'link_count_limit must be positive' unless link_count_limit.positive? - raise ArgumentError, 'event_attribute_count_limit must be positive' unless event_attribute_count_limit.positive? - raise ArgumentError, 'event_attribute_length_limit must not be less than 32' unless event_attribute_length_limit.nil? || Integer(event_attribute_length_limit) >= 32 - raise ArgumentError, 'link_attribute_count_limit must be positive' unless link_attribute_count_limit.positive? - - @attribute_count_limit = attribute_count_limit - @attribute_length_limit = attribute_length_limit.nil? ? nil : Integer(attribute_length_limit) - @event_count_limit = event_count_limit - @link_count_limit = link_count_limit - @event_attribute_count_limit = event_attribute_count_limit - @event_attribute_length_limit = event_attribute_length_limit.nil? ? nil : Integer(event_attribute_length_limit) - @link_attribute_count_limit = link_attribute_count_limit - end - - # The default {SpanLimits}. - DEFAULT = new +require 'opentelemetry-common' + +module Instana + module Trace + # Class that holds global trace parameters. + class SpanLimits + # The global default max number of attributes per {Span}. + attr_reader :attribute_count_limit + + # The global default max length of attribute value per {Span}. + attr_reader :attribute_length_limit + + # The global default max number of {OpenTelemetry::SDK::Trace::Event}s per {Span}. + attr_reader :event_count_limit + + # The global default max number of {OpenTelemetry::Trace::Link} entries per {Span}. + attr_reader :link_count_limit + + # The global default max number of attributes per {OpenTelemetry::SDK::Trace::Event}. + attr_reader :event_attribute_count_limit + + # The global default max length of attribute value per {OpenTelemetry::SDK::Trace::Event}. + attr_reader :event_attribute_length_limit + + # The global default max number of attributes per {OpenTelemetry::Trace::Link}. + attr_reader :link_attribute_count_limit + + # Returns a {SpanLimits} with the desired values. + # + # @return [SpanLimits] with the desired values. + # @raise [ArgumentError] if any of the max numbers are not positive. + def initialize(attribute_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT', 'OTEL_ATTRIBUTE_COUNT_LIMIT', default: 128)), # rubocop:disable Metrics/ParameterLists + attribute_length_limit: OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT', 'OTEL_RUBY_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT', + 'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT'), + event_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_EVENT_COUNT_LIMIT', default: 128)), + link_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_LINK_COUNT_LIMIT', default: 128)), + event_attribute_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT', default: 128)), + event_attribute_length_limit: OpenTelemetry::Common::Utilities.config_opt('OTEL_EVENT_ATTRIBUTE_VALUE_LENGTH_LIMIT', 'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT'), + link_attribute_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_LINK_ATTRIBUTE_COUNT_LIMIT', default: 128))) + raise ArgumentError, 'attribute_count_limit must be positive' unless attribute_count_limit.positive? + raise ArgumentError, 'attribute_length_limit must not be less than 32' unless attribute_length_limit.nil? || Integer(attribute_length_limit) >= 32 + raise ArgumentError, 'event_count_limit must be positive' unless event_count_limit.positive? + raise ArgumentError, 'link_count_limit must be positive' unless link_count_limit.positive? + raise ArgumentError, 'event_attribute_count_limit must be positive' unless event_attribute_count_limit.positive? + raise ArgumentError, 'event_attribute_length_limit must not be less than 32' unless event_attribute_length_limit.nil? || Integer(event_attribute_length_limit) >= 32 + raise ArgumentError, 'link_attribute_count_limit must be positive' unless link_attribute_count_limit.positive? + + @attribute_count_limit = attribute_count_limit + @attribute_length_limit = attribute_length_limit.nil? ? nil : Integer(attribute_length_limit) + @event_count_limit = event_count_limit + @link_count_limit = link_count_limit + @event_attribute_count_limit = event_attribute_count_limit + @event_attribute_length_limit = event_attribute_length_limit.nil? ? nil : Integer(event_attribute_length_limit) + @link_attribute_count_limit = link_attribute_count_limit end + + # The default {SpanLimits}. + DEFAULT = new end end end diff --git a/lib/instana/trace/tracer.rb b/lib/instana/trace/tracer.rb index ce0b5cfc..e1d6acce 100644 --- a/lib/instana/trace/tracer.rb +++ b/lib/instana/trace/tracer.rb @@ -3,6 +3,7 @@ require 'opentelemetry/trace/tracer' require 'instana/trace/span' require "instana/trace/span_context" +require 'opentelemetry/context' module Instana class Tracer < OpenTelemetry::Trace::Tracer @@ -103,10 +104,10 @@ def log_start_or_continue(name, kvs = {}, incoming_context = nil) if incoming_context.is_a?(Hash) unless incoming_context.empty? parent_context = SpanContext.new( - incoming_context[:trace_id], - incoming_context[:span_id], - incoming_context[:level], - { + trace_id: incoming_context[:trace_id], + span_id: incoming_context[:span_id], + level: incoming_context[:level], + baggage: { external_trace_id: incoming_context[:external_trace_id], external_state: incoming_context[:external_state] } @@ -118,7 +119,7 @@ def log_start_or_continue(name, kvs = {}, incoming_context = nil) end self.current_span = if parent_context - Span.new(name, parent_ctx: parent_context) + Span.new(name, parent_context) else Span.new(name) end @@ -133,13 +134,13 @@ def log_start_or_continue(name, kvs = {}, incoming_context = nil) # @param name [String, Symbol] the name of the span to create # @param kvs [Hash] list of key values to be reported in the span # - def log_entry(name, kvs = nil, start_time = ::Instana::Util.now_in_ms, child_of = nil) + def log_entry(name, kvs = nil, _start_time = ::Instana::Util.now_in_ms, child_of = nil) return unless tracing? || child_of new_span = if child_of.nil? && !current_span.nil? - Span.new(name, parent_ctx: current_span, start_time: start_time) + Span.new(name, current_span) else - Span.new(name, parent_ctx: child_of, start_time: start_time) + Span.new(name, child_of) end new_span.set_tags(kvs) if kvs self.current_span = new_span @@ -223,7 +224,7 @@ def log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms) def log_async_entry(name, kvs) return unless tracing? - new_span = Span.new(name, parent_ctx: current_span) + new_span = Span.new(name, current_span) new_span.set_tags(kvs) unless kvs.empty? new_span end @@ -305,5 +306,13 @@ def context def clear! self.current_span = nil end + + def start_span(name, with_parent: nil, attributes: nil, links: nil, start_timestamp: nil, kind: nil) + with_parent ||= OpenTelemetry::Context.current + name ||= 'empty' + kind ||= :internal + + @tracer_provider.internal_start_span(name, kind, attributes, links, start_timestamp, with_parent, @instrumentation_scope) + end end end diff --git a/lib/instana/trace/tracer_provider.rb b/lib/instana/trace/tracer_provider.rb index e11bc02d..b4a04389 100644 --- a/lib/instana/trace/tracer_provider.rb +++ b/lib/instana/trace/tracer_provider.rb @@ -2,6 +2,7 @@ require 'opentelemetry/trace/tracer_provider' require 'instana/samplers' +require 'instana/trace/span_limits' module Instana module Trace @@ -32,7 +33,7 @@ class TracerProvider < OpenTelemetry::Trace::TracerProvider def initialize(sampler: sampler_from_environment(Samplers.parent_based(root: Samplers::ALWAYS_ON)), resource: nil, # Instana::Resources::Resource.create id_generator: ::Instana::Trace, - span_limits: nil) # SpanLimits::DEFAULT) + span_limits: SpanLimits::DEFAULT) super() @mutex = Mutex.new @registry = {} @@ -130,10 +131,10 @@ def add_span_processor(span_processor) # @api private def internal_start_span(name, kind, attributes, links, start_timestamp, parent_context, instrumentation_scope) # rubocop:disable Metrics/ParameterLists - parent_span = Instana::Trace.current_span(parent_context) - parent_span_context = parent_span.context + parent_span = Instana.tracer.current_span + parent_span_context = parent_span.context if parent_span - if parent_span_context.valid? + if parent_span_context&.valid? parent_span_id = parent_span_context.span_id trace_id = parent_span_context.trace_id end @@ -143,28 +144,28 @@ def internal_start_span(name, kind, attributes, links, start_timestamp, parent_c span_id = parent_span_id || @id_generator.generate_span_id return OpenTelemetry::Trace.non_recording_span(OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id)) end - - result = @sampler.should_sample?(trace_id: trace_id, parent_context: parent_context, links: links, name: name, kind: kind, attributes: attributes) + # Todo add dummy samplers to always turn off sampling, also enable the user to send cutom samplers + # result = @sampler.should_sample?(trace_id: trace_id, parent_context: parent_context, links: links, name: name, kind: kind, attributes: attributes) span_id = @id_generator.generate_span_id - if result.recording? && !@stopped - trace_flags = result.sampled? ? OpenTelemetry::Trace::TraceFlags::SAMPLED : OpenTelemetry::Trace::TraceFlags::DEFAULT - context = OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id, trace_flags: trace_flags, tracestate: result.tracestate) - attributes = attributes&.merge(result.attributes) || result.attributes.dup - Span.new( - context, - parent_context, - parent_span, - name, - kind, - parent_span_id, - @span_limits, - @span_processors, - attributes, - links, - start_timestamp, - @resource, - instrumentation_scope - ) + if !@stopped # && result.recording? && + trace_flags = OpenTelemetry::Trace::TraceFlags::SAMPLED # Todo Add InstanaTraceFlags module + Instana::SpanContext.new(trace_id: trace_id, span_id: span_id) # trace_flags: trace_flags#, tracestate: result.tracestate) + # attributes = attributes&.merge(result.attributes) || result.attributes.dup + Instana::Span.new( + name, + parent_context, + context, + parent_span, + kind, + parent_span_id, + @span_limits, + @span_processors, + attributes, + links, + start_timestamp, + @resource, + instrumentation_scope + ) else Instana::Trace.non_recording_span(OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id, tracestate: result.tracestate)) end diff --git a/lib/instana/tracer.rb b/lib/instana/tracer.rb deleted file mode 100644 index 9ef3e35d..00000000 --- a/lib/instana/tracer.rb +++ /dev/null @@ -1,304 +0,0 @@ -# (c) Copyright IBM Corp. 2021 -# (c) Copyright Instana Inc. 2016 - -require "instana/tracing/span" -require "instana/tracing/span_context" - -module Instana - class Tracer - # Support ::Instana::Tracer.xxx call style for the instantiated tracer - class << self - def method_missing(method, *args, &block) - if ::Instana.tracer.respond_to?(method) - ::Instana.tracer.send(method, *args, &block) - else - super - end - end - end - - def initialize(logger: Instana.logger) - @current_span = Concurrent::ThreadLocalVar.new - @logger = logger - end - - # @return [Instana::Span, NilClass] the current active span or nil if we are not tracing - def current_span - @current_span.value - end - - # @param [Instana::Span, NilClas] v the new current span - # Set the value of the current span - def current_span=(v) - @current_span.value = v - end - - ####################################### - # Tracing blocks API methods - ####################################### - - # Will start a new trace or continue an on-going one (such as - # from incoming remote requests with context headers). - # - # @param name [String, Symbol] the name of the span to start - # @param kvs [Hash] list of key values to be reported in the span - # @param incoming_context [Hash] specifies the incoming context. At a - # minimum, it should specify :trace_id and :span_id from the following: - # @:trace_id the trace ID (must be an unsigned hex-string) - # :span_id the ID of the parent span (must be an unsigned hex-string) - # :level specifies data collection level (optional) - # - def start_or_continue_trace(name, kvs = {}, incoming_context = nil, &block) - span = log_start_or_continue(name, kvs, incoming_context) - yield(span) - rescue Exception => e - log_error(e) - raise - ensure - log_end(name) - end - - # Trace a block of code within the context of the exiting trace - # - # Example usage: - # - # ::Instana.tracer.trace(:dbwork, { :db_name => @db.name }) do - # @db.select(1) - # end - # - # @param name [String, Symbol] the name of the span to start - # @param kvs [Hash] list of key values to be reported in this new span - # - def trace(name, kvs = {}, &block) - span = log_entry(name, kvs) - yield(span) - rescue Exception => e - log_error(e) - raise - ensure - log_exit(name) - end - - ####################################### - # Lower level tracing API methods - ####################################### - - # Will start a new trace or continue an on-going one (such as - # from incoming remote requests with context headers). - # - # @param name [String, Symbol] the name of the span to start - # @param kvs [Hash] list of key values to be reported in the span - # @param incoming_context [SpanContext or Hash] specifies the incoming context. At a - # minimum, it should specify :trace_id and :span_id from the following: - # :trace_id the trace ID (must be an unsigned hex-string) - # :span_id the ID of the parent span (must be an unsigned hex-string) - # :level specifies data collection level (optional) - # - def log_start_or_continue(name, kvs = {}, incoming_context = nil) - return if !::Instana.agent.ready? || !::Instana.config[:tracing][:enabled] - - # Handle the potential variations on `incoming_context` - if incoming_context - if incoming_context.is_a?(Hash) - if !incoming_context.empty? - parent_context = SpanContext.new( - incoming_context[:trace_id], - incoming_context[:span_id], - incoming_context[:level], - { - external_trace_id: incoming_context[:external_trace_id], - external_state: incoming_context[:external_state] - } - ) - end - else - parent_context = incoming_context - end - end - - if parent_context - self.current_span = Span.new(name, parent_ctx: parent_context) - else - self.current_span = Span.new(name) - end - - self.current_span.set_tags(kvs) unless kvs.empty? - self.current_span - end - - # Will establish a new span as a child of the current span - # in an existing trace - # - # @param name [String, Symbol] the name of the span to create - # @param kvs [Hash] list of key values to be reported in the span - # - def log_entry(name, kvs = nil, start_time = ::Instana::Util.now_in_ms, child_of = nil) - return unless tracing? || child_of - - new_span = if child_of.nil? && !self.current_span.nil? - Span.new(name, parent_ctx: self.current_span, start_time: start_time) - else - Span.new(name, parent_ctx: child_of, start_time: start_time) - end - new_span.set_tags(kvs) if kvs - self.current_span = new_span - end - - # Add info to the current span - # - # @param kvs [Hash] list of key values to be reported in the span - # - def log_info(kvs) - return unless self.current_span - self.current_span.set_tags(kvs) - end - - # Add an error to the current span - # - # @param e [Exception] Add exception to the current span - # - def log_error(e) - return unless self.current_span - self.current_span.add_error(e) - end - - # Closes out the current span - # - # @note `name` isn't really required but helps keep sanity that - # we're closing out the span that we really want to close out. - # - # @param name [String, Symbol] the name of the span to exit (close out) - # @param kvs [Hash] list of key values to be reported in the span - # - def log_exit(name, kvs = {}) - return unless self.current_span - - if self.current_span.name != name - @logger.warn "Span mismatch: Attempt to end #{name} span but #{self.current_span.name} is active." - end - - self.current_span.set_tags(kvs) - self.current_span.close - - self.current_span = self.current_span.parent || nil - end - - # Closes out the current span in the current trace - # and queues the trace for reporting - # - # @note `name` isn't really required but helps keep sanity that - # we're ending the span that we really want to close out. - # - # @param name [String] the name of the span to end - # @param kvs [Hash] list of key values to be reported in the span - # - def log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms) - return unless self.current_span - - if self.current_span.name != name - @logger.warn "Span mismatch: Attempt to end #{name} span but #{self.current_span.name} is active." - end - - self.current_span.set_tags(kvs) - self.current_span.close(end_time) - self.current_span = nil - end - - ########################################################################### - # Asynchronous API methods - ########################################################################### - - # Starts a new asynchronous span on the current trace. - # - # @param name [String] the name of the span to create - # @param kvs [Hash] list of key values to be reported in the span - # - # @return [Hash] the context: Trace ID and Span ID in the form of - # :trace_id => 12345 - # :span_id => 12345 - # - def log_async_entry(name, kvs) - return unless tracing? - - new_span = Span.new(name, parent_ctx: self.current_span) - new_span.set_tags(kvs) unless kvs.empty? - new_span - end - - # Add info to an asynchronous span - # - # @param kvs [Hash] list of key values to be reported in the span - # @param span [Span] the span for this Async op (previously returned from `log_async_entry`) - # - def log_async_info(kvs, span) - span.set_tags(kvs) - end - - # Add an error to an asynchronous span - # - # @param e [Exception] Add exception to the current span - # @param span [Span] the span for this Async op (previously returned from `log_async_entry`) - # - def log_async_error(e, span) - span.add_error(e) - end - - # Closes out an asynchronous span - # - # @param name [String] the name of the async span to exit (close out) - # @param kvs [Hash] list of additional key/values to be reported in the span (or use {}) - # @param span [Span] the span for this Async op (previously returned from `log_async_entry`) - # - def log_async_exit(_name, kvs, span) - span.set_tags(kvs) unless kvs.empty? - span.close - end - - ########################################################################### - # Helper methods - ########################################################################### - - # Indicates if we're are currently in the process of - # collecting a trace. This is false when the host agent isn - # available. - # - # @return [Boolean] true or false on whether we are currently tracing or not - # - def tracing? - # The non-nil value of this instance variable - # indicates if we are currently tracing - # in this thread or not. - (self.current_span ? true : false) || - (::Instana.config[:allow_exit_as_root] && ::Instana.config[:tracing][:enabled]) - end - - # Indicates if we're tracing and the current span name matches - # - # - # @param name [Symbol] the name to check against the current span - # - # @return [Boolean] - # - def tracing_span?(name) - if self.current_span - return self.current_span.name == name - end - false - end - - # Retrieve the current context of the tracer. - # - # @return [SpanContext] or nil if not tracing - # - def context - return unless self.current_span - self.current_span.context - end - - # Used in the test suite, this resets the tracer to non-tracing state. - # - def clear! - self.current_span = nil - end - end -end diff --git a/test/instrumentation/rails_action_cable_test.rb b/test/instrumentation/rails_action_cable_test.rb index aad59a00..9dba00b4 100644 --- a/test/instrumentation/rails_action_cable_test.rb +++ b/test/instrumentation/rails_action_cable_test.rb @@ -42,7 +42,7 @@ def test_transmit_parent connection = mock_connection connection.instance_variable_set( :@instana_trace_context, - Instana::SpanContext.new('ABC', 'ABC') + Instana::SpanContext.new(trace_id: 'ABC', span_id: 'ABC') ) channel_klass = Class.new(ActionCable::Channel::Base) @@ -95,7 +95,7 @@ def test_action_parent connection = mock_connection connection.instance_variable_set( :@instana_trace_context, - Instana::SpanContext.new('ABC', 'ABC') + Instana::SpanContext.new(trace_id: 'ABC', span_id: 'ABC') ) channel_klass = Class.new(ActionCable::Channel::Base) do def sample diff --git a/test/tracing/processor_test.rb b/test/tracing/processor_test.rb index e8801b2f..6b034c85 100644 --- a/test/tracing/processor_test.rb +++ b/test/tracing/processor_test.rb @@ -13,8 +13,8 @@ def test_queued_spans_valid_level clear_all! subject = Instana::Processor.new - span_context = Instana::SpanContext.new('9', '8', 0) - span = Instana::Span.new(:rack, parent_ctx: span_context) + span_context = Instana::SpanContext.new(trace_id: '9', span_id: '8', level: 0) + span = Instana::Span.new(:rack, span_context) span2 = Instana::Span.new(:"net-http") subject.on_finish(span) diff --git a/test/tracing/span_context_test.rb b/test/tracing/span_context_test.rb index 46a6d5dd..f275f5e3 100644 --- a/test/tracing/span_context_test.rb +++ b/test/tracing/span_context_test.rb @@ -5,17 +5,17 @@ class SpanContextTest < Minitest::Test def test_to_hash - subject = Instana::SpanContext.new('trace', 'span') + subject = Instana::SpanContext.new(trace_id: 'trace', span_id: 'span') assert_equal({trace_id: 'trace', span_id: 'span'}, subject.to_hash) end def test_invalid - subject = Instana::SpanContext.new(nil, nil) + subject = Instana::SpanContext.new(trace_id: nil, span_id: nil) refute subject.valid? end def test_flags_level_zero - subject = Instana::SpanContext.new('trace', 'span', 0, {external_state: 'cn=test'}) + subject = Instana::SpanContext.new(trace_id: 'trace', span_id: 'span', level: 0, baggage: {external_state: 'cn=test'}) assert_equal '00-000000000000000000000000000trace-000000000000span-00', subject.trace_parent_header assert_equal 'cn=test', subject.trace_state_header end diff --git a/test/tracing/span_test.rb b/test/tracing/span_test.rb index 20d474b2..e3d21593 100644 --- a/test/tracing/span_test.rb +++ b/test/tracing/span_test.rb @@ -39,15 +39,15 @@ def test_exit_span end def test_span_from_contetx - context = Instana::SpanContext.new('test', 'test', 0) - span = Instana::Span.new(:test, parent_ctx: context) + context = Instana::SpanContext.new(trace_id: 'test', span_id: 'test', level: 0) + span = Instana::Span.new(:test, context) assert_equal 'test', span.parent_id assert_equal 'test', span.trace_id end def test_span_from_contetx_invalid - context = Instana::SpanContext.new(nil, nil, 1) + context = Instana::SpanContext.new(trace_id: nil, span_id: nil, level: 1) span = Instana::Span.new(:test, parent_ctx: context) assert_nil span.parent_id diff --git a/test/tracing/tracer_provider_test.rb b/test/tracing/tracer_provider_test.rb index 0ecda9ce..229917e6 100644 --- a/test/tracing/tracer_provider_test.rb +++ b/test/tracing/tracer_provider_test.rb @@ -13,4 +13,11 @@ def test_tracer # This tests the global tracer is the same as tracer from tracer_provider assert_equal Instana.tracer, @tracer_provider.tracer("instana_tracer") end + + def test_donot_commit + # span = Instana.tracer_provider.tracer("instana_tracer").in_span("sdk") do + # print("abc") + # end + # Instana.processor + end end diff --git a/test/tracing/tracer_test.rb b/test/tracing/tracer_test.rb index da30ba27..ca935ba9 100644 --- a/test/tracing/tracer_test.rb +++ b/test/tracing/tracer_test.rb @@ -337,7 +337,7 @@ def test_log_entry_span_context clear_all! subject = Instana::Tracer.new(nil, nil, nil) - span_context = Instana::SpanContext.new('test', 'test') + span_context = Instana::SpanContext.new(trace_id: 'test', span_id: 'test') subject.log_entry(:sample, {}, ::Instana::Util.now_in_ms, span_context) assert subject.tracing?