diff --git a/lib/datadog/ci.rb b/lib/datadog/ci.rb
index 55c14c74..2d56b52d 100644
--- a/lib/datadog/ci.rb
+++ b/lib/datadog/ci.rb
@@ -10,33 +10,179 @@ module Datadog
# @public_api
module CI
class << self
- # Trace a test run
+ # Return a {Datadog::CI::Test ci_test} that will trace a test called `test_name`.
+ #
+ # 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
- # Start a test run trace.
+ # Same as {#trace_test} but it does not accept a block.
+ #
+ # 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
+ # 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
diff --git a/lib/datadog/ci/span.rb b/lib/datadog/ci/span.rb
index 7dbfb4e0..19e45a85 100644
--- a/lib/datadog/ci/span.rb
+++ b/lib/datadog/ci/span.rb
@@ -3,7 +3,6 @@
require_relative "ext/test"
module Datadog
- # Public API for Datadog CI visibility
module CI
# Represents a single part of a test run.
# Could be a session, suite, test, or any custom span.
@@ -16,46 +15,73 @@ def initialize(tracer_span)
@tracer_span = tracer_span
end
+ # @return [String] the name of the span.
def name
tracer_span.name
end
+ # @return [String] the type of the span (for example "test" or type that was provided to [Datadog::CI.trace]).
+ def span_type
+ tracer_span.type
+ end
+
+ # Sets the status of the span to "pass".
+ # @return [void]
def passed!
tracer_span.set_tag(Ext::Test::TAG_STATUS, Ext::Test::Status::PASS)
end
+ # Sets the status of the span to "fail".
+ # @param [Exception] exception the exception that caused the test to fail.
+ # @return [void]
def failed!(exception: nil)
tracer_span.status = 1
tracer_span.set_tag(Ext::Test::TAG_STATUS, Ext::Test::Status::FAIL)
tracer_span.set_error(exception) unless exception.nil?
end
+ # Sets the status of the span to "skip".
+ # @param [Exception] exception the exception that caused the test to fail.
+ # @param [String] reason the reason why the test was skipped.
+ # @return [void]
def skipped!(exception: nil, reason: nil)
tracer_span.set_tag(Ext::Test::TAG_STATUS, Ext::Test::Status::SKIP)
tracer_span.set_error(exception) unless exception.nil?
tracer_span.set_tag(Ext::Test::TAG_SKIP_REASON, reason) unless reason.nil?
end
+ # Gets tag value by key.
+ # @param [String] key the key of the tag.
+ # @return [String] the value of the tag.
def get_tag(key)
tracer_span.get_tag(key)
end
+ # Sets tag value by key.
+ # @param [String] key the key of the tag.
+ # @param [String] value the value of the tag.
+ # @return [void]
def set_tag(key, value)
tracer_span.set_tag(key, value)
end
+ # Sets metric value by key.
+ # @param [String] key the key of the metric.
+ # @param [Numeric] value the value of the metric.
+ # @return [void]
def set_metric(key, value)
tracer_span.set_metric(key, value)
end
+ # Finishes the span.
+ # @return [void]
def finish
tracer_span.finish
end
- def span_type
- tracer_span.type
- end
-
+ # Sets multiple tags at once.
+ # @param [Hash[String, String]] tags the tags to set.
+ # @return [void]
def set_tags(tags)
tags.each do |key, value|
tracer_span.set_tag(key, value)
diff --git a/lib/datadog/ci/test.rb b/lib/datadog/ci/test.rb
index 2ab77b62..6cf43de2 100644
--- a/lib/datadog/ci/test.rb
+++ b/lib/datadog/ci/test.rb
@@ -4,16 +4,23 @@
module Datadog
module CI
+ # Represents a single part of a test run.
+ # Could be a session, suite, test, or any custom span.
+ #
+ # @public_api
class Test < Span
+ # @return [String] the name of the test.
+ def name
+ get_tag(Ext::Test::TAG_NAME)
+ end
+
+ # Finishes the current test.
+ # @return [void]
def finish
super
CI.deactivate_test(self)
end
-
- def name
- get_tag(Ext::Test::TAG_NAME)
- end
end
end
end