Skip to content

Commit 61ead84

Browse files
authored
fix: add container id to dogstatsd metrics (#7435)
* add container id to dogstatsd metrics * add docker helper tests * prevent real container id from being used in test
1 parent c5e98c0 commit 61ead84

File tree

4 files changed

+51
-11
lines changed

4 files changed

+51
-11
lines changed

packages/dd-trace/src/dogstatsd.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const log = require('./log')
99
const Histogram = require('./histogram')
1010
const defaults = require('./config/defaults')
1111
const { getAgentUrl } = require('./agent/url')
12+
const { entityId } = require('./exporters/common/docker')
1213

1314
const MAX_BUFFER_SIZE = 1024 // limit from the agent
1415

@@ -116,16 +117,20 @@ class DogStatsDClient {
116117
}
117118

118119
_add (stat, value, type, tags) {
119-
const message = `${this._prefix + stat}:${value}|${type}`
120+
let message = `${this._prefix + stat}:${value}|${type}`
120121

121122
// Don't manipulate this._tags as it is still used
122123
tags = tags ? [...this._tags, ...tags] : this._tags
123124

124125
if (tags.length > 0) {
125-
this._write(`${message}|#${tags.join(',')}\n`)
126-
} else {
127-
this._write(`${message}\n`)
126+
message += `|#${tags.join(',')}`
127+
}
128+
129+
if (entityId) {
130+
message += `|c:${entityId}`
128131
}
132+
133+
this._write(`${message}\n`)
129134
}
130135

131136
_write (message) {

packages/dd-trace/src/exporters/common/docker.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ const entityReg = new RegExp(String.raw`.*(${uuidSource}|${containerSource}|${ta
1616

1717
let inode = 0
1818
let cgroup = ''
19-
let entityId
19+
let containerId
2020

2121
try {
2222
cgroup = fs.readFileSync('/proc/self/cgroup', 'utf8').trim()
23-
entityId = cgroup.match(entityReg)?.[1]
23+
containerId = cgroup.match(entityReg)?.[1]
2424
} catch { /* Ignore error */ }
2525

2626
const inodePath = cgroup.match(lineReg)?.[3]
@@ -32,13 +32,17 @@ if (inodePath) {
3232
} catch { /* Ignore error */ }
3333
}
3434

35+
const entityId = containerId ? `ci-${containerId}` : inode && `in-${inode}`
36+
3537
module.exports = {
38+
entityId,
39+
3640
inject (carrier) {
37-
if (entityId) {
38-
carrier['Datadog-Container-Id'] = entityId
39-
carrier['Datadog-Entity-ID'] = `ci-${entityId}`
41+
if (containerId) {
42+
carrier['Datadog-Container-Id'] = containerId
43+
carrier['Datadog-Entity-ID'] = entityId
4044
} else if (inode) {
41-
carrier['Datadog-Entity-ID'] = `in-${inode}`
45+
carrier['Datadog-Entity-ID'] = entityId
4246
}
4347

4448
if (DD_EXTERNAL_ENV) {

packages/dd-trace/test/dogstatsd.spec.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ describe('dogstatsd', () => {
2727
let statusCode
2828
let sockets
2929
let assertData
30+
let docker
3031

3132
beforeEach((done) => {
3233
udp6 = {
@@ -67,9 +68,12 @@ describe('dogstatsd', () => {
6768
callback(null, hostname, 6)
6869
})
6970

70-
const dogstatsd = proxyquire.noPreserveCache()('../src/dogstatsd', {
71+
docker = {}
72+
73+
const dogstatsd = proxyquire.noPreserveCache().noCallThru()('../src/dogstatsd', {
7174
dgram,
7275
dns,
76+
'./exporters/common/docker': docker,
7377
})
7478
DogStatsDClient = dogstatsd.DogStatsDClient
7579
CustomMetrics = dogstatsd.CustomMetrics
@@ -612,5 +616,23 @@ describe('dogstatsd', () => {
612616
sinon.assert.called(udp4.send)
613617
assert.strictEqual(udp4.send.firstCall.args[0].toString(), 'test.avg:10|g|#foo:bar\n')
614618
})
619+
620+
it('should send the Docker entity ID when available', () => {
621+
docker.entityId = 'ci-1234'
622+
623+
const { CustomMetrics } = proxyquire.noPreserveCache()('../src/dogstatsd', {
624+
dgram,
625+
dns,
626+
'./exporters/common/docker': docker,
627+
})
628+
629+
client = new CustomMetrics({ dogstatsd: {} })
630+
631+
client.gauge('test.avg', 10, { foo: 'bar' })
632+
client.flush()
633+
634+
sinon.assert.called(udp4.send)
635+
assert.strictEqual(udp4.send.firstCall.args[0].toString(), 'test.avg:10|g|#foo:bar|c:ci-1234\n')
636+
})
615637
})
616638
})

packages/dd-trace/test/exporters/common/docker.spec.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ describe('docker', () => {
4747

4848
assert.strictEqual(carrier['Datadog-Container-Id'], id)
4949
assert.strictEqual(carrier['Datadog-Entity-ID'], `ci-${id}`)
50+
assert.strictEqual(docker.entityId, `ci-${id}`)
5051
})
5152

5253
it('should support IDs with UUID format', () => {
@@ -61,6 +62,7 @@ describe('docker', () => {
6162

6263
assert.strictEqual(carrier['Datadog-Container-Id'], id)
6364
assert.strictEqual(carrier['Datadog-Entity-ID'], `ci-${id}`)
65+
assert.strictEqual(docker.entityId, `ci-${id}`)
6466
})
6567

6668
it('should support IDs with ECS task format', () => {
@@ -75,6 +77,7 @@ describe('docker', () => {
7577

7678
assert.strictEqual(carrier['Datadog-Container-Id'], id)
7779
assert.strictEqual(carrier['Datadog-Entity-ID'], `ci-${id}`)
80+
assert.strictEqual(docker.entityId, `ci-${id}`)
7881
})
7982

8083
it('should support IDs with Kubernetes format', () => {
@@ -89,6 +92,7 @@ describe('docker', () => {
8992

9093
assert.strictEqual(carrier['Datadog-Container-Id'], id)
9194
assert.strictEqual(carrier['Datadog-Entity-ID'], `ci-${id}`)
95+
assert.strictEqual(docker.entityId, `ci-${id}`)
9296
})
9397

9498
it('should support finding IDs on any line of the cgroup', () => {
@@ -105,6 +109,7 @@ describe('docker', () => {
105109

106110
assert.strictEqual(carrier['Datadog-Container-Id'], id)
107111
assert.strictEqual(carrier['Datadog-Entity-ID'], `ci-${id}`)
112+
assert.strictEqual(docker.entityId, `ci-${id}`)
108113
})
109114

110115
it('should support Control Group v2', () => {
@@ -119,6 +124,7 @@ describe('docker', () => {
119124

120125
assert.strictEqual(carrier['Datadog-Container-Id'], id)
121126
assert.strictEqual(carrier['Datadog-Entity-ID'], `ci-${id}`)
127+
assert.strictEqual(docker.entityId, `ci-${id}`)
122128
})
123129

124130
it('should support Cloud Foundry', () => {
@@ -133,6 +139,7 @@ describe('docker', () => {
133139

134140
assert.strictEqual(carrier['Datadog-Container-Id'], id)
135141
assert.strictEqual(carrier['Datadog-Entity-ID'], `ci-${id}`)
142+
assert.strictEqual(docker.entityId, `ci-${id}`)
136143
})
137144

138145
it('should support inode when the ID is not available', () => {
@@ -148,6 +155,7 @@ describe('docker', () => {
148155

149156
assert.strictEqual(carrier['Datadog-Container-Id'], undefined)
150157
assert.strictEqual(carrier['Datadog-Entity-ID'], `in-${ino}`)
158+
assert.strictEqual(docker.entityId, `in-${ino}`)
151159
})
152160

153161
it('should support inode when the ID is not available (any line)', () => {
@@ -164,6 +172,7 @@ describe('docker', () => {
164172

165173
assert.strictEqual(carrier['Datadog-Container-Id'], undefined)
166174
assert.strictEqual(carrier['Datadog-Entity-ID'], `in-${ino}`)
175+
assert.strictEqual(docker.entityId, `in-${ino}`)
167176
})
168177

169178
it('should support external env', () => {

0 commit comments

Comments
 (0)