# frozen_string_literal: true require_relative "ci/version" require "datadog/core" module Datadog # Datadog CI visibility public API. # # @public_api module CI class << self # Return a {Datadog::CI::Test ci_test} that will trace a test called `test_name`. # Raises an error if a test is already active. # # You could trace your test using a do-block like: # # ``` # Datadog::CI.trace_test( # "test_add_two_numbers", # service_name: "my-web-site-tests", # operation_name: "test", # tags: { Datadog::CI::Ext::Test::TAG_FRAMEWORK => "my-test-framework" } # ) do |ci_test| # result = run_test # # if result.ok? # ci_test.passed! # else # ci_test.failed!(exception: result.exception) # end # end # ``` # # The {#trace_test} method can also be used without a block in this way: # ``` # ci_test = Datadog::CI.trace_test( # "test_add_two_numbers', # service: "my-web-site-tests", # operation_name: "test", # tags: { Datadog::CI::Ext::Test::TAG_FRAMEWORK => "my-test-framework" } # ) # run_test # ci_test.finish # ``` # # Remember that in this case, calling {Datadog::CI::Test#finish} is mandatory. # # @param [String] test_name {Datadog::CI::Test} name (example: "test_add_two_numbers"). # @param [String] operation_name defines label for a test span in trace view ("test" if it's missing) # @param [String] service_name the service name for this test # @param [Hash] tags extra tags which should be added to the test. # @return [Object] If a block is provided, returns the result of the block execution. # @return [Datadog::CI::Test] If no block is provided, returns the active, # unfinished {Datadog::CI::Test}. # @yield Optional block where new newly created {Datadog::CI::Test} captures the execution. # @yieldparam [Datadog::CI::Test] ci_test the newly created and active [Datadog::CI::Test] # # @public_api def trace_test(test_name, service_name: nil, operation_name: "test", tags: {}, &block) recorder.trace_test(test_name, service_name: service_name, operation_name: operation_name, tags: tags, &block) end # Same as {#trace_test} but it does not accept a block. # Raises an error if a test is already active. # # Usage: # # ``` # ci_test = Datadog::CI.start_test( # "test_add_two_numbers', # service: "my-web-site-tests", # operation_name: "test", # tags: { Datadog::CI::Ext::Test::TAG_FRAMEWORK => "my-test-framework" } # ) # run_test # ci_test.finish # ``` # # @param [String] test_name {Datadog::CI::Test} name (example: "test_add_two_numbers"). # @param [String] operation_name the resource this span refers, or `test` if it's missing # @param [String] service_name the service name for this span. # @param [Hash] tags extra tags which should be added to the test. # @return [Datadog::CI::Test] Returns the active, unfinished {Datadog::CI::Test}. # # @public_api def start_test(test_name, service_name: nil, operation_name: "test", tags: {}) recorder.trace_test(test_name, service_name: service_name, operation_name: operation_name, tags: tags) end # Trace any custom span inside a test. For example, you could trace: # - cucumber step # - database query # - any custom operation you want to see in your trace view # # You can use thi method with a do-block like: # # ``` # Datadog::CI.trace( # "step", # "Given I have 42 cucumbers", # tags: {} # ) do # run_operation # end # ``` # # The {#trace} method can also be used without a block in this way: # ``` # ci_span = Datadog::CI.trace( # "step", # "Given I have 42 cucumbers", # tags: {} # ) # run_test # ci_span.finish # ``` # Remember that in this case, calling {Datadog::CI::Span#finish} is mandatory. # # @param [String] span_type custom, user-defined span type (for example "step" or "query"). # @param [String] span_name the resource this span refers, or `test` if it's missing # @param [Hash] tags extra tags which should be added to the span. # @return [Object] If a block is provided, returns the result of the block execution. # @return [Datadog::CI::Span] If no block is provided, returns the active, # unfinished {Datadog::CI::Span}. # @yield Optional block where new newly created {Datadog::CI::Span} captures the execution. # @yieldparam [Datadog::CI::Span] ci_span the newly created and active [Datadog::CI::Span] # # @public_api def trace(span_type, span_name, tags: {}, &block) recorder.trace(span_type, span_name, tags: tags, &block) end # The active, unfinished custom span if it matches given type. # If no span is active, or if the active span is not a custom span with given type, returns nil. # # The active span belongs to an {.active_test}. # # Usage: # # ``` # # start span # Datadog::CI.trace( # "step", # "Given I have 42 cucumbers", # tags: {} # ) # # # somewhere else, access the active "step" span # step_span = Datadog::CI.active_span("step") # step_span.finish() # ``` # # @param [String] span_type type of the span to retrieve (for example "step" or "query") that was provided to {.trace} # @return [Datadog::CI::Span] the active span # @return [nil] if no span is active, or if the active span is not a custom span with given type def active_span(span_type) span = recorder.active_span span if span && span.span_type == span_type end # The active, unfinished test span. # # Usage: # # ``` # # start a test # Datadog::CI.start_test( # "test_add_two_numbers', # service: "my-web-site-tests", # operation_name: "test", # tags: { Datadog::CI::Ext::Test::TAG_FRAMEWORK => "my-test-framework" } # ) # # # somewhere else, access the active test # test_span = Datadog::CI.active_test # test_span.passed! # test_span.finish # ``` # # @return [Datadog::CI::Test] the active test # @return [nil] if no test is active def active_test recorder.active_test end # Internal only, to finish a test use Datadog::CI::Test#finish def deactivate_test(test) recorder.deactivate_test(test) end private def components Datadog.send(:components) end def recorder components.ci_recorder end end end end # Integrations require_relative "ci/contrib/cucumber/integration" require_relative "ci/contrib/rspec/integration" require_relative "ci/contrib/minitest/integration" # Extensions require_relative "ci/extensions" Datadog::CI::Extensions.activate!