Skip to content

Add customer-facing API for CI Visibility#5005

Merged
nikita-tkachenko-datadog merged 79 commits into
masterfrom
nikita-tkachenko/ci-visibility-manual-api
Apr 27, 2023
Merged

Add customer-facing API for CI Visibility#5005
nikita-tkachenko-datadog merged 79 commits into
masterfrom
nikita-tkachenko/ci-visibility-manual-api

Conversation

@nikita-tkachenko-datadog

@nikita-tkachenko-datadog nikita-tkachenko-datadog commented Mar 31, 2023

Copy link
Copy Markdown
Contributor

What Does This Do

Adds an API to create CI Visibility events (session, module, test suite, test case) programmatically.
The API is exposed to the customers.

Motivation

The API is needed to support the needs of customers who are using either test frameworks that we do not instrument, or ad-hoc testing logic.
Such customers would be able to manually demarcate the start and end of their tests, and to supply additional test metadata.

Additional Notes

In Scope of this PR existing CI Visibility logic was refactored to make test framework instrumentations use the same domain objects that are used by the manual API.

…k & test command calculation in Gradle build listener
… only in the project, but also in the included builds
…s stubbing of that particular class does not work on Java 9+
…rnal-api, since corresponding classes were moved
@nikita-tkachenko-datadog nikita-tkachenko-datadog removed the tag: do not merge Do not merge changes label Mar 31, 2023
public class CIProviderGitInfoBuilder implements GitInfoBuilder {
@Override
public GitInfo build(@Nullable String repositoryPath) {
Path currentPath = repositoryPath != null ? Paths.get(repositoryPath) : null;

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression

[User-provided value](1) flows to here and is used in a path. [User-provided value](2) flows to here and is used in a path. [User-provided value](3) flows to here and is used in a path. [User-provided value](4) flows to here and is used in a path. [User-provided value](5) flows to here and is used in a path. [User-provided value](6) flows to here and is used in a path. [User-provided value](7) flows to here and is used in a path. [User-provided value](8) flows to here and is used in a path.
@nikita-tkachenko-datadog
nikita-tkachenko-datadog force-pushed the nikita-tkachenko/ci-visibility-manual-api branch from 390e97f to 15012e0 Compare April 9, 2023 14:34
@nikita-tkachenko-datadog nikita-tkachenko-datadog changed the title WIP: add customer-facing API for CI Visibility Add customer-facing API for CI Visibility Apr 10, 2023
@nikita-tkachenko-datadog
nikita-tkachenko-datadog marked this pull request as ready for review April 23, 2023 20:03
import java.util.Map;
import javax.annotation.Nullable;

public abstract class AbstractTestDecorator extends BaseDecorator implements TestDecorator {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that all integrations have a Decorator class that extends BaseDecorator. With your change, our integrations don't use the BaseDecorator at all (nor the logic in it). I'm not sure if there's any implication in doing that, have you checked?

@nikita-tkachenko-datadog nikita-tkachenko-datadog Apr 26, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are components in the tracer that do not use decorators and instead add tags to their spans "manually" (I took inspiration from IAST, as it is similar to CI Visibility from the code organisation point of view).

I have also checked the code in BaseDecorator, and the only thing that will be missing is the ability so set spans sampling rate (which is disabled by default and has to be enabled explicitly by providing the instrumentation name - and is not applicable for CI Visibility spans anyway).


@Override
protected String[] instrumentationNames() {
return new String[] {"junit", "junit-4", "junit-4-suite-events"};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to the removal of the Decorator classes. Weren't those instrumentation names needed? I see there's logic in BaseDecorator that uses them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They were used to calculate the names of config properties, that were then used to determine if sampling is enabled for instrumentation and which sampling rate should be used.
We do not apply sampling to CI Visibility spans as it makes little sense from the product point of view.

final String frameworkVersion) {
DDTestModule testModule = getTestModule(sessionKey, moduleName);
testModule.setTag(Tags.TEST_FRAMEWORK, frameworkName);
testModule.setTag(Tags.TEST_FRAMEWORK_VERSION, frameworkVersion);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have both "detected" and "start"? This seems more complex to me that just passing those two tags and setting them in the "start" function. I'm not asking you to change it, I'm just curious to know the reasons :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it looks somewhat clumsy from the API point of view, but there's a reason for it :)

In Gradle we emit the session start event as soon as the build begins. Then follows a (sometimes lengthy) configuration phase when projects are evaluated, and only at the end of that phase we can examine the list of dependencies to determine the test frameworks.

If we fire the session start event after projects evaluation finishes, our total session duration will be skewed since we won't be counting the configuration phase.
Besides, it is possible to fail during configuration phase - before projects are evaluated - in which case we'd have to emit a failed session span.

Having two different events seemed like a simple way to cover the two cases above.

Comment on lines +35 to +37
protected String runtimeName() {
return System.getProperty("java.runtime.name");
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to this PR, but we could cache those properties in local strings instead of calling getProperty each time.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, could be worth doing.

minimumInstructionCoverage = 0.8

excludedClassesCoverage += ["datadog.trace.civisibility.CiVisibilitySystem", "datadog.trace.civisibility.git.GitObject",]
excludedClassesCoverage += [

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to remember to add every class we create here manually? Can't we use wildcards? What's this for?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a logic that evaluates code coverage stats during CI tests and fails the build if coverage percentage criteria are not met.

This list is needed to disable coverage check for specific classes (e.g. DTOs, or those that are covered with integration/smoke tests).

Wildcards are supported, but I think it's already bad enough without them :) at least now every entry has to be added consciously.

@albertvaka albertvaka left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nikita-tkachenko-datadog
nikita-tkachenko-datadog merged commit 95a9b32 into master Apr 27, 2023
@nikita-tkachenko-datadog
nikita-tkachenko-datadog deleted the nikita-tkachenko/ci-visibility-manual-api branch April 27, 2023 09:08
@github-actions github-actions Bot added this to the 1.13.0 milestone Apr 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: ci visibility Continuous Integration Visibility type: refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants