| 26 | import PluginInstaller from '../core/PluginInstaller'; |
| 27 | |
| 28 | class AMQPLibPlugin implements SwPlugin { |
| 29 | readonly module = 'amqplib'; |
| 30 | readonly versions = '*'; |
| 31 | |
| 32 | install(installer: PluginInstaller): void { |
| 33 | const { BaseChannel } = installer.require?.('amqplib/lib/channel') ?? require('amqplib/lib/channel'); |
| 34 | |
| 35 | this.interceptProducer(BaseChannel); |
| 36 | this.interceptConsumer(BaseChannel); |
| 37 | } |
| 38 | |
| 39 | interceptProducer(BaseChannel: any): void { |
| 40 | const _sendMessage = BaseChannel.prototype.sendMessage; |
| 41 | |
| 42 | BaseChannel.prototype.sendMessage = function (fields: any, properties: any, content: any) { |
| 43 | const topic = fields.exchange || ''; |
| 44 | const queue = fields.routingKey || ''; |
| 45 | const peer = `${this.connection.stream.remoteAddress}:${this.connection.stream.remotePort}`; |
| 46 | const span = ContextManager.current.newExitSpan( |
| 47 | 'RabbitMQ/' + topic + '/' + queue + '/Producer', |
| 48 | Component.RABBITMQ_PRODUCER, |
| 49 | ); |
| 50 | |
| 51 | span.start(); |
| 52 | |
| 53 | try { |
| 54 | span.inject().items.forEach((item) => { |
| 55 | fields.headers[item.key] = item.value; |
| 56 | }); |
| 57 | |
| 58 | span.component = Component.RABBITMQ_PRODUCER; |
| 59 | span.layer = SpanLayer.MQ; |
| 60 | span.peer = peer; |
| 61 | |
| 62 | span.tag(Tag.mqBroker((this.connection.stream.constructor.name === 'Socket' ? 'amqp://' : 'amqps://') + peer)); |
| 63 | |
| 64 | if (topic) span.tag(Tag.mqTopic(topic)); |
| 65 | |
| 66 | if (queue) span.tag(Tag.mqQueue(queue)); |
| 67 | |
| 68 | const ret = _sendMessage.call(this, fields, properties, content); |
| 69 | |
| 70 | span.stop(); |
| 71 | |
| 72 | return ret; |
| 73 | } catch (e) { |
| 74 | span.error(e); |
| 75 | span.stop(); |
| 76 | |
| 77 | throw e; |
| 78 | } |
| 79 | }; |
| 80 | } |
| 81 | |
| 82 | interceptConsumer(BaseChannel: any): void { |
| 83 | const _dispatchMessage = BaseChannel.prototype.dispatchMessage; |
| 84 | |
| 85 | BaseChannel.prototype.dispatchMessage = function (fields: any, message: any) { |
nothing calls this directly
no outgoing calls
no test coverage detected