Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
767526c
initial
jcstorms1 Jul 16, 2025
e0a0dd2
wrap eventhub methods
jcstorms1 Jul 16, 2025
3e57935
trace eventhub in azure function
jcstorms1 Jul 16, 2025
b8eaf5d
add span attributes for event hub
jcstorms1 Jul 16, 2025
3a7230d
update hooks
jcstorms1 Jul 28, 2025
a15e8c7
add list and single message support
jcstorms1 Aug 25, 2025
dbdfa32
refactor
jcstorms1 Aug 25, 2025
e7c4ac1
use this to get the config
jcstorms1 Aug 26, 2025
40e6353
refactor and add span links
jcstorms1 Sep 10, 2025
40bf893
add buffered event queues
jcstorms1 Sep 12, 2025
09e06a3
initial eventhubs test passing
jcstorms1 Sep 12, 2025
d796013
add event hubs producer tests
jcstorms1 Sep 15, 2025
4d4524b
break apart tests
jcstorms1 Sep 19, 2025
975ef63
initial eventhub function test
jcstorms1 Sep 23, 2025
b085289
use batches span context array
jcstorms1 Sep 25, 2025
96fc0db
finalize tests
jcstorms1 Sep 29, 2025
c5bcc4e
uncomment tests
jcstorms1 Sep 29, 2025
0d5160f
Merge branch 'master' into storms/instrument-event-hub
jcstorms1 Sep 29, 2025
85f50e2
update docker compose
jcstorms1 Sep 29, 2025
0cb912f
remove env file and hardcode volume
jcstorms1 Sep 29, 2025
a9b858f
tests
jcstorms1 Sep 29, 2025
9354e55
try workaround
jcstorms1 Sep 30, 2025
94ee7bd
typo
jcstorms1 Sep 30, 2025
1c61388
fix docker cp command
jcstorms1 Sep 30, 2025
4d897c9
update test package.json
jcstorms1 Sep 30, 2025
7867061
test reordering service
jcstorms1 Oct 1, 2025
8e5ca50
update eventhubs service
jcstorms1 Oct 1, 2025
07f441d
missing import
jcstorms1 Oct 1, 2025
4484701
update dd-trace dependancies
jcstorms1 Oct 1, 2025
872c5c0
refactor tests
jcstorms1 Oct 2, 2025
7c54c68
update ports
jcstorms1 Oct 2, 2025
b58dfd2
reorder services
jcstorms1 Oct 2, 2025
2f886fa
start with azure edge
jcstorms1 Oct 3, 2025
cdfb243
add docker cp to functions for config
jcstorms1 Oct 3, 2025
31bf564
try new action
jcstorms1 Oct 3, 2025
c4e4859
typo
jcstorms1 Oct 3, 2025
18974d7
retry test
jcstorms1 Oct 6, 2025
63175db
try using service id
jcstorms1 Oct 6, 2025
8a10b57
update service bus version
jcstorms1 Oct 6, 2025
c31b0b6
remove localhost reference
jcstorms1 Oct 6, 2025
7181770
pin core tools version for fx
jcstorms1 Oct 7, 2025
ee296b9
update path for http
jcstorms1 Oct 7, 2025
a2de912
reset func core tool version
jcstorms1 Oct 7, 2025
261c11e
simplify github workflow
jcstorms1 Oct 7, 2025
d4f5721
move tests to serverless action
jcstorms1 Oct 7, 2025
b41b693
update node version used
jcstorms1 Oct 7, 2025
bfd438f
fix messaging system in fx
jcstorms1 Oct 8, 2025
15ed318
update test
jcstorms1 Oct 8, 2025
c50259a
fix tests and add check for empty events
jcstorms1 Oct 10, 2025
d5814ee
fix index in eventhub test
jcstorms1 Oct 10, 2025
71e3cfc
move test to appropriate plugin
jcstorms1 Oct 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 41 additions & 3 deletions .github/workflows/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,30 @@ jobs:
with:
suffix: plugins-${{ github.job }}-${{ matrix.node-version }}
- uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1

azure-event-hubs:
runs-on: ubuntu-latest
services:
azurite:
image: mcr.microsoft.com/azure-storage/azurite:3.35.0
ports:
- "127.0.0.1:10000:10000"
- "127.0.0.1:10001:10001"
- "127.0.0.1:10002:10002"
azureeventhubsemulator:
image: mcr.microsoft.com/azure-messaging/eventhubs-emulator:2.1.0
ports:
- "127.0.0.1:5673:5672"
- "127.0.0.1:9092:9092"
env:
BLOB_SERVER: azurite
METADATA_SERVER: azurite
ACCEPT_EULA: "Y"
env:
PLUGINS: azure-event-hubs
SERVICES: azurite,azureeventhubsemulator
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: ./.github/actions/plugins/test
azure-functions:
runs-on: ubuntu-latest
services:
Expand All @@ -97,6 +120,15 @@ jobs:
- "127.0.0.1:10000:10000"
- "127.0.0.1:10001:10001"
- "127.0.0.1:10002:10002"
azureeventhubsemulator:
image: mcr.microsoft.com/azure-messaging/eventhubs-emulator:2.1.0
ports:
- "127.0.0.1:5673:5672"
- "127.0.0.1:9092:9092"
env:
BLOB_SERVER: azurite
METADATA_SERVER: azurite
ACCEPT_EULA: "Y"
azureservicebusemulator:
image: mcr.microsoft.com/azure-messaging/servicebus-emulator:1.1.2
ports:
Expand All @@ -115,10 +147,16 @@ jobs:
MSSQL_SA_PASSWORD: "Localtestpass1!"
env:
PLUGINS: azure-functions
SERVICES: azureservicebusemulator,azuresqledge
SERVICES: azureservicebusemulator,azuresqledge,azurite,azureeventhubsemulator
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: ./.github/actions/node/active-lts
- run: |
docker cp \
Copy link
Contributor Author

@jcstorms1 jcstorms1 Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add a config file for the Event Hubs emulator, but in github workflows we can't mount the file. The workaround is to use docker cp and restart the service. https://github.com/orgs/community/discussions/42127#discussioncomment-7591609

${{ github.workspace }}/packages/datadog-plugin-azure-functions/test/fixtures/eventhub-emulator-config.json \
${{ job.services.azureeventhubsemulator.id }}:/Eventhubs_Emulator/ConfigFiles/Config.json
- run : |
docker restart ${{ job.services.azureeventhubsemulator.id }}
- uses: ./.github/actions/node/newest-maintenance-lts
- uses: ./.github/actions/install
- run: npm install -g [email protected]
- run: echo "$(dirname $(which func))" >> $GITHUB_PATH
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,6 @@ packages/dd-trace/test/plugins/versions/node_modules
packages/dd-trace/test/plugins/versions/yarn.lock
!packages/dd-trace/**/telemetry/logs
packages/datadog-plugin-azure-functions/test/integration-test/fixtures/node_modules
__azurite_db_queue__.json
__azurite_db_queue_extent__.json
__queuestorage__/AzuriteConfig
25 changes: 18 additions & 7 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,36 @@ services:
ports:
- "127.0.0.1:3000-3002:3000-3002"
azurite:
image: mcr.microsoft.com/azure-storage/azurite:3.34.0
image: mcr.microsoft.com/azure-storage/azurite:3.35.0
ports:
- "127.0.0.1:10000:10000"
- "127.0.0.1:10001:10001"
- "127.0.0.1:10002:10002"
azureeventhubsemulator:
image: mcr.microsoft.com/azure-messaging/eventhubs-emulator:2.1.0
volumes:
- "./packages/datadog-plugin-azure-functions/test/fixtures/eventhub-emulator-config.json:/Eventhubs_Emulator/ConfigFiles/Config.json"
ports:
- "127.0.0.1:5673:5672"
- "127.0.0.1:9092:9092"
environment:
BLOB_SERVER: azurite
METADATA_SERVER: azurite
ACCEPT_EULA: "Y"
azureservicebusemulator:
image: mcr.microsoft.com/azure-messaging/servicebus-emulator:1.1.2
ports:
- "127.0.0.1:5672:5672"
- "127.0.0.1:5300:5300"
- "127.0.0.1:5672:5672"
- "127.0.0.1:5300:5300"
environment:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "Localtestpass1!"
SQL_SERVER: azuresqledge
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "Localtestpass1!"
SQL_SERVER: azuresqledge
azuresqledge:
image: mcr.microsoft.com/azure-sql-edge:1.0.7
platform: linux/amd64
ports:
- "127.0.0.1:1433:1433"
- "127.0.0.1:1433:1433"
environment:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "Localtestpass1!"
Expand Down
1 change: 1 addition & 0 deletions docs/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ tracer.use('amqplib');
tracer.use('avsc');
tracer.use('aws-sdk');
tracer.use('aws-sdk', awsSdkOptions);
tracer.use('azure-event-hubs')
tracer.use('azure-functions');
tracer.use('bunyan');
tracer.use('couchbase');
Expand Down
8 changes: 8 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ interface Plugins {
"apollo": tracer.plugins.apollo;
"avsc": tracer.plugins.avsc;
"aws-sdk": tracer.plugins.aws_sdk;
"azure-event-hubs": tracer.plugins.azure_event_hubs;
"azure-functions": tracer.plugins.azure_functions;
"azure-service-bus": tracer.plugins.azure_service_bus;
"bunyan": tracer.plugins.bunyan;
Expand Down Expand Up @@ -1409,6 +1410,12 @@ declare namespace tracer {
[key: string]: boolean | Object | undefined;
}

/**
* This plugin automatically instruments the
* @azure/event-hubs module
*/
interface azure_event_hubs extends Integration {}

/**
* This plugin automatically instruments the
* @azure/functions module.
Expand All @@ -1420,6 +1427,7 @@ declare namespace tracer {
* @azure/service-bus module
*/
interface azure_service_bus extends Integration {}

/**
* This plugin patches the [bunyan](https://github.com/trentm/node-bunyan)
* to automatically inject trace identifiers in log records when the
Expand Down
37 changes: 37 additions & 0 deletions packages/datadog-instrumentations/src/azure-event-hubs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict'

const {
addHook
} = require('./helpers/instrument')
const shimmer = require('../../datadog-shimmer')
const dc = require('dc-polyfill')

const producerCh = dc.tracingChannel('apm:azure-event-hubs:send')

addHook({
name: '@azure/event-hubs',
versions: ['>=6.0.0']
}, obj => {
const EventHubProducerClient = obj.EventHubProducerClient
shimmer.wrap(EventHubProducerClient.prototype, 'createBatch',
createBatch => async function () {
const batch = await createBatch.apply(this, arguments)
shimmer.wrap(batch, 'tryAdd',
tryAdd => function (eventData) {
const config = this._context.config
const functionName = tryAdd.name
return producerCh.tracePromise(
tryAdd,
{ functionName, eventData, batch: this, config },
this, ...arguments)
})
return batch
})
shimmer.wrap(EventHubProducerClient.prototype, 'sendBatch',
sendBatch => function (eventData) {
const config = this._context.config
const functionName = sendBatch.name
return producerCh.tracePromise(sendBatch, { functionName, eventData, config }, this, ...arguments)
})
return obj
})
3 changes: 3 additions & 0 deletions packages/datadog-instrumentations/src/azure-functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ addHook({ name: '@azure/functions', versions: ['>=4'], patchDefault: false }, (a
shimmer.wrap(app, 'serviceBusQueue', wrapHandler)
shimmer.wrap(app, 'serviceBusTopic', wrapHandler)

// Event Hub triggers
shimmer.wrap(app, 'eventHub', wrapHandler)

return azureFunction
})

Expand Down
1 change: 1 addition & 0 deletions packages/datadog-instrumentations/src/helpers/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
'@apollo/gateway': () => require('../apollo'),
'apollo-server-core': () => require('../apollo-server-core'),
'@aws-sdk/smithy-client': () => require('../aws-sdk'),
'@azure/event-hubs': () => require('../azure-event-hubs'),
'@azure/functions': () => require('../azure-functions'),
'@azure/service-bus': () => require('../azure-service-bus'),
'@cucumber/cucumber': () => require('../cucumber'),
Expand Down
15 changes: 15 additions & 0 deletions packages/datadog-plugin-azure-event-hubs/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict'

const ProducerPlugin = require('./producer')
const CompositePlugin = require('../../dd-trace/src/plugins/composite')

class AzureEventHubsPlugin extends CompositePlugin {
static get id () { return 'azure-event-hubs' }
static get plugins () {
return {
producer: ProducerPlugin
}
}
}

module.exports = AzureEventHubsPlugin
82 changes: 82 additions & 0 deletions packages/datadog-plugin-azure-event-hubs/src/producer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use strict'

const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const ProducerPlugin = require('../../dd-trace/src/plugins/producer')

class AzureEventHubsProducerPlugin extends ProducerPlugin {
static get id () { return 'azure-event-hubs' }
static get operation () { return 'send' }
static get prefix () { return 'tracing:apm:azure-event-hubs:send' }

bindStart (ctx) {
// we do not want to make these spans when batch linking is disabled.
if (!batchLinksAreEnabled() && ctx.functionName === 'tryAdd') {
return ctx.currentStore
}

const qualifiedNamespace = ctx.config.endpoint.replace('sb://', '').replace('/', '')
const entityPath = ctx.config.entityPath
const span = this.startSpan({
resource: entityPath,
type: 'messaging',
meta: {
component: 'azure-event-hubs',
'messaging.system': 'eventhubs',
'messaging.destination.name': entityPath,
'network.destination.name': qualifiedNamespace,
}
}, ctx)

if (ctx.functionName === 'tryAdd') {
span._spanContext._name = 'azure.eventhubs.create'
span.setTag('messaging.operation', 'create')

if (ctx.eventData.messageID !== undefined) {
span.setTag('message.id', ctx.eventData.messageID)
}

if (batchLinksAreEnabled()) {
ctx.batch._spanContexts.push(span.context())
injectTraceContext(this.tracer, span, ctx.eventData)
}
}

if (ctx.functionName === 'sendBatch') {
const eventData = ctx.eventData
const eventDataLength = eventData.length || eventData._context.connection._eventsCount
span.setTag('messaging.operation', 'send')
span.setTag('messaging.batch.message_count', eventDataLength)

if (eventData.constructor.name !== 'EventDataBatchImpl' && Array.isArray(eventData)) {
eventData.forEach(event => {
injectTraceContext(this.tracer, span, event)
})
} else {
if (batchLinksAreEnabled()) {
eventData._spanContexts.forEach(spanContext => {
span.addLink(spanContext)
})
}
}
}
return ctx.currentStore
}

asyncEnd (ctx) {
super.finish()
}
}

function injectTraceContext (tracer, span, event) {
if (!event.properties) {
event.properties = {}
}
tracer.inject(span, 'text_map', event.properties)
}

function batchLinksAreEnabled () {
const eh = getEnvironmentVariable('DD_TRACE_AZURE_EVENTHUBS_BATCH_LINKS_ENABLED')
return eh !== 'false'
}

module.exports = AzureEventHubsProducerPlugin
Loading