Skip to content

Commit a9ba396

Browse files
feat: Added attribute reconciliation for message producer spans (#2942)
1 parent acfe953 commit a9ba396

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

lib/otel/constants.js

+14
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ module.exports = {
120120
*/
121121
ATTR_HTTP_STATUS_TEXT: 'http.status_text',
122122

123+
/**
124+
* The correlation id
125+
*
126+
* @example MyConversationId
127+
*/
128+
ATTR_MESSAGING_MESSAGE_CONVERSATION_ID: 'messaging.message.conversation_id',
129+
123130
/**
124131
* The message destination name.
125132
*
@@ -157,6 +164,13 @@ module.exports = {
157164
*/
158165
ATTR_MESSAGING_OPERATION_NAME: 'messaging.operation.name',
159166

167+
/**
168+
* RabbitMQ message routing key
169+
*
170+
* @example myKey
171+
*/
172+
ATTR_MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY: 'messaging.rabbitmq.destination.routing_key',
173+
160174
/**
161175
* Target messaging system name.
162176
*

lib/otel/span-processor.js

+26
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const {
1717
ATTR_HTTP_ROUTE,
1818
ATTR_HTTP_STATUS_CODE,
1919
ATTR_HTTP_STATUS_TEXT,
20+
ATTR_MESSAGING_MESSAGE_CONVERSATION_ID,
21+
ATTR_MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY,
2022
ATTR_NET_PEER_NAME,
2123
ATTR_NET_PEER_PORT,
2224
ATTR_NET_HOST_NAME,
@@ -69,6 +71,8 @@ module.exports = class NrSpanProcessor {
6971
this.reconcileServerAttributes({ segment, span, transaction })
7072
} else if (span.kind === SpanKind.CLIENT && span.attributes[ATTR_DB_SYSTEM]) {
7173
this.reconcileDbAttributes({ segment, span })
74+
} else if (span.kind === SpanKind.PRODUCER) {
75+
this.reconcileProducerAttributes({ segment, span })
7276
}
7377
// TODO: add http external checks
7478
}
@@ -159,4 +163,26 @@ module.exports = class NrSpanProcessor {
159163
segment.addAttribute(key, sanitized)
160164
}
161165
}
166+
167+
reconcileProducerAttributes({ segment, span }) {
168+
for (const [prop, value] of Object.entries(span.attributes)) {
169+
let key = prop
170+
let sanitized = value
171+
172+
if (prop === ATTR_SERVER_ADDRESS) {
173+
key = 'host'
174+
if (urltils.isLocalhost(sanitized)) {
175+
sanitized = this.agent.config.getHostnameSafe(sanitized)
176+
}
177+
} else if (prop === ATTR_SERVER_PORT) {
178+
key = 'port'
179+
} else if (prop === ATTR_MESSAGING_MESSAGE_CONVERSATION_ID) {
180+
key = 'correlation_id'
181+
} else if (prop === ATTR_MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY) {
182+
key = 'routing_key'
183+
}
184+
185+
segment.addAttribute(key, sanitized)
186+
}
187+
}
162188
}

test/versioned/otel-bridge/span.test.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ const {
2626
ATTR_HTTP_URL,
2727
ATTR_MESSAGING_DESTINATION,
2828
ATTR_MESSAGING_DESTINATION_KIND,
29+
ATTR_MESSAGING_MESSAGE_CONVERSATION_ID,
2930
ATTR_MESSAGING_OPERATION,
31+
ATTR_MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY,
3032
ATTR_MESSAGING_SYSTEM,
3133
ATTR_NET_PEER_NAME,
3234
ATTR_NET_PEER_PORT,
@@ -375,10 +377,16 @@ test('Otel producer span test', (t, end) => {
375377
const attributes = {
376378
[ATTR_MESSAGING_SYSTEM]: 'messaging-lib',
377379
[ATTR_MESSAGING_DESTINATION_KIND]: MESSAGING_SYSTEM_KIND_VALUES.QUEUE,
378-
[ATTR_MESSAGING_DESTINATION]: 'test-queue'
380+
[ATTR_MESSAGING_DESTINATION]: 'test-queue',
381+
[ATTR_SERVER_ADDRESS]: 'localhost',
382+
[ATTR_SERVER_PORT]: 5672,
383+
[ATTR_MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY]: 'myKey',
384+
[ATTR_MESSAGING_MESSAGE_CONVERSATION_ID]: 'MyConversationId'
379385
}
380386
helper.runInTransaction(agent, (tx) => {
381387
tx.name = 'prod-test'
388+
389+
const expectedHost = agent.config.getHostnameSafe('localhost')
382390
tracer.startActiveSpan('prod-test', { kind: otel.SpanKind.PRODUCER, attributes }, (span) => {
383391
const segment = agent.tracer.getSegment()
384392
assert.equal(segment.name, 'MessageBroker/messaging-lib/queue/Produce/Named/test-queue')
@@ -391,6 +399,14 @@ test('Otel producer span test', (t, end) => {
391399
const unscopedMetrics = tx.metrics.unscoped
392400
assert.equal(unscopedMetrics['MessageBroker/messaging-lib/queue/Produce/Named/test-queue'].callCount, 1)
393401

402+
const attrs = segment.getAttributes()
403+
assert.equal(attrs.host, expectedHost)
404+
assert.equal(attrs.port, 5672)
405+
assert.equal(attrs.correlation_id, 'MyConversationId')
406+
assert.equal(attrs.routing_key, 'myKey')
407+
assert.equal(attrs[ATTR_MESSAGING_SYSTEM], 'messaging-lib')
408+
assert.equal(attrs[ATTR_MESSAGING_DESTINATION], 'test-queue')
409+
assert.equal(attrs[ATTR_MESSAGING_DESTINATION_KIND], MESSAGING_SYSTEM_KIND_VALUES.QUEUE)
394410
end()
395411
})
396412
})

0 commit comments

Comments
 (0)