UNPKG

dd-trace

Version:

Datadog APM tracing client for JavaScript

105 lines (94 loc) 3.19 kB
'use strict' const ProducerPlugin = require('../../dd-trace/src/plugins/producer') const { DsmPathwayCodec, getMessageSize } = require('../../dd-trace/src/datastreams') const BOOTSTRAP_SERVERS_KEY = 'messaging.kafka.bootstrap.servers' const MESSAGING_DESTINATION_KEY = 'messaging.destination.name' class KafkajsProducerPlugin extends ProducerPlugin { static get id () { return 'kafkajs' } static get operation () { return 'produce' } static get peerServicePrecursors () { return [BOOTSTRAP_SERVERS_KEY] } constructor () { super(...arguments) this.addSub('apm:kafkajs:produce:commit', message => this.commit(message)) } /** * Transform individual commit details sent by kafkajs' event reporter * into actionable backlog items for DSM * * @typedef {object} ProducerBacklog * @property {number} type * @property {string} topic * @property {number} partition * @property {number} offset * * @typedef {object} ProducerResponseItem * @property {string} topic * @property {number} partition * @property {import('kafkajs/utils/long').Long} [offset] * @property {import('kafkajs/utils/long').Long} [baseOffset] * * @param {ProducerResponseItem} response * @returns {ProducerBacklog} */ transformProduceResponse (response) { // In produce protocol >=v3, the offset key changes from `offset` to `baseOffset` const { topicName: topic, partition, offset, baseOffset } = response const offsetAsLong = offset || baseOffset return { type: 'kafka_produce', partition, offset: offsetAsLong ? Number(offsetAsLong) : undefined, topic } } /** * * @param {ProducerResponseItem[]} commitList * @returns {void} */ commit (commitList) { if (!this.config.dsmEnabled) return const keys = [ 'type', 'partition', 'offset', 'topic' ] for (const commit of commitList.map(this.transformProduceResponse)) { if (keys.some(key => !commit.hasOwnProperty(key))) continue this.tracer.setOffset(commit) } } start ({ topic, messages, bootstrapServers, clusterId }) { const span = this.startSpan({ resource: topic, meta: { component: 'kafkajs', 'kafka.topic': topic, 'kafka.cluster_id': clusterId, [MESSAGING_DESTINATION_KEY]: topic }, metrics: { 'kafka.batch_size': messages.length } }) if (bootstrapServers) { span.setTag(BOOTSTRAP_SERVERS_KEY, bootstrapServers) } for (const message of messages) { if (message !== null && typeof message === 'object') { this.tracer.inject(span, 'text_map', message.headers) if (this.config.dsmEnabled) { const payloadSize = getMessageSize(message) const edgeTags = ['direction:out', `topic:${topic}`, 'type:kafka'] if (clusterId) { edgeTags.push(`kafka_cluster_id:${clusterId}`) } const dataStreamsContext = this.tracer.setCheckpoint(edgeTags, span, payloadSize) DsmPathwayCodec.encode(dataStreamsContext, message.headers) } } } } } module.exports = KafkajsProducerPlugin