From 564795fbe9351450e3172680dad55508f4b918c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Antonio=20Fern=C3=A1ndez=20de=20Alba?= Date: Mon, 28 Oct 2024 15:09:48 +0100 Subject: [PATCH] [test visibility] Add dynamic instrumentation logs writer for test visibility (#4821) * Apply suggestions from code review Co-authored-by: Nikita Tkachenko <121111529+nikita-tkachenko-datadog@users.noreply.github.com> --- .../exporters/agent-proxy/index.js | 20 +++- .../exporters/agentless/di-logs-writer.js | 53 +++++++++ .../exporters/agentless/index.js | 9 +- .../exporters/ci-visibility-exporter.js | 43 +++++++ packages/dd-trace/src/config.js | 5 +- .../exporters/agent-proxy/agent-proxy.spec.js | 64 ++++++++++- .../agentless/di-logs-writer.spec.js | 105 ++++++++++++++++++ .../exporters/agentless/exporter.spec.js | 28 +++++ .../exporters/ci-visibility-exporter.spec.js | 93 ++++++++++++++++ packages/dd-trace/test/config.spec.js | 22 ++++ 10 files changed, 438 insertions(+), 4 deletions(-) create mode 100644 packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js create mode 100644 packages/dd-trace/test/ci-visibility/exporters/agentless/di-logs-writer.spec.js diff --git a/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js b/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js index bb1367057f4..991031dd3e4 100644 --- a/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +++ b/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js @@ -7,6 +7,7 @@ const CiVisibilityExporter = require('../ci-visibility-exporter') const AGENT_EVP_PROXY_PATH_PREFIX = '/evp_proxy/v' const AGENT_EVP_PROXY_PATH_REGEX = /\/evp_proxy\/v(\d+)\/?/ +const AGENT_DEBUGGER_INPUT = '/debugger/v1/input' function getLatestEvpProxyVersion (err, agentInfo) { if (err) { @@ -24,6 +25,10 @@ function getLatestEvpProxyVersion (err, agentInfo) { }, 0) } +function getCanForwardDebuggerLogs (err, agentInfo) { + return !err && agentInfo.endpoints.some(endpoint => endpoint === AGENT_DEBUGGER_INPUT) +} + class AgentProxyCiVisibilityExporter extends CiVisibilityExporter { constructor (config) { super(config) @@ -33,7 +38,8 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter { prioritySampler, lookup, protocolVersion, - headers + headers, + isTestDynamicInstrumentationEnabled } = config this.getAgentInfo((err, agentInfo) => { @@ -60,6 +66,18 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter { url: this._url, evpProxyPrefix }) + if (isTestDynamicInstrumentationEnabled) { + const canFowardLogs = getCanForwardDebuggerLogs(err, agentInfo) + if (canFowardLogs) { + const DynamicInstrumentationLogsWriter = require('../agentless/di-logs-writer') + this._logsWriter = new DynamicInstrumentationLogsWriter({ + url: this._url, + tags, + isAgentProxy: true + }) + this._canForwardLogs = true + } + } } else { this._writer = new AgentWriter({ url: this._url, diff --git a/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js b/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js new file mode 100644 index 00000000000..eebc3c5e6a9 --- /dev/null +++ b/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js @@ -0,0 +1,53 @@ +'use strict' +const request = require('../../../exporters/common/request') +const log = require('../../../log') +const { safeJSONStringify } = require('../../../exporters/common/util') +const { JSONEncoder } = require('../../encode/json-encoder') + +const BaseWriter = require('../../../exporters/common/writer') + +// Writer used by the integration between Dynamic Instrumentation and Test Visibility +// It is used to encode and send logs to both the logs intake directly and the +// `/debugger/v1/input` endpoint in the agent, which is a proxy to the logs intake. +class DynamicInstrumentationLogsWriter extends BaseWriter { + constructor ({ url, timeout, isAgentProxy = false }) { + super(...arguments) + this._url = url + this._encoder = new JSONEncoder() + this._isAgentProxy = isAgentProxy + this.timeout = timeout + } + + _sendPayload (data, _, done) { + const options = { + path: '/api/v2/logs', + method: 'POST', + headers: { + 'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY, + 'Content-Type': 'application/json' + }, + // TODO: what's a good value for timeout for the logs intake? + timeout: this.timeout || 15000, + url: this._url + } + + if (this._isAgentProxy) { + delete options.headers['dd-api-key'] + options.path = '/debugger/v1/input' + } + + log.debug(() => `Request to the logs intake: ${safeJSONStringify(options)}`) + + request(data, options, (err, res) => { + if (err) { + log.error(err) + done() + return + } + log.debug(`Response from the logs intake: ${res}`) + done() + }) + } +} + +module.exports = DynamicInstrumentationLogsWriter diff --git a/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js b/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js index dcbded6a54e..5895bb573cd 100644 --- a/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +++ b/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js @@ -9,10 +9,11 @@ const log = require('../../../log') class AgentlessCiVisibilityExporter extends CiVisibilityExporter { constructor (config) { super(config) - const { tags, site, url } = config + const { tags, site, url, isTestDynamicInstrumentationEnabled } = config // we don't need to request /info because we are using agentless by configuration this._isInitialized = true this._resolveCanUseCiVisProtocol(true) + this._canForwardLogs = true this._url = url || new URL(`https://citestcycle-intake.${site}`) this._writer = new Writer({ url: this._url, tags }) @@ -20,6 +21,12 @@ class AgentlessCiVisibilityExporter extends CiVisibilityExporter { this._coverageUrl = url || new URL(`https://citestcov-intake.${site}`) this._coverageWriter = new CoverageWriter({ url: this._coverageUrl }) + if (isTestDynamicInstrumentationEnabled) { + const DynamicInstrumentationLogsWriter = require('./di-logs-writer') + this._logsUrl = url || new URL(`https://http-intake.logs.${site}`) + this._logsWriter = new DynamicInstrumentationLogsWriter({ url: this._logsUrl, tags }) + } + this._apiUrl = url || new URL(`https://api.${site}`) // Agentless is always gzip compatible this._isGzipCompatible = true diff --git a/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js b/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js index 9dabd34f7f3..f555603e0cb 100644 --- a/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +++ b/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js @@ -8,6 +8,7 @@ const { getSkippableSuites: getSkippableSuitesRequest } = require('../intelligen const { getKnownTests: getKnownTestsRequest } = require('../early-flake-detection/get-known-tests') const log = require('../../log') const AgentInfoExporter = require('../../exporters/common/agent-info-exporter') +const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../../plugins/util/tags') function getTestConfigurationTags (tags) { if (!tags) { @@ -36,6 +37,7 @@ class CiVisibilityExporter extends AgentInfoExporter { super(config) this._timer = undefined this._coverageTimer = undefined + this._logsTimer = undefined this._coverageBuffer = [] // The library can use new features like ITR and test suite level visibility // AKA CI Vis Protocol @@ -255,6 +257,47 @@ class CiVisibilityExporter extends AgentInfoExporter { this._export(formattedCoverage, this._coverageWriter, '_coverageTimer') } + formatLogMessage (testConfiguration, logMessage) { + const { + [GIT_REPOSITORY_URL]: gitRepositoryUrl, + [GIT_COMMIT_SHA]: gitCommitSha + } = testConfiguration + + const { service, env, version } = this._config + + return { + ddtags: [ + ...(logMessage.ddtags || []), + `${GIT_REPOSITORY_URL}:${gitRepositoryUrl}`, + `${GIT_COMMIT_SHA}:${gitCommitSha}` + ].join(','), + level: 'error', + service, + dd: { + ...(logMessage.dd || []), + service, + env, + version + }, + ddsource: 'dd_debugger', + ...logMessage + } + } + + // DI logs + exportDiLogs (testConfiguration, logMessage) { + // TODO: could we lose logs if it's not initialized? + if (!this._config.isTestDynamicInstrumentationEnabled || !this._isInitialized || !this._canForwardLogs) { + return + } + + this._export( + this.formatLogMessage(testConfiguration, logMessage), + this._logsWriter, + '_logsTimer' + ) + } + flush (done = () => {}) { if (!this._isInitialized) { return done() diff --git a/packages/dd-trace/src/config.js b/packages/dd-trace/src/config.js index fa502ccb5a2..defa10bffa0 100644 --- a/packages/dd-trace/src/config.js +++ b/packages/dd-trace/src/config.js @@ -503,6 +503,7 @@ class Config { this._setValue(defaults, 'isManualApiEnabled', false) this._setValue(defaults, 'ciVisibilityTestSessionName', '') this._setValue(defaults, 'ciVisAgentlessLogSubmissionEnabled', false) + this._setValue(defaults, 'isTestDynamicInstrumentationEnabled', false) this._setValue(defaults, 'logInjection', false) this._setValue(defaults, 'lookup', undefined) this._setValue(defaults, 'memcachedCommandEnabled', false) @@ -1054,7 +1055,8 @@ class Config { DD_CIVISIBILITY_FLAKY_RETRY_ENABLED, DD_CIVISIBILITY_FLAKY_RETRY_COUNT, DD_TEST_SESSION_NAME, - DD_AGENTLESS_LOG_SUBMISSION_ENABLED + DD_AGENTLESS_LOG_SUBMISSION_ENABLED, + DD_TEST_DYNAMIC_INSTRUMENTATION_ENABLED } = process.env if (DD_CIVISIBILITY_AGENTLESS_URL) { @@ -1072,6 +1074,7 @@ class Config { this._setBoolean(calc, 'isManualApiEnabled', !isFalse(this._isCiVisibilityManualApiEnabled())) this._setString(calc, 'ciVisibilityTestSessionName', DD_TEST_SESSION_NAME) this._setBoolean(calc, 'ciVisAgentlessLogSubmissionEnabled', isTrue(DD_AGENTLESS_LOG_SUBMISSION_ENABLED)) + this._setBoolean(calc, 'isTestDynamicInstrumentationEnabled', isTrue(DD_TEST_DYNAMIC_INSTRUMENTATION_ENABLED)) } this._setString(calc, 'dogstatsd.hostname', this._getHostname()) this._setBoolean(calc, 'isGitUploadEnabled', diff --git a/packages/dd-trace/test/ci-visibility/exporters/agent-proxy/agent-proxy.spec.js b/packages/dd-trace/test/ci-visibility/exporters/agent-proxy/agent-proxy.spec.js index 4ff8f12ace6..1abae9e82f1 100644 --- a/packages/dd-trace/test/ci-visibility/exporters/agent-proxy/agent-proxy.spec.js +++ b/packages/dd-trace/test/ci-visibility/exporters/agent-proxy/agent-proxy.spec.js @@ -6,6 +6,7 @@ const nock = require('nock') const AgentProxyCiVisibilityExporter = require('../../../../src/ci-visibility/exporters/agent-proxy') const AgentlessWriter = require('../../../../src/ci-visibility/exporters/agentless/writer') +const DynamicInstrumentationLogsWriter = require('../../../../src/ci-visibility/exporters/agentless/di-logs-writer') const CoverageWriter = require('../../../../src/ci-visibility/exporters/agentless/coverage-writer') const AgentWriter = require('../../../../src/exporters/agent/writer') @@ -68,7 +69,10 @@ describe('AgentProxyCiVisibilityExporter', () => { .get('/info') .delay(queryDelay) .reply(200, JSON.stringify({ - endpoints: ['/evp_proxy/v2/'] + endpoints: [ + '/evp_proxy/v2/', + '/debugger/v1/input' + ] })) }) @@ -112,6 +116,35 @@ describe('AgentProxyCiVisibilityExporter', () => { agentProxyCiVisibilityExporter.exportCoverage(coverage) expect(mockWriter.append).to.have.been.calledWith({ spanId: '1', traceId: '1', files: [] }) }) + + context('if isTestDynamicInstrumentationEnabled is set', () => { + it('should initialise DynamicInstrumentationLogsWriter', async () => { + const agentProxyCiVisibilityExporter = new AgentProxyCiVisibilityExporter({ + port, + tags, + isTestDynamicInstrumentationEnabled: true + }) + await agentProxyCiVisibilityExporter._canUseCiVisProtocolPromise + expect(agentProxyCiVisibilityExporter._logsWriter).to.be.instanceOf(DynamicInstrumentationLogsWriter) + }) + + it('should process logs', async () => { + const mockWriter = { + append: sinon.spy(), + flush: sinon.spy() + } + const agentProxyCiVisibilityExporter = new AgentProxyCiVisibilityExporter({ + port, + tags, + isTestDynamicInstrumentationEnabled: true + }) + await agentProxyCiVisibilityExporter._canUseCiVisProtocolPromise + agentProxyCiVisibilityExporter._logsWriter = mockWriter + const log = { message: 'hello' } + agentProxyCiVisibilityExporter.exportDiLogs({}, log) + expect(mockWriter.append).to.have.been.calledWith(sinon.match(log)) + }) + }) }) describe('agent is not evp compatible', () => { @@ -166,6 +199,35 @@ describe('AgentProxyCiVisibilityExporter', () => { }) expect(mockWriter.append).not.to.have.been.called }) + + context('if isTestDynamicInstrumentationEnabled is set', () => { + it('should not initialise DynamicInstrumentationLogsWriter', async () => { + const agentProxyCiVisibilityExporter = new AgentProxyCiVisibilityExporter({ + port, + tags, + isTestDynamicInstrumentationEnabled: true + }) + await agentProxyCiVisibilityExporter._canUseCiVisProtocolPromise + expect(agentProxyCiVisibilityExporter._logsWriter).to.be.undefined + }) + + it('should not process logs', async () => { + const mockWriter = { + append: sinon.spy(), + flush: sinon.spy() + } + const agentProxyCiVisibilityExporter = new AgentProxyCiVisibilityExporter({ + port, + tags, + isTestDynamicInstrumentationEnabled: true + }) + await agentProxyCiVisibilityExporter._canUseCiVisProtocolPromise + agentProxyCiVisibilityExporter._logsWriter = mockWriter + const log = { message: 'hello' } + agentProxyCiVisibilityExporter.exportDiLogs({}, log) + expect(mockWriter.append).not.to.have.been.called + }) + }) }) describe('export', () => { diff --git a/packages/dd-trace/test/ci-visibility/exporters/agentless/di-logs-writer.spec.js b/packages/dd-trace/test/ci-visibility/exporters/agentless/di-logs-writer.spec.js new file mode 100644 index 00000000000..85a674a0d85 --- /dev/null +++ b/packages/dd-trace/test/ci-visibility/exporters/agentless/di-logs-writer.spec.js @@ -0,0 +1,105 @@ +'use strict' + +require('../../../../../dd-trace/test/setup/tap') + +const { expect } = require('chai') +const sinon = require('sinon') +const nock = require('nock') +const DynamicInstrumentationLogsWriter = require('../../../../src/ci-visibility/exporters/agentless/di-logs-writer') +const log = require('../../../../src/log') + +describe('Test Visibility DI Writer', () => { + beforeEach(() => { + nock.cleanAll() + process.env.DD_API_KEY = '1' + }) + + afterEach(() => { + delete process.env.DD_API_KEY + sinon.restore() + }) + + context('agentless', () => { + it('can send logs to the logs intake', (done) => { + const scope = nock('http://www.example.com') + .post('/api/v2/logs', body => { + expect(body).to.deep.equal([{ message: 'test' }, { message: 'test2' }]) + return true + }) + .reply(202) + + const logsWriter = new DynamicInstrumentationLogsWriter({ url: 'http://www.example.com' }) + + logsWriter.append({ message: 'test' }) + logsWriter.append({ message: 'test2' }) + + logsWriter.flush(() => { + scope.done() + done() + }) + }) + + it('logs an error if the request fails', (done) => { + const logErrorSpy = sinon.spy(log, 'error') + + const scope = nock('http://www.example.com') + .post('/api/v2/logs') + .reply(500) + + const logsWriter = new DynamicInstrumentationLogsWriter({ url: 'http://www.example.com' }) + + logsWriter.append({ message: 'test5' }) + logsWriter.append({ message: 'test6' }) + + logsWriter.flush(() => { + expect(logErrorSpy.called).to.be.true + scope.done() + done() + }) + }) + }) + + context('agent based', () => { + it('can send logs to the debugger endpoint in the agent', (done) => { + delete process.env.DD_API_KEY + + const scope = nock('http://www.example.com') + .post('/debugger/v1/input', body => { + expect(body).to.deep.equal([{ message: 'test3' }, { message: 'test4' }]) + return true + }) + .reply(202) + + const logsWriter = new DynamicInstrumentationLogsWriter({ url: 'http://www.example.com', isAgentProxy: true }) + + logsWriter.append({ message: 'test3' }) + logsWriter.append({ message: 'test4' }) + + logsWriter.flush(() => { + scope.done() + done() + }) + }) + + it('logs an error if the request fails', (done) => { + delete process.env.DD_API_KEY + + const logErrorSpy = sinon.spy(log, 'error') + + const scope = nock('http://www.example.com') + .post('/debugger/v1/input') + .reply(500) + + const logsWriter = new DynamicInstrumentationLogsWriter({ url: 'http://www.example.com', isAgentProxy: true }) + + logsWriter.append({ message: 'test5' }) + logsWriter.append({ message: 'test6' }) + + logsWriter.flush(() => { + expect(logErrorSpy.called).to.be.true + scope.done() + done() + }) + }) + }) +}) diff --git a/packages/dd-trace/test/ci-visibility/exporters/agentless/exporter.spec.js b/packages/dd-trace/test/ci-visibility/exporters/agentless/exporter.spec.js index 11b3bf1ec4c..dd229984bd2 100644 --- a/packages/dd-trace/test/ci-visibility/exporters/agentless/exporter.spec.js +++ b/packages/dd-trace/test/ci-visibility/exporters/agentless/exporter.spec.js @@ -8,6 +8,7 @@ const { expect } = require('chai') const nock = require('nock') const AgentlessCiVisibilityExporter = require('../../../../src/ci-visibility/exporters/agentless') +const DynamicInstrumentationLogsWriter = require('../../../../src/ci-visibility/exporters/agentless/di-logs-writer') describe('CI Visibility Agentless Exporter', () => { const url = new URL('http://www.example.com') @@ -177,6 +178,33 @@ describe('CI Visibility Agentless Exporter', () => { }) }) + context('if isTestDynamicInstrumentationEnabled is set', () => { + it('should initialise DynamicInstrumentationLogsWriter', async () => { + const agentProxyCiVisibilityExporter = new AgentlessCiVisibilityExporter({ + tags: {}, + isTestDynamicInstrumentationEnabled: true + }) + await agentProxyCiVisibilityExporter._canUseCiVisProtocolPromise + expect(agentProxyCiVisibilityExporter._logsWriter).to.be.instanceOf(DynamicInstrumentationLogsWriter) + }) + + it('should process logs', async () => { + const mockWriter = { + append: sinon.spy(), + flush: sinon.spy() + } + const agentProxyCiVisibilityExporter = new AgentlessCiVisibilityExporter({ + tags: {}, + isTestDynamicInstrumentationEnabled: true + }) + await agentProxyCiVisibilityExporter._canUseCiVisProtocolPromise + agentProxyCiVisibilityExporter._logsWriter = mockWriter + const log = { message: 'hello' } + agentProxyCiVisibilityExporter.exportDiLogs({}, log) + expect(mockWriter.append).to.have.been.calledWith(sinon.match(log)) + }) + }) + describe('url', () => { it('sets the default if URL param is not specified', () => { const site = 'd4tad0g.com' diff --git a/packages/dd-trace/test/ci-visibility/exporters/ci-visibility-exporter.spec.js b/packages/dd-trace/test/ci-visibility/exporters/ci-visibility-exporter.spec.js index b92d5b3ae98..7b09f8fba2d 100644 --- a/packages/dd-trace/test/ci-visibility/exporters/ci-visibility-exporter.spec.js +++ b/packages/dd-trace/test/ci-visibility/exporters/ci-visibility-exporter.spec.js @@ -815,4 +815,97 @@ describe('CI Visibility Exporter', () => { }) }) }) + + describe('exportDiLogs', () => { + context('is not initialized', () => { + it('should do nothing', () => { + const log = { message: 'log' } + const ciVisibilityExporter = new CiVisibilityExporter({ port, isTestDynamicInstrumentationEnabled: true }) + ciVisibilityExporter.exportDiLogs(log) + ciVisibilityExporter._export = sinon.spy() + expect(ciVisibilityExporter._export).not.to.be.called + }) + }) + + context('is initialized but can not forward logs', () => { + it('should do nothing', () => { + const writer = { + append: sinon.spy(), + flush: sinon.spy(), + setUrl: sinon.spy() + } + const log = { message: 'log' } + const ciVisibilityExporter = new CiVisibilityExporter({ port, isTestDynamicInstrumentationEnabled: true }) + ciVisibilityExporter._isInitialized = true + ciVisibilityExporter._logsWriter = writer + ciVisibilityExporter._canForwardLogs = false + ciVisibilityExporter.exportDiLogs(log) + expect(ciVisibilityExporter._logsWriter.append).not.to.be.called + }) + }) + + context('is initialized and can forward logs', () => { + it('should export formatted logs', () => { + const writer = { + append: sinon.spy(), + flush: sinon.spy(), + setUrl: sinon.spy() + } + const diLog = { + message: 'log', + debugger: { + snapshot: { + id: '1234', + timestamp: 1234567890, + probe: { + id: '54321', + version: '1', + location: { + file: 'example.js', + lines: ['1'] + } + }, + stack: [ + { + fileName: 'example.js', + function: 'sum', + lineNumber: 1 + } + ], + language: 'javascript' + } + } + } + const ciVisibilityExporter = new CiVisibilityExporter({ + env: 'ci', + version: '1.0.0', + port, + isTestDynamicInstrumentationEnabled: true, + service: 'my-service' + }) + ciVisibilityExporter._isInitialized = true + ciVisibilityExporter._logsWriter = writer + ciVisibilityExporter._canForwardLogs = true + ciVisibilityExporter.exportDiLogs( + { + 'git.repository_url': 'https://github.com/datadog/dd-trace-js.git', + 'git.commit.sha': '1234' + }, + diLog + ) + expect(ciVisibilityExporter._logsWriter.append).to.be.calledWith(sinon.match({ + ddtags: 'git.repository_url:https://github.com/datadog/dd-trace-js.git,git.commit.sha:1234', + level: 'error', + ddsource: 'dd_debugger', + service: 'my-service', + dd: { + service: 'my-service', + env: 'ci', + version: '1.0.0' + }, + ...diLog + })) + }) + }) + }) }) diff --git a/packages/dd-trace/test/config.spec.js b/packages/dd-trace/test/config.spec.js index 4246167725d..f083fa4b07d 100644 --- a/packages/dd-trace/test/config.spec.js +++ b/packages/dd-trace/test/config.spec.js @@ -331,6 +331,8 @@ describe('Config', () => { { name: 'isIntelligentTestRunnerEnabled', value: false, origin: 'default' }, { name: 'isManualApiEnabled', value: false, origin: 'default' }, { name: 'ciVisibilityTestSessionName', value: '', origin: 'default' }, + { name: 'ciVisAgentlessLogSubmissionEnabled', value: false, origin: 'default' }, + { name: 'isTestDynamicInstrumentationEnabled', value: false, origin: 'default' }, { name: 'logInjection', value: false, origin: 'default' }, { name: 'lookup', value: undefined, origin: 'default' }, { name: 'openAiLogsEnabled', value: false, origin: 'default' }, @@ -1875,6 +1877,8 @@ describe('Config', () => { delete process.env.DD_CIVISIBILITY_FLAKY_RETRY_COUNT delete process.env.DD_TEST_SESSION_NAME delete process.env.JEST_WORKER_ID + delete process.env.DD_TEST_DYNAMIC_INSTRUMENTATION_ENABLED + delete process.env.DD_AGENTLESS_LOG_SUBMISSION_ENABLED options = {} }) context('ci visibility mode is enabled', () => { @@ -1963,6 +1967,24 @@ describe('Config', () => { const config = new Config(options) expect(config).to.have.property('ciVisibilityTestSessionName', 'my-test-session') }) + it('should not enable agentless log submission by default', () => { + const config = new Config(options) + expect(config).to.have.property('ciVisAgentlessLogSubmissionEnabled', false) + }) + it('should enable agentless log submission if DD_AGENTLESS_LOG_SUBMISSION_ENABLED is true', () => { + process.env.DD_AGENTLESS_LOG_SUBMISSION_ENABLED = 'true' + const config = new Config(options) + expect(config).to.have.property('ciVisAgentlessLogSubmissionEnabled', true) + }) + it('should not set isTestDynamicInstrumentationEnabled by default', () => { + const config = new Config(options) + expect(config).to.have.property('isTestDynamicInstrumentationEnabled', false) + }) + it('should set isTestDynamicInstrumentationEnabled if DD_TEST_DYNAMIC_INSTRUMENTATION_ENABLED is passed', () => { + process.env.DD_TEST_DYNAMIC_INSTRUMENTATION_ENABLED = 'true' + const config = new Config(options) + expect(config).to.have.property('isTestDynamicInstrumentationEnabled', true) + }) }) context('ci visibility mode is not enabled', () => { it('should not activate intelligent test runner or git metadata upload', () => {