datadog-ci 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -1
  3. data/LICENSE-3rdparty.csv +1 -0
  4. data/README.md +64 -0
  5. data/lib/datadog/ci/configuration/components.rb +72 -5
  6. data/lib/datadog/ci/configuration/settings.rb +36 -8
  7. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +2 -3
  8. data/lib/datadog/ci/contrib/cucumber/formatter.rb +8 -10
  9. data/lib/datadog/ci/contrib/cucumber/integration.rb +3 -5
  10. data/lib/datadog/ci/contrib/integration.rb +149 -0
  11. data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +2 -3
  12. data/lib/datadog/ci/contrib/minitest/hooks.rb +8 -4
  13. data/lib/datadog/ci/contrib/minitest/integration.rb +3 -5
  14. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +2 -3
  15. data/lib/datadog/ci/contrib/rspec/example.rb +5 -8
  16. data/lib/datadog/ci/contrib/rspec/integration.rb +3 -5
  17. data/lib/datadog/ci/contrib/settings.rb +33 -0
  18. data/lib/datadog/ci/ext/environment/providers/appveyor.rb +4 -0
  19. data/lib/datadog/ci/ext/environment/providers/aws_code_pipeline.rb +39 -0
  20. data/lib/datadog/ci/ext/environment/providers/azure.rb +4 -0
  21. data/lib/datadog/ci/ext/environment/providers/base.rb +4 -0
  22. data/lib/datadog/ci/ext/environment/providers/bitbucket.rb +4 -0
  23. data/lib/datadog/ci/ext/environment/providers/bitrise.rb +4 -0
  24. data/lib/datadog/ci/ext/environment/providers/buddy.rb +4 -0
  25. data/lib/datadog/ci/ext/environment/providers/buildkite.rb +4 -0
  26. data/lib/datadog/ci/ext/environment/providers/circleci.rb +4 -0
  27. data/lib/datadog/ci/ext/environment/providers/codefresh.rb +4 -0
  28. data/lib/datadog/ci/ext/environment/providers/github_actions.rb +4 -0
  29. data/lib/datadog/ci/ext/environment/providers/gitlab.rb +4 -0
  30. data/lib/datadog/ci/ext/environment/providers/jenkins.rb +4 -0
  31. data/lib/datadog/ci/ext/environment/providers/local_git.rb +7 -0
  32. data/lib/datadog/ci/ext/environment/providers/teamcity.rb +4 -0
  33. data/lib/datadog/ci/ext/environment/providers/travis.rb +4 -0
  34. data/lib/datadog/ci/ext/environment/providers.rb +16 -14
  35. data/lib/datadog/ci/ext/settings.rb +2 -0
  36. data/lib/datadog/ci/ext/transport.rb +24 -0
  37. data/lib/datadog/ci/{test.rb → recorder.rb} +6 -5
  38. data/lib/datadog/ci/test_visibility/flush.rb +40 -0
  39. data/lib/datadog/ci/test_visibility/serializers/base.rb +161 -0
  40. data/lib/datadog/ci/test_visibility/serializers/factories/test_level.rb +30 -0
  41. data/lib/datadog/ci/test_visibility/serializers/span.rb +51 -0
  42. data/lib/datadog/ci/test_visibility/serializers/test_v1.rb +60 -0
  43. data/lib/datadog/ci/test_visibility/transport.rb +151 -0
  44. data/lib/datadog/ci/transport/api/base.rb +36 -0
  45. data/lib/datadog/ci/transport/api/builder.rb +46 -0
  46. data/lib/datadog/ci/transport/api/ci_test_cycle.rb +30 -0
  47. data/lib/datadog/ci/transport/api/evp_proxy.rb +44 -0
  48. data/lib/datadog/ci/transport/gzip.rb +22 -0
  49. data/lib/datadog/ci/transport/http.rb +77 -0
  50. data/lib/datadog/ci/version.rb +2 -2
  51. data/sig/datadog/ci/configuration/components.rbs +4 -0
  52. data/sig/datadog/ci/configuration/settings.rbs +2 -0
  53. data/sig/datadog/ci/contrib/cucumber/configuration/settings.rbs +1 -1
  54. data/sig/datadog/ci/contrib/cucumber/integration.rbs +2 -1
  55. data/sig/datadog/ci/contrib/integration.rbs +44 -0
  56. data/sig/datadog/ci/contrib/minitest/configuration/settings.rbs +1 -1
  57. data/sig/datadog/ci/contrib/minitest/integration.rbs +4 -3
  58. data/sig/datadog/ci/contrib/rspec/configuration/settings.rbs +1 -1
  59. data/sig/datadog/ci/contrib/rspec/integration.rbs +3 -2
  60. data/sig/datadog/ci/contrib/settings.rbs +25 -0
  61. data/sig/datadog/ci/ext/environment/providers/aws_code_pipeline.rbs +19 -0
  62. data/sig/datadog/ci/ext/environment/providers/base.rbs +2 -0
  63. data/sig/datadog/ci/ext/environment/providers.rbs +1 -1
  64. data/sig/datadog/ci/ext/settings.rbs +2 -0
  65. data/sig/datadog/ci/ext/transport.rbs +29 -0
  66. data/sig/datadog/ci/{test.rbs → recorder.rbs} +1 -1
  67. data/sig/datadog/ci/test_visibility/flush.rbs +17 -0
  68. data/sig/datadog/ci/test_visibility/serializers/base.rbs +73 -0
  69. data/sig/datadog/ci/test_visibility/serializers/factories/test_level.rbs +13 -0
  70. data/sig/datadog/ci/test_visibility/serializers/span.rbs +18 -0
  71. data/sig/datadog/ci/test_visibility/serializers/test_v1.rbs +23 -0
  72. data/sig/datadog/ci/test_visibility/transport.rbs +35 -0
  73. data/sig/datadog/ci/transport/api/base.rbs +21 -0
  74. data/sig/datadog/ci/transport/api/builder.rbs +12 -0
  75. data/sig/datadog/ci/transport/api/ci_test_cycle.rbs +21 -0
  76. data/sig/datadog/ci/transport/api/evp_proxy.rbs +19 -0
  77. data/sig/datadog/ci/transport/gzip.rbs +9 -0
  78. data/sig/datadog/ci/transport/http.rbs +36 -0
  79. metadata +52 -8
  80. data/lib/datadog/ci/flush.rb +0 -38
  81. data/sig/datadog/ci/flush.rbs +0 -15
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "datadog/tracing/contrib"
4
- require "datadog/tracing/contrib/integration"
5
-
3
+ require_relative "../integration"
6
4
  require_relative "configuration/settings"
7
5
  require_relative "patcher"
8
6
 
@@ -12,11 +10,11 @@ module Datadog
12
10
  module RSpec
13
11
  # Description of RSpec integration
14
12
  class Integration
15
- include Datadog::Tracing::Contrib::Integration
13
+ include Datadog::CI::Contrib::Integration
16
14
 
17
15
  MINIMUM_VERSION = Gem::Version.new("3.0.0")
18
16
 
19
- register_as :rspec, auto_patch: true
17
+ register_as :rspec
20
18
 
21
19
  def self.version
22
20
  Gem.loaded_specs["rspec-core"] \
@@ -0,0 +1,33 @@
1
+ require "datadog/core/configuration/base"
2
+
3
+ module Datadog
4
+ module CI
5
+ module Contrib
6
+ # Common settings for all integrations
7
+ # @public_api
8
+ class Settings
9
+ include Core::Configuration::Base
10
+
11
+ option :enabled, default: true
12
+ option :service_name
13
+ option :operation_name
14
+
15
+ def configure(options = {})
16
+ self.class.options.each do |name, _value|
17
+ self[name] = options[name] if options.key?(name)
18
+ end
19
+
20
+ yield(self) if block_given?
21
+ end
22
+
23
+ def [](name)
24
+ respond_to?(name) ? send(name) : get_option(name)
25
+ end
26
+
27
+ def []=(name, value)
28
+ respond_to?("#{name}=") ? send("#{name}=", value) : set_option(name, value)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -10,6 +10,10 @@ module Datadog
10
10
  # Appveyor: https://www.appveyor.com/
11
11
  # Environment variables docs: https://www.appveyor.com/docs/environment-variables/
12
12
  class Appveyor < Base
13
+ def self.handles?(env)
14
+ env.key?("APPVEYOR")
15
+ end
16
+
13
17
  def provider_name
14
18
  "appveyor"
15
19
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Datadog
6
+ module CI
7
+ module Ext
8
+ module Environment
9
+ module Providers
10
+ # AWS CodePipeline: https://aws.amazon.com/codepipeline/
11
+ # Environment variables docs: https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-variables.html
12
+ # AWS CodeBuild: https://aws.amazon.com/codebuild/
13
+ # Environment variable docs: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html
14
+ class AwsCodePipeline < Base
15
+ def self.handles?(env)
16
+ !env["CODEBUILD_INITIATOR"].nil? && env["CODEBUILD_INITIATOR"].start_with?("codepipeline")
17
+ end
18
+
19
+ def provider_name
20
+ "awscodepipeline"
21
+ end
22
+
23
+ def pipeline_id
24
+ env["DD_PIPELINE_EXECUTION_ID"]
25
+ end
26
+
27
+ def ci_env_vars
28
+ {
29
+ "CODEBUILD_BUILD_ARN" => env["CODEBUILD_BUILD_ARN"],
30
+ "DD_PIPELINE_EXECUTION_ID" => env["DD_PIPELINE_EXECUTION_ID"],
31
+ "DD_ACTION_EXECUTION_ID" => env["DD_ACTION_EXECUTION_ID"]
32
+ }.to_json
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -12,6 +12,10 @@ module Datadog
12
12
  # Azure Pipelines: https://azure.microsoft.com/en-us/products/devops/pipelines
13
13
  # Environment variables docs: https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml
14
14
  class Azure < Base
15
+ def self.handles?(env)
16
+ env.key?("TF_BUILD")
17
+ end
18
+
15
19
  def provider_name
16
20
  "azurepipelines"
17
21
  end
@@ -8,6 +8,10 @@ module Datadog
8
8
  class Base
9
9
  attr_reader :env
10
10
 
11
+ def self.handles?(_env)
12
+ false
13
+ end
14
+
11
15
  def initialize(env)
12
16
  @env = env
13
17
  end
@@ -10,6 +10,10 @@ module Datadog
10
10
  # Bitbucket Pipelines: https://bitbucket.org/product/features/pipelines
11
11
  # Environment variables docs: https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/
12
12
  class Bitbucket < Base
13
+ def self.handles?(env)
14
+ env.key?("BITBUCKET_COMMIT")
15
+ end
16
+
13
17
  # overridden methods
14
18
  def provider_name
15
19
  "bitbucket"
@@ -10,6 +10,10 @@ module Datadog
10
10
  # Bitrise: https://bitrise.io/
11
11
  # Environment variables docs: https://devcenter.bitrise.io/en/references/available-environment-variables.html
12
12
  class Bitrise < Base
13
+ def self.handles?(env)
14
+ env.key?("BITRISE_BUILD_SLUG")
15
+ end
16
+
13
17
  def provider_name
14
18
  "bitrise"
15
19
  end
@@ -10,6 +10,10 @@ module Datadog
10
10
  # Buddy: https://buddy.works/
11
11
  # Environment variables docs: https://buddy.works/docs/pipelines/environment-variables
12
12
  class Buddy < Base
13
+ def self.handles?(env)
14
+ env.key?("BUDDY")
15
+ end
16
+
13
17
  def provider_name
14
18
  "buddy"
15
19
  end
@@ -12,6 +12,10 @@ module Datadog
12
12
  # Buildkite: https://buildkite.com/
13
13
  # Environment variables docs: https://buildkite.com/docs/pipelines/environment-variables
14
14
  class Buildkite < Base
15
+ def self.handles?(env)
16
+ env.key?("BUILDKITE")
17
+ end
18
+
15
19
  def provider_name
16
20
  "buildkite"
17
21
  end
@@ -12,6 +12,10 @@ module Datadog
12
12
  # Circle CI: https://circleci.com/
13
13
  # Environment variables docs: https://circleci.com/docs/variables/#built-in-environment-variables
14
14
  class Circleci < Base
15
+ def self.handles?(env)
16
+ env.key?("CIRCLECI")
17
+ end
18
+
15
19
  def provider_name
16
20
  "circleci"
17
21
  end
@@ -12,6 +12,10 @@ module Datadog
12
12
  # Codefresh: https://codefresh.io/
13
13
  # Environment variables docs: https://codefresh.io/docs/docs/pipelines/variables/#export-variables-to-all-steps-with-cf_export
14
14
  class Codefresh < Base
15
+ def self.handles?(env)
16
+ env.key?("CF_BUILD_ID")
17
+ end
18
+
15
19
  def provider_name
16
20
  "codefresh"
17
21
  end
@@ -12,6 +12,10 @@ module Datadog
12
12
  # Github Actions: https://github.com/features/actions
13
13
  # Environment variables docs: https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
14
14
  class GithubActions < Base
15
+ def self.handles?(env)
16
+ env.key?("GITHUB_SHA")
17
+ end
18
+
15
19
  def provider_name
16
20
  "github"
17
21
  end
@@ -10,6 +10,10 @@ module Datadog
10
10
  # Gitlab CI: https://docs.gitlab.com/ee/ci/
11
11
  # Environment variables docs: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
12
12
  class Gitlab < Base
13
+ def self.handles?(env)
14
+ env.key?("GITLAB_CI")
15
+ end
16
+
13
17
  def provider_name
14
18
  "gitlab"
15
19
  end
@@ -13,6 +13,10 @@ module Datadog
13
13
  # Jenkins: https://www.jenkins.io/
14
14
  # Environment variables docs: https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables
15
15
  class Jenkins < Base
16
+ def self.handles?(env)
17
+ env.key?("JENKINS_URL")
18
+ end
19
+
16
20
  def provider_name
17
21
  "jenkins"
18
22
  end
@@ -97,6 +97,13 @@ module Datadog
97
97
 
98
98
  raise "Failed to run git command #{cmd}: #{out}" unless status.success?
99
99
 
100
+ # Sometimes Encoding.default_external is somehow set to US-ASCII which breaks
101
+ # commit messages with UTF-8 characters like emojis
102
+ # We force output's encoding to be UTF-8 in this case
103
+ # This is safe to do as UTF-8 is compatible with US-ASCII
104
+ if Encoding.default_external == Encoding::US_ASCII
105
+ out = out.force_encoding(Encoding::UTF_8)
106
+ end
100
107
  out.strip! # There's always a "\n" at the end of the command output
101
108
 
102
109
  return nil if out.empty?
@@ -10,6 +10,10 @@ module Datadog
10
10
  # Teamcity: https://www.jetbrains.com/teamcity/
11
11
  # Environment variables docs: https://www.jetbrains.com/help/teamcity/predefined-build-parameters.html
12
12
  class Teamcity < Base
13
+ def self.handles?(env)
14
+ env.key?("TEAMCITY_VERSION")
15
+ end
16
+
13
17
  def provider_name
14
18
  "teamcity"
15
19
  end
@@ -10,6 +10,10 @@ module Datadog
10
10
  # Travis CI: https://www.travis-ci.com/
11
11
  # Environment variables docs: https://docs.travis-ci.com/user/environment-variables#default-environment-variables
12
12
  class Travis < Base
13
+ def self.handles?(env)
14
+ env.key?("TRAVIS")
15
+ end
16
+
13
17
  def provider_name
14
18
  "travisci"
15
19
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "providers/base"
4
4
  require_relative "providers/appveyor"
5
+ require_relative "providers/aws_code_pipeline"
5
6
  require_relative "providers/azure"
6
7
  require_relative "providers/bitbucket"
7
8
  require_relative "providers/bitrise"
@@ -24,23 +25,24 @@ module Datadog
24
25
  module Environment
25
26
  module Providers
26
27
  PROVIDERS = [
27
- ["APPVEYOR", Providers::Appveyor],
28
- ["TF_BUILD", Providers::Azure],
29
- ["BITBUCKET_COMMIT", Providers::Bitbucket],
30
- ["BITRISE_BUILD_SLUG", Providers::Bitrise],
31
- ["BUDDY", Providers::Buddy],
32
- ["BUILDKITE", Providers::Buildkite],
33
- ["CIRCLECI", Providers::Circleci],
34
- ["CF_BUILD_ID", Providers::Codefresh],
35
- ["GITHUB_SHA", Providers::GithubActions],
36
- ["GITLAB_CI", Providers::Gitlab],
37
- ["JENKINS_URL", Providers::Jenkins],
38
- ["TEAMCITY_VERSION", Providers::Teamcity],
39
- ["TRAVIS", Providers::Travis]
28
+ Providers::Appveyor,
29
+ Providers::AwsCodePipeline,
30
+ Providers::Azure,
31
+ Providers::Bitbucket,
32
+ Providers::Bitrise,
33
+ Providers::Buddy,
34
+ Providers::Buildkite,
35
+ Providers::Circleci,
36
+ Providers::Codefresh,
37
+ Providers::GithubActions,
38
+ Providers::Gitlab,
39
+ Providers::Jenkins,
40
+ Providers::Teamcity,
41
+ Providers::Travis
40
42
  ]
41
43
 
42
44
  def self.for_environment(env)
43
- _, provider_klass = PROVIDERS.find { |provider_env_var, _| env.key?(provider_env_var) }
45
+ provider_klass = PROVIDERS.find { |klass| klass.handles?(env) }
44
46
  provider_klass = Providers::Base if provider_klass.nil?
45
47
 
46
48
  provider_klass.new(env)
@@ -6,6 +6,8 @@ module Datadog
6
6
  # Defines constants for test tags
7
7
  module Settings
8
8
  ENV_MODE_ENABLED = "DD_TRACE_CI_ENABLED"
9
+ ENV_AGENTLESS_MODE_ENABLED = "DD_CIVISIBILITY_AGENTLESS_ENABLED"
10
+ ENV_AGENTLESS_URL = "DD_CIVISIBILITY_AGENTLESS_URL"
9
11
  end
10
12
  end
11
13
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module Ext
6
+ module Transport
7
+ DEFAULT_DD_SITE = "datadoghq.com"
8
+
9
+ HEADER_DD_API_KEY = "DD-API-KEY"
10
+ HEADER_CONTENT_TYPE = "Content-Type"
11
+ HEADER_CONTENT_ENCODING = "Content-Encoding"
12
+ HEADER_EVP_SUBDOMAIN = "X-Datadog-EVP-Subdomain"
13
+ HEADER_CONTAINER_ID = "Datadog-Container-ID"
14
+
15
+ EVP_PROXY_PATH_PREFIX = "/evp_proxy/v2/"
16
+ TEST_VISIBILITY_INTAKE_HOST_PREFIX = "citestcycle-intake"
17
+ TEST_VISIBILITY_INTAKE_PATH = "/api/v2/citestcycle"
18
+
19
+ CONTENT_TYPE_MESSAGEPACK = "application/msgpack"
20
+ CONTENT_ENCODING_GZIP = "gzip"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "datadog/tracing"
3
4
  require "datadog/tracing/contrib/analytics"
4
5
 
5
6
  require_relative "ext/app_types"
@@ -11,7 +12,7 @@ require "rbconfig"
11
12
  module Datadog
12
13
  module CI
13
14
  # Common behavior for CI tests
14
- module Test
15
+ module Recorder
15
16
  # Creates a new span for a CI test
16
17
  def self.trace(span_name, options = {})
17
18
  span_options = {
@@ -19,13 +20,13 @@ module Datadog
19
20
  }.merge(options[:span_options] || {})
20
21
 
21
22
  if block_given?
22
- Tracing.trace(span_name, **span_options) do |span, trace|
23
+ ::Datadog::Tracing.trace(span_name, **span_options) do |span, trace|
23
24
  set_tags!(trace, span, options)
24
25
  yield(span, trace)
25
26
  end
26
27
  else
27
- span = Tracing.trace(span_name, **span_options)
28
- trace = Tracing.active_trace
28
+ span = ::Datadog::Tracing.trace(span_name, **span_options)
29
+ trace = ::Datadog::Tracing.active_trace
29
30
  set_tags!(trace, span, options)
30
31
  span
31
32
  end
@@ -37,7 +38,7 @@ module Datadog
37
38
 
38
39
  # Set default tags
39
40
  trace.origin = Ext::Test::CONTEXT_ORIGIN if trace
40
- Datadog::Tracing::Contrib::Analytics.set_measured(span)
41
+ ::Datadog::Tracing::Contrib::Analytics.set_measured(span)
41
42
  span.set_tag(Ext::Test::TAG_SPAN_KIND, Ext::AppTypes::TYPE_TEST)
42
43
 
43
44
  # Set environment tags
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/tracing/metadata/ext"
4
+ require "datadog/tracing/flush"
5
+
6
+ module Datadog
7
+ module CI
8
+ module TestVisibility
9
+ module Flush
10
+ # Common behavior for CI flushing
11
+ module Tagging
12
+ # Decorate a trace with CI tags
13
+ def get_trace(trace_op)
14
+ trace = trace_op.flush!
15
+
16
+ # Origin tag is required on every span
17
+ trace.spans.each do |span|
18
+ span.set_tag(
19
+ Tracing::Metadata::Ext::Distributed::TAG_ORIGIN,
20
+ trace.origin
21
+ )
22
+ end
23
+
24
+ trace
25
+ end
26
+ end
27
+
28
+ # Consumes only completed traces (where all spans have finished)
29
+ class Finished < Tracing::Flush::Finished
30
+ prepend Tagging
31
+ end
32
+
33
+ # Performs partial trace flushing to avoid large traces residing in memory for too long
34
+ class Partial < Tracing::Flush::Partial
35
+ prepend Tagging
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module TestVisibility
6
+ module Serializers
7
+ class Base
8
+ MINIMUM_TIMESTAMP_NANO = 946684800000000000
9
+ MINIMUM_DURATION_NANO = 0
10
+ MAXIMUM_DURATION_NANO = 9223372036854775807
11
+
12
+ attr_reader :trace, :span
13
+
14
+ def initialize(trace, span)
15
+ @trace = trace
16
+ @span = span
17
+ end
18
+
19
+ def to_msgpack(packer = nil)
20
+ packer ||= MessagePack::Packer.new
21
+
22
+ packer.write_map_header(3)
23
+
24
+ write_field(packer, "type")
25
+ write_field(packer, "version")
26
+
27
+ packer.write("content")
28
+ packer.write_map_header(content_map_size)
29
+
30
+ content_fields.each do |field|
31
+ if field.is_a?(Hash)
32
+ field.each do |field_name, method|
33
+ write_field(packer, field_name, method)
34
+ end
35
+ else
36
+ write_field(packer, field)
37
+ end
38
+ end
39
+ end
40
+
41
+ # validates according to citestcycle json schema
42
+ def valid?
43
+ required_fields_present? && valid_start_time? && valid_duration?
44
+ end
45
+
46
+ def content_fields
47
+ []
48
+ end
49
+
50
+ def content_map_size
51
+ 0
52
+ end
53
+
54
+ def runtime_id
55
+ @trace.runtime_id
56
+ end
57
+
58
+ def trace_id
59
+ @trace.id
60
+ end
61
+
62
+ def span_id
63
+ @span.id
64
+ end
65
+
66
+ def parent_id
67
+ @span.parent_id
68
+ end
69
+
70
+ def type
71
+ end
72
+
73
+ def version
74
+ 1
75
+ end
76
+
77
+ def span_type
78
+ @span.type
79
+ end
80
+
81
+ def name
82
+ @span.name
83
+ end
84
+
85
+ def resource
86
+ @span.resource
87
+ end
88
+
89
+ def service
90
+ @span.service
91
+ end
92
+
93
+ def start
94
+ @start ||= time_nano(@span.start_time)
95
+ end
96
+
97
+ def duration
98
+ @duration ||= duration_nano(@span.duration)
99
+ end
100
+
101
+ def meta
102
+ @span.meta
103
+ end
104
+
105
+ def metrics
106
+ @span.metrics
107
+ end
108
+
109
+ def error
110
+ @span.status
111
+ end
112
+
113
+ def self.calculate_content_map_size(fields_list)
114
+ fields_list.reduce(0) do |size, field|
115
+ if field.is_a?(Hash)
116
+ size + field.size
117
+ else
118
+ size + 1
119
+ end
120
+ end
121
+ end
122
+
123
+ private
124
+
125
+ def valid_start_time?
126
+ !start.nil? && start >= MINIMUM_TIMESTAMP_NANO
127
+ end
128
+
129
+ def valid_duration?
130
+ !duration.nil? && duration >= MINIMUM_DURATION_NANO && duration <= MAXIMUM_DURATION_NANO
131
+ end
132
+
133
+ def required_fields_present?
134
+ required_fields.all? { |field| !send(field).nil? }
135
+ end
136
+
137
+ def required_fields
138
+ []
139
+ end
140
+
141
+ def write_field(packer, field_name, method = nil)
142
+ method ||= field_name
143
+
144
+ packer.write(field_name)
145
+ packer.write(send(method))
146
+ end
147
+
148
+ # in nanoseconds since Epoch
149
+ def time_nano(time)
150
+ time.to_i * 1000000000 + time.nsec
151
+ end
152
+
153
+ # in nanoseconds
154
+ def duration_nano(duration)
155
+ (duration * 1e9).to_i
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../test_v1"
4
+ require_relative "../span"
5
+
6
+ module Datadog
7
+ module CI
8
+ module TestVisibility
9
+ module Serializers
10
+ module Factories
11
+ # This factory takes care of creating citestcycle serializers when test-level visibility is enabled
12
+ # NOTE: citestcycle is a protocol Datadog uses to submit test execution tracing information to CI visibility
13
+ # backend
14
+ module TestLevel
15
+ module_function
16
+
17
+ def serializer(trace, span)
18
+ case span.type
19
+ when Datadog::CI::Ext::AppTypes::TYPE_TEST
20
+ Serializers::TestV1.new(trace, span)
21
+ else
22
+ Serializers::Span.new(trace, span)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end