Skip to content

Commit 4e7da80

Browse files
SCI Embedding of git metadata (#3118)
1 parent c42c3df commit 4e7da80

File tree

6 files changed

+122
-19
lines changed

6 files changed

+122
-19
lines changed

integration-tests/esbuild.spec.js

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,28 @@ const path = require('path')
88
const CWD = process.cwd()
99
const TEST_DIR = path.join(__dirname, 'esbuild')
1010

11-
// eslint-disable-next-line no-console
12-
console.log(`cd ${TEST_DIR}`)
13-
process.chdir(TEST_DIR)
11+
describe('esbuild', () => {
12+
it('works', () => {
13+
// eslint-disable-next-line no-console
14+
console.log(`cd ${TEST_DIR}`)
15+
process.chdir(TEST_DIR)
1416

15-
// eslint-disable-next-line no-console
16-
console.log('npm run build')
17-
chproc.execSync('npm run build')
17+
// eslint-disable-next-line no-console
18+
console.log('npm run build')
19+
chproc.execSync('npm run build')
1820

19-
// eslint-disable-next-line no-console
20-
console.log('npm run built')
21-
try {
22-
chproc.execSync('npm run built', {
23-
timeout: 1000 * 30
21+
// eslint-disable-next-line no-console
22+
console.log('npm run built')
23+
try {
24+
chproc.execSync('npm run built', {
25+
timeout: 1000 * 30
26+
})
27+
} catch (err) {
28+
// eslint-disable-next-line no-console
29+
console.error(err)
30+
process.exit(1)
31+
} finally {
32+
process.chdir(CWD)
33+
}
2434
})
25-
} catch (err) {
26-
// eslint-disable-next-line no-console
27-
console.error(err)
28-
process.exit(1)
29-
} finally {
30-
process.chdir(CWD)
31-
}
35+
})

packages/dd-trace/src/config.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const coalesce = require('koalas')
99
const tagger = require('./tagger')
1010
const { isTrue, isFalse } = require('./util')
1111
const uuid = require('crypto-randomuuid')
12+
const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('./plugins/util/tags')
1213

1314
const fromEntries = Object.fromEntries || (entries =>
1415
entries.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {}))
@@ -408,6 +409,11 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
408409
true
409410
)
410411

412+
const DD_TRACE_GIT_METADATA_ENABLED = coalesce(
413+
process.env.DD_TRACE_GIT_METADATA_ENABLED,
414+
true
415+
)
416+
411417
const ingestion = options.ingestion || {}
412418
const dogstatsd = coalesce(options.dogstatsd, {})
413419
const sampler = {
@@ -522,6 +528,19 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
522528
this.isGitUploadEnabled = this.isCiVisibility &&
523529
(this.isIntelligentTestRunnerEnabled && !isFalse(DD_CIVISIBILITY_GIT_UPLOAD_ENABLED))
524530

531+
this.gitMetadataEnabled = isTrue(DD_TRACE_GIT_METADATA_ENABLED)
532+
533+
if (this.gitMetadataEnabled) {
534+
this.repositoryUrl = coalesce(
535+
process.env.DD_GIT_REPOSITORY_URL,
536+
this.tags[GIT_REPOSITORY_URL]
537+
)
538+
this.commitSHA = coalesce(
539+
process.env.DD_GIT_COMMIT_SHA,
540+
this.tags[GIT_COMMIT_SHA]
541+
)
542+
}
543+
525544
this.stats = {
526545
enabled: isTrue(DD_TRACE_STATS_COMPUTATION_ENABLED)
527546
}

packages/dd-trace/src/constants.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,7 @@ module.exports = {
2525
ERROR_MESSAGE: 'error.message',
2626
ERROR_STACK: 'error.stack',
2727
COMPONENT: 'component',
28-
CLIENT_PORT_KEY: 'network.destination.port'
28+
CLIENT_PORT_KEY: 'network.destination.port',
29+
SCI_REPOSITORY_URL: '_dd.git.repository_url',
30+
SCI_COMMIT_SHA: '_dd.git.commit.sha'
2931
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const { SCI_COMMIT_SHA, SCI_REPOSITORY_URL } = require('./constants')
2+
3+
class GitMetadataTagger {
4+
constructor (config) {
5+
this._config = config
6+
}
7+
8+
tagGitMetadata (spanContext) {
9+
if (this._config.gitMetadataEnabled) {
10+
// These tags are added only to the local root span
11+
spanContext._trace.tags[SCI_COMMIT_SHA] = this._config.commitSHA
12+
spanContext._trace.tags[SCI_REPOSITORY_URL] = this._config.repositoryUrl
13+
}
14+
}
15+
}
16+
17+
module.exports = GitMetadataTagger

packages/dd-trace/src/span_processor.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const log = require('./log')
44
const format = require('./format')
55
const SpanSampler = require('./span_sampler')
6+
const GitMetadataTagger = require('./git_metadata_tagger')
67

78
const { SpanStatsProcessor } = require('./span_stats')
89

@@ -18,6 +19,7 @@ class SpanProcessor {
1819

1920
this._stats = new SpanStatsProcessor(config)
2021
this._spanSampler = new SpanSampler(config.sampler)
22+
this._gitMetadataTagger = new GitMetadataTagger(config)
2123
}
2224

2325
process (span) {
@@ -32,6 +34,7 @@ class SpanProcessor {
3234
if (started.length === finished.length || finished.length >= flushMinSpans) {
3335
this._prioritySampler.sample(spanContext)
3436
this._spanSampler.sample(spanContext)
37+
this._gitMetadataTagger.tagGitMetadata(spanContext)
3538

3639
for (const span of started) {
3740
if (span._duration !== undefined) {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
'use strict'
2+
3+
require('./setup/tap')
4+
5+
const agent = require('./plugins/agent')
6+
const { SCI_COMMIT_SHA, SCI_REPOSITORY_URL } = require('../src/constants')
7+
8+
const DUMMY_GIT_SHA = '13851f2b092e97acebab1b73f6c0e7818e795b50'
9+
const DUMMY_REPOSITORY_URL = '[email protected]:DataDog/sci_git_example.git'
10+
11+
const oldEnv = process.env
12+
13+
describe('git metadata tagging', () => {
14+
let tracer
15+
16+
beforeEach(() => {
17+
process.env = {
18+
...oldEnv,
19+
DD_GIT_COMMIT_SHA: DUMMY_GIT_SHA,
20+
DD_TAGS: `git.repository_url:${DUMMY_REPOSITORY_URL}`
21+
}
22+
tracer = require('../')
23+
return agent.load()
24+
})
25+
26+
afterEach(() => {
27+
agent.close()
28+
})
29+
30+
afterEach(() => {
31+
process.env = oldEnv
32+
})
33+
34+
it('should include git metadata when using DD_GIT_* tags and DD_TAGS', async () => {
35+
const span = tracer.startSpan('hello', {
36+
tags: {
37+
'resource.name': '/hello/:name'
38+
}
39+
})
40+
41+
const childSpan = tracer.startSpan('world', {
42+
childOf: span
43+
})
44+
45+
childSpan.finish()
46+
span.finish()
47+
48+
return agent.use((payload) => {
49+
const firstSpan = payload[0][0]
50+
expect(firstSpan.meta[SCI_COMMIT_SHA]).to.equal(DUMMY_GIT_SHA)
51+
expect(firstSpan.meta[SCI_REPOSITORY_URL]).to.equal(DUMMY_REPOSITORY_URL)
52+
53+
const secondSpan = payload[0][1]
54+
expect(secondSpan.meta[SCI_COMMIT_SHA]).not.to.exist
55+
expect(secondSpan.meta[SCI_REPOSITORY_URL]).not.to.exist
56+
})
57+
})
58+
})

0 commit comments

Comments
 (0)